Commit d0f4c654 authored by Matija Obreza's avatar Matija Obreza

Merge branch '293-dataset-location-and-timing' into 'master'

Resolve "Dataset location and timing"

Closes #293

See merge request genesys-pgr/genesys-server!182
parents a67ea924 8252d12f
......@@ -16,6 +16,7 @@
package org.genesys.catalog.api.v0;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
......@@ -244,6 +245,13 @@ public class DatasetController {
return datasetService.addDescriptors(dataset, descriptors.toArray(new Descriptor[] {}));
}
@PostMapping(value = "/set-descriptors/{UUID},{version}")
public Dataset updateDescriptors(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version, @RequestBody final List<UUID> descriptorUuids) {
final Dataset dataset = datasetService.loadDataset(uuid, version);
final List<Descriptor> descriptors = descriptorUuids.stream().map(descriptorUuid -> descriptorService.getDescriptor(descriptorUuid)).collect(Collectors.toList());
return datasetService.updateDescriptors(dataset, descriptors);
}
/**
* Removes the descriptors.
*
......
/*
* Copyright 2018 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.genesys.catalog.api.v0;
import java.util.UUID;
import org.genesys.catalog.exceptions.NotFoundElement;
import org.genesys.catalog.model.dataset.Dataset;
import org.genesys.catalog.model.dataset.DatasetLocation;
import org.genesys.catalog.service.DatasetService;
import org.genesys.catalog.service.LocationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* The Class LocationController.
*
* @author Andrey Lugovskoy.
*/
@RestController
@RequestMapping(LocationController.CONTROLLER_URL)
public class LocationController {
/** The Constant API_BASE. */
protected static final String CONTROLLER_URL = DatasetController.CONTROLLER_URL + "/{UUID}/location";
/** The dataset service. */
@Autowired
protected DatasetService datasetService;
@Autowired
private LocationService locationService;
/**
* List location.
*
* @param page the page
* @param pageSize the page size
* @param direction the direction
* @param sort the sort
* @param uuid the uuid
* @return the page
*/
@GetMapping(value = "/list")
public Page<DatasetLocation> listLocation(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "ASC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "id") final String[] sort, @PathVariable("UUID") final UUID uuid) {
return locationService.listLocation(uuid, new PageRequest(page, Integer.min(pageSize, 100), direction, sort));
}
/**
* Load by uuid.
*
* @param locationUuid the location uuid
* @return the dataset location
* @throws NotFoundElement the not found element
*/
@GetMapping(value = "/{locationUuid}")
public DatasetLocation loadByUuid(@PathVariable("locationUuid") final UUID locationUuid) throws NotFoundElement {
return locationService.loadLocation(locationUuid);
}
/**
* Creates the location.
*
* @param datasetUuid the dataset uuid
* @param datasetLocation the dataset location
* @return the dataset location
* @throws NotFoundElement the not found element
*/
@PostMapping(value = "/create")
public DatasetLocation createLocation(@PathVariable("UUID") final UUID datasetUuid, @RequestBody final DatasetLocation datasetLocation) throws NotFoundElement {
final Dataset dataset = datasetService.loadDataset(datasetUuid);
return locationService.createLocation(dataset, datasetLocation);
}
/**
* Delete location.
*
* @param datasetUuid the dataset uuid
* @param datasetLocation the dataset location
* @return the dataset location
* @throws NotFoundElement the not found element
*/
@RequestMapping(value = "/delete", method = { RequestMethod.POST, RequestMethod.DELETE })
public DatasetLocation deleteLocation(@PathVariable("UUID") final UUID datasetUuid, @RequestBody final DatasetLocation datasetLocation) throws NotFoundElement {
final Dataset dataset = datasetService.loadDataset(datasetUuid);
return locationService.removeLocation(dataset, datasetLocation);
}
/**
* Update location.
*
* @param datasetUuid the dataset uuid
* @param datasetLocation the dataset location
* @return the dataset location
* @throws NotFoundElement the not found element
*/
@PostMapping(value = "/update")
public DatasetLocation updateLocation(@PathVariable("UUID") final UUID datasetUuid, @RequestBody final DatasetLocation datasetLocation) throws NotFoundElement {
final Dataset dataset = datasetService.loadDataset(datasetUuid);
return locationService.updateLocation(dataset, datasetLocation);
}
}
......@@ -28,6 +28,7 @@ import org.genesys.catalog.model.Partner;
import org.genesys.catalog.model.traits.Descriptor;
import org.genesys.catalog.service.PublishValidationInterface;
import org.genesys.filerepository.model.RepositoryFile;
import org.genesys2.util.MCPDUtil;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
......@@ -45,7 +46,7 @@ import java.util.Set;
* @author Maxim Borodenko
*/
@Entity
@Table(name="dataset")
@Table(name = "dataset")
@Cacheable
@Audited
@Document(indexName = "catalog")
......@@ -73,7 +74,7 @@ public class Dataset extends UuidModel implements Publishable, SelfCleaning, Pub
@CollectionTable(name = "dataset_accessions", joinColumns = @JoinColumn(name = "datasetId"),
// index
indexes = { @Index(columnList = "datasetId, instCode, acceNumb"), @Index(columnList = "datasetId, genus") })
@Field(type=FieldType.Object)
@Field(type = FieldType.Object)
@JsonView({ JsonViews.Public.class })
private Set<AccessionIdentifier> accessionIdentifiers;
......@@ -89,24 +90,32 @@ public class Dataset extends UuidModel implements Publishable, SelfCleaning, Pub
@OneToMany(fetch = FetchType.LAZY, cascade = {})
@JoinTable(name = "dataset_repositoryfile", joinColumns = @JoinColumn(name = "datasetId", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "repositoryfileId", referencedColumnName = "id"))
@OrderColumn(name = "position")
@Field(type=FieldType.Object)
@Field(type = FieldType.Object)
@JsonView({ JsonViews.Public.class })
private List<RepositoryFile> repositoryFiles;
/** The creators. */
@PublishValidation(innerCheck = true)
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "dataset", orphanRemoval = true, fetch = FetchType.LAZY)
@Field(type=FieldType.Object)
@Field(type = FieldType.Object)
@JsonView({ JsonViews.Public.class })
private List<DatasetCreator> creators;
/** The locations. */
@PublishValidation(innerCheck = true)
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "dataset", orphanRemoval = true, fetch = FetchType.LAZY)
@Field(type=FieldType.Object)
@Field(type = FieldType.Object)
@JsonView({ JsonViews.Public.class })
private List<DatasetLocation> locations;
/** The min start date of all locations */
@Column(length = 8)
private String startDate;
/** The max end date of all locations */
@Column(length = 8)
private String endDate;
/** The accession count. */
// Number of accessions in the {@link #accessionIdentifiers} list
@Column(name = "accessions")
......@@ -182,10 +191,14 @@ public class Dataset extends UuidModel implements Publishable, SelfCleaning, Pub
if (descriptors != null) {
this.descriptorCount = descriptors.size();
}
if (locations != null) {
this.startDate = locations.stream().map(DatasetLocation::getStartDate).filter(d -> d != null).min(String::compareTo).orElse(null);
this.endDate = locations.stream().map(DatasetLocation::getEndDate).filter(d -> d != null).max(String::compareTo).orElse(null);
}
trimStringsToNull();
}
/**
* Owner is the ACL parent object for the dataset
*/
......@@ -284,6 +297,46 @@ public class Dataset extends UuidModel implements Publishable, SelfCleaning, Pub
this.locations = locations;
}
/**
* Gets the start date.
*
* @return the start date
*/
public String getStartDate() {
return startDate;
}
/**
* Sets the start date if startDate is valid McpdDate.
*
* @param startDate the new start date
*/
public void setStartDate(String startDate) {
if (MCPDUtil.isMcpdDate(startDate)) {
this.startDate = startDate;
}
}
/**
* Gets the end date.
*
* @return the end date
*/
public String getEndDate() {
return endDate;
}
/**
* Sets the end date if endDate is valid McpdDate.
*
* @param endDate the new start date
*/
public void setEndDate(String endDate) {
if (MCPDUtil.isMcpdDate(endDate)) {
this.endDate = endDate;
}
}
/**
* Gets the version tag.
*
......
......@@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import org.genesys.blocks.model.UuidModel;
import org.genesys.catalog.annotations.PublishValidation;
import org.genesys.catalog.service.PublishValidationInterface;
import org.genesys2.util.MCPDUtil;
import javax.persistence.*;
import java.util.Map;
......@@ -60,6 +61,14 @@ public class DatasetLocation extends UuidModel implements PublishValidationInter
@PublishValidation
private Double decimalLongitude;
/** The start date */
@Column(length = 8)
private String startDate;
/** The end date */
@Column(length = 8)
private String endDate;
/** The dataset. */
@ManyToOne(cascade = { CascadeType.REFRESH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.DETACH }, optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "datasetId")
......@@ -198,6 +207,46 @@ public class DatasetLocation extends UuidModel implements PublishValidationInter
this.decimalLongitude = decimalLongitude;
}
/**
* Gets the start date.
*
* @return the start date
*/
public String getStartDate() {
return startDate;
}
/**
* Sets the start date if startDate is valid McpdDate.
*
* @param startDate the new start date
*/
public void setStartDate(String startDate) {
if(MCPDUtil.isMcpdDate(startDate)) {
this.startDate = startDate;
}
}
/**
* Gets the end date.
*
* @return the end date
*/
public String getEndDate() {
return endDate;
}
/**
* Sets the end date if endDate is valid McpdDate.
*
* @param endDate the new start date
*/
public void setEndDate(String endDate) {
if(MCPDUtil.isMcpdDate(endDate)) {
this.endDate = endDate;
}
}
/*
* (non-Javadoc)
* @see org.genesys.catalog.service.PublishValidationInterface#validation()
......
......@@ -517,6 +517,8 @@ public class DatasetServiceImpl implements DatasetService {
target.setOwner(source.getOwner());
target.setVersionTag(source.getVersionTag());
target.setCreated(source.getCreated());
target.setStartDate(source.getStartDate());
target.setEndDate(source.getEndDate());
if (source.getCrops() != null) {
if (target.getCrops() == null) {
......@@ -525,6 +527,16 @@ public class DatasetServiceImpl implements DatasetService {
target.getCrops().clear();
target.getCrops().addAll(source.getCrops());
}
if (source.getLocations() != null) {
if (target.getLocations() == null) {
target.setLocations(new ArrayList<>());
}
if(target != source) {
target.getLocations().clear();
target.getLocations().addAll(source.getLocations());
}
}
// target.setDescriptors(source.getDescriptors());
}
......
......@@ -62,7 +62,14 @@ public class LocationServiceImpl implements LocationService {
dataset = datasetService.loadDataset(dataset);
LOG.info("Create DatasetLocation {} for dataset {}", input, dataset.getUuid());
input.setDataset(dataset);
return locationRepository.save(input);
DatasetLocation saved = locationRepository.save(input);
dataset.setStartDate(saved.getStartDate());
dataset.setEndDate(saved.getEndDate());
dataset.getLocations().add(saved);
datasetService.updateDataset(dataset);
return saved;
}
/**
......@@ -79,6 +86,9 @@ public class LocationServiceImpl implements LocationService {
throw new InvalidApiUsageException("Location does not belong to dataset");
}
dataset.getLocations().remove(datasetLocation);
dataset.setStartDate("--------");
dataset.setEndDate("--------");
datasetService.updateDataset(dataset);
return datasetLocation;
}
......@@ -148,7 +158,15 @@ public class LocationServiceImpl implements LocationService {
throw new InvalidApiUsageException("Location does not belong to dataset");
}
copyValue(datasetLocation, input);
return locationRepository.save(datasetLocation);
DatasetLocation saved = locationRepository.save(datasetLocation);
dataset.getLocations().remove(input);
dataset.getLocations().add(saved);
dataset.setStartDate(saved.getStartDate());
dataset.setEndDate(saved.getEndDate());
datasetService.updateDataset(dataset);
return saved;
}
/**
......@@ -164,5 +182,7 @@ public class LocationServiceImpl implements LocationService {
target.setVerbatimLocality(source.getVerbatimLocality());
target.setDecimalLatitude(source.getDecimalLatitude());
target.setDecimalLongitude(source.getDecimalLongitude());
target.setStartDate(source.getStartDate());
target.setEndDate(source.getEndDate());
}
}
......@@ -26,7 +26,7 @@ import org.apache.commons.lang3.StringUtils;
public class MCPDUtil {
static Pattern mcpdSplit = Pattern.compile("\\s*;\\s*");
public static final Pattern MCPDDATE_PATTERN = Pattern.compile("^[1-9]\\d{3}(\\d|-){4}$");
public static final Pattern MCPDDATE_PATTERN = Pattern.compile("^(?:(?:[1-9]\\d{3})|(?:----)|(?:0000))(?:--|(?:0[0-9])|(?:1[0-2]))(?:--|(?:0[0-9])|(?:[1-2][0-9])|(?:3[0-1]))$");
public static final Pattern WIEWSCODE_PATTERN = Pattern.compile("^\\p{Upper}{3}(\\d){3,4}$");
......
......@@ -3566,6 +3566,31 @@ databaseChangeLog:
sql: >-
CREATE INDEX UK_1my8xep8hi5fv42o3ivu0t41o ON short_filter(json(250))
- changeSet:
id: 1533223466241-1
author: vpavlov
comment: Added Dataset location timing
changes:
- addColumn:
tableName: dataset
columns:
- column:
name: startDate
type: varchar(8)
- column:
name: endDate
type: varchar(8)
- addColumn:
tableName: dataset_location
columns:
- column:
name: startDate
type: varchar(8)
- column:
name: endDate
type: varchar(8)
- changeSet:
id: 1533138107794-1
author: mborodenko
......
......@@ -28,6 +28,7 @@ import org.genesys.catalog.persistence.dataset.DatasetRepository;
import org.genesys.catalog.persistence.dataset.DatasetVersionsRepository;
import org.genesys.catalog.service.DatasetCreatorService;
import org.genesys.catalog.service.DatasetService;
import org.genesys.catalog.service.LocationService;
import org.genesys.filerepository.persistence.RepositoryFilePersistence;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.AccessionId;
......@@ -67,6 +68,8 @@ public abstract class AbstractDatasetServiceTest extends CatalogServiceTest {
private InstituteService instituteService;
@Autowired
private TaxonomyService taxonomyService;
@Autowired
protected LocationService locationService;
public AbstractDatasetServiceTest() {
super();
......
......@@ -20,6 +20,7 @@ import java.net.URL;
import java.util.Set;
import org.genesys.catalog.model.Partner;
import org.genesys.catalog.model.dataset.DatasetLocation;
import org.genesys.catalog.model.traits.Descriptor;
import org.genesys.catalog.model.traits.Descriptor.Category;
import org.genesys.catalog.model.traits.DescriptorList;
......@@ -135,4 +136,17 @@ public abstract class CatalogServiceTest extends AbstractServiceTest {
protected Descriptor setupDescriptor(final Partner owner, final String title, final String versionTag, final Descriptor.DataType type) {
return descriptorService.createDescriptor(createDescriptor(owner, title, versionTag, type));
}
protected DatasetLocation createDatasetLocation(final String userCountry, final String mapCountry, final String stateProvince, final String verbatimLocality, final Double decimalLatitude, final Double decimalLongitude, final String startDate, final String endDate){
final DatasetLocation input = new DatasetLocation();
input.setUserCountry(userCountry);
input.setMapCountry(mapCountry);
input.setStateProvince(stateProvince);
input.setDecimalLatitude(decimalLatitude);
input.setDecimalLongitude(decimalLongitude);
input.setStartDate(startDate);
input.setEndDate(endDate);
return input;
}
}
......@@ -16,6 +16,7 @@
package org.genesys.test.catalog.services;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.io.File;
......@@ -34,6 +35,7 @@ import org.genesys.catalog.exceptions.InvalidApiUsageException;
import org.genesys.catalog.exceptions.NotFoundElement;
import org.genesys.catalog.model.dataset.AccessionIdentifier;
import org.genesys.catalog.model.dataset.Dataset;
import org.genesys.catalog.model.dataset.DatasetLocation;
import org.genesys.catalog.model.filters.AccessionIdentifierFilter;
import org.genesys.catalog.model.filters.DatasetFilter;
import org.genesys.catalog.model.traits.Descriptor;
......@@ -601,4 +603,100 @@ public class DatasetServiceTest extends AbstractDatasetServiceTest {
input = datasetService.updateDataset(input);
assertThat(input.getOwner(), not(partner2));
}
@Test
public void testAddLocationToDataset(){
DatasetLocation savedLocation = createDatasetLocation("testCountry", "testMapCountry", "testStateProvince", "testVerbatimLocality", 10.0, 20.0, "20000101", "20010101");
Dataset savedDataset = buildAndSaveDataset(DATASET_TITLE_1, DATASET_DESCRIPTION_1, partner, false);
savedLocation = locationService.createLocation(savedDataset, savedLocation);
Dataset loadedDataset = datasetService.loadDataset(savedDataset.getUuid());
assertThat(loadedDataset.getLocations(), hasSize(1));
assertEquals(savedLocation.getStartDate(), loadedDataset.getStartDate());
assertEquals(savedLocation.getEndDate(), loadedDataset.getEndDate());
}
@Test
public void testAddMultipleLocationsToDataset(){
DatasetLocation savedLocation1 = createDatasetLocation("testCountry1", "testMapCountry1", "testStateProvince1", "testVerbatimLocality1", 10.0, 20.0, "20010101", "20110101");
DatasetLocation savedLocation2 = createDatasetLocation("testCountry2", "testMapCountry2", "testStateProvince2", "testVerbatimLocality2", 11.0, 21.0, "20020202", "20120202");
DatasetLocation savedLocation3 = createDatasetLocation("testCountry3", "testMapCountry3", "testStateProvince3", "testVerbatimLocality3", 12.0, 22.0, "20030303", "20130303");
Dataset savedDataset = buildAndSaveDataset(DATASET_TITLE_1, DATASET_DESCRIPTION_1, partner, false);
savedLocation1 = locationService.createLocation(savedDataset, savedLocation1);
savedDataset = datasetService.loadDataset(savedDataset.getUuid());
savedLocation2 = locationService.createLocation(savedDataset, savedLocation2);
savedDataset = datasetService.loadDataset(savedDataset.getUuid());
savedLocation3 = locationService.createLocation(savedDataset, savedLocation3);
Dataset loadedDataset = datasetService.loadDataset(savedDataset.getUuid());
assertThat(loadedDataset.getLocations(), hasSize(3));
assertEquals(savedLocation1.getStartDate(), loadedDataset.getStartDate());
assertEquals(savedLocation3.getEndDate(), loadedDataset.getEndDate());
}
@Test
public void testUpdateLocation(){
DatasetLocation savedLocation = createDatasetLocation("testCountry", "testMapCountry", "testStateProvince", "testVerbatimLocality", 10.0, 20.0, "20000101", "20010101");
Dataset savedDataset = buildAndSaveDataset(DATASET_TITLE_1, DATASET_DESCRIPTION_1, partner, false);
savedLocation = locationService.createLocation(savedDataset, savedLocation);
Dataset loadedDataset = datasetService.loadDataset(savedDataset.getUuid());
assertThat(loadedDataset.getLocations(), hasSize(1));
assertEquals(savedLocation.getStartDate(), loadedDataset.getStartDate());
assertEquals(savedLocation.getEndDate(), loadedDataset.getEndDate());
savedLocation.setEndDate("20120011");
savedLocation.setStartDate("2002----");
savedLocation = locationService.updateLocation(loadedDataset, savedLocation);
loadedDataset = datasetService.loadDataset(savedDataset.getUuid());
assertThat(loadedDataset.getLocations(), hasSize(1));
assertEquals(savedLocation.getStartDate(), loadedDataset.getStartDate());
assertEquals(savedLocation.getEndDate(), loadedDataset.getEndDate());
savedLocation.setEndDate(null);