From b66aaec1a25afe95a3b6b25f66c30ae821648f77 Mon Sep 17 00:00:00 2001 From: Maxym Borodenko Date: Wed, 1 Aug 2018 19:18:39 +0300 Subject: [PATCH] #284 Dataset AccessionIdentifier --- .../model/dataset/AccessionIdentifier.java | 74 +++++++++++++++++-- .../service/impl/DatasetServiceImpl.java | 37 +++++++++- .../AccessionRepositoryCustomImpl.java | 15 +++- .../service/impl/GenesysServiceImpl.java | 4 +- .../liquibase/liquibase-changeLog.yml | 36 +++++++++ .../services/AbstractDatasetServiceTest.java | 36 +++++++++ .../catalog/services/DatasetServiceTest.java | 36 +++++++++ 7 files changed, 225 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/genesys/catalog/model/dataset/AccessionIdentifier.java b/src/main/java/org/genesys/catalog/model/dataset/AccessionIdentifier.java index e984b36a9..c700c6279 100644 --- a/src/main/java/org/genesys/catalog/model/dataset/AccessionIdentifier.java +++ b/src/main/java/org/genesys/catalog/model/dataset/AccessionIdentifier.java @@ -17,8 +17,14 @@ package org.genesys.catalog.model.dataset; import javax.persistence.Column; import javax.persistence.Embeddable; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import java.io.Serializable; +import org.genesys2.server.model.genesys.AccessionId; +import org.genesys2.server.model.impl.AccessionIdentifier3; + /** * Identifies an accession by it's INSTCODE, ACCENUMB and GENUS. Use of DOI * remains optional. @@ -27,30 +33,35 @@ import java.io.Serializable; * @author Matija Obreza */ @Embeddable -public class AccessionIdentifier implements Serializable { +public class AccessionIdentifier implements AccessionIdentifier3, Serializable { /** The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; /** The DOI. */ @Column(length = 100) - public String doi; + private String doi; /** The inst code. */ @Column(length = 10, nullable = false) - public String instCode; + private String instCode; /** The acce numb. */ @Column(nullable = false, length = 50) - public String acceNumb; + private String acceNumb; /** The genus. */ @Column(nullable = false, length = 100) - public String genus; + private String genus; /** The species. */ @Column(nullable = true, length = 100) - public String species; + private String species; + + /** The accession. */ + @ManyToOne(optional = true, fetch = FetchType.LAZY, cascade = {}) + @JoinColumn(name = "accessionId", nullable = true) + private AccessionId accession; /** * Gets the doi. @@ -142,6 +153,44 @@ public class AccessionIdentifier implements Serializable { this.species = species; } + /** + * Gets the accession. + * + * @return the accession + */ + public AccessionId getAccession() { + return accession; + } + + /** + * Sets the accession. + * + * @param accession the new accession + */ + public void setAccession(final AccessionId accession) { + this.accession = accession; + } + + /** + * Gets holding institute code. + * + * @return the instCode + */ + @Override + public String getHoldingInstitute() { + return instCode; + } + + /** + * Gets accession number. + * + * @return the acceNumb + */ + @Override + public String getAccessionNumber() { + return acceNumb; + } + @Override public int hashCode() { final int prime = 31; @@ -201,6 +250,19 @@ public class AccessionIdentifier implements Serializable { } else if (!species.equals(other.species)) { return false; } + if (accession == null) { + if (other.accession != null) { + return false; + } + } else { + if (other.accession != null) { + if (!accession.getUuid().equals(other.accession.getUuid())) { + return false; + } + } else { + return false; + } + } return true; } } diff --git a/src/main/java/org/genesys/catalog/service/impl/DatasetServiceImpl.java b/src/main/java/org/genesys/catalog/service/impl/DatasetServiceImpl.java index c523cdec3..dcc37ad07 100644 --- a/src/main/java/org/genesys/catalog/service/impl/DatasetServiceImpl.java +++ b/src/main/java/org/genesys/catalog/service/impl/DatasetServiceImpl.java @@ -27,6 +27,7 @@ import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; +import org.apache.commons.lang.StringUtils; import org.genesys.blocks.security.service.CustomAclService; import org.genesys.catalog.exceptions.InvalidApiUsageException; import org.genesys.catalog.exceptions.NotFoundElement; @@ -46,7 +47,10 @@ import org.genesys.filerepository.NoSuchRepositoryFileException; import org.genesys.filerepository.model.RepositoryFile; import org.genesys.filerepository.service.RepositoryService; import org.genesys2.server.model.UserRole; +import org.genesys2.server.model.genesys.Accession; import org.genesys2.server.security.SecurityUtils; +import org.genesys2.server.service.GenesysService; +import org.genesys2.server.service.impl.NonUniqueAccessionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.ConcurrencyFailureException; @@ -88,6 +92,9 @@ public class DatasetServiceImpl implements DatasetService { @Autowired private SecurityUtils securityUtils; + @Autowired + private GenesysService genesysService; + /** The file repository path. */ @Value("${file.repository.datasets.folder}") public String datasetRepositoryPath; @@ -115,7 +122,7 @@ public class DatasetServiceImpl implements DatasetService { dataset.setCrops(source.getCrops()); if (source.getAccessionIdentifiers() != null && !source.getAccessionIdentifiers().isEmpty()) { - dataset.setAccessionIdentifiers(new HashSet<>(source.getAccessionIdentifiers())); + dataset.setAccessionIdentifiers(lookupMatchingAccessions(new HashSet<>(source.getAccessionIdentifiers()))); } copyDescriptors(dataset, source.getDescriptors()); @@ -162,7 +169,7 @@ public class DatasetServiceImpl implements DatasetService { LOG.info("Update AccessionIdentifiers. Input dataset: {}, input accessionIdentifiers {}", dataset, accessionIdentifiers); dataset = loadDataset(dataset); dataset.getAccessionIdentifiers().clear(); - dataset.setAccessionIdentifiers(new HashSet<>(accessionIdentifiers)); + dataset.setAccessionIdentifiers(lookupMatchingAccessions(new HashSet<>(accessionIdentifiers))); return lazyLoad(datasetRepository.save(dataset)); } @@ -408,7 +415,7 @@ public class DatasetServiceImpl implements DatasetService { if (loadedDataset == null) { throw new NotFoundElement("Dataset doesn't exist"); } - loadedDataset.setAccessionIdentifiers(new HashSet<>(accessionIdentifiers)); + loadedDataset.setAccessionIdentifiers(lookupMatchingAccessions(new HashSet<>(accessionIdentifiers))); return lazyLoad(datasetRepository.save(loadedDataset)); } @@ -536,4 +543,28 @@ public class DatasetServiceImpl implements DatasetService { target.getDescriptors().addAll(descriptors.stream().distinct().collect(Collectors.toList())); } + /** + * Looking for matching Accession and then sets that to AccessionIdentifier + * + * @param accessionIdentifiers the accessionIdentifiers + * @return accessionIdentifiers with matching accessions from Genesys + */ + private Set lookupMatchingAccessions(final Set accessionIdentifiers) { + accessionIdentifiers.forEach(accei -> { + Accession foundAccession = null; + if (!StringUtils.isBlank(accei.getDoi())) { + foundAccession = genesysService.getAccessionByDOI(accei.getDoi()); + } else { + try { + foundAccession = genesysService.getAccession(accei.getInstCode(), accei.getDoi(), accei.getAcceNumb(), accei.getGenus()); + } catch (final NonUniqueAccessionException e) { + LOG.warn(e.getMessage()); + } + } + accei.setAccession(foundAccession != null ? foundAccession.getAccessionId() : null); + }); + + return accessionIdentifiers; + } + } diff --git a/src/main/java/org/genesys2/server/persistence/AccessionRepositoryCustomImpl.java b/src/main/java/org/genesys2/server/persistence/AccessionRepositoryCustomImpl.java index 4822b04b6..9a89bbc2e 100644 --- a/src/main/java/org/genesys2/server/persistence/AccessionRepositoryCustomImpl.java +++ b/src/main/java/org/genesys2/server/persistence/AccessionRepositoryCustomImpl.java @@ -45,6 +45,7 @@ import org.genesys2.server.service.impl.NonUniqueAccessionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.support.Querydsl; import org.springframework.stereotype.Repository; @@ -217,7 +218,7 @@ public class AccessionRepositoryCustomImpl implements AccessionRepositoryCustom, if (doi != null) { restrictions.add(criteriaBuilder.equal(root.get("doi"), doi)); - } else if (institute.hasUniqueAcceNumbs()) { + } else if (institute != null && institute.hasUniqueAcceNumbs()) { restrictions.add(criteriaBuilder.equal(root.get("accessionNumber"), acceNumb)); } else { restrictions.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("accessionNumber"), acceNumb), criteriaBuilder.equal(tax.get("genus"), genus))); @@ -225,7 +226,17 @@ public class AccessionRepositoryCustomImpl implements AccessionRepositoryCustom, cq.where(criteriaBuilder.and(criteriaBuilder.equal(root.get("institute"), institute), criteriaBuilder.or(restrictions.toArray(new Predicate[] {})))); - return em.createQuery(cq).getSingleResult(); + List result = em.createQuery(cq).getResultList(); + + if (result.isEmpty()) { + return null; + } + + if (result.size() > 1) { + throw new IncorrectResultSizeDataAccessException(1, result.size()); + } + + return result.get(0); } @Override diff --git a/src/main/java/org/genesys2/server/service/impl/GenesysServiceImpl.java b/src/main/java/org/genesys2/server/service/impl/GenesysServiceImpl.java index 342ad7d5e..65dca950b 100644 --- a/src/main/java/org/genesys2/server/service/impl/GenesysServiceImpl.java +++ b/src/main/java/org/genesys2/server/service/impl/GenesysServiceImpl.java @@ -319,8 +319,8 @@ public class GenesysServiceImpl implements GenesysService, DatasetService { Accession accession = accessionRepository.findOne(instituteRepository.findByCode(instCode), doi, acceNumb, genus); return lazyLoadAccession(accession); } catch (IncorrectResultSizeDataAccessException e) { - LOG.error("Duplicate accession name instCode={} acceNumb={}", instCode, acceNumb); - throw new NonUniqueAccessionException(instCode, acceNumb); + LOG.error("Duplicate accession name instCode={} acceNumb={} genus={}", instCode, acceNumb, genus); + throw new NonUniqueAccessionException(instCode, acceNumb, genus); } } diff --git a/src/main/resources/liquibase/liquibase-changeLog.yml b/src/main/resources/liquibase/liquibase-changeLog.yml index fe9bffe5c..1ea98fc34 100644 --- a/src/main/resources/liquibase/liquibase-changeLog.yml +++ b/src/main/resources/liquibase/liquibase-changeLog.yml @@ -3565,3 +3565,39 @@ databaseChangeLog: - sql: sql: >- CREATE INDEX UK_1my8xep8hi5fv42o3ivu0t41o ON short_filter(json(250)) + +- changeSet: + id: 1533138107794-1 + author: mborodenko + comment: Add column `accessionId` to dataset_accessions table + changes: + - addColumn: + columns: + - column: + constraints: + nullable: true + name: accessionId + type: BIGINT(20) + tableName: dataset_accessions + +- changeSet: + id: 1533138107794-2 + author: mborodenko + comment: Add constraints + changes: + - addForeignKeyConstraint: + baseColumnNames: accessionId + baseTableName: dataset_accessions + constraintName: FK_ekss0g19xg9h2tsp1zl8g9h2t + deferrable: false + initiallyDeferred: false + onDelete: NO ACTION + onUpdate: NO ACTION + referencedColumnNames: id + referencedTableName: acce + - createIndex: + columns: + - column: + name: accessionId + indexName: FK_ekss0g19xg9h2tsp1zl8g9h2t + tableName: dataset_accessions diff --git a/src/test/java/org/genesys/test/catalog/services/AbstractDatasetServiceTest.java b/src/test/java/org/genesys/test/catalog/services/AbstractDatasetServiceTest.java index 11597dea1..50ef1f40a 100644 --- a/src/test/java/org/genesys/test/catalog/services/AbstractDatasetServiceTest.java +++ b/src/test/java/org/genesys/test/catalog/services/AbstractDatasetServiceTest.java @@ -18,6 +18,7 @@ package org.genesys.test.catalog.services; import java.util.HashSet; import java.util.Set; +import com.google.common.collect.Lists; import org.genesys.catalog.model.Partner; import org.genesys.catalog.model.dataset.AccessionIdentifier; import org.genesys.catalog.model.dataset.Dataset; @@ -28,6 +29,14 @@ import org.genesys.catalog.persistence.dataset.DatasetVersionsRepository; import org.genesys.catalog.service.DatasetCreatorService; import org.genesys.catalog.service.DatasetService; import org.genesys.filerepository.persistence.RepositoryFilePersistence; +import org.genesys2.server.model.genesys.Accession; +import org.genesys2.server.model.genesys.AccessionId; +import org.genesys2.server.model.genesys.Taxonomy2; +import org.genesys2.server.model.impl.FaoInstitute; +import org.genesys2.server.persistence.AccessionRepository; +import org.genesys2.server.persistence.FaoInstituteRepository; +import org.genesys2.server.service.InstituteService; +import org.genesys2.server.service.TaxonomyService; import org.junit.After; import org.junit.Before; import org.springframework.beans.factory.annotation.Autowired; @@ -50,6 +59,14 @@ public abstract class AbstractDatasetServiceTest extends CatalogServiceTest { protected RepositoryFilePersistence repositoryFilePersistence; @Autowired protected DatasetCreatorService datasetCreatorService; + @Autowired + protected AccessionRepository accessionRepository; + @Autowired + protected FaoInstituteRepository instituteRepository; + @Autowired + private InstituteService instituteService; + @Autowired + private TaxonomyService taxonomyService; public AbstractDatasetServiceTest() { super(); @@ -68,6 +85,8 @@ public abstract class AbstractDatasetServiceTest extends CatalogServiceTest { datasetVersionsRepository.deleteAll(); descriptorRepository.deleteAll(); repositoryFilePersistence.deleteAll(); + accessionRepository.deleteAll(); + instituteRepository.deleteAll(); super.cleanup(); } @@ -130,4 +149,21 @@ public abstract class AbstractDatasetServiceTest extends CatalogServiceTest { return accessionIdentifier; } + protected Accession buildAndSaveAccession(final String acceNumb, final String instCode, final String genus) { + FaoInstitute institute = new FaoInstitute(); + institute.setCode(instCode); + institute.setFullName("Test institute " + instCode); + instituteService.update(Lists.newArrayList(institute)); + institute = instituteService.getInstitute(instCode); + + Accession a = new Accession(); + a.setAccessionId(new AccessionId()); + a.setInstitute(institute); + a.setAccessionNumber(acceNumb); + Taxonomy2 taxon = new Taxonomy2(); + taxon.setGenus(genus); + a.setTaxonomy(taxonomyService.ensureTaxonomy(taxon)); + return accessionRepository.save(a); + } + } \ No newline at end of file diff --git a/src/test/java/org/genesys/test/catalog/services/DatasetServiceTest.java b/src/test/java/org/genesys/test/catalog/services/DatasetServiceTest.java index b6f804626..e7206d463 100644 --- a/src/test/java/org/genesys/test/catalog/services/DatasetServiceTest.java +++ b/src/test/java/org/genesys/test/catalog/services/DatasetServiceTest.java @@ -42,6 +42,8 @@ import org.genesys.filerepository.InvalidRepositoryFileDataException; import org.genesys.filerepository.InvalidRepositoryPathException; import org.genesys.filerepository.NoSuchRepositoryFileException; import org.genesys.filerepository.model.RepositoryFile; +import org.genesys2.server.model.genesys.Accession; +import org.genesys2.server.model.genesys.AccessionId; import org.junit.Test; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.DataIntegrityViolationException; @@ -149,6 +151,40 @@ public class DatasetServiceTest extends AbstractDatasetServiceTest { assertThat(input, not(nullValue())); assertThat(input.getAccessionIdentifiers().size(), is(1)); assertThat(input.getAccessionIdentifiers().iterator().next(), is(accessionIdentifiers.iterator().next())); + + AccessionIdentifier accessionIdentifier = input.getAccessionIdentifiers().stream().findFirst().orElse(null); + assertThat(accessionIdentifier, notNullValue()); + AccessionId accessionId = accessionIdentifier.getAccession(); + assertThat(accessionId, nullValue()); + } + + @Test + public void testLookupAccessionsForAccessionIdentifiersInDataset() { + final Accession accession = buildAndSaveAccession("TestAccNum", TEST_INSTCODE, "TestGen"); + + Dataset input = buildDataset(DATASET_TITLE_1, DATASET_DESCRIPTION_1, partner, null, false); + input = datasetService.createDataset(input); + + final Set accessionIdentifiers = new HashSet() { + /** + * + */ + private static final long serialVersionUID = 8866546652858324612L; + + { + add(makeAccessionIdentifier(TEST_INSTCODE, "TestAccNum", "TestGen", null)); + } + }; + + input = datasetService.updateAccessionIdentifiers(input, accessionIdentifiers); + assertThat(input, not(nullValue())); + assertThat(input.getAccessionIdentifiers().size(), is(1)); + assertThat(input.getAccessionIdentifiers().iterator().next(), is(accessionIdentifiers.iterator().next())); + + final AccessionIdentifier accessionIdentifier = input.getAccessionIdentifiers().stream().findFirst().orElse(null); + assertThat(accessionIdentifier, notNullValue()); + final AccessionId accessionId = accessionIdentifier.getAccession(); + assertThat(accessionId.getUuid(), is(accession.getAccessionId().getUuid())); } /** -- GitLab