Commit 3b99eddf authored by Matija Obreza's avatar Matija Obreza

New taxonomy

parent 78fdb4b0
...@@ -21,7 +21,7 @@ import org.apache.commons.logging.LogFactory; ...@@ -21,7 +21,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document; import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field; import org.apache.lucene.document.Field;
import org.genesys2.server.model.genesys.Accession; 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.Country;
import org.genesys2.server.model.impl.FaoInstitute; import org.genesys2.server.model.impl.FaoInstitute;
import org.hibernate.search.bridge.FieldBridge; import org.hibernate.search.bridge.FieldBridge;
...@@ -51,7 +51,7 @@ public class AccessionBridge implements FieldBridge { ...@@ -51,7 +51,7 @@ public class AccessionBridge implements FieldBridge {
sd.append(countryOfOrigin.getName()); sd.append(countryOfOrigin.getName());
} }
Taxonomy taxonomy = accession.getTaxonomy(); Taxonomy2 taxonomy = accession.getTaxonomy();
if (taxonomy != null) { if (taxonomy != null) {
sd.append(taxonomy.getTaxonName()); sd.append(taxonomy.getTaxonName());
} }
......
...@@ -135,18 +135,14 @@ public class Accession extends VersionedAuditedModel { ...@@ -135,18 +135,14 @@ public class Accession extends VersionedAuditedModel {
this.accessionName = accessionName; this.accessionName = accessionName;
} }
public Taxonomy getTaxonomy() { public Taxonomy getTaxonomy1() {
return this.taxonomy; return this.taxonomy;
} }
public Taxonomy2 getTaxonomy2() { public Taxonomy2 getTaxonomy() {
return this.taxonomy2; return this.taxonomy2;
} }
public void setTaxonomy(final Taxonomy taxonomy) {
this.taxonomy = taxonomy;
}
public String getAcquisitionSource() { public String getAcquisitionSource() {
return this.acquisitionSource; return this.acquisitionSource;
} }
...@@ -252,7 +248,7 @@ public class Accession extends VersionedAuditedModel { ...@@ -252,7 +248,7 @@ public class Accession extends VersionedAuditedModel {
this.taxSpecies = taxSpecies; this.taxSpecies = taxSpecies;
} }
public void setTaxonomy2(Taxonomy2 taxonomy2) { public void setTaxonomy(Taxonomy2 taxonomy2) {
this.taxonomy2 = taxonomy2; this.taxonomy2 = taxonomy2;
} }
......
...@@ -20,6 +20,7 @@ import java.text.MessageFormat; ...@@ -20,6 +20,7 @@ import java.text.MessageFormat;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.UniqueConstraint; import javax.persistence.UniqueConstraint;
...@@ -49,6 +50,14 @@ public class Taxonomy2 extends GlobalVersionedAuditedModel { ...@@ -49,6 +50,14 @@ public class Taxonomy2 extends GlobalVersionedAuditedModel {
@Column(nullable = true, length = 100) @Column(nullable = true, length = 100)
private String subtAuthor; private String subtAuthor;
@Column(nullable = false)
@Lob
private String taxonName;
private long taxGenus;
private Long taxSpecies;
// @OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "taxonomy") // @OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "taxonomy")
// private List<CropTaxonomy> cropTaxonomies; // private List<CropTaxonomy> cropTaxonomies;
...@@ -80,6 +89,11 @@ public class Taxonomy2 extends GlobalVersionedAuditedModel { ...@@ -80,6 +89,11 @@ public class Taxonomy2 extends GlobalVersionedAuditedModel {
return sb.toString(); return sb.toString();
} }
public void setTaxonName(String taxonName) {
// Ignore what they provide
taxonName = getTaxonName();
}
// public List<CropTaxonomy> getCropTaxonomies() { // public List<CropTaxonomy> getCropTaxonomies() {
// return cropTaxonomies; // return cropTaxonomies;
// } // }
...@@ -88,13 +102,53 @@ public class Taxonomy2 extends GlobalVersionedAuditedModel { ...@@ -88,13 +102,53 @@ public class Taxonomy2 extends GlobalVersionedAuditedModel {
// this.cropTaxonomies = cropTaxonomies; // this.cropTaxonomies = cropTaxonomies;
// } // }
@Override public String getSpAuthor() {
public String toString() { return spAuthor;
return MessageFormat.format("Tax id={0} taxonName=", id, getTaxonName()); }
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) { public boolean sameAs(Taxonomy2 taxonomy) {
return taxonomy == null ? false : taxonomy.getId().equals(id); 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());
}
} }
...@@ -24,6 +24,7 @@ import javax.persistence.Table; ...@@ -24,6 +24,7 @@ import javax.persistence.Table;
import org.genesys2.server.model.BusinessModel; import org.genesys2.server.model.BusinessModel;
import org.genesys2.server.model.genesys.Taxonomy; import org.genesys2.server.model.genesys.Taxonomy;
// TODO FIXME Need to link to {@link Taxonomy2}
@Entity @Entity
@Table(name = "croptaxonomy") @Table(name = "croptaxonomy")
public class CropTaxonomy extends BusinessModel { public class CropTaxonomy extends BusinessModel {
......
...@@ -87,6 +87,7 @@ public class FaoInstitute extends BusinessModel implements GeoReferencedEntity, ...@@ -87,6 +87,7 @@ public class FaoInstitute extends BusinessModel implements GeoReferencedEntity,
private Double latitude; private Double latitude;
private Double longitude; private Double longitude;
private Double elevation; private Double elevation;
private boolean uniqueAcceNumbs;
public FaoInstitute() { public FaoInstitute() {
} }
...@@ -210,4 +211,12 @@ public class FaoInstitute extends BusinessModel implements GeoReferencedEntity, ...@@ -210,4 +211,12 @@ public class FaoInstitute extends BusinessModel implements GeoReferencedEntity,
public void setSettings(Map<String, FaoInstituteSetting> settings) { public void setSettings(Map<String, FaoInstituteSetting> settings) {
this.settings = settings; this.settings = settings;
} }
public boolean hasUniqueAcceNumbs() {
return this.uniqueAcceNumbs;
}
public void setUniqueAcceNumbs(boolean uniqueAcceNumbs) {
this.uniqueAcceNumbs = uniqueAcceNumbs;
}
} }
...@@ -96,8 +96,7 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> { ...@@ -96,8 +96,7 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> {
@Query("select a from Accession a where a.taxonomy in ( ?1 )") @Query("select a from Accession a where a.taxonomy in ( ?1 )")
Page<Accession> findByTaxonomy(Collection<Taxonomy> taxonomies, Pageable pageable); Page<Accession> findByTaxonomy(Collection<Taxonomy> taxonomies, Pageable pageable);
// Accession findByInstituteCodeAndAccessionName(String holdingInstitute, Accession findByInstituteCodeAndAccessionName(String instCode, String acceNumb);
// String accessionName);
Accession findByInstituteCodeAndAccessionNameAndGenus(String holdingInstitute, String accessionName, String genus); Accession findByInstituteCodeAndAccessionNameAndGenus(String holdingInstitute, String accessionName, String genus);
......
/**
* 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<Taxonomy2, Long> {
@Query("select distinct t.genus from Taxonomy2 t where t.genus like ?1")
List<String> autocompleteGenus(String term, Pageable page);
@Query("select distinct t.taxonName from Taxonomy2 t where t.taxonName like ?1")
List<String> 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);
}
...@@ -20,6 +20,7 @@ import java.util.List; ...@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.genesys2.server.model.impl.FaoInstitute; 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.AccessionJson;
import org.genesys2.server.servlet.controller.rest.model.AccessionNamesJson; import org.genesys2.server.servlet.controller.rest.model.AccessionNamesJson;
...@@ -27,7 +28,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; ...@@ -27,7 +28,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
public interface BatchRESTService { public interface BatchRESTService {
boolean upsertAccessionData(FaoInstitute institute, Map<AccessionJson, ObjectNode> batch); boolean upsertAccessionData(FaoInstitute institute, Map<AccessionJson, ObjectNode> batch) throws RESTApiException;
void upsertAccessionNames(FaoInstitute institute, List<AccessionNamesJson> batch); void upsertAccessionNames(FaoInstitute institute, List<AccessionNamesJson> batch);
......
...@@ -20,6 +20,7 @@ import java.util.List; ...@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.genesys2.server.model.genesys.Taxonomy; 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.Crop;
import org.genesys2.server.model.impl.CropRule; import org.genesys2.server.model.impl.CropRule;
import org.genesys2.server.model.impl.CropTaxonomy; import org.genesys2.server.model.impl.CropTaxonomy;
...@@ -36,6 +37,8 @@ public interface CropService { ...@@ -36,6 +37,8 @@ public interface CropService {
List<Crop> getCrops(Taxonomy taxonomy); List<Crop> getCrops(Taxonomy taxonomy);
List<Crop> getCrops(Taxonomy2 taxonomy2);
void rebuildTaxonomies(); void rebuildTaxonomies();
Page<CropTaxonomy> getCropTaxonomies(Crop crop, Pageable pageable); Page<CropTaxonomy> getCropTaxonomies(Crop crop, Pageable pageable);
......
...@@ -95,7 +95,7 @@ public interface GenesysService { ...@@ -95,7 +95,7 @@ public interface GenesysService {
Accession getAccession(AccessionIdentifier3 aid3); Accession getAccession(AccessionIdentifier3 aid3);
Accession getAccession(String instCode, String genus, String acceNumb); Accession getAccession(String instCode, String acceNumb, String genus);
Page<Object[]> statisticsGenusByInstitute(FaoInstitute faoInstitute, Pageable pageable); Page<Object[]> statisticsGenusByInstitute(FaoInstitute faoInstitute, Pageable pageable);
...@@ -163,4 +163,13 @@ public interface GenesysService { ...@@ -163,4 +163,13 @@ public interface GenesysService {
long countAll(); long countAll();
/**
* For institutes with {@link FaoInstitute#uniqueAcceNumbs}
*
* @param instCode
* @param acceNumb
* @return the 1 accession
*/
Accession getAccession(String instCode, String acceNumb);
} }
...@@ -19,6 +19,7 @@ package org.genesys2.server.service; ...@@ -19,6 +19,7 @@ package org.genesys2.server.service;
import java.util.List; import java.util.List;
import org.genesys2.server.model.genesys.Taxonomy; import org.genesys2.server.model.genesys.Taxonomy;
import org.genesys2.server.model.genesys.Taxonomy2;
public interface TaxonomyService { public interface TaxonomyService {
...@@ -31,4 +32,10 @@ public interface TaxonomyService { ...@@ -31,4 +32,10 @@ public interface TaxonomyService {
List<String> autocompleteTaxonomy(String term); List<String> 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);
} }
...@@ -36,7 +36,7 @@ import org.genesys2.server.model.genesys.AccessionBreeding; ...@@ -36,7 +36,7 @@ import org.genesys2.server.model.genesys.AccessionBreeding;
import org.genesys2.server.model.genesys.AccessionCollect; import org.genesys2.server.model.genesys.AccessionCollect;
import org.genesys2.server.model.genesys.AccessionExchange; import org.genesys2.server.model.genesys.AccessionExchange;
import org.genesys2.server.model.genesys.AccessionGeo; 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.Country;
import org.genesys2.server.model.impl.FaoInstitute; import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.BatchRESTService; import org.genesys2.server.service.BatchRESTService;
...@@ -81,8 +81,11 @@ public class BatchRESTServiceImpl implements BatchRESTService { ...@@ -81,8 +81,11 @@ public class BatchRESTServiceImpl implements BatchRESTService {
@Override @Override
@Transactional @Transactional
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#institute, 'WRITE') or hasPermission(#institute, 'CREATE')") @PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#institute, 'WRITE') or hasPermission(#institute, 'CREATE')")
public boolean upsertAccessionData(FaoInstitute institute, Map<AccessionJson, ObjectNode> batch) { public boolean upsertAccessionData(FaoInstitute institute, Map<AccessionJson, ObjectNode> batch) throws RESTApiException {
LOG.info("Batch processing " + batch.size() + " entries for " + institute); LOG.info("Batch processing " + batch.size() + " entries for " + institute);
boolean useUniqueAcceNumbs = institute.hasUniqueAcceNumbs();
List<Accession> toSave = new ArrayList<Accession>(); List<Accession> toSave = new ArrayList<Accession>();
List<AccessionCollect> toSaveColl = new ArrayList<AccessionCollect>(); List<AccessionCollect> toSaveColl = new ArrayList<AccessionCollect>();
List<AccessionGeo> toSaveGeo = new ArrayList<AccessionGeo>(); List<AccessionGeo> toSaveGeo = new ArrayList<AccessionGeo>();
...@@ -102,94 +105,39 @@ public class BatchRESTServiceImpl implements BatchRESTService { ...@@ -102,94 +105,39 @@ public class BatchRESTServiceImpl implements BatchRESTService {
throw new RuntimeException("Accession does not belong to instCode=" + institute.getCode() + " acn=" + dataJson); 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; boolean updated = false;
ObjectNode accnJson = batch.get(dataJson);
if (accession == null) { if (accession == null) {
LOG.warn("New accession " + dataJson); LOG.warn("New accession " + dataJson);
accession = new Accession(); accession = new Accession();
accession.setInstituteCode(dataJson.instCode); accession.setInstituteCode(dataJson.instCode);
accession.setInstitute(institute); accession.setInstitute(institute);
accession.setGenus(dataJson.genus);
accession.setAccessionName(dataJson.acceNumb); accession.setAccessionName(dataJson.acceNumb);
updated = true; if (accnJson.get("genus") == null || accnJson.get("newGenus") == null) {
} throw new RESTApiException("Cannot create new accession without specifying genus");
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);
}
} }
}
value = accnJson.get("species"); updated = true;
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;
}
} }
value = accnJson.get("uuid"); updated |= updateAcceNumb(accession, accnJson.get("newAcceNumb"));
if (value != null) { updated |= updateTaxonomy(accession, accnJson);
String uuid = value.isNull() ? null : value.textValue(); updated |= updateOrgCty(accession, accnJson.get("orgCty"));
if (!StringUtils.equals(uuid, accession.getUuid())) { updated |= updateUuid(accession, accnJson.get("uuid"));
if (uuid != null) {
// Throws a runtime exception if format is invalid
UUID.fromString(uuid);
}
accession.setUuid(uuid);
updated = true;
}
}
value = accnJson.get("acqDate"); // TODO Move other setters to methods
JsonNode value = accnJson.get("acqDate");
if (value != null) { if (value != null) {
String acqDate = value.isNull() ? null : value.textValue(); String acqDate = value.isNull() ? null : value.textValue();
if (!StringUtils.equals(acqDate, accession.getAcquisitionDate())) { if (!StringUtils.equals(acqDate, accession.getAcquisitionDate())) {
...@@ -417,6 +365,128 @@ public class BatchRESTServiceImpl implements BatchRESTService { ...@@ -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; 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");