X-Git-Url: https://dev.e-taxonomy.eu/gitweb/cdmlib.git/blobdiff_plain/199ed72a78b464290b2470e7f5dc823a1373d6aa..ad80fdc31885697feed8d22235415bedff69c30b:/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 1aa70ce295..2cd090df46 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 @@ -13,11 +13,14 @@ package eu.etaxonomy.cdm.api.service; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; 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.apache.lucene.index.CorruptIndexException; @@ -25,6 +28,7 @@ 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.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -33,8 +37,11 @@ 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.dto.DerivateHierarchyDTO; +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; @@ -53,15 +60,22 @@ import eu.etaxonomy.cdm.model.description.DescriptionElementBase; import eu.etaxonomy.cdm.model.description.IndividualsAssociation; import eu.etaxonomy.cdm.model.location.Country; import eu.etaxonomy.cdm.model.media.Media; +import eu.etaxonomy.cdm.model.media.MediaRepresentation; +import eu.etaxonomy.cdm.model.media.MediaRepresentationPart; +import eu.etaxonomy.cdm.model.molecular.DnaSample; +import eu.etaxonomy.cdm.model.molecular.Sequence; import eu.etaxonomy.cdm.model.occurrence.DerivationEvent; import eu.etaxonomy.cdm.model.occurrence.DerivedUnit; import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent; 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.IDefinedTermDao; +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; @@ -86,12 +100,17 @@ public class OccurrenceServiceImpl extends IdentifiableServiceBase(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); @@ -260,6 +287,162 @@ public class OccurrenceServiceImpl extends IdentifiableServiceBase listFieldUnitsByAssociatedTaxon(Set includeRelationships, + Taxon associatedTaxon, Integer maxDepth, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { + + if(!getSession().contains(associatedTaxon)){ + associatedTaxon = (Taxon) taxonDao.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 Collection listDerivateHierarchyDTOsByAssociatedTaxon(Set includeRelationships, + Taxon associatedTaxon, Integer maxDepth, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { + + if(!getSession().contains(associatedTaxon)){ + associatedTaxon = (Taxon) taxonDao.load(associatedTaxon.getUuid()); + } + + Collection fieldUnits = listFieldUnitsByAssociatedTaxon(includeRelationships, associatedTaxon, maxDepth, pageSize, pageNumber, orderHints, propertyPaths); + + Collection derivateHierarchyDTOs = new ArrayList(); + for(FieldUnit fieldUnit:fieldUnits){ + derivateHierarchyDTOs.add(assembleDerivateHierarchyDTO(fieldUnit, associatedTaxon)); + } + return derivateHierarchyDTOs; + } + + private DerivateHierarchyDTO assembleDerivateHierarchyDTO(FieldUnit fieldUnit, Taxon associatedTaxon){ + + DerivateHierarchyDTO dto = new DerivateHierarchyDTO(); + // TaxonNameBase name = associatedTaxon.getName(); + // name = HibernateProxyHelper.deproxy(name, TaxonNameBase.class); + // dto.setType(!name.getTypeDesignations().isEmpty()); + + if(fieldUnit.getGatheringEvent()!=null){ + GatheringEvent gatheringEvent = fieldUnit.getGatheringEvent(); + //Country + dto.setCountry(gatheringEvent.getCountry()!=null?gatheringEvent.getCountry().getDescription():""); + //Collection + dto.setCollection((gatheringEvent.getCollector()!=null?gatheringEvent.getCollector():"") + fieldUnit.getFieldNumber()!=null?fieldUnit.getFieldNumber():""); + //Date + dto.setDate(gatheringEvent.getGatheringDate()!=null?gatheringEvent.getGatheringDate().toString():""); + } + + //Taxon Name + dto.setTaxonName(associatedTaxon.getName().getFullTitleCache()); + + + Collection derivedUnits = new ArrayList(); + getDerivedUnitsFor(fieldUnit, derivedUnits); + //Herbaria map + Map collectionToCountMap = new HashMap(); + + //iterate over sub derivates + for (DerivedUnit derivedUnit : derivedUnits) { + //assemble molecular data + if(derivedUnit instanceof DnaSample){//.getRecordBasis()==SpecimenOrObservationType.DnaSample){ + dto.setHasDna(true); + + DnaSample dna = (DnaSample)derivedUnit; + if(dna.getBankNumber()!=null){ + dto.addMolecularData(dna.getBankNumber()); + } + } + //assemble media data + else if(derivedUnit instanceof MediaSpecimen){ + + MediaSpecimen media = (MediaSpecimen)derivedUnit; + String mediaUriString = getMediaUriString(media); + if(media.getKindOfUnit()!=null){ + if(media.getKindOfUnit().getUuid().equals(UUID.fromString("acda15be-c0e2-4ea8-8783-b9b0c4ad7f03"))){ + dto.setHasSpecimenScan(true); + if(mediaUriString!=null){ + dto.addSpecimenScan(mediaUriString); + } + } + else if(media.getKindOfUnit().getUuid().equals(UUID.fromString("31eb8d02-bf5d-437c-bcc6-87a626445f34"))){ + dto.setHasDetailImage(true); + if(mediaUriString!=null){ + dto.addDetailImage(mediaUriString); + } + } + } + } + //assemble preserved specimen data + else if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.PreservedSpecimen){ + eu.etaxonomy.cdm.model.occurrence.Collection collection = derivedUnit.getCollection(); + if(collection!=null){ + Integer count = collectionToCountMap.get(collection); + if(count==null){ + count = 1; + } + else{ + count++; + } + collectionToCountMap.put(collection, count); + } + } + } + //assemble herbaria string + String herbariaString = ""; + final String herbariaSeparator = ", "; + 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 += herbariaSeparator; + } + if(herbariaString.endsWith(herbariaSeparator)){ + herbariaString = herbariaString.substring(0, herbariaString.length()-herbariaSeparator.length()); + } + dto.setHerbarium(herbariaString); + return dto; + } + + private String getMediaUriString(MediaSpecimen mediaSpecimen){ + if(!getSession().contains(mediaSpecimen)){ + mediaSpecimen = (MediaSpecimen) load(mediaSpecimen.getUuid()); + } + 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) @@ -276,7 +459,9 @@ public class OccurrenceServiceImpl extends IdentifiableServiceBase) dao.listByIds(occurrenceIds, pageSize, pageNumber, orderHints, propertyPaths); return new DefaultPagerImpl(pageNumber, occurrenceIds.size(), pageSize, occurrences); } + /* (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, + String taxonUUID, Integer maxDepth, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { + + UUID uuid = UUID.fromString(taxonUUID); + Taxon tax = (Taxon) taxonDao.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, @@ -338,11 +539,11 @@ public class OccurrenceServiceImpl extends IdentifiableServiceBase 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 + to.addDerivationEvent(DerivationEvent.NewSimpleInstance(to, derivate, eventToRemove==null?null:eventToRemove.getType())); + saveOrUpdate(to); + return true; + } + return false; + } + }