X-Git-Url: https://dev.e-taxonomy.eu/gitweb/cdmlib.git/blobdiff_plain/8c1dd6181fd3fb247ddb85247d3a1ea3d35f84a5..a7f43cf4c361fc3288a5b1a6c50bd002b56d9629:/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/OccurrenceServiceImpl.java diff --git a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/OccurrenceServiceImpl.java b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/OccurrenceServiceImpl.java index 27c4c07534..74b2b6cb5d 100644 --- a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/OccurrenceServiceImpl.java +++ b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/OccurrenceServiceImpl.java @@ -1,55 +1,106 @@ // $Id$ /** * Copyright (C) 2007 EDIT - * European Distributed Institute of Taxonomy + * European Distributed Institute of Taxonomy * http://www.e-taxonomy.eu - * + * * The contents of this file are subject to the Mozilla Public License Version 1.1 * See LICENSE.TXT at the top of this package for the full license terms. */ package eu.etaxonomy.cdm.api.service; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; import org.apache.log4j.Logger; -import org.hibernate.Hibernate; +import org.apache.lucene.index.CorruptIndexException; +import org.apache.lucene.queryParser.ParseException; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.SortField; +import org.hibernate.TransientObjectException; +import org.hibernate.search.spatial.impl.Rectangle; +import org.joda.time.Partial; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade; import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeConfigurator; import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeNotSupportedException; +import eu.etaxonomy.cdm.api.service.DeleteResult.DeleteStatus; +import eu.etaxonomy.cdm.api.service.config.SpecimenDeleteConfigurator; +import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO; +import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO.ContigFile; +import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO.MolecularData; +import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException; +import eu.etaxonomy.cdm.api.service.molecular.ISequenceService; import eu.etaxonomy.cdm.api.service.pager.Pager; import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl; +import eu.etaxonomy.cdm.api.service.search.ILuceneIndexToolProvider; +import eu.etaxonomy.cdm.api.service.search.ISearchResultBuilder; +import eu.etaxonomy.cdm.api.service.search.LuceneSearch; +import eu.etaxonomy.cdm.api.service.search.LuceneSearch.TopGroupsWithMaxScore; +import eu.etaxonomy.cdm.api.service.search.QueryFactory; +import eu.etaxonomy.cdm.api.service.search.SearchResult; +import eu.etaxonomy.cdm.api.service.search.SearchResultBuilder; +import eu.etaxonomy.cdm.api.service.util.TaxonRelationshipEdge; import eu.etaxonomy.cdm.common.monitor.IProgressMonitor; import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper; +import eu.etaxonomy.cdm.model.CdmBaseType; +import eu.etaxonomy.cdm.model.agent.AgentBase; +import eu.etaxonomy.cdm.model.common.CdmBase; +import eu.etaxonomy.cdm.model.common.DefinedTerm; import eu.etaxonomy.cdm.model.common.DefinedTermBase; +import eu.etaxonomy.cdm.model.common.ICdmBase; +import eu.etaxonomy.cdm.model.common.Language; import eu.etaxonomy.cdm.model.common.UuidAndTitleCache; import eu.etaxonomy.cdm.model.description.DescriptionBase; import eu.etaxonomy.cdm.model.description.DescriptionElementBase; +import eu.etaxonomy.cdm.model.description.DescriptionElementSource; import eu.etaxonomy.cdm.model.description.IndividualsAssociation; import eu.etaxonomy.cdm.model.description.TaxonDescription; -import eu.etaxonomy.cdm.model.location.WaterbodyOrCountry; +import eu.etaxonomy.cdm.model.location.Country; +import eu.etaxonomy.cdm.model.location.NamedArea; import eu.etaxonomy.cdm.model.media.Media; -import eu.etaxonomy.cdm.model.name.HomotypicalGroup; +import eu.etaxonomy.cdm.model.media.MediaRepresentation; +import eu.etaxonomy.cdm.model.media.MediaRepresentationPart; +import eu.etaxonomy.cdm.model.media.MediaUtils; +import eu.etaxonomy.cdm.model.molecular.DnaSample; +import eu.etaxonomy.cdm.model.molecular.Sequence; +import eu.etaxonomy.cdm.model.molecular.SingleRead; +import eu.etaxonomy.cdm.model.name.NameTypeDesignation; +import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation; import eu.etaxonomy.cdm.model.name.TaxonNameBase; +import eu.etaxonomy.cdm.model.name.TypeDesignationBase; +import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase; import eu.etaxonomy.cdm.model.occurrence.DerivationEvent; -import eu.etaxonomy.cdm.model.occurrence.DerivedUnitBase; +import eu.etaxonomy.cdm.model.occurrence.DerivedUnit; import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent; -import eu.etaxonomy.cdm.model.occurrence.FieldObservation; +import eu.etaxonomy.cdm.model.occurrence.FieldUnit; +import eu.etaxonomy.cdm.model.occurrence.GatheringEvent; +import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen; import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase; +import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType; import eu.etaxonomy.cdm.model.taxon.Taxon; import eu.etaxonomy.cdm.model.taxon.TaxonBase; -import eu.etaxonomy.cdm.persistence.dao.AbstractBeanInitializer; +import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao; import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao; -import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao; +import eu.etaxonomy.cdm.persistence.dao.initializer.AbstractBeanInitializer; import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao; -import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao; import eu.etaxonomy.cdm.persistence.query.OrderHint; import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy; @@ -58,185 +109,978 @@ import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy; * @created 01.09.2008 */ @Service -@Transactional(propagation = Propagation.SUPPORTS, readOnly = true) +@Transactional(readOnly = true) public class OccurrenceServiceImpl extends IdentifiableServiceBase implements IOccurrenceService { - static private final Logger logger = Logger.getLogger(OccurrenceServiceImpl.class); - - @Autowired - private IDefinedTermDao definedTermDao; - - @Autowired - private IDescriptionService descriptionService; - - @Autowired - private AbstractBeanInitializer beanInitializer; - - @Autowired - private ITaxonDao taxonDao; - - - - public OccurrenceServiceImpl() { - logger.debug("Load OccurrenceService Bean"); - } - - - /* (non-Javadoc) - * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy) - */ - @Override - @Transactional(readOnly = false) + static private final Logger logger = Logger.getLogger(OccurrenceServiceImpl.class); + + @Autowired + private IDefinedTermDao definedTermDao; + + @Autowired + private IDescriptionService descriptionService; + + @Autowired + private ITaxonService taxonService; + + @Autowired + private ITermService termService; + + @Autowired + private INameService nameService; + + @Autowired + private ISequenceService sequenceService; + + @Autowired + private AbstractBeanInitializer beanInitializer; + + @Autowired + private ILuceneIndexToolProvider luceneIndexToolProvider; + + @Autowired + private ICdmGenericDao genericDao; + + + public OccurrenceServiceImpl() { + logger.debug("Load OccurrenceService Bean"); + } + + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy) + */ + @Override + @Transactional(readOnly = false) public void updateTitleCache(Class clazz, Integer stepSize, IIdentifiableEntityCacheStrategy cacheStrategy, IProgressMonitor monitor) { - if (clazz == null){ - clazz = SpecimenOrObservationBase.class; - } - super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor); - } - - - /** - * FIXME Candidate for harmonization - * move to termService - */ - public WaterbodyOrCountry getCountryByIso(String iso639) { - return this.definedTermDao.getCountryByIso(iso639); - - } - - /** - * FIXME Candidate for harmonization - * move to termService - */ - public List getWaterbodyOrCountryByName(String name) { - List terms = this.definedTermDao.findByTitle(WaterbodyOrCountry.class, name, null, null, null, null, null, null) ; - List countries = new ArrayList(); - for (int i=0;i getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize,Integer pageNumber, List propertyPaths) { + if (clazz == null){ + clazz = SpecimenOrObservationBase.class; + } + super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor); + } + + + /** + * FIXME Candidate for harmonization + * move to termService + */ + @Override + public Country getCountryByIso(String iso639) { + return this.definedTermDao.getCountryByIso(iso639); + + } + + /** + * FIXME Candidate for harmonization + * move to termService + */ + @Override + public List getCountryByName(String name) { + List terms = this.definedTermDao.findByTitle(Country.class, name, null, null, null, null, null, null) ; + List countries = new ArrayList(); + for (int i=0;i getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize,Integer pageNumber, List propertyPaths) { Integer numberOfResults = dao.countDerivationEvents(occurence); - - List results = new ArrayList(); - if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) - results = dao.getDerivationEvents(occurence, pageSize, pageNumber,propertyPaths); - } - - return new DefaultPagerImpl(pageNumber, numberOfResults, pageSize, results); - } - - public Pager getDeterminations(SpecimenOrObservationBase occurrence, TaxonBase taxonBase, Integer pageSize,Integer pageNumber, List propertyPaths) { + + List results = new ArrayList(); + if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) + results = dao.getDerivationEvents(occurence, pageSize, pageNumber,propertyPaths); + } + + return new DefaultPagerImpl(pageNumber, numberOfResults, pageSize, results); + } + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#countDeterminations(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.taxon.TaxonBase) + */ + @Override + public int countDeterminations(SpecimenOrObservationBase occurence, TaxonBase taxonbase) { + return dao.countDeterminations(occurence, taxonbase); + } + + @Override + public Pager getDeterminations(SpecimenOrObservationBase occurrence, TaxonBase taxonBase, Integer pageSize,Integer pageNumber, List propertyPaths) { Integer numberOfResults = dao.countDeterminations(occurrence, taxonBase); - - List results = new ArrayList(); - if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) - results = dao.getDeterminations(occurrence,taxonBase, pageSize, pageNumber, propertyPaths); - } - - return new DefaultPagerImpl(pageNumber, numberOfResults, pageSize, results); - } - - public Pager getMedia(SpecimenOrObservationBase occurence,Integer pageSize, Integer pageNumber, List propertyPaths) { + + List results = new ArrayList(); + if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) + results = dao.getDeterminations(occurrence,taxonBase, pageSize, pageNumber, propertyPaths); + } + + return new DefaultPagerImpl(pageNumber, numberOfResults, pageSize, results); + } + + @Override + public Pager getMedia(SpecimenOrObservationBase occurence,Integer pageSize, Integer pageNumber, List propertyPaths) { Integer numberOfResults = dao.countMedia(occurence); - - List results = new ArrayList(); - if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) - results = dao.getMedia(occurence, pageSize, pageNumber, propertyPaths); - } - - return new DefaultPagerImpl(pageNumber, numberOfResults, pageSize, results); - } - - /* (non-Javadoc) - * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#list(java.lang.Class, eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List) - */ - public Pager list(Class type, TaxonBase determinedAs, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { - Integer numberOfResults = dao.count(type,determinedAs); - List results = new ArrayList(); - pageNumber = pageNumber == null ? 0 : pageNumber; - if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) - Integer start = pageSize == null ? 0 : pageSize * pageNumber; - results = dao.list(type,determinedAs, pageSize, start, orderHints,propertyPaths); - } - return new DefaultPagerImpl(pageNumber, numberOfResults, pageSize, results); - } - - @Override - public List> getDerivedUnitBaseUuidAndTitleCache() { - return dao.getDerivedUnitBaseUuidAndTitleCache(); - } - - @Override - public List> getFieldObservationUuidAndTitleCache() { - return dao.getFieldObservationUuidAndTitleCache(); - } - - /* (non-Javadoc) - * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getDerivedUnitFacade(eu.etaxonomy.cdm.model.occurrence.DerivedUnitBase) - */ - @Override - public DerivedUnitFacade getDerivedUnitFacade(DerivedUnitBase derivedUnit, List propertyPaths) throws DerivedUnitFacadeNotSupportedException { - derivedUnit = (DerivedUnitBase)dao.load(derivedUnit.getUuid(), null); - DerivedUnitFacadeConfigurator config = DerivedUnitFacadeConfigurator.NewInstance(); - config.setThrowExceptionForNonSpecimenPreservationMethodRequest(false); - DerivedUnitFacade derivedUnitFacade = DerivedUnitFacade.NewInstance(derivedUnit, config); - beanInitializer.initialize(derivedUnitFacade, propertyPaths); - return derivedUnitFacade; - } - - /* (non-Javadoc) - * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listDerivedUnitFacades(eu.etaxonomy.cdm.model.description.DescriptionBase, java.util.List) - */ - @Override - public List listDerivedUnitFacades( - DescriptionBase description, List propertyPaths) { - - List derivedUnitFacadeList = new ArrayList(); - IndividualsAssociation tempIndividualsAssociation; - SpecimenOrObservationBase tempSpecimenOrObservationBase; - List elements = descriptionService.listDescriptionElements(description, null, IndividualsAssociation.class, null, 0, Arrays.asList(new String []{"associatedSpecimenOrObservation"})); - for(DescriptionElementBase element : elements){ - if(element instanceof IndividualsAssociation){ - tempIndividualsAssociation = (IndividualsAssociation)element; - if(tempIndividualsAssociation.getAssociatedSpecimenOrObservation() != null){ - tempSpecimenOrObservationBase = HibernateProxyHelper.deproxy(tempIndividualsAssociation.getAssociatedSpecimenOrObservation(), SpecimenOrObservationBase.class); - if(tempSpecimenOrObservationBase instanceof DerivedUnitBase){ - try { - derivedUnitFacadeList.add(DerivedUnitFacade.NewInstance((DerivedUnitBase)tempSpecimenOrObservationBase)); - } catch (DerivedUnitFacadeNotSupportedException e) { - logger.warn(tempIndividualsAssociation.getAssociatedSpecimenOrObservation().getTitleCache() + " : " +e.getMessage()); - } - } - } - - } - } - - beanInitializer.initializeAll(derivedUnitFacadeList, propertyPaths); - - return derivedUnitFacadeList; - } - - /* (non-Javadoc) - * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listSpecimenOrObservationsFor(java.lang.Class, eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List) - */ - @Override - public List listByAnyAssociation(Class type, - Taxon associatedTaxon, Integer limit, Integer start, List orderHints, List propertyPaths) - { - - associatedTaxon = (Taxon) taxonDao.load(associatedTaxon.getUuid()); - return dao.listByAnyAssociation(type, associatedTaxon, limit, start, orderHints, propertyPaths); - - } - - + + List results = new ArrayList(); + if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) + results = dao.getMedia(occurence, pageSize, pageNumber, propertyPaths); + } + + return new DefaultPagerImpl(pageNumber, numberOfResults, pageSize, results); + } + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#list(java.lang.Class, eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List) + */ + @Override + public Pager list(Class type, TaxonBase determinedAs, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { + Integer numberOfResults = dao.count(type,determinedAs); + List results = new ArrayList(); + pageNumber = pageNumber == null ? 0 : pageNumber; + if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) + Integer start = pageSize == null ? 0 : pageSize * pageNumber; + results = dao.list(type,determinedAs, pageSize, start, orderHints,propertyPaths); + } + return new DefaultPagerImpl(pageNumber, numberOfResults, pageSize, results); + } + + @Override + public List> getDerivedUnitUuidAndTitleCache() { + return dao.getDerivedUnitUuidAndTitleCache(); + } + + @Override + public List> getFieldUnitUuidAndTitleCache() { + return dao.getFieldUnitUuidAndTitleCache(); + } + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getDerivedUnitFacade(eu.etaxonomy.cdm.model.occurrence.DerivedUnit) + */ + @Override + public DerivedUnitFacade getDerivedUnitFacade(DerivedUnit derivedUnit, List propertyPaths) throws DerivedUnitFacadeNotSupportedException { + derivedUnit = (DerivedUnit)dao.load(derivedUnit.getUuid(), null); + DerivedUnitFacadeConfigurator config = DerivedUnitFacadeConfigurator.NewInstance(); + config.setThrowExceptionForNonSpecimenPreservationMethodRequest(false); + DerivedUnitFacade derivedUnitFacade = DerivedUnitFacade.NewInstance(derivedUnit, config); + beanInitializer.initialize(derivedUnitFacade, propertyPaths); + return derivedUnitFacade; + } + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listDerivedUnitFacades(eu.etaxonomy.cdm.model.description.DescriptionBase, java.util.List) + */ + @Override + public List listDerivedUnitFacades( + DescriptionBase description, List propertyPaths) { + + List derivedUnitFacadeList = new ArrayList(); + IndividualsAssociation tempIndividualsAssociation; + SpecimenOrObservationBase tempSpecimenOrObservationBase; + List elements = descriptionService.listDescriptionElements(description, null, IndividualsAssociation.class, null, 0, Arrays.asList(new String []{"associatedSpecimenOrObservation"})); + for(DescriptionElementBase element : elements){ + if(element instanceof IndividualsAssociation){ + tempIndividualsAssociation = (IndividualsAssociation)element; + if(tempIndividualsAssociation.getAssociatedSpecimenOrObservation() != null){ + tempSpecimenOrObservationBase = HibernateProxyHelper.deproxy(tempIndividualsAssociation.getAssociatedSpecimenOrObservation(), SpecimenOrObservationBase.class); + if(tempSpecimenOrObservationBase instanceof DerivedUnit){ + try { + derivedUnitFacadeList.add(DerivedUnitFacade.NewInstance((DerivedUnit)tempSpecimenOrObservationBase)); + } catch (DerivedUnitFacadeNotSupportedException e) { + logger.warn(tempIndividualsAssociation.getAssociatedSpecimenOrObservation().getTitleCache() + " : " +e.getMessage()); + } + } + } + + } + } + + beanInitializer.initializeAll(derivedUnitFacadeList, propertyPaths); + + return derivedUnitFacadeList; + } + + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listByAnyAssociation(java.lang.Class, java.util.Set, eu.etaxonomy.cdm.model.taxon.Taxon, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List) + */ + @Override + public List listByAssociatedTaxon(Class type, Set includeRelationships, + Taxon associatedTaxon, Integer maxDepth, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { + + return pageByAssociatedTaxon(type, includeRelationships, associatedTaxon, maxDepth, pageSize, pageNumber, orderHints, propertyPaths).getRecords(); + } + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listByAnyAssociation(java.lang.Class, java.util.Set, eu.etaxonomy.cdm.model.taxon.Taxon, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List) + */ + @Override + public Collection listFieldUnitsByAssociatedTaxon(Set includeRelationships, + Taxon associatedTaxon, Integer maxDepth, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { + + if(!getSession().contains(associatedTaxon)){ + associatedTaxon = (Taxon) taxonService.load(associatedTaxon.getUuid()); + } + + Set fieldUnits = new HashSet(); + + List records = pageByAssociatedTaxon(null, includeRelationships, associatedTaxon, maxDepth, pageSize, pageNumber, orderHints, propertyPaths).getRecords(); + for(SpecimenOrObservationBase specimen:records){ + fieldUnits.addAll(getFieldUnits(specimen.getUuid())); + } + return fieldUnits; + } + + @Override + public DerivateHierarchyDTO assembleDerivateHierarchyDTO(FieldUnit fieldUnit, UUID associatedTaxonUuid){ + + if(!getSession().contains(fieldUnit)){ + fieldUnit = (FieldUnit) load(fieldUnit.getUuid()); + } + TaxonBase associatedTaxon = taxonService.load(associatedTaxonUuid); + + DerivateHierarchyDTO dto = new DerivateHierarchyDTO(); + Map typeSpecimenUUIDtoTypeDesignationStatus = new HashMap(); + + //gather types for this taxon name + TaxonNameBase name = associatedTaxon.getName(); + Set typeDesignations = name.getSpecimenTypeDesignations(); + for (Object object : typeDesignations) { + if(object instanceof SpecimenTypeDesignation){ + SpecimenTypeDesignation specimenTypeDesignation = (SpecimenTypeDesignation)object; + DerivedUnit typeSpecimen = specimenTypeDesignation.getTypeSpecimen(); + final TypeDesignationStatusBase typeStatus = specimenTypeDesignation.getTypeStatus(); + typeSpecimenUUIDtoTypeDesignationStatus.put(typeSpecimen.getUuid(), typeStatus); + } + } + + if(fieldUnit.getGatheringEvent()!=null){ + GatheringEvent gatheringEvent = fieldUnit.getGatheringEvent(); + //Country + final NamedArea country = gatheringEvent.getCountry(); + dto.setCountry(country!=null?country.getDescription():""); + //Collection + final AgentBase collector = gatheringEvent.getCollector(); + final String fieldNumber = fieldUnit.getFieldNumber(); + dto.setCollection(((collector!=null?collector:"") + " " + (fieldNumber!=null?fieldNumber:"")).trim()); + //Date + final Partial gatheringDate = gatheringEvent.getGatheringDate(); + dto.setDate(gatheringDate!=null?gatheringDate.toString():""); + } + + //Taxon Name + dto.setTaxonName(associatedTaxon.getName().getFullTitleCache()); + + + Collection derivedUnits = new ArrayList(); + getDerivedUnitsFor(fieldUnit, derivedUnits); + + //Herbaria map + Map collectionToCountMap = new HashMap(); + //List of accession numbers for citation + List preservedSpecimenAccessionNumbers = new ArrayList(); + + //iterate over sub derivates + for (DerivedUnit derivedUnit : derivedUnits) { + //current accession number + String currentAccessionNumber = derivedUnit.getAccessionNumber()!=null?derivedUnit.getAccessionNumber():""; + //current herbarium + String currentHerbarium = ""; + eu.etaxonomy.cdm.model.occurrence.Collection collection = derivedUnit.getCollection(); + if(collection!=null){ + currentHerbarium = collection.getCode()!=null?collection.getCode():""; + //count herbaria + Integer count = collectionToCountMap.get(collection); + if(count==null){ + count = 1; + } + else{ + count++; + } + collectionToCountMap.put(collection, count); + } + //check if derived unit is a type + if(typeSpecimenUUIDtoTypeDesignationStatus.keySet().contains(derivedUnit.getUuid())){ + dto.setHasType(true); + TypeDesignationStatusBase typeDesignationStatus = typeSpecimenUUIDtoTypeDesignationStatus.get(derivedUnit.getUuid()); + String typeStatus = typeDesignationStatus.getLabel(); + dto.addTypes(typeStatus, currentAccessionNumber); + } + //assemble molecular data + //pattern: DNAMarker [contig1, primer1_1, primer1_2, ...][contig2, primer2_1, ...]... + if(derivedUnit instanceof DnaSample){ + if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.TissueSample){ + //TODO implement TissueSample assembly for web service + } + if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.DnaSample){ + + DnaSample dna = (DnaSample)derivedUnit; + if(!dna.getSequences().isEmpty()){ + dto.setHasDna(true); + } + for(Sequence sequence:dna.getSequences()){ + URI boldUri = null; + try { + boldUri = sequence.getBoldUri(); + } catch (URISyntaxException e1) { + logger.error("Could not create BOLD URI", e1); + } + final DefinedTerm dnaMarker = sequence.getDnaMarker(); + MolecularData molecularData = dto.addProviderLink(boldUri!=null?boldUri:null,dnaMarker!=null?dnaMarker.getLabel():"[no marker]"); + + //contig file FIXME show primer although contig not present? + if(sequence.getContigFile()!=null){ + MediaRepresentationPart contigMediaRepresentationPart = MediaUtils.getFirstMediaRepresentationPart(sequence.getContigFile()); + if(contigMediaRepresentationPart!=null){ + ContigFile contigFile = molecularData.addContigFile(contigMediaRepresentationPart.getUri(), "contig"); + //primer files + if(sequence.getSingleReads()!=null){ + for (SingleRead singleRead : sequence.getSingleReads()) { + MediaRepresentationPart pherogramMediaRepresentationPart = MediaUtils.getFirstMediaRepresentationPart(singleRead.getPherogram()); + if(pherogramMediaRepresentationPart!=null){ + contigFile.addPrimerLink(pherogramMediaRepresentationPart.getUri(), "primer"); + } + } + } + } + } + } + } + } + //assemble media data + else if(derivedUnit instanceof MediaSpecimen){ + + MediaSpecimen media = (MediaSpecimen)derivedUnit; + String mediaUriString = getMediaUriString(media); + if(media.getKindOfUnit()!=null){ + //specimen scan + if(media.getKindOfUnit().getUuid().equals(UUID.fromString("acda15be-c0e2-4ea8-8783-b9b0c4ad7f03"))){ + dto.setHasSpecimenScan(true); + final String imageLinkText = currentHerbarium+" "+currentAccessionNumber; + dto.addSpecimenScan(mediaUriString==null?"":mediaUriString, !imageLinkText.equals(" ")?imageLinkText:"[no accession]"); + } + //detail image + else if(media.getKindOfUnit().getUuid().equals(UUID.fromString("31eb8d02-bf5d-437c-bcc6-87a626445f34"))){ + dto.setHasDetailImage(true); + String motif = ""; + if(media.getMediaSpecimen()!=null && media.getMediaSpecimen().getTitle()!=null){ + motif = media.getMediaSpecimen().getTitle().getText(); + } + dto.addDetailImage(mediaUriString==null?"":mediaUriString, motif!=null?motif:"[no motif]"); + } + } + } + //assemble preserved specimen data + else if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.PreservedSpecimen){ + if(!currentAccessionNumber.isEmpty()){ + preservedSpecimenAccessionNumbers.add(currentAccessionNumber); + } + } + } + + final String separator = ", "; + //assemble citation + String citation = ""; + citation += !dto.getCountry().isEmpty()?dto.getCountry()+separator:""; + if(fieldUnit.getGatheringEvent()!=null){ + if(fieldUnit.getGatheringEvent().getLocality()!=null){ + citation += fieldUnit.getGatheringEvent().getLocality().getText(); + citation += separator; + } + if(fieldUnit.getGatheringEvent().getExactLocation()!=null + && fieldUnit.getGatheringEvent().getExactLocation().getLatitude()!=null + && fieldUnit.getGatheringEvent().getExactLocation().getLongitude()!=null){ + citation += fieldUnit.getGatheringEvent().getExactLocation().getLatitude().toString(); + citation += separator; + citation += fieldUnit.getGatheringEvent().getExactLocation().getLongitude().toString(); + citation += separator; + } + } + citation += !dto.getCollection().isEmpty()?dto.getCollection():""; + if(!preservedSpecimenAccessionNumbers.isEmpty()){ + citation += " ("; + for(String accessionNumber:preservedSpecimenAccessionNumbers){ + if(!accessionNumber.isEmpty()){ + citation += accessionNumber+separator; + } + } + citation = removeTail(citation, separator); + citation += ")"; + } + citation = removeTail(citation, separator); + dto.setCitation(citation); + + //assemble herbaria string + String herbariaString = ""; + for(Entry e:collectionToCountMap.entrySet()){ + eu.etaxonomy.cdm.model.occurrence.Collection collection = e.getKey(); + if(collection.getCode()!=null){ + herbariaString += collection.getCode(); + } + if(e.getValue()>1){ + herbariaString += "("+e.getValue()+")"; + } + herbariaString += separator; + } + herbariaString = removeTail(herbariaString, separator); + dto.setHerbarium(herbariaString); + + return dto; + } + + + /** + * @param string + * @param tail + * @return + */ + private String removeTail(String string, final String tail) { + if(string.endsWith(tail)){ + string = string.substring(0, string.length()-tail.length()); + } + return string; + } + + private String getMediaUriString(MediaSpecimen mediaSpecimen){ + String mediaUri = null; + Collection mediaRepresentations = mediaSpecimen.getMediaSpecimen().getRepresentations(); + if(mediaRepresentations!=null && !mediaRepresentations.isEmpty()){ + Collection mediaRepresentationParts = mediaRepresentations.iterator().next().getParts(); + if(mediaRepresentationParts!=null && !mediaRepresentationParts.isEmpty()){ + MediaRepresentationPart part = mediaRepresentationParts.iterator().next(); + if(part.getUri()!=null){ + mediaUri = part.getUri().toASCIIString(); + } + } + } + return mediaUri; + } + + private void getDerivedUnitsFor(SpecimenOrObservationBase specimen, Collection derivedUnits){ + for(DerivationEvent derivationEvent:specimen.getDerivationEvents()){ + for(DerivedUnit derivative:derivationEvent.getDerivatives()){ + derivedUnits.add(derivative); + getDerivedUnitsFor(derivative, derivedUnits); + } + } + } + + + /* (non-Javadoc) + * @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) + */ + @SuppressWarnings("unchecked") + @Override + public Pager pageByAssociatedTaxon(Class type, Set includeRelationships, + Taxon associatedTaxon, Integer maxDepth, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { + + Set taxa = new HashSet(); + Set occurrenceIds = new HashSet(); + List occurrences = new ArrayList(); + +// Integer limit = PagerUtils.limitFor(pageSize); +// Integer start = PagerUtils.startFor(pageSize, pageNumber); + + if(!getSession().contains(associatedTaxon)){ + associatedTaxon = (Taxon) taxonService.load(associatedTaxon.getUuid()); + } + + if(includeRelationships != null) { + taxa = taxonService.listRelatedTaxa(associatedTaxon, includeRelationships, maxDepth, null, null, propertyPaths); + } + + taxa.add(associatedTaxon); + + for (Taxon taxon : taxa) { + List perTaxonOccurrences = dao.listByAssociatedTaxon(type, taxon, null, null, orderHints, propertyPaths); + for (SpecimenOrObservationBase o : perTaxonOccurrences) { + occurrenceIds.add(o.getId()); + } + } + occurrences = (List) dao.listByIds(occurrenceIds, pageSize, pageNumber, orderHints, propertyPaths); + + return new DefaultPagerImpl(pageNumber, occurrenceIds.size(), pageSize, occurrences); + + } + + + @Override + public Pager pageByAssociatedTaxon(Class type, Set includeRelationships, + String taxonUUID, Integer maxDepth, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { + + UUID uuid = UUID.fromString(taxonUUID); + Taxon tax = (Taxon) taxonService.load(uuid); + //TODO REMOVE NULL STATEMENT + type=null; + return pageByAssociatedTaxon( type,includeRelationships,tax, maxDepth, pageSize, pageNumber, orderHints, propertyPaths ); + + } + + + @Override + public Pager> findByFullText( + Class clazz, String queryString, Rectangle boundingBox, List languages, + boolean highlightFragments, Integer pageSize, Integer pageNumber, List orderHints, + List propertyPaths) throws CorruptIndexException, IOException, ParseException { + + LuceneSearch luceneSearch = prepareByFullTextSearch(clazz, queryString, boundingBox, languages, highlightFragments); + + // --- execute search + TopGroupsWithMaxScore topDocsResultSet = luceneSearch.executeSearch(pageSize, pageNumber); + + Map idFieldMap = new HashMap(); + idFieldMap.put(CdmBaseType.SPECIMEN_OR_OBSERVATIONBASE, "id"); + + // --- initialize taxa, highlight matches .... + ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery()); + @SuppressWarnings("rawtypes") + List> searchResults = searchResultBuilder.createResultSet( + topDocsResultSet, luceneSearch.getHighlightFields(), dao, idFieldMap, propertyPaths); + + int totalHits = topDocsResultSet != null ? topDocsResultSet.topGroups.totalGroupCount : 0; + + return new DefaultPagerImpl>(pageNumber, totalHits, pageSize, + searchResults); + + } + + + /** + * @param clazz + * @param queryString + * @param languages + * @param highlightFragments + * @return + */ + private LuceneSearch prepareByFullTextSearch(Class clazz, String queryString, Rectangle bbox, + List languages, boolean highlightFragments) { + + BooleanQuery finalQuery = new BooleanQuery(); + BooleanQuery textQuery = new BooleanQuery(); + + LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, FieldUnit.class); + QueryFactory queryFactory = luceneIndexToolProvider.newQueryFactoryFor(FieldUnit.class); + + // --- criteria + luceneSearch.setCdmTypRestriction(clazz); + if(queryString != null){ + textQuery.add(queryFactory.newTermQuery("titleCache", queryString), Occur.SHOULD); + finalQuery.add(textQuery, Occur.MUST); + } + + // --- spacial query + if(bbox != null){ + finalQuery.add(QueryFactory.buildSpatialQueryByRange(bbox, "gatheringEvent.exactLocation.point"), Occur.MUST); + } + + luceneSearch.setQuery(finalQuery); + + // --- sorting + SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)}; + luceneSearch.setSortFields(sortFields); + + if(highlightFragments){ + luceneSearch.setHighlightFields(queryFactory.getTextFieldNamesAsArray()); + } + return luceneSearch; + } + + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getFieldUnits(eu.etaxonomy.cdm.model.occurrence.DerivedUnit) + */ + @Override + public Collection getFieldUnits(UUID derivedUnitUuid) { + //It will search recursively over all {@link DerivationEvent}s and get the "originals" ({@link SpecimenOrObservationBase}) + //from which this DerivedUnit was derived until all FieldUnits are found. + + //FIXME: use HQL queries to increase performance + SpecimenOrObservationBase specimen = load(derivedUnitUuid); +// specimen = HibernateProxyHelper.deproxy(specimen, SpecimenOrObservationBase.class); + Collection fieldUnits = new ArrayList(); + + if(specimen instanceof FieldUnit){ + fieldUnits.add((FieldUnit) specimen); + } + else if(specimen instanceof DerivedUnit){ + getFieldUnits((DerivedUnit) specimen, fieldUnits); + } + return fieldUnits; + } + + + /** + * @param original + * @param fieldUnits + */ + private void getFieldUnits(DerivedUnit derivedUnit, Collection fieldUnits) { + Set originals = derivedUnit.getOriginals(); + if(originals!=null && !originals.isEmpty()){ + for(SpecimenOrObservationBase original:originals){ + if(original instanceof FieldUnit){ + fieldUnits.add((FieldUnit) original); + } + else if(original instanceof DerivedUnit){ + getFieldUnits((DerivedUnit) original, fieldUnits); + } + } + } + } + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#moveSequence(eu.etaxonomy.cdm.model.molecular.DnaSample, eu.etaxonomy.cdm.model.molecular.DnaSample, eu.etaxonomy.cdm.model.molecular.Sequence) + */ + @Override + public boolean moveSequence(DnaSample from, DnaSample to, Sequence sequence) { + //reload specimens to avoid session conflicts + from = (DnaSample) load(from.getUuid()); + to = (DnaSample) load(to.getUuid()); + sequence = sequenceService.load(sequence.getUuid()); + + if(from==null || to==null || sequence==null){ + throw new TransientObjectException("One of the CDM entities has not been saved to the data base yet. Moving only works for persisted/saved CDM entities.\n" + + "Operation was move "+sequence+ " from "+from+" to "+to); + } + from.removeSequence(sequence); + saveOrUpdate(from); + to.addSequence(sequence); + saveOrUpdate(to); + return true; + } + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#moveDerivate(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.occurrence.DerivedUnit) + */ + @Override + public boolean moveDerivate(SpecimenOrObservationBase from, SpecimenOrObservationBase to, DerivedUnit derivate) { + //reload specimens to avoid session conflicts + from = load(from.getUuid()); + to = load(to.getUuid()); + derivate = (DerivedUnit) load(derivate.getUuid()); + + if(from==null || to==null || derivate==null){ + throw new TransientObjectException("One of the CDM entities has not been saved to the data base yet. Moving only works for persisted/saved CDM entities.\n" + + "Operation was move "+derivate+ " from "+from+" to "+to); + } + + SpecimenOrObservationType derivateType = derivate.getRecordBasis(); + SpecimenOrObservationType toType = to.getRecordBasis(); + //check if type is a sub derivate type + if(toType==SpecimenOrObservationType.FieldUnit //moving to FieldUnit always works + || derivateType==SpecimenOrObservationType.Media //moving media always works + || (derivateType.isKindOf(toType) && toType!=derivateType)){ //moving only to parent derivate type + //remove derivation event from parent specimen of dragged object + DerivationEvent eventToRemove = null; + for(DerivationEvent event:from.getDerivationEvents()){ + if(event.getDerivatives().contains(derivate)){ + eventToRemove = event; + break; + } + } + from.removeDerivationEvent(eventToRemove); + saveOrUpdate(from); + //add new derivation event to target + DerivationEvent derivedFromNewOriginalEvent = DerivationEvent.NewSimpleInstance(to, derivate, eventToRemove==null?null:eventToRemove.getType()); + to.addDerivationEvent(derivedFromNewOriginalEvent); + derivate.setDerivedFrom(derivedFromNewOriginalEvent); + saveOrUpdate(to); + return true; + } + return false; + } + + @Override + public Collection getNonCascadedAssociatedElements(SpecimenOrObservationBase specimen){ + //potential fields that are not persisted cascadingly + /* + * SOOB + -DescriptionBase + -determinations + --modifier TERM + -kindOfUnit TERM + -lifeStage TERM + -sex TERM + + FieldUnit + -GatheringEvent + --Country TERM + --CollectingAreas TERM + + DerivedUnit + -collection + --institute + ---types TERM + -preservationMethod + --medium TERM + -storedUnder CDM TaxonNameBase + */ + + Collection nonCascadedCdmEntities = new HashSet(); + + //Choose the correct entry point to traverse the graph (FieldUnit or DerivedUnit) + + //FieldUnit + if(specimen instanceof FieldUnit){ + nonCascadedCdmEntities.addAll(getFieldUnitNonCascadedAssociatedElements((FieldUnit)specimen)); + } + //DerivedUnit + else if(specimen instanceof DerivedUnit){ + DerivedUnit derivedUnit = (DerivedUnit)specimen; + if(derivedUnit.getDerivedFrom()!=null){ + Collection fieldUnits = new ArrayList(); + getFieldUnits(derivedUnit, fieldUnits); + for(FieldUnit fieldUnit:fieldUnits){ + nonCascadedCdmEntities.addAll(getFieldUnitNonCascadedAssociatedElements(fieldUnit)); + } + } + } + return nonCascadedCdmEntities; + } + + private Collection getFieldUnitNonCascadedAssociatedElements(FieldUnit fieldUnit){ + //get non cascaded element on SpecimenOrObservationBase level + Collection nonCascadedCdmEntities = getSpecimenOrObservationNonCascadedAssociatedElements(fieldUnit); + + //get FieldUnit specific elements + GatheringEvent gatheringEvent = fieldUnit.getGatheringEvent(); + if(gatheringEvent!=null){ + //country + if(gatheringEvent.getCountry()!=null){ + nonCascadedCdmEntities.add(gatheringEvent.getCountry()); + } + //collecting areas + for (NamedArea namedArea : gatheringEvent.getCollectingAreas()) { + nonCascadedCdmEntities.add(namedArea); + } + } + for (DerivationEvent derivationEvent : fieldUnit.getDerivationEvents()) { + for (DerivedUnit derivedUnit : derivationEvent.getDerivatives()) { + nonCascadedCdmEntities.addAll(getDerivedUnitNonCascadedAssociatedElements(derivedUnit)); + } + } + return nonCascadedCdmEntities; + } + + private Collection getDerivedUnitNonCascadedAssociatedElements(DerivedUnit derivedUnit){ + //get non cascaded element on SpecimenOrObservationBase level + Collection nonCascadedCdmEntities = getSpecimenOrObservationNonCascadedAssociatedElements(derivedUnit); + + //get DerivedUnit specific elements + if(derivedUnit.getCollection()!=null && derivedUnit.getCollection().getInstitute()!=null){ + for (DefinedTerm type : derivedUnit.getCollection().getInstitute().getTypes()) { + nonCascadedCdmEntities.add(type); + } + } + if(derivedUnit.getPreservation()!=null && derivedUnit.getPreservation().getMedium()!=null){ + nonCascadedCdmEntities.add(derivedUnit.getPreservation().getMedium()); + } + if(derivedUnit.getStoredUnder()!=null){ + nonCascadedCdmEntities.add(derivedUnit.getStoredUnder()); + } + return nonCascadedCdmEntities; + } + + /** + * @param specimen + * @return + */ + private Collection getSpecimenOrObservationNonCascadedAssociatedElements( + SpecimenOrObservationBase specimen) { + Collection nonCascadedCdmEntities = new HashSet(); + //scan SpecimenOrObservationBase + for(DeterminationEvent determinationEvent:specimen.getDeterminations()){ + //modifier + if(determinationEvent.getModifier()!=null){ + nonCascadedCdmEntities.add(determinationEvent.getModifier()); + } + } + //kindOfUnit + if(specimen.getKindOfUnit()!=null){ + nonCascadedCdmEntities.add(specimen.getKindOfUnit()); + } + //lifeStage + if(specimen.getLifeStage()!=null){ + nonCascadedCdmEntities.add(specimen.getLifeStage()); + } + //sex + if(specimen.getSex()!=null){ + nonCascadedCdmEntities.add(specimen.getSex()); + } + return nonCascadedCdmEntities; + } + + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#delete(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.api.service.config.SpecimenDeleteConfigurator) + */ + @Override + public DeleteResult delete(SpecimenOrObservationBase specimen, SpecimenDeleteConfigurator config) { + DeleteResult deleteResult = new DeleteResult(); + //check for derivation events + Set derivationEvents = specimen.getDerivationEvents(); + for (DerivationEvent derivationEvent : derivationEvents) { + if(!derivationEvent.getDerivatives().isEmpty()){ + deleteResult.setAbort(); + deleteResult.addException(new ReferencedObjectUndeletableException("Derivate with children cannot be deleted.")); + return deleteResult; + } + } + //check for original (parent derivate) + if(specimen instanceof DerivedUnit){ + DerivationEvent derivedFromEvent = ((DerivedUnit) specimen).getDerivedFrom(); + if(derivedFromEvent!=null){ + derivedFromEvent.removeDerivative((DerivedUnit) specimen); + } + } + //check for IndividualsAssociation (e.g. in TaxonDescriptions) + Collection> associatedTaxa = listAssociatedTaxa(specimen, null, null, null, null); + if(!associatedTaxa.isEmpty()){ + if(config.isDeleteFromIndividualsAssociation()){ + for (TaxonBase taxonBase : associatedTaxa) { + if(taxonBase instanceof Taxon){ + Set descriptions = ((Taxon) taxonBase).getDescriptions(); + for (TaxonDescription taxonDescription : descriptions) { + Set elements = taxonDescription.getElements(); + for (DescriptionElementBase descriptionElementBase : elements) { + if(descriptionElementBase instanceof IndividualsAssociation){ + IndividualsAssociation individualsAssociation = (IndividualsAssociation) descriptionElementBase; + if(individualsAssociation.getAssociatedSpecimenOrObservation().equals(specimen)){ + individualsAssociation.setAssociatedSpecimenOrObservation(null); + } + } + } + } + } + } + } + else{ + deleteResult.addRelatedObjects(new HashSet(associatedTaxa)); + deleteResult.setAbort(); + deleteResult.addException(new ReferencedObjectUndeletableException("Specimen is still associated with taxa.")); + return deleteResult; + } + } + //check for TypeDesignations + Collection> typedTaxa = listTypedTaxa(specimen, null, null, null, null); + if(!typedTaxa.isEmpty()){ + if(config.isdeleteFromTypeDesignation()){ + for (TaxonBase taxonBase : typedTaxa) { + if(taxonBase.getName()!=null){ + Set typeDesignations = taxonBase.getName().getTypeDesignations(); + for (TypeDesignationBase typeDesignationBase : typeDesignations) { + if(typeDesignationBase instanceof SpecimenTypeDesignation){ + ((SpecimenTypeDesignation) typeDesignationBase).setTypeSpecimen(null); + } + } + } + } + } + else{ + deleteResult.addRelatedObjects(new HashSet(typedTaxa)); + deleteResult.setAbort(); + deleteResult.addException(new ReferencedObjectUndeletableException("Specimen is a type specimen.")); + return deleteResult; + } + } + if(!config.isDeleteChildren()){ + Set referencingObjects = genericDao.getReferencingObjects(specimen); + for (CdmBase referencingObject : referencingObjects){ + //DerivedUnit?.storedUnder + if (referencingObject.isInstanceOf(DerivedUnit.class)){ + String message = "Name can't be deleted as it is used as derivedUnit#storedUnder by %s. Remove 'stored under' prior to deleting this name"; + message = String.format(message, CdmBase.deproxy(referencingObject, DerivedUnit.class).getTitleCache()); + } + //DescriptionElementSource#nameUsedInSource + if (referencingObject.isInstanceOf(DescriptionElementSource.class)){ + String message = "Name can't be deleted as it is used as descriptionElementSource#nameUsedInSource"; + } + //NameTypeDesignation#typeName + if (referencingObject.isInstanceOf(NameTypeDesignation.class)){ + String message = "Name can't be deleted as it is used as a name type in a NameTypeDesignation"; + } + } + deleteResult = delete(specimen); + } + else{ + //TODO implement deep delete + } + return deleteResult; + } + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#deleteDerivateHierarchy(eu.etaxonomy.cdm.model.common.ICdmBase) + */ + @Override + public DeleteResult deleteDerivateHierarchy(ICdmBase from, SpecimenDeleteConfigurator config) { + DeleteResult deleteResult = new DeleteResult(); + if(from instanceof Sequence){ + Sequence sequence = (Sequence)from; + sequence.getDnaSample().removeSequence(sequence); + deleteResult.setStatus(DeleteStatus.OK); + } + else if(from instanceof SpecimenOrObservationBase) { + deleteResult = delete((SpecimenOrObservationBase) from, config); + } + return deleteResult; + } + + private Set collectEntitiesToDelete(ICdmBase entity){ + Set entitiesToDelete = new LinkedHashSet(); + + if(entity instanceof SpecimenOrObservationBase){ + SpecimenOrObservationBase specimen = (SpecimenOrObservationBase) entity; + if(entity instanceof DerivedUnit){ + DerivedUnit derivedUnit = (DerivedUnit)entity; + DerivationEvent derivedFrom = derivedUnit.getDerivedFrom(); + Set originals = derivedFrom.getOriginals(); + for (SpecimenOrObservationBase original: originals) { + original.removeDerivationEvent(derivedFrom); +// saveOrUpdate(original); + } + } + if(entity instanceof DnaSample && ((DnaSample) entity).getRecordBasis()==SpecimenOrObservationType.DnaSample){ + DnaSample dnaSample = (DnaSample)entity; + for (Sequence sequence : dnaSample.getSequences()) { + entitiesToDelete.addAll(collectEntitiesToDelete(sequence)); + dnaSample.removeSequence(sequence); +// saveOrUpdate(dnaSample); + } + } + Set derivationEvents = specimen.getDerivationEvents(); + for (DerivationEvent derivationEvent : derivationEvents) { + for (DerivedUnit derivedUnit : derivationEvent.getDerivatives()) { + entitiesToDelete.addAll(collectEntitiesToDelete(derivedUnit)); + } + } + } + else if(entity instanceof Sequence){ + Sequence sequence = (Sequence)entity; + for (SingleRead singleRead : sequence.getSingleReads()) { + entitiesToDelete.addAll(collectEntitiesToDelete(singleRead)); + sequence.removeSingleRead(singleRead); + } +// sequenceService.saveOrUpdate(sequence); + } + entitiesToDelete.add(entity); + return entitiesToDelete; + } + + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#listAssociatedTaxa(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase) + */ + @Override + public Collection> listAssociatedTaxa(SpecimenOrObservationBase specimen, Integer limit, Integer start, List orderHints, List propertyPaths) { + return dao.listAssociatedTaxa(specimen, null, null, null, null); + } + + @Override + public Collection> listTypedTaxa(SpecimenOrObservationBase specimen, Integer limit, Integer start, List orderHints, List propertyPaths) { + return dao.listTypedTaxa(specimen, limit, start, orderHints, propertyPaths); + } + }