From 3b99eddf40c88b25cc711da30cb1f48d6db5ba06 Mon Sep 17 00:00:00 2001 From: Matija Obreza Date: Wed, 26 Feb 2014 20:01:00 +0100 Subject: [PATCH] New taxonomy --- .../lucene/genesys/AccessionBridge.java | 4 +- .../server/model/genesys/Accession.java | 12 +- .../server/model/genesys/Taxonomy2.java | 60 ++++- .../server/model/impl/CropTaxonomy.java | 1 + .../server/model/impl/FaoInstitute.java | 9 + .../domain/AccessionRepository.java | 3 +- .../domain/Taxonomy2Repository.java | 36 +++ .../server/service/BatchRESTService.java | 3 +- .../genesys2/server/service/CropService.java | 3 + .../server/service/GenesysService.java | 11 +- .../server/service/TaxonomyService.java | 7 + .../service/impl/BatchRESTServiceImpl.java | 222 ++++++++++++------ .../server/service/impl/CropServiceImpl.java | 10 +- .../service/impl/GenesysServiceImpl.java | 8 +- .../impl/RESTApiDataTypeException.java | 9 + .../server/service/impl/RESTApiException.java | 9 + .../service/impl/RESTApiValueException.java | 8 + .../service/impl/TaxonomyServiceImpl.java | 80 +++++++ .../server/service/worker/SGSVEntry.java | 54 +++++ .../service/worker/SGSVInsertMissing.java | 45 +--- .../server/service/worker/SGSVUpdate.java | 73 ++---- .../controller/AccessionController.java | 2 +- .../controller/rest/AccessionController.java | 8 +- .../controller/rest/RestController.java | 10 + 24 files changed, 488 insertions(+), 199 deletions(-) create mode 100644 src/main/java/org/genesys2/server/persistence/domain/Taxonomy2Repository.java create mode 100644 src/main/java/org/genesys2/server/service/impl/RESTApiDataTypeException.java create mode 100644 src/main/java/org/genesys2/server/service/impl/RESTApiException.java create mode 100644 src/main/java/org/genesys2/server/service/impl/RESTApiValueException.java create mode 100644 src/main/java/org/genesys2/server/service/worker/SGSVEntry.java diff --git a/src/main/java/org/genesys2/server/lucene/genesys/AccessionBridge.java b/src/main/java/org/genesys2/server/lucene/genesys/AccessionBridge.java index 66c75dae3..98f30ee23 100644 --- a/src/main/java/org/genesys2/server/lucene/genesys/AccessionBridge.java +++ b/src/main/java/org/genesys2/server/lucene/genesys/AccessionBridge.java @@ -21,7 +21,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.genesys2.server.model.genesys.Accession; -import org.genesys2.server.model.genesys.Taxonomy; +import org.genesys2.server.model.genesys.Taxonomy2; import org.genesys2.server.model.impl.Country; import org.genesys2.server.model.impl.FaoInstitute; import org.hibernate.search.bridge.FieldBridge; @@ -51,7 +51,7 @@ public class AccessionBridge implements FieldBridge { sd.append(countryOfOrigin.getName()); } - Taxonomy taxonomy = accession.getTaxonomy(); + Taxonomy2 taxonomy = accession.getTaxonomy(); if (taxonomy != null) { sd.append(taxonomy.getTaxonName()); } diff --git a/src/main/java/org/genesys2/server/model/genesys/Accession.java b/src/main/java/org/genesys2/server/model/genesys/Accession.java index 260857ba1..0dcb2ba05 100644 --- a/src/main/java/org/genesys2/server/model/genesys/Accession.java +++ b/src/main/java/org/genesys2/server/model/genesys/Accession.java @@ -135,18 +135,14 @@ public class Accession extends VersionedAuditedModel { this.accessionName = accessionName; } - public Taxonomy getTaxonomy() { + public Taxonomy getTaxonomy1() { return this.taxonomy; } - public Taxonomy2 getTaxonomy2() { + public Taxonomy2 getTaxonomy() { return this.taxonomy2; } - - public void setTaxonomy(final Taxonomy taxonomy) { - this.taxonomy = taxonomy; - } - + public String getAcquisitionSource() { return this.acquisitionSource; } @@ -252,7 +248,7 @@ public class Accession extends VersionedAuditedModel { this.taxSpecies = taxSpecies; } - public void setTaxonomy2(Taxonomy2 taxonomy2) { + public void setTaxonomy(Taxonomy2 taxonomy2) { this.taxonomy2 = taxonomy2; } diff --git a/src/main/java/org/genesys2/server/model/genesys/Taxonomy2.java b/src/main/java/org/genesys2/server/model/genesys/Taxonomy2.java index 3610e4f72..cfb92f4f0 100644 --- a/src/main/java/org/genesys2/server/model/genesys/Taxonomy2.java +++ b/src/main/java/org/genesys2/server/model/genesys/Taxonomy2.java @@ -20,6 +20,7 @@ import java.text.MessageFormat; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.Lob; import javax.persistence.Table; import javax.persistence.UniqueConstraint; @@ -49,6 +50,14 @@ public class Taxonomy2 extends GlobalVersionedAuditedModel { @Column(nullable = true, length = 100) private String subtAuthor; + @Column(nullable = false) + @Lob + private String taxonName; + + private long taxGenus; + + private Long taxSpecies; + // @OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "taxonomy") // private List cropTaxonomies; @@ -80,6 +89,11 @@ public class Taxonomy2 extends GlobalVersionedAuditedModel { return sb.toString(); } + public void setTaxonName(String taxonName) { + // Ignore what they provide + taxonName = getTaxonName(); + } + // public List getCropTaxonomies() { // return cropTaxonomies; // } @@ -88,13 +102,53 @@ public class Taxonomy2 extends GlobalVersionedAuditedModel { // this.cropTaxonomies = cropTaxonomies; // } - @Override - public String toString() { - return MessageFormat.format("Tax id={0} taxonName=", id, getTaxonName()); + public String getSpAuthor() { + return spAuthor; + } + + public void setSpAuthor(String spAuthor) { + this.spAuthor = spAuthor; + } + + public String getSubtaxa() { + return subtaxa; + } + + public void setSubtaxa(String subtaxa) { + this.subtaxa = subtaxa; + } + + public String getSubtAuthor() { + return subtAuthor; + } + + public void setSubtAuthor(String subtAuthor) { + this.subtAuthor = subtAuthor; } public boolean sameAs(Taxonomy2 taxonomy) { return taxonomy == null ? false : taxonomy.getId().equals(id); } + public long getTaxGenus() { + return this.taxGenus; + } + + public void setTaxGenus(long taxGenus) { + this.taxGenus = taxGenus; + } + + public Long getTaxSpecies() { + return this.taxSpecies; + } + + public void setTaxSpecies(Long taxSpecies) { + this.taxSpecies = taxSpecies; + } + + @Override + public String toString() { + return MessageFormat.format("Tax id={0} taxonName=", id, getTaxonName()); + } + } diff --git a/src/main/java/org/genesys2/server/model/impl/CropTaxonomy.java b/src/main/java/org/genesys2/server/model/impl/CropTaxonomy.java index f4cfba790..08fc2d272 100644 --- a/src/main/java/org/genesys2/server/model/impl/CropTaxonomy.java +++ b/src/main/java/org/genesys2/server/model/impl/CropTaxonomy.java @@ -24,6 +24,7 @@ import javax.persistence.Table; import org.genesys2.server.model.BusinessModel; import org.genesys2.server.model.genesys.Taxonomy; +// TODO FIXME Need to link to {@link Taxonomy2} @Entity @Table(name = "croptaxonomy") public class CropTaxonomy extends BusinessModel { diff --git a/src/main/java/org/genesys2/server/model/impl/FaoInstitute.java b/src/main/java/org/genesys2/server/model/impl/FaoInstitute.java index f3ba3ae1d..9765200a5 100644 --- a/src/main/java/org/genesys2/server/model/impl/FaoInstitute.java +++ b/src/main/java/org/genesys2/server/model/impl/FaoInstitute.java @@ -87,6 +87,7 @@ public class FaoInstitute extends BusinessModel implements GeoReferencedEntity, private Double latitude; private Double longitude; private Double elevation; + private boolean uniqueAcceNumbs; public FaoInstitute() { } @@ -210,4 +211,12 @@ public class FaoInstitute extends BusinessModel implements GeoReferencedEntity, public void setSettings(Map settings) { this.settings = settings; } + + public boolean hasUniqueAcceNumbs() { + return this.uniqueAcceNumbs; + } + + public void setUniqueAcceNumbs(boolean uniqueAcceNumbs) { + this.uniqueAcceNumbs = uniqueAcceNumbs; + } } diff --git a/src/main/java/org/genesys2/server/persistence/domain/AccessionRepository.java b/src/main/java/org/genesys2/server/persistence/domain/AccessionRepository.java index 19131b2d4..cca86b9ec 100644 --- a/src/main/java/org/genesys2/server/persistence/domain/AccessionRepository.java +++ b/src/main/java/org/genesys2/server/persistence/domain/AccessionRepository.java @@ -96,8 +96,7 @@ public interface AccessionRepository extends JpaRepository { @Query("select a from Accession a where a.taxonomy in ( ?1 )") Page findByTaxonomy(Collection taxonomies, Pageable pageable); - // Accession findByInstituteCodeAndAccessionName(String holdingInstitute, - // String accessionName); + Accession findByInstituteCodeAndAccessionName(String instCode, String acceNumb); Accession findByInstituteCodeAndAccessionNameAndGenus(String holdingInstitute, String accessionName, String genus); diff --git a/src/main/java/org/genesys2/server/persistence/domain/Taxonomy2Repository.java b/src/main/java/org/genesys2/server/persistence/domain/Taxonomy2Repository.java new file mode 100644 index 000000000..4fb71de64 --- /dev/null +++ b/src/main/java/org/genesys2/server/persistence/domain/Taxonomy2Repository.java @@ -0,0 +1,36 @@ +/** + * Copyright 2014 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.genesys2.server.persistence.domain; + +import java.util.List; + +import org.genesys2.server.model.genesys.Taxonomy2; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +public interface Taxonomy2Repository extends JpaRepository { + + @Query("select distinct t.genus from Taxonomy2 t where t.genus like ?1") + List autocompleteGenus(String term, Pageable page); + + @Query("select distinct t.taxonName from Taxonomy2 t where t.taxonName like ?1") + List autocompleteTaxonomy(String term, Pageable page); + + @Query("select t from Taxonomy2 t where t.genus=?1 and t.species=?2 and t.spAuthor=?3 and t.subtaxa=?4 and t.subtAuthor=?5") + Taxonomy2 findOne(String genus, String species, String spAuthor, String subtaxa, String subtAuthor); +} diff --git a/src/main/java/org/genesys2/server/service/BatchRESTService.java b/src/main/java/org/genesys2/server/service/BatchRESTService.java index df4ef7b88..0c1ebd599 100644 --- a/src/main/java/org/genesys2/server/service/BatchRESTService.java +++ b/src/main/java/org/genesys2/server/service/BatchRESTService.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import org.genesys2.server.model.impl.FaoInstitute; +import org.genesys2.server.service.impl.RESTApiException; import org.genesys2.server.servlet.controller.rest.model.AccessionJson; import org.genesys2.server.servlet.controller.rest.model.AccessionNamesJson; @@ -27,7 +28,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; public interface BatchRESTService { - boolean upsertAccessionData(FaoInstitute institute, Map batch); + boolean upsertAccessionData(FaoInstitute institute, Map batch) throws RESTApiException; void upsertAccessionNames(FaoInstitute institute, List batch); diff --git a/src/main/java/org/genesys2/server/service/CropService.java b/src/main/java/org/genesys2/server/service/CropService.java index db68d28fe..41e208a12 100644 --- a/src/main/java/org/genesys2/server/service/CropService.java +++ b/src/main/java/org/genesys2/server/service/CropService.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Locale; import org.genesys2.server.model.genesys.Taxonomy; +import org.genesys2.server.model.genesys.Taxonomy2; import org.genesys2.server.model.impl.Crop; import org.genesys2.server.model.impl.CropRule; import org.genesys2.server.model.impl.CropTaxonomy; @@ -36,6 +37,8 @@ public interface CropService { List getCrops(Taxonomy taxonomy); + List getCrops(Taxonomy2 taxonomy2); + void rebuildTaxonomies(); Page getCropTaxonomies(Crop crop, Pageable pageable); diff --git a/src/main/java/org/genesys2/server/service/GenesysService.java b/src/main/java/org/genesys2/server/service/GenesysService.java index 28a01e0bd..5d9c6ad9b 100644 --- a/src/main/java/org/genesys2/server/service/GenesysService.java +++ b/src/main/java/org/genesys2/server/service/GenesysService.java @@ -95,7 +95,7 @@ public interface GenesysService { Accession getAccession(AccessionIdentifier3 aid3); - Accession getAccession(String instCode, String genus, String acceNumb); + Accession getAccession(String instCode, String acceNumb, String genus); Page statisticsGenusByInstitute(FaoInstitute faoInstitute, Pageable pageable); @@ -163,4 +163,13 @@ public interface GenesysService { long countAll(); + /** + * For institutes with {@link FaoInstitute#uniqueAcceNumbs} + * + * @param instCode + * @param acceNumb + * @return the 1 accession + */ + Accession getAccession(String instCode, String acceNumb); + } diff --git a/src/main/java/org/genesys2/server/service/TaxonomyService.java b/src/main/java/org/genesys2/server/service/TaxonomyService.java index 1ae2d5dc8..2f1569df8 100644 --- a/src/main/java/org/genesys2/server/service/TaxonomyService.java +++ b/src/main/java/org/genesys2/server/service/TaxonomyService.java @@ -19,6 +19,7 @@ package org.genesys2.server.service; import java.util.List; import org.genesys2.server.model.genesys.Taxonomy; +import org.genesys2.server.model.genesys.Taxonomy2; public interface TaxonomyService { @@ -31,4 +32,10 @@ public interface TaxonomyService { List autocompleteTaxonomy(String term); + long getTaxonomy2Id(String genus); + + long getTaxonomy2Id(String genus, String species); + + Taxonomy2 ensureTaxonomy2(String genus, String species, String spAuthor, String subtaxa, String subtAuthor); + } diff --git a/src/main/java/org/genesys2/server/service/impl/BatchRESTServiceImpl.java b/src/main/java/org/genesys2/server/service/impl/BatchRESTServiceImpl.java index df65fa8a8..56ab25c6b 100644 --- a/src/main/java/org/genesys2/server/service/impl/BatchRESTServiceImpl.java +++ b/src/main/java/org/genesys2/server/service/impl/BatchRESTServiceImpl.java @@ -36,7 +36,7 @@ import org.genesys2.server.model.genesys.AccessionBreeding; import org.genesys2.server.model.genesys.AccessionCollect; import org.genesys2.server.model.genesys.AccessionExchange; import org.genesys2.server.model.genesys.AccessionGeo; -import org.genesys2.server.model.genesys.Taxonomy; +import org.genesys2.server.model.genesys.Taxonomy2; import org.genesys2.server.model.impl.Country; import org.genesys2.server.model.impl.FaoInstitute; import org.genesys2.server.service.BatchRESTService; @@ -81,8 +81,11 @@ public class BatchRESTServiceImpl implements BatchRESTService { @Override @Transactional @PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#institute, 'WRITE') or hasPermission(#institute, 'CREATE')") - public boolean upsertAccessionData(FaoInstitute institute, Map batch) { + public boolean upsertAccessionData(FaoInstitute institute, Map batch) throws RESTApiException { LOG.info("Batch processing " + batch.size() + " entries for " + institute); + + boolean useUniqueAcceNumbs = institute.hasUniqueAcceNumbs(); + List toSave = new ArrayList(); List toSaveColl = new ArrayList(); List toSaveGeo = new ArrayList(); @@ -102,94 +105,39 @@ public class BatchRESTServiceImpl implements BatchRESTService { throw new RuntimeException("Accession does not belong to instCode=" + institute.getCode() + " acn=" + dataJson); } - Accession accession = genesysService.getAccession(dataJson.instCode, dataJson.genus, dataJson.acceNumb); + Accession accession = null; + if (useUniqueAcceNumbs) + accession = genesysService.getAccession(dataJson.instCode, dataJson.acceNumb); + else + accession = genesysService.getAccession(dataJson.instCode, dataJson.acceNumb, dataJson.genus); boolean updated = false; + ObjectNode accnJson = batch.get(dataJson); + if (accession == null) { LOG.warn("New accession " + dataJson); accession = new Accession(); accession.setInstituteCode(dataJson.instCode); accession.setInstitute(institute); - accession.setGenus(dataJson.genus); accession.setAccessionName(dataJson.acceNumb); - updated = true; - } - - ObjectNode accnJson = batch.get(dataJson); - - JsonNode value = accnJson.get("orgCty"); - if (value != null) { - String orgCty = value.textValue(); - if (!StringUtils.equals(orgCty, accession.getOrigin())) { - Country country = geoService.getCountry(orgCty); - accession.setOrigin(orgCty); - accession.setCountryOfOrigin(country); - updated = true; - } - } - - /* Allow updating AcceNumb */ - value = accnJson.get("newAcceNumb"); - if (value != null) { - String newAcceNumb = value.isNull() ? null : value.textValue(); - if (!StringUtils.equals(newAcceNumb, accession.getAccessionName())) { - accession.setAccessionName(newAcceNumb); - updated = true; - } - } - - /* Allow updating Genus */ - value = accnJson.get("newGenus"); - if (value != null) { - String newGenus = value.isNull() ? null : value.textValue(); - if (!StringUtils.equals(newGenus, accession.getGenus())) { - accession.setGenus(newGenus); - updated = true; - - // Need to do taxonomy - String species = null; - if (accession.getTaxonomy() != null) - species = accession.getTaxonomy().getSpecies(); - - value = accnJson.get("species"); - if (value != null) { - species = value.isNull() ? null : value.textValue(); - } - - Taxonomy taxonomy = taxonomyService.ensureTaxonomy(accession.getGenus(), species); - if (!taxonomy.sameAs(accession.getTaxonomy())) { - accession.setTaxonomy(taxonomy); - } + if (accnJson.get("genus") == null || accnJson.get("newGenus") == null) { + throw new RESTApiException("Cannot create new accession without specifying genus"); } - } - value = accnJson.get("species"); - if (value != null) { - String species = value.isNull() ? null : value.textValue(); - Taxonomy taxonomy = taxonomyService.ensureTaxonomy(accession.getGenus(), species); - if (!taxonomy.sameAs(accession.getTaxonomy())) { - accession.setTaxonomy(taxonomy); - updated = true; - } + updated = true; } - value = accnJson.get("uuid"); - if (value != null) { - String uuid = value.isNull() ? null : value.textValue(); - if (!StringUtils.equals(uuid, accession.getUuid())) { - if (uuid != null) { - // Throws a runtime exception if format is invalid - UUID.fromString(uuid); - } - accession.setUuid(uuid); - updated = true; - } - } + updated |= updateAcceNumb(accession, accnJson.get("newAcceNumb")); + updated |= updateTaxonomy(accession, accnJson); + updated |= updateOrgCty(accession, accnJson.get("orgCty")); + updated |= updateUuid(accession, accnJson.get("uuid")); - value = accnJson.get("acqDate"); + // TODO Move other setters to methods + + JsonNode value = accnJson.get("acqDate"); if (value != null) { String acqDate = value.isNull() ? null : value.textValue(); if (!StringUtils.equals(acqDate, accession.getAcquisitionDate())) { @@ -417,6 +365,128 @@ public class BatchRESTServiceImpl implements BatchRESTService { return toSave.size() > 0 || toSaveColl.size() > 0 || toSaveGeo.size() > 0 || toSaveBreed.size() > 0 || toSaveExch.size() > 0; } + private boolean updateAcceNumb(Accession accession, JsonNode value) throws RESTApiDataTypeException, RESTApiValueException { + if (value != null) { + if (!value.isTextual()) { + throw new RESTApiDataTypeException("newAcceNumb must be a String"); + } + + if (value.isNull()) { + throw new RESTApiValueException("newAcceNumb cannot be null"); + } + + String newAcceNumb=value.textValue(); + if (!StringUtils.equals(newAcceNumb, accession.getAccessionName())) { + accession.setAccessionName(newAcceNumb); + return true; + } + } + return false; + } + + private boolean updateOrgCty(Accession accession, JsonNode value) throws RESTApiDataTypeException, RESTApiValueException { + if (value != null) { + if (!value.isNull() && !value.isTextual()) + throw new RESTApiDataTypeException("orgCty must be a String"); + + String orgCty = value.textValue(); + if (!StringUtils.equals(orgCty, accession.getOrigin())) { + Country country = null; + if (orgCty != null) { + country = geoService.getCountry(orgCty); + if (country == null) + throw new RESTApiValueException("No country with ISO3 code: " + orgCty); + } + accession.setOrigin(orgCty); + accession.setCountryOfOrigin(country); + return true; + } + } + return false; + } + + private boolean updateUuid(Accession accession, JsonNode value) throws RESTApiValueException { + if (value != null) { + String uuid = value.isNull() ? null : value.textValue(); + if (!StringUtils.equals(uuid, accession.getUuid())) { + if (uuid != null) { + try { + // Throws a runtime exception if format is invalid + UUID.fromString(uuid); + } catch (RuntimeException e) { + throw new RESTApiValueException("UUID " + uuid + " is not in valid format: " + e.getMessage()); + } + } + accession.setUuid(uuid); + return true; + } + } + // No change + return false; + } + + /** + * Inspect incoming JSON and change taxonomy if required + * + * @param accession + * @param accnJson + * + * @return true if taxonomy was modified + * @throws RESTApiException + */ + private boolean updateTaxonomy(Accession accession, JsonNode accnJson) throws RESTApiException { + boolean updated = false; + + // Do not persist this one, temporary use + Taxonomy2 current = accession.getTaxonomy(); + if (current == null) { + current = new Taxonomy2(); + } + + // Load JSON values into "current" + current.setGenus(StringUtils.defaultIfBlank(stringIfProvided(accnJson.get("genus")), current.getGenus())); + current.setGenus(StringUtils.defaultIfBlank(stringIfProvided(accnJson.get("newGenus")), current.getGenus())); + current.setSpecies(StringUtils.defaultIfBlank(stringIfProvided(accnJson.get("species")), current.getSpecies())); + current.setSpAuthor(StringUtils.defaultIfBlank(stringIfProvided(accnJson.get("spauthor")), current.getSpAuthor())); + current.setSubtaxa(StringUtils.defaultIfBlank(stringIfProvided(accnJson.get("subtaxa")), current.getSubtaxa())); + current.setSubtAuthor(StringUtils.defaultIfBlank(stringIfProvided(accnJson.get("subtauthor")), current.getSubtAuthor())); + + Taxonomy2 ensuredTaxonomy = null; + if (current.getId() == null + || !((ensuredTaxonomy = taxonomyService.ensureTaxonomy2(current.getGenus(), current.getSpecies(), current.getSpAuthor(), current.getSubtaxa(), + current.getSubtAuthor())).sameAs(current))) { + + accession.setTaxonomy(ensuredTaxonomy); + accession.setTaxGenus(ensuredTaxonomy.getTaxGenus()); + accession.setTaxSpecies(ensuredTaxonomy.getTaxSpecies()); + + updated = true; + } + + return updated; + } + + /** + * Return + * + * @param jsonNode + * @return + * @throws RESTApiDataTypeException + */ + private String stringIfProvided(JsonNode jsonNode) throws RESTApiException { + if (jsonNode != null) { + if (!jsonNode.isTextual()) { + // We expect a String node + throw new RESTApiDataTypeException("Not a String"); + } + if (StringUtils.isBlank(jsonNode.textValue())) { + throw new RESTApiValueException("Value cannot be a blank String"); + } + return StringUtils.defaultIfBlank(jsonNode.textValue(), null); + } + return null; + } + private String arrayToString(ArrayNode arr) { if (arr == null || arr.isNull()) return null; @@ -514,7 +584,7 @@ public class BatchRESTServiceImpl implements BatchRESTService { List toRemove = new ArrayList(); for (AccessionNamesJson dataJson : batch) { - Accession accession = genesysService.getAccession(institute.getCode(), dataJson.genus, dataJson.acceNumb); + Accession accession = genesysService.getAccession(institute.getCode(), dataJson.acceNumb, dataJson.genus); if (accession == null) { LOG.warn("No such accession " + dataJson); continue; @@ -599,7 +669,7 @@ public class BatchRESTServiceImpl implements BatchRESTService { throw new RuntimeException("Accession does not belong to instCode=" + institute.getCode() + " acn=" + dataJson); } - Accession accession = genesysService.getAccession(dataJson.instCode, dataJson.genus, dataJson.acceNumb); + Accession accession = genesysService.getAccession(dataJson.instCode, dataJson.acceNumb, dataJson.genus); if (accession != null) { toDelete.add(accession); } diff --git a/src/main/java/org/genesys2/server/service/impl/CropServiceImpl.java b/src/main/java/org/genesys2/server/service/impl/CropServiceImpl.java index 66c72f312..02a8ff97c 100644 --- a/src/main/java/org/genesys2/server/service/impl/CropServiceImpl.java +++ b/src/main/java/org/genesys2/server/service/impl/CropServiceImpl.java @@ -26,6 +26,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.genesys2.server.model.genesys.Taxonomy; +import org.genesys2.server.model.genesys.Taxonomy2; import org.genesys2.server.model.impl.Crop; import org.genesys2.server.model.impl.CropRule; import org.genesys2.server.model.impl.CropTaxonomy; @@ -69,12 +70,11 @@ public class CropServiceImpl implements CropService { return cropRepository.findByShortName(shortName); } - @Override public List listCrops() { return cropRepository.findAll(); } - + @Override public List list(final Locale locale) { List crops = cropRepository.findAll(); @@ -92,6 +92,12 @@ public class CropServiceImpl implements CropService { return cropTaxonomyRepository.findByTaxonomy(taxonomy); } + @Override + public List getCrops(Taxonomy2 taxonomy2) { + // TODO FIXME get the crops! + return null; + } + @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) @PreAuthorize("hasRole('ADMINISTRATOR')") 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 b55edd4ca..5ccc02d6c 100644 --- a/src/main/java/org/genesys2/server/service/impl/GenesysServiceImpl.java +++ b/src/main/java/org/genesys2/server/service/impl/GenesysServiceImpl.java @@ -224,9 +224,15 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset public Accession getAccession(AccessionIdentifier3 aid3) { return accessionRepository.findByInstituteCodeAndAccessionNameAndGenus(aid3.getHoldingInstitute(), aid3.getAccessionName(), aid3.getGenus()); } + + + @Override + public Accession getAccession(String instCode, String acceNumb) { + return accessionRepository.findByInstituteCodeAndAccessionName(instCode, acceNumb); + } @Override - public Accession getAccession(String instCode, String genus, String acceNumb) { + public Accession getAccession(String instCode, String acceNumb, String genus) { return accessionRepository.findByInstituteCodeAndAccessionNameAndGenus(instCode, acceNumb, genus); } diff --git a/src/main/java/org/genesys2/server/service/impl/RESTApiDataTypeException.java b/src/main/java/org/genesys2/server/service/impl/RESTApiDataTypeException.java new file mode 100644 index 000000000..bc8417571 --- /dev/null +++ b/src/main/java/org/genesys2/server/service/impl/RESTApiDataTypeException.java @@ -0,0 +1,9 @@ +package org.genesys2.server.service.impl; + +public class RESTApiDataTypeException extends RESTApiException { + + public RESTApiDataTypeException(String message) { + super(message); + } + +} diff --git a/src/main/java/org/genesys2/server/service/impl/RESTApiException.java b/src/main/java/org/genesys2/server/service/impl/RESTApiException.java new file mode 100644 index 000000000..c4d131160 --- /dev/null +++ b/src/main/java/org/genesys2/server/service/impl/RESTApiException.java @@ -0,0 +1,9 @@ +package org.genesys2.server.service.impl; + +public class RESTApiException extends Exception { + + public RESTApiException(String message) { + super(message); + } + +} diff --git a/src/main/java/org/genesys2/server/service/impl/RESTApiValueException.java b/src/main/java/org/genesys2/server/service/impl/RESTApiValueException.java new file mode 100644 index 000000000..83d64f73a --- /dev/null +++ b/src/main/java/org/genesys2/server/service/impl/RESTApiValueException.java @@ -0,0 +1,8 @@ +package org.genesys2.server.service.impl; + +public class RESTApiValueException extends RESTApiException { + + public RESTApiValueException(String message) { + super(message); + } +} diff --git a/src/main/java/org/genesys2/server/service/impl/TaxonomyServiceImpl.java b/src/main/java/org/genesys2/server/service/impl/TaxonomyServiceImpl.java index 995be900a..e915e7c53 100644 --- a/src/main/java/org/genesys2/server/service/impl/TaxonomyServiceImpl.java +++ b/src/main/java/org/genesys2/server/service/impl/TaxonomyServiceImpl.java @@ -22,6 +22,8 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.genesys2.server.model.genesys.Taxonomy; +import org.genesys2.server.model.genesys.Taxonomy2; +import org.genesys2.server.persistence.domain.Taxonomy2Repository; import org.genesys2.server.persistence.domain.TaxonomyRepository; import org.genesys2.server.service.TaxonomyService; import org.springframework.beans.factory.annotation.Autowired; @@ -37,6 +39,8 @@ public class TaxonomyServiceImpl implements TaxonomyService { @Autowired private TaxonomyRepository taxonomyRepository; + private Taxonomy2Repository taxonomy2Repository; + @Override public Taxonomy get(String genus, String species) { return taxonomyRepository.getByGenusAndSpecies(genus, species); @@ -85,4 +89,80 @@ public class TaxonomyServiceImpl implements TaxonomyService { public List autocompleteTaxonomy(String term) { return taxonomyRepository.autocompleteTaxonomy("%" + term + "%", new PageRequest(0, 10)); } + + @Override + @Transactional + public Taxonomy2 ensureTaxonomy2(String genus, String species, String spAuthor, String subtaxa, String subtAuthor) { + if (species == null && spAuthor != null) { + species = "sp."; + } + if (subtaxa == null && subtAuthor != null) { + subtaxa = "subsp."; + } + + Taxonomy2 existing = taxonomy2Repository.findOne(genus, species, spAuthor, subtaxa, subtAuthor); + if (existing == null) { + return internalEnsure(genus, species, spAuthor, subtaxa, subtAuthor); + } + return existing; + } + + private synchronized Taxonomy2 internalEnsure(String genus, String species, String spAuthor, String subtaxa, String subtAuthor) { + // Loop it a bit if required + for (int i = 5; i > 0; i--) { + Taxonomy2 taxonomy = taxonomy2Repository.findOne(genus, species, spAuthor, subtaxa, subtAuthor); + if (taxonomy == null) { + taxonomy = new Taxonomy2(); + LOG.warn("Inserting new taxonomy"); + taxonomy.setGenus(genus); + taxonomy.setSpecies(species); + taxonomy.setSpAuthor(spAuthor); + taxonomy.setSubtaxa(subtaxa); + taxonomy.setSubtAuthor(subtAuthor); + + try { + taxonomy = taxonomy2Repository.save(taxonomy); + LOG.warn("Inserted new:" + taxonomy); + + if (!StringUtils.equals(species, "sp.") && spAuthor != null && subtaxa != null && subtAuthor != null) { + Taxonomy2 genusTaxa = internalEnsure(genus, "sp.", null, null, null); + taxonomy.setTaxGenus(genusTaxa.getId()); + + if (species != null && subtaxa != null && !StringUtils.equals(subtaxa, "subsp.") && subtAuthor != null) { + Taxonomy2 speciesTaxa = internalEnsure(genus, species, null, "subsp.", null); + taxonomy.setTaxSpecies(speciesTaxa.getId()); + } else { + // No species taxonomy + } + + } else { + taxonomy.setTaxGenus(taxonomy.getId()); + } + + taxonomy = taxonomy2Repository.save(taxonomy); + + // TODO Should update crop taxonomy lists? + + return taxonomy; + + } catch (Throwable e) { + LOG.warn("Error " + e.getMessage() + " :" + taxonomy); + continue; + } + } + } + + // Should not get here! + throw new RuntimeException("Could not persist Taxonomy2"); + } + + @Override + public long getTaxonomy2Id(String genus) { + return taxonomy2Repository.findOne(genus, "sp.", null, null, null).getId(); + } + + @Override + public long getTaxonomy2Id(String genus, String species) { + return taxonomy2Repository.findOne(genus, species, null, "subsp.", null).getId(); + } } diff --git a/src/main/java/org/genesys2/server/service/worker/SGSVEntry.java b/src/main/java/org/genesys2/server/service/worker/SGSVEntry.java new file mode 100644 index 000000000..c50016615 --- /dev/null +++ b/src/main/java/org/genesys2/server/service/worker/SGSVEntry.java @@ -0,0 +1,54 @@ +package org.genesys2.server.service.worker; + +import org.genesys2.server.model.impl.AccessionIdentifier3; + +class SGSVEntry implements AccessionIdentifier3 { + String instCode; + String acceNumb; + String origCty; + String genus; + String species; + String subtAuthor; + String subtaxa; + String spAuthor; + String fullTaxa; + String boxNo; + String depositDate; + Float quantity; + + public SGSVEntry(String[] entry) { + instCode = entry[1]; + acceNumb = entry[4]; + fullTaxa = entry[5]; + origCty = entry[12]; + genus = entry[16]; + species = entry[17]; + spAuthor = entry[25]; + subtaxa = entry[26]; + depositDate = entry[20]; + if (entry[7] != null) { + quantity = Float.parseFloat(entry[7]); + } + boxNo = entry[2]; + } + + @Override + public String getHoldingInstitute() { + return instCode; + } + + @Override + public String getAccessionName() { + return acceNumb; + } + + @Override + public String getGenus() { + return genus; + } + + @Override + public String toString() { + return "SGSVEntry " + instCode + " " + acceNumb; + } +} \ No newline at end of file diff --git a/src/main/java/org/genesys2/server/service/worker/SGSVInsertMissing.java b/src/main/java/org/genesys2/server/service/worker/SGSVInsertMissing.java index 78f6e7848..a1511e127 100644 --- a/src/main/java/org/genesys2/server/service/worker/SGSVInsertMissing.java +++ b/src/main/java/org/genesys2/server/service/worker/SGSVInsertMissing.java @@ -41,7 +41,6 @@ import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.genesys2.server.model.genesys.Accession; -import org.genesys2.server.model.impl.AccessionIdentifier3; import org.genesys2.server.model.impl.FaoInstitute; import org.genesys2.server.service.GenesysService; import org.genesys2.server.service.GeoService; @@ -266,9 +265,9 @@ public class SGSVInsertMissing { accn.setAccessionName(entry.acceNumb); accn.setOrigin(entry.origCty); accn.setCountryOfOrigin(geoService.getCountry(entry.origCty)); - accn.setGenus(entry.genus); - accn.setTaxonomy(taxonomyService.ensureTaxonomy(entry.genus, entry.species)); - // entry.fullTaxa)); + accn.setTaxonomy(taxonomyService.ensureTaxonomy2(entry.genus, entry.species, entry.spAuthor, entry.subtaxa, entry.subtAuthor)); + accn.setTaxGenus(taxonomyService.getTaxonomy2Id(entry.genus)); + accn.setTaxSpecies(taxonomyService.getTaxonomy2Id(entry.genus, entry.species)); accn.setInstituteCode(entry.instCode); accn.setInstitute(getFromCache(entry.instCode)); @@ -302,42 +301,4 @@ public class SGSVInsertMissing { } return inst; } - - private class SGSVEntry implements AccessionIdentifier3 { - String instCode; - String acceNumb; - String origCty; - String genus; - String fullTaxa; - String species; - - public SGSVEntry(String[] entry) { - instCode = entry[1]; - acceNumb = entry[4]; - fullTaxa = entry[5]; - origCty = entry[12]; - genus = entry[16]; - species = entry[17]; - } - - @Override - public String getHoldingInstitute() { - return instCode; - } - - @Override - public String getAccessionName() { - return acceNumb; - } - - @Override - public String getGenus() { - return genus; - } - - @Override - public String toString() { - return "SGSVEntry " + instCode + " " + acceNumb; - } - } } diff --git a/src/main/java/org/genesys2/server/service/worker/SGSVUpdate.java b/src/main/java/org/genesys2/server/service/worker/SGSVUpdate.java index ad3ba4a46..fee0f1962 100644 --- a/src/main/java/org/genesys2/server/service/worker/SGSVUpdate.java +++ b/src/main/java/org/genesys2/server/service/worker/SGSVUpdate.java @@ -40,7 +40,6 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.genesys2.server.model.genesys.Accession; import org.genesys2.server.model.genesys.SvalbardData; -import org.genesys2.server.model.impl.AccessionIdentifier3; import org.genesys2.server.persistence.domain.SvalbardRepository; import org.genesys2.server.service.GenesysService; import org.genesys2.server.service.GeoService; @@ -275,17 +274,22 @@ public class SGSVUpdate { updateAccession = true; } -// // Doesn't have taxonomy due to no species -// if (accn.getTaxonomy() == null && StringUtils.isNotBlank(entry.species)) { -// accn.setTaxonomy(taxonomyService.ensureTaxonomy(entry.genus, entry.species)); -// updateAccession = true; -// } -// -// if (entry.origCty != null && StringUtils.isBlank(accn.getOrigin()) && !StringUtils.equals(accn.getOrigin(), entry.origCty)) { -// accn.setOrigin(entry.origCty); -// accn.setCountryOfOrigin(geoService.getCountry(entry.origCty)); -// updateAccession = true; -// } + // // Doesn't have taxonomy due to no species + // if (accn.getTaxonomy() == null && + // StringUtils.isNotBlank(entry.species)) { + // accn.setTaxonomy(taxonomyService.ensureTaxonomy(entry.genus, + // entry.species)); + // updateAccession = true; + // } + // + // if (entry.origCty != null && + // StringUtils.isBlank(accn.getOrigin()) && + // !StringUtils.equals(accn.getOrigin(), + // entry.origCty)) { + // accn.setOrigin(entry.origCty); + // accn.setCountryOfOrigin(geoService.getCountry(entry.origCty)); + // updateAccession = true; + // } SvalbardData svalbardData = svalbardRepository.findOne(accn.getId()); if (svalbardData == null) { @@ -335,49 +339,4 @@ public class SGSVUpdate { } }); } - - private class SGSVEntry implements AccessionIdentifier3 { - String instCode; - String acceNumb; - String origCty; - String genus; - String species; - String fullTaxa; - String boxNo; - String depositDate; - Float quantity; - - public SGSVEntry(String[] entry) { - instCode = entry[10]; // provider_institute_code - acceNumb = entry[4]; - fullTaxa = entry[5]; - origCty = entry[12]; - genus = entry[16]; - species = entry[17]; - depositDate = entry[20]; - if (entry[7] != null) { - quantity = Float.parseFloat(entry[7]); - } - boxNo = entry[2]; - } - - @Override - public String getHoldingInstitute() { - return instCode; - } - - @Override - public String getAccessionName() { - return acceNumb; - } - - public String getGenus() { - return genus; - } - - @Override - public String toString() { - return "SGSVEntry " + instCode + "+" + acceNumb; - } - } } diff --git a/src/main/java/org/genesys2/server/servlet/controller/AccessionController.java b/src/main/java/org/genesys2/server/servlet/controller/AccessionController.java index 4603b694a..f3fefeb42 100644 --- a/src/main/java/org/genesys2/server/servlet/controller/AccessionController.java +++ b/src/main/java/org/genesys2/server/servlet/controller/AccessionController.java @@ -87,7 +87,7 @@ public class AccessionController extends BaseController { if (faoInstitute == null) { throw new ResourceNotFoundException(); } - Accession accession = genesysService.getAccession(holdingInstitute, genus, accessionName); + Accession accession = genesysService.getAccession(holdingInstitute, accessionName, genus); if (accession == null) { throw new ResourceNotFoundException(); } else { diff --git a/src/main/java/org/genesys2/server/servlet/controller/rest/AccessionController.java b/src/main/java/org/genesys2/server/servlet/controller/rest/AccessionController.java index 3d629276c..3e40d8080 100644 --- a/src/main/java/org/genesys2/server/servlet/controller/rest/AccessionController.java +++ b/src/main/java/org/genesys2/server/servlet/controller/rest/AccessionController.java @@ -28,6 +28,7 @@ import org.genesys2.server.service.GenesysService; import org.genesys2.server.service.GeoService; import org.genesys2.server.service.InstituteService; import org.genesys2.server.service.TaxonomyService; +import org.genesys2.server.service.impl.RESTApiException; import org.genesys2.server.servlet.controller.rest.model.AccessionJson; import org.genesys2.server.servlet.controller.rest.model.AccessionNamesJson; import org.genesys2.spring.ResourceNotFoundException; @@ -81,7 +82,7 @@ public class AccessionController extends RestController { if (LOG.isDebugEnabled()) LOG.debug("Checking if accn exists " + instCode + "." + acceNumb + " genus=" + genus); - Accession accession = genesysService.getAccession(instCode, genus, acceNumb); + Accession accession = genesysService.getAccession(instCode, acceNumb, genus); if (accession == null) { LOG.warn("No accession " + instCode + "." + acceNumb + " genus=" + genus); @@ -132,7 +133,7 @@ public class AccessionController extends RestController { ret.put("genus", dataJson.genus); ret.put("acceNumb", dataJson.acceNumb); - Accession accession = genesysService.getAccession(dataJson.instCode, dataJson.genus, dataJson.acceNumb); + Accession accession = genesysService.getAccession(dataJson.instCode, dataJson.acceNumb, dataJson.genus); if (accession != null) { ret.put("id", accession.getId()); @@ -154,10 +155,11 @@ public class AccessionController extends RestController { * @return * @throws IOException * @throws JsonProcessingException + * @throws RESTApiException */ @RequestMapping(value = "/{instCode}/upsert", method = { RequestMethod.POST, RequestMethod.PUT }, produces = { MediaType.APPLICATION_JSON_VALUE }) public @ResponseBody - String upsertInstituteAccession(@PathVariable("instCode") String instCode, @RequestBody String content) throws JsonProcessingException, IOException { + String upsertInstituteAccession(@PathVariable("instCode") String instCode, @RequestBody String content) throws JsonProcessingException, IOException, RESTApiException { // User's permission to WRITE to this WIEWS institute are checked in // BatchRESTService. FaoInstitute institute = instituteService.getInstitute(instCode); diff --git a/src/main/java/org/genesys2/server/servlet/controller/rest/RestController.java b/src/main/java/org/genesys2/server/servlet/controller/rest/RestController.java index 71b6fbe37..c0d7d4fe7 100644 --- a/src/main/java/org/genesys2/server/servlet/controller/rest/RestController.java +++ b/src/main/java/org/genesys2/server/servlet/controller/rest/RestController.java @@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.genesys2.server.security.AuthUserDetails; +import org.genesys2.server.service.impl.RESTApiException; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -66,4 +67,13 @@ public abstract class RestController { return new ExceptionJson(ex); } + @ExceptionHandler(RESTApiException.class) + @ResponseBody + public ExceptionJson handleRESTApiException(Exception ex, HttpServletRequest request, HttpServletResponse response) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + LOG.warn(request.getRequestURI() + " " + ex.getMessage() + " for " + + (authentication != null ? ((AuthUserDetails) authentication.getPrincipal()).getUsername() : "null")); + return new ExceptionJson(ex); + } + } -- GitLab