package eu.etaxonomy.cdm.api.service;\r
\r
import java.io.IOException;\r
+import java.net.URI;\r
+import java.net.URISyntaxException;\r
import java.util.ArrayList;\r
import java.util.Arrays;\r
import java.util.Collection;\r
import java.util.HashMap;\r
import java.util.HashSet;\r
+import java.util.LinkedHashSet;\r
import java.util.List;\r
import java.util.Map;\r
import java.util.Map.Entry;\r
import org.apache.lucene.search.SortField;\r
import org.hibernate.TransientObjectException;\r
import org.hibernate.search.spatial.impl.Rectangle;\r
+import org.joda.time.Partial;\r
import org.springframework.beans.factory.annotation.Autowired;\r
import org.springframework.stereotype.Service;\r
import org.springframework.transaction.annotation.Transactional;\r
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;\r
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeConfigurator;\r
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeNotSupportedException;\r
+import eu.etaxonomy.cdm.api.service.DeleteResult.DeleteStatus;\r
+import eu.etaxonomy.cdm.api.service.config.SpecimenDeleteConfigurator;\r
import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO.ContigFile;\r
+import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO.MolecularData;\r
+import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;\r
import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;\r
import eu.etaxonomy.cdm.api.service.pager.Pager;\r
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;\r
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;\r
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;\r
import eu.etaxonomy.cdm.model.CdmBaseType;\r
+import eu.etaxonomy.cdm.model.agent.AgentBase;\r
+import eu.etaxonomy.cdm.model.common.CdmBase;\r
+import eu.etaxonomy.cdm.model.common.DefinedTerm;\r
import eu.etaxonomy.cdm.model.common.DefinedTermBase;\r
+import eu.etaxonomy.cdm.model.common.ICdmBase;\r
import eu.etaxonomy.cdm.model.common.Language;\r
import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;\r
import eu.etaxonomy.cdm.model.description.DescriptionBase;\r
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\r
+import eu.etaxonomy.cdm.model.description.DescriptionElementSource;\r
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;\r
+import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
import eu.etaxonomy.cdm.model.location.Country;\r
+import eu.etaxonomy.cdm.model.location.NamedArea;\r
import eu.etaxonomy.cdm.model.media.Media;\r
import eu.etaxonomy.cdm.model.media.MediaRepresentation;\r
import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;\r
+import eu.etaxonomy.cdm.model.media.MediaUtils;\r
import eu.etaxonomy.cdm.model.molecular.DnaSample;\r
import eu.etaxonomy.cdm.model.molecular.Sequence;\r
+import eu.etaxonomy.cdm.model.molecular.SingleRead;\r
+import eu.etaxonomy.cdm.model.name.NameTypeDesignation;\r
+import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;\r
+import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
+import eu.etaxonomy.cdm.model.name.TypeDesignationBase;\r
+import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;\r
import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;\r
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;\r
import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;\r
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;\r
import eu.etaxonomy.cdm.model.taxon.Taxon;\r
import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
+import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;\r
import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;\r
import eu.etaxonomy.cdm.persistence.dao.initializer.AbstractBeanInitializer;\r
import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;\r
-import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;\r
import eu.etaxonomy.cdm.persistence.query.OrderHint;\r
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;\r
\r
@Autowired\r
private ITaxonService taxonService;\r
\r
+ @Autowired\r
+ private ITermService termService;\r
+\r
+ @Autowired\r
+ private INameService nameService;\r
+\r
@Autowired\r
private ISequenceService sequenceService;\r
\r
private AbstractBeanInitializer beanInitializer;\r
\r
@Autowired\r
- private ITaxonDao taxonDao;\r
+ private ILuceneIndexToolProvider luceneIndexToolProvider;\r
\r
@Autowired\r
- private ILuceneIndexToolProvider luceneIndexToolProvider;\r
+ private ICdmGenericDao genericDao;\r
\r
\r
public OccurrenceServiceImpl() {\r
Taxon associatedTaxon, Integer maxDepth, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
\r
if(!getSession().contains(associatedTaxon)){\r
- associatedTaxon = (Taxon) taxonDao.load(associatedTaxon.getUuid());\r
+ associatedTaxon = (Taxon) taxonService.load(associatedTaxon.getUuid());\r
}\r
\r
Set<FieldUnit> fieldUnits = new HashSet<FieldUnit>();\r
}\r
\r
@Override\r
- public Collection<DerivateHierarchyDTO> listDerivateHierarchyDTOsByAssociatedTaxon(Set<TaxonRelationshipEdge> includeRelationships,\r
- Taxon associatedTaxon, Integer maxDepth, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
+ public DerivateHierarchyDTO assembleDerivateHierarchyDTO(FieldUnit fieldUnit, UUID associatedTaxonUuid){\r
\r
- if(!getSession().contains(associatedTaxon)){\r
- associatedTaxon = (Taxon) taxonDao.load(associatedTaxon.getUuid());\r
+ if(!getSession().contains(fieldUnit)){\r
+ fieldUnit = (FieldUnit) load(fieldUnit.getUuid());\r
}\r
-\r
- Collection<FieldUnit> fieldUnits = listFieldUnitsByAssociatedTaxon(includeRelationships, associatedTaxon, maxDepth, pageSize, pageNumber, orderHints, propertyPaths);\r
-\r
- Collection<DerivateHierarchyDTO> derivateHierarchyDTOs = new ArrayList<DerivateHierarchyDTO>();\r
- for(FieldUnit fieldUnit:fieldUnits){\r
- derivateHierarchyDTOs.add(assembleDerivateHierarchyDTO(fieldUnit, associatedTaxon));\r
- }\r
- return derivateHierarchyDTOs;\r
- }\r
-\r
- private DerivateHierarchyDTO assembleDerivateHierarchyDTO(FieldUnit fieldUnit, Taxon associatedTaxon){\r
+ TaxonBase associatedTaxon = taxonService.load(associatedTaxonUuid);\r
\r
DerivateHierarchyDTO dto = new DerivateHierarchyDTO();\r
- // TaxonNameBase name = associatedTaxon.getName();\r
- // name = HibernateProxyHelper.deproxy(name, TaxonNameBase.class);\r
- // dto.setType(!name.getTypeDesignations().isEmpty());\r
+ Map<UUID, TypeDesignationStatusBase> typeSpecimenUUIDtoTypeDesignationStatus = new HashMap<UUID, TypeDesignationStatusBase>();\r
+\r
+ //gather types for this taxon name\r
+ TaxonNameBase<?,?> name = associatedTaxon.getName();\r
+ Set<?> typeDesignations = name.getSpecimenTypeDesignations();\r
+ for (Object object : typeDesignations) {\r
+ if(object instanceof SpecimenTypeDesignation){\r
+ SpecimenTypeDesignation specimenTypeDesignation = (SpecimenTypeDesignation)object;\r
+ DerivedUnit typeSpecimen = specimenTypeDesignation.getTypeSpecimen();\r
+ final TypeDesignationStatusBase typeStatus = specimenTypeDesignation.getTypeStatus();\r
+ typeSpecimenUUIDtoTypeDesignationStatus.put(typeSpecimen.getUuid(), typeStatus);\r
+ }\r
+ }\r
\r
if(fieldUnit.getGatheringEvent()!=null){\r
GatheringEvent gatheringEvent = fieldUnit.getGatheringEvent();\r
//Country\r
- dto.setCountry(gatheringEvent.getCountry()!=null?gatheringEvent.getCountry().getDescription():"");\r
+ final NamedArea country = gatheringEvent.getCountry();\r
+ dto.setCountry(country!=null?country.getDescription():"");\r
//Collection\r
- dto.setCollection((gatheringEvent.getCollector()!=null?gatheringEvent.getCollector():"") + fieldUnit.getFieldNumber()!=null?fieldUnit.getFieldNumber():"");\r
+ final AgentBase collector = gatheringEvent.getCollector();\r
+ final String fieldNumber = fieldUnit.getFieldNumber();\r
+ dto.setCollection(((collector!=null?collector:"") + " " + (fieldNumber!=null?fieldNumber:"")).trim());\r
//Date\r
- dto.setDate(gatheringEvent.getGatheringDate()!=null?gatheringEvent.getGatheringDate().toString():"");\r
+ final Partial gatheringDate = gatheringEvent.getGatheringDate();\r
+ dto.setDate(gatheringDate!=null?gatheringDate.toString():"");\r
}\r
\r
//Taxon Name\r
\r
Collection<DerivedUnit> derivedUnits = new ArrayList<DerivedUnit>();\r
getDerivedUnitsFor(fieldUnit, derivedUnits);\r
+\r
//Herbaria map\r
Map<eu.etaxonomy.cdm.model.occurrence.Collection, Integer> collectionToCountMap = new HashMap<eu.etaxonomy.cdm.model.occurrence.Collection, Integer>();\r
+ //List of accession numbers for citation\r
+ List<String> preservedSpecimenAccessionNumbers = new ArrayList<String>();\r
\r
//iterate over sub derivates\r
for (DerivedUnit derivedUnit : derivedUnits) {\r
+ //current accession number\r
+ String currentAccessionNumber = derivedUnit.getAccessionNumber()!=null?derivedUnit.getAccessionNumber():"";\r
+ //current herbarium\r
+ String currentHerbarium = "";\r
+ eu.etaxonomy.cdm.model.occurrence.Collection collection = derivedUnit.getCollection();\r
+ if(collection!=null){\r
+ currentHerbarium = collection.getCode()!=null?collection.getCode():"";\r
+ //count herbaria\r
+ Integer count = collectionToCountMap.get(collection);\r
+ if(count==null){\r
+ count = 1;\r
+ }\r
+ else{\r
+ count++;\r
+ }\r
+ collectionToCountMap.put(collection, count);\r
+ }\r
+ //check if derived unit is a type\r
+ if(typeSpecimenUUIDtoTypeDesignationStatus.keySet().contains(derivedUnit.getUuid())){\r
+ dto.setHasType(true);\r
+ TypeDesignationStatusBase typeDesignationStatus = typeSpecimenUUIDtoTypeDesignationStatus.get(derivedUnit.getUuid());\r
+ String typeStatus = typeDesignationStatus.getLabel();\r
+ dto.addTypes(typeStatus, currentAccessionNumber);\r
+ }\r
//assemble molecular data\r
- if(derivedUnit instanceof DnaSample){//.getRecordBasis()==SpecimenOrObservationType.DnaSample){\r
- dto.setHasDna(true);\r
+ //pattern: DNAMarker [contig1, primer1_1, primer1_2, ...][contig2, primer2_1, ...]...\r
+ if(derivedUnit instanceof DnaSample){\r
+ if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.TissueSample){\r
+ //TODO implement TissueSample assembly for web service\r
+ }\r
+ if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.DnaSample){\r
\r
- DnaSample dna = (DnaSample)derivedUnit;\r
- if(dna.getBankNumber()!=null){\r
- dto.addMolecularData(dna.getBankNumber());\r
+ DnaSample dna = (DnaSample)derivedUnit;\r
+ if(!dna.getSequences().isEmpty()){\r
+ dto.setHasDna(true);\r
+ }\r
+ for(Sequence sequence:dna.getSequences()){\r
+ URI boldUri = null;\r
+ try {\r
+ boldUri = sequence.getBoldUri();\r
+ } catch (URISyntaxException e1) {\r
+ logger.error("Could not create BOLD URI", e1);\r
+ }\r
+ final DefinedTerm dnaMarker = sequence.getDnaMarker();\r
+ MolecularData molecularData = dto.addProviderLink(boldUri!=null?boldUri:null,dnaMarker!=null?dnaMarker.getLabel():"[no marker]");\r
+\r
+ //contig file FIXME show primer although contig not present?\r
+ if(sequence.getContigFile()!=null){\r
+ MediaRepresentationPart contigMediaRepresentationPart = MediaUtils.getFirstMediaRepresentationPart(sequence.getContigFile());\r
+ if(contigMediaRepresentationPart!=null){\r
+ ContigFile contigFile = molecularData.addContigFile(contigMediaRepresentationPart.getUri(), "contig");\r
+ //primer files\r
+ if(sequence.getSingleReads()!=null){\r
+ for (SingleRead singleRead : sequence.getSingleReads()) {\r
+ MediaRepresentationPart pherogramMediaRepresentationPart = MediaUtils.getFirstMediaRepresentationPart(singleRead.getPherogram());\r
+ if(pherogramMediaRepresentationPart!=null){\r
+ contigFile.addPrimerLink(pherogramMediaRepresentationPart.getUri(), "primer");\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
}\r
}\r
//assemble media data\r
MediaSpecimen media = (MediaSpecimen)derivedUnit;\r
String mediaUriString = getMediaUriString(media);\r
if(media.getKindOfUnit()!=null){\r
+ //specimen scan\r
if(media.getKindOfUnit().getUuid().equals(UUID.fromString("acda15be-c0e2-4ea8-8783-b9b0c4ad7f03"))){\r
dto.setHasSpecimenScan(true);\r
- if(mediaUriString!=null){\r
- dto.addSpecimenScan(mediaUriString);\r
- }\r
+ final String imageLinkText = currentHerbarium+" "+currentAccessionNumber;\r
+ dto.addSpecimenScan(mediaUriString==null?"":mediaUriString, !imageLinkText.equals(" ")?imageLinkText:"[no accession]");\r
}\r
+ //detail image\r
else if(media.getKindOfUnit().getUuid().equals(UUID.fromString("31eb8d02-bf5d-437c-bcc6-87a626445f34"))){\r
dto.setHasDetailImage(true);\r
- if(mediaUriString!=null){\r
- dto.addDetailImage(mediaUriString);\r
+ String motif = "";\r
+ if(media.getMediaSpecimen()!=null && media.getMediaSpecimen().getTitle()!=null){\r
+ motif = media.getMediaSpecimen().getTitle().getText();\r
}\r
+ dto.addDetailImage(mediaUriString==null?"":mediaUriString, motif!=null?motif:"[no motif]");\r
}\r
}\r
}\r
//assemble preserved specimen data\r
else if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.PreservedSpecimen){\r
- eu.etaxonomy.cdm.model.occurrence.Collection collection = derivedUnit.getCollection();\r
- Integer count = collectionToCountMap.get(collection);\r
- if(count==null){\r
- count = 1;\r
+ if(!currentAccessionNumber.isEmpty()){\r
+ preservedSpecimenAccessionNumbers.add(currentAccessionNumber);\r
}\r
- else{\r
- count++;\r
+ }\r
+ }\r
+\r
+ final String separator = ", ";\r
+ //assemble citation\r
+ String citation = "";\r
+ citation += !dto.getCountry().isEmpty()?dto.getCountry()+separator:"";\r
+ if(fieldUnit.getGatheringEvent()!=null){\r
+ if(fieldUnit.getGatheringEvent().getLocality()!=null){\r
+ citation += fieldUnit.getGatheringEvent().getLocality().getText();\r
+ citation += separator;\r
+ }\r
+ if(fieldUnit.getGatheringEvent().getExactLocation()!=null\r
+ && fieldUnit.getGatheringEvent().getExactLocation().getLatitude()!=null\r
+ && fieldUnit.getGatheringEvent().getExactLocation().getLongitude()!=null){\r
+ citation += fieldUnit.getGatheringEvent().getExactLocation().getLatitude().toString();\r
+ citation += separator;\r
+ citation += fieldUnit.getGatheringEvent().getExactLocation().getLongitude().toString();\r
+ citation += separator;\r
+ }\r
+ }\r
+ citation += !dto.getCollection().isEmpty()?dto.getCollection():"";\r
+ if(!preservedSpecimenAccessionNumbers.isEmpty()){\r
+ citation += " (";\r
+ for(String accessionNumber:preservedSpecimenAccessionNumbers){\r
+ if(!accessionNumber.isEmpty()){\r
+ citation += accessionNumber+separator;\r
}\r
- collectionToCountMap.put(collection, count);\r
}\r
+ citation = removeTail(citation, separator);\r
+ citation += ")";\r
}\r
+ citation = removeTail(citation, separator);\r
+ dto.setCitation(citation);\r
+\r
//assemble herbaria string\r
String herbariaString = "";\r
- final String herbariaSeparator = ", ";\r
for(Entry<eu.etaxonomy.cdm.model.occurrence.Collection, Integer> e:collectionToCountMap.entrySet()){\r
eu.etaxonomy.cdm.model.occurrence.Collection collection = e.getKey();\r
- herbariaString += collection.getCode();\r
+ if(collection.getCode()!=null){\r
+ herbariaString += collection.getCode();\r
+ }\r
if(e.getValue()>1){\r
herbariaString += "("+e.getValue()+")";\r
}\r
- herbariaString += herbariaSeparator;\r
- }\r
- if(herbariaString.endsWith(herbariaSeparator)){\r
- herbariaString = herbariaString.substring(0, herbariaString.length()-herbariaSeparator.length());\r
+ herbariaString += separator;\r
}\r
+ herbariaString = removeTail(herbariaString, separator);\r
dto.setHerbarium(herbariaString);\r
+\r
return dto;\r
}\r
\r
- private String getMediaUriString(MediaSpecimen mediaSpecimen){\r
- if(!getSession().contains(mediaSpecimen)){\r
- mediaSpecimen = (MediaSpecimen) load(mediaSpecimen.getUuid());\r
+\r
+ /**\r
+ * @param string\r
+ * @param tail\r
+ * @return\r
+ */\r
+ private String removeTail(String string, final String tail) {\r
+ if(string.endsWith(tail)){\r
+ string = string.substring(0, string.length()-tail.length());\r
}\r
+ return string;\r
+ }\r
+\r
+ private String getMediaUriString(MediaSpecimen mediaSpecimen){\r
String mediaUri = null;\r
Collection<MediaRepresentation> mediaRepresentations = mediaSpecimen.getMediaSpecimen().getRepresentations();\r
if(mediaRepresentations!=null && !mediaRepresentations.isEmpty()){\r
// Integer start = PagerUtils.startFor(pageSize, pageNumber);\r
\r
if(!getSession().contains(associatedTaxon)){\r
- associatedTaxon = (Taxon) taxonDao.load(associatedTaxon.getUuid());\r
+ associatedTaxon = (Taxon) taxonService.load(associatedTaxon.getUuid());\r
}\r
\r
if(includeRelationships != null) {\r
\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#pageByAssociatedTaxon(java.lang.Class, java.util.Set, eu.etaxonomy.cdm.model.taxon.Taxon, java.lang.Integer, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
- */\r
- @SuppressWarnings("unchecked")\r
+\r
@Override\r
public <T extends SpecimenOrObservationBase> Pager<T> pageByAssociatedTaxon(Class<T> type, Set<TaxonRelationshipEdge> includeRelationships,\r
String taxonUUID, Integer maxDepth, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
\r
UUID uuid = UUID.fromString(taxonUUID);\r
- Taxon tax = (Taxon) taxonDao.load(uuid);\r
+ Taxon tax = (Taxon) taxonService.load(uuid);\r
//TODO REMOVE NULL STATEMENT\r
-type=null;\r
+ type=null;\r
return pageByAssociatedTaxon( type,includeRelationships,tax, maxDepth, pageSize, pageNumber, orderHints, propertyPaths );\r
\r
}\r
from.removeDerivationEvent(eventToRemove);\r
saveOrUpdate(from);\r
//add new derivation event to target\r
- to.addDerivationEvent(DerivationEvent.NewSimpleInstance(to, derivate, eventToRemove==null?null:eventToRemove.getType()));\r
+ DerivationEvent derivedFromNewOriginalEvent = DerivationEvent.NewSimpleInstance(to, derivate, eventToRemove==null?null:eventToRemove.getType());\r
+ to.addDerivationEvent(derivedFromNewOriginalEvent);\r
+ derivate.setDerivedFrom(derivedFromNewOriginalEvent);\r
saveOrUpdate(to);\r
return true;\r
}\r
return false;\r
}\r
\r
+ @Override\r
+ public Collection<ICdmBase> getNonCascadedAssociatedElements(SpecimenOrObservationBase<?> specimen){\r
+ //potential fields that are not persisted cascadingly\r
+ /*\r
+ * SOOB\r
+ -DescriptionBase\r
+ -determinations\r
+ --modifier TERM\r
+ -kindOfUnit TERM\r
+ -lifeStage TERM\r
+ -sex TERM\r
+\r
+ FieldUnit\r
+ -GatheringEvent\r
+ --Country TERM\r
+ --CollectingAreas TERM\r
+\r
+ DerivedUnit\r
+ -collection\r
+ --institute\r
+ ---types TERM\r
+ -preservationMethod\r
+ --medium TERM\r
+ -storedUnder CDM TaxonNameBase\r
+ */\r
+\r
+ Collection<ICdmBase> nonCascadedCdmEntities = new HashSet<ICdmBase>();\r
+\r
+ //Choose the correct entry point to traverse the graph (FieldUnit or DerivedUnit)\r
+\r
+ //FieldUnit\r
+ if(specimen instanceof FieldUnit){\r
+ nonCascadedCdmEntities.addAll(getFieldUnitNonCascadedAssociatedElements((FieldUnit)specimen));\r
+ }\r
+ //DerivedUnit\r
+ else if(specimen instanceof DerivedUnit){\r
+ DerivedUnit derivedUnit = (DerivedUnit)specimen;\r
+ if(derivedUnit.getDerivedFrom()!=null){\r
+ Collection<FieldUnit> fieldUnits = new ArrayList<FieldUnit>();\r
+ getFieldUnits(derivedUnit, fieldUnits);\r
+ for(FieldUnit fieldUnit:fieldUnits){\r
+ nonCascadedCdmEntities.addAll(getFieldUnitNonCascadedAssociatedElements(fieldUnit));\r
+ }\r
+ }\r
+ }\r
+ return nonCascadedCdmEntities;\r
+ }\r
+\r
+ private Collection<ICdmBase> getFieldUnitNonCascadedAssociatedElements(FieldUnit fieldUnit){\r
+ //get non cascaded element on SpecimenOrObservationBase level\r
+ Collection<ICdmBase> nonCascadedCdmEntities = getSpecimenOrObservationNonCascadedAssociatedElements(fieldUnit);\r
+\r
+ //get FieldUnit specific elements\r
+ GatheringEvent gatheringEvent = fieldUnit.getGatheringEvent();\r
+ if(gatheringEvent!=null){\r
+ //country\r
+ if(gatheringEvent.getCountry()!=null){\r
+ nonCascadedCdmEntities.add(gatheringEvent.getCountry());\r
+ }\r
+ //collecting areas\r
+ for (NamedArea namedArea : gatheringEvent.getCollectingAreas()) {\r
+ nonCascadedCdmEntities.add(namedArea);\r
+ }\r
+ }\r
+ for (DerivationEvent derivationEvent : fieldUnit.getDerivationEvents()) {\r
+ for (DerivedUnit derivedUnit : derivationEvent.getDerivatives()) {\r
+ nonCascadedCdmEntities.addAll(getDerivedUnitNonCascadedAssociatedElements(derivedUnit));\r
+ }\r
+ }\r
+ return nonCascadedCdmEntities;\r
+ }\r
+\r
+ private Collection<ICdmBase> getDerivedUnitNonCascadedAssociatedElements(DerivedUnit derivedUnit){\r
+ //get non cascaded element on SpecimenOrObservationBase level\r
+ Collection<ICdmBase> nonCascadedCdmEntities = getSpecimenOrObservationNonCascadedAssociatedElements(derivedUnit);\r
+\r
+ //get DerivedUnit specific elements\r
+ if(derivedUnit.getCollection()!=null && derivedUnit.getCollection().getInstitute()!=null){\r
+ for (DefinedTerm type : derivedUnit.getCollection().getInstitute().getTypes()) {\r
+ nonCascadedCdmEntities.add(type);\r
+ }\r
+ }\r
+ if(derivedUnit.getPreservation()!=null && derivedUnit.getPreservation().getMedium()!=null){\r
+ nonCascadedCdmEntities.add(derivedUnit.getPreservation().getMedium());\r
+ }\r
+ if(derivedUnit.getStoredUnder()!=null){\r
+ nonCascadedCdmEntities.add(derivedUnit.getStoredUnder());\r
+ }\r
+ return nonCascadedCdmEntities;\r
+ }\r
+\r
+ /**\r
+ * @param specimen\r
+ * @return\r
+ */\r
+ private Collection<ICdmBase> getSpecimenOrObservationNonCascadedAssociatedElements(\r
+ SpecimenOrObservationBase<?> specimen) {\r
+ Collection<ICdmBase> nonCascadedCdmEntities = new HashSet<ICdmBase>();\r
+ //scan SpecimenOrObservationBase\r
+ for(DeterminationEvent determinationEvent:specimen.getDeterminations()){\r
+ //modifier\r
+ if(determinationEvent.getModifier()!=null){\r
+ nonCascadedCdmEntities.add(determinationEvent.getModifier());\r
+ }\r
+ }\r
+ //kindOfUnit\r
+ if(specimen.getKindOfUnit()!=null){\r
+ nonCascadedCdmEntities.add(specimen.getKindOfUnit());\r
+ }\r
+ //lifeStage\r
+ if(specimen.getLifeStage()!=null){\r
+ nonCascadedCdmEntities.add(specimen.getLifeStage());\r
+ }\r
+ //sex\r
+ if(specimen.getSex()!=null){\r
+ nonCascadedCdmEntities.add(specimen.getSex());\r
+ }\r
+ return nonCascadedCdmEntities;\r
+ }\r
+\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#delete(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.api.service.config.SpecimenDeleteConfigurator)\r
+ */\r
+ @Override\r
+ public DeleteResult delete(SpecimenOrObservationBase<?> specimen, SpecimenDeleteConfigurator config) {\r
+ DeleteResult deleteResult = new DeleteResult();\r
+ //check for derivation events\r
+ Set<DerivationEvent> derivationEvents = specimen.getDerivationEvents();\r
+ for (DerivationEvent derivationEvent : derivationEvents) {\r
+ if(!derivationEvent.getDerivatives().isEmpty()){\r
+ deleteResult.setAbort();\r
+ deleteResult.addException(new ReferencedObjectUndeletableException("Derivate with children cannot be deleted."));\r
+ return deleteResult;\r
+ }\r
+ }\r
+ //check for original (parent derivate)\r
+ if(specimen instanceof DerivedUnit){\r
+ DerivationEvent derivedFromEvent = ((DerivedUnit) specimen).getDerivedFrom();\r
+ if(derivedFromEvent!=null){\r
+ derivedFromEvent.removeDerivative((DerivedUnit) specimen);\r
+ }\r
+ }\r
+ //check for IndividualsAssociation (e.g. in TaxonDescriptions)\r
+ Collection<TaxonBase<?>> associatedTaxa = listAssociatedTaxa(specimen, null, null, null, null);\r
+ if(!associatedTaxa.isEmpty()){\r
+ if(config.isDeleteFromIndividualsAssociation()){\r
+ for (TaxonBase<?> taxonBase : associatedTaxa) {\r
+ if(taxonBase instanceof Taxon){\r
+ Set<TaxonDescription> descriptions = ((Taxon) taxonBase).getDescriptions();\r
+ for (TaxonDescription taxonDescription : descriptions) {\r
+ Set<DescriptionElementBase> elements = taxonDescription.getElements();\r
+ for (DescriptionElementBase descriptionElementBase : elements) {\r
+ if(descriptionElementBase instanceof IndividualsAssociation){\r
+ IndividualsAssociation individualsAssociation = (IndividualsAssociation) descriptionElementBase;\r
+ if(individualsAssociation.getAssociatedSpecimenOrObservation().equals(specimen)){\r
+ individualsAssociation.setAssociatedSpecimenOrObservation(null);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else{\r
+ deleteResult.addRelatedObjects(new HashSet<CdmBase>(associatedTaxa));\r
+ deleteResult.setAbort();\r
+ deleteResult.addException(new ReferencedObjectUndeletableException("Specimen is still associated with taxa."));\r
+ return deleteResult;\r
+ }\r
+ }\r
+ //check for TypeDesignations\r
+ Collection<TaxonBase<?>> typedTaxa = listTypedTaxa(specimen, null, null, null, null);\r
+ if(!typedTaxa.isEmpty()){\r
+ if(config.isdeleteFromTypeDesignation()){\r
+ for (TaxonBase<?> taxonBase : typedTaxa) {\r
+ if(taxonBase.getName()!=null){\r
+ Set<TypeDesignationBase> typeDesignations = taxonBase.getName().getTypeDesignations();\r
+ for (TypeDesignationBase typeDesignationBase : typeDesignations) {\r
+ if(typeDesignationBase instanceof SpecimenTypeDesignation){\r
+ ((SpecimenTypeDesignation) typeDesignationBase).setTypeSpecimen(null);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else{\r
+ deleteResult.addRelatedObjects(new HashSet<CdmBase>(typedTaxa));\r
+ deleteResult.setAbort();\r
+ deleteResult.addException(new ReferencedObjectUndeletableException("Specimen is a type specimen."));\r
+ return deleteResult;\r
+ }\r
+ }\r
+ if(!config.isDeleteChildren()){\r
+ Set<CdmBase> referencingObjects = genericDao.getReferencingObjects(specimen);\r
+ for (CdmBase referencingObject : referencingObjects){\r
+ //DerivedUnit?.storedUnder\r
+ if (referencingObject.isInstanceOf(DerivedUnit.class)){\r
+ String message = "Name can't be deleted as it is used as derivedUnit#storedUnder by %s. Remove 'stored under' prior to deleting this name";\r
+ message = String.format(message, CdmBase.deproxy(referencingObject, DerivedUnit.class).getTitleCache());\r
+ }\r
+ //DescriptionElementSource#nameUsedInSource\r
+ if (referencingObject.isInstanceOf(DescriptionElementSource.class)){\r
+ String message = "Name can't be deleted as it is used as descriptionElementSource#nameUsedInSource";\r
+ }\r
+ //NameTypeDesignation#typeName\r
+ if (referencingObject.isInstanceOf(NameTypeDesignation.class)){\r
+ String message = "Name can't be deleted as it is used as a name type in a NameTypeDesignation";\r
+ }\r
+ }\r
+ deleteResult = delete(specimen);\r
+ }\r
+ else{\r
+ //TODO implement deep delete\r
+ }\r
+ return deleteResult;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#deleteDerivateHierarchy(eu.etaxonomy.cdm.model.common.ICdmBase)\r
+ */\r
+ @Override\r
+ public DeleteResult deleteDerivateHierarchy(ICdmBase from, SpecimenDeleteConfigurator config) {\r
+ DeleteResult deleteResult = new DeleteResult();\r
+ if(from instanceof Sequence){\r
+ Sequence sequence = (Sequence)from;\r
+ sequence.getDnaSample().removeSequence(sequence);\r
+ deleteResult.setStatus(DeleteStatus.OK);\r
+ }\r
+ else if(from instanceof SpecimenOrObservationBase<?>) {\r
+ deleteResult = delete((SpecimenOrObservationBase<?>) from, config);\r
+ }\r
+ return deleteResult;\r
+ }\r
+\r
+ private Set<ICdmBase> collectEntitiesToDelete(ICdmBase entity){\r
+ Set<ICdmBase> entitiesToDelete = new LinkedHashSet<ICdmBase>();\r
+\r
+ if(entity instanceof SpecimenOrObservationBase<?>){\r
+ SpecimenOrObservationBase<?> specimen = (SpecimenOrObservationBase<?>) entity;\r
+ if(entity instanceof DerivedUnit){\r
+ DerivedUnit derivedUnit = (DerivedUnit)entity;\r
+ DerivationEvent derivedFrom = derivedUnit.getDerivedFrom();\r
+ Set<SpecimenOrObservationBase> originals = derivedFrom.getOriginals();\r
+ for (SpecimenOrObservationBase<?> original: originals) {\r
+ original.removeDerivationEvent(derivedFrom);\r
+// saveOrUpdate(original);\r
+ }\r
+ }\r
+ if(entity instanceof DnaSample && ((DnaSample) entity).getRecordBasis()==SpecimenOrObservationType.DnaSample){\r
+ DnaSample dnaSample = (DnaSample)entity;\r
+ for (Sequence sequence : dnaSample.getSequences()) {\r
+ entitiesToDelete.addAll(collectEntitiesToDelete(sequence));\r
+ dnaSample.removeSequence(sequence);\r
+// saveOrUpdate(dnaSample);\r
+ }\r
+ }\r
+ Set<DerivationEvent> derivationEvents = specimen.getDerivationEvents();\r
+ for (DerivationEvent derivationEvent : derivationEvents) {\r
+ for (DerivedUnit derivedUnit : derivationEvent.getDerivatives()) {\r
+ entitiesToDelete.addAll(collectEntitiesToDelete(derivedUnit));\r
+ }\r
+ }\r
+ }\r
+ else if(entity instanceof Sequence){\r
+ Sequence sequence = (Sequence)entity;\r
+ for (SingleRead singleRead : sequence.getSingleReads()) {\r
+ entitiesToDelete.addAll(collectEntitiesToDelete(singleRead));\r
+ sequence.removeSingleRead(singleRead);\r
+ }\r
+// sequenceService.saveOrUpdate(sequence);\r
+ }\r
+ entitiesToDelete.add(entity);\r
+ return entitiesToDelete;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listAssociatedTaxa(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)\r
+ */\r
+ @Override\r
+ public Collection<TaxonBase<?>> listAssociatedTaxa(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
+ return dao.listAssociatedTaxa(specimen, null, null, null, null);\r
+ }\r
+\r
+ @Override\r
+ public Collection<TaxonBase<?>> listTypedTaxa(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
+ return dao.listTypedTaxa(specimen, limit, start, orderHints, propertyPaths);\r
+ }\r
+\r
}\r