X-Git-Url: https://dev.e-taxonomy.eu/gitweb/cdmlib.git/blobdiff_plain/a692a96bbadd85429ff187b33b0ffcd46fb91f90..041e26e260df6566ae0737678e20ef06c5caa276:/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/DescriptiveDataSetService.java diff --git a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/DescriptiveDataSetService.java b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/DescriptiveDataSetService.java index a4e07478f9..d5d97989b0 100644 --- a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/DescriptiveDataSetService.java +++ b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/DescriptiveDataSetService.java @@ -8,8 +8,10 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; @@ -17,12 +19,15 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import eu.etaxonomy.cdm.api.service.dto.RowWrapperDTO; +import eu.etaxonomy.cdm.api.service.dto.SpecimenRowWrapperDTO; +import eu.etaxonomy.cdm.api.service.dto.TaxonRowWrapperDTO; import eu.etaxonomy.cdm.common.monitor.IProgressMonitor; import eu.etaxonomy.cdm.common.monitor.IRemotingProgressMonitor; import eu.etaxonomy.cdm.common.monitor.RemotingProgressMonitorThread; import eu.etaxonomy.cdm.filter.TaxonNodeFilter; import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper; import eu.etaxonomy.cdm.model.common.Language; +import eu.etaxonomy.cdm.model.common.MarkerType; import eu.etaxonomy.cdm.model.description.CategoricalData; import eu.etaxonomy.cdm.model.description.DescriptionBase; import eu.etaxonomy.cdm.model.description.DescriptionElementBase; @@ -31,13 +36,15 @@ import eu.etaxonomy.cdm.model.description.DescriptiveSystemRole; import eu.etaxonomy.cdm.model.description.Feature; import eu.etaxonomy.cdm.model.description.QuantitativeData; import eu.etaxonomy.cdm.model.description.SpecimenDescription; +import eu.etaxonomy.cdm.model.description.StatisticalMeasure; +import eu.etaxonomy.cdm.model.description.TaxonDescription; import eu.etaxonomy.cdm.model.description.TextData; import eu.etaxonomy.cdm.model.location.NamedArea; import eu.etaxonomy.cdm.model.occurrence.DerivedUnit; import eu.etaxonomy.cdm.model.occurrence.FieldUnit; import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase; +import eu.etaxonomy.cdm.model.taxon.Classification; import eu.etaxonomy.cdm.model.taxon.Taxon; -import eu.etaxonomy.cdm.model.taxon.TaxonBase; import eu.etaxonomy.cdm.model.taxon.TaxonNode; import eu.etaxonomy.cdm.persistence.dao.description.IDescriptiveDataSetDao; import eu.etaxonomy.cdm.persistence.dto.SpecimenNodeWrapper; @@ -55,6 +62,9 @@ public class DescriptiveDataSetService @Autowired private IOccurrenceService occurrenceService; + @Autowired + private ITaxonService taxonService; + @Autowired private IDescriptionService descriptionService; @@ -112,7 +122,16 @@ public class DescriptiveDataSetService if(monitor.isCanceled()){ return new ArrayList<>(); } - wrappers.add(createRowWrapper(null, description, null, descriptiveDataSet)); + RowWrapperDTO rowWrapper = null; + if(HibernateProxyHelper.isInstanceOf(description, TaxonDescription.class)){ + rowWrapper = createTaxonRowWrapper(HibernateProxyHelper.deproxy(description, TaxonDescription.class), descriptiveDataSet); + } + else if (HibernateProxyHelper.isInstanceOf(description, SpecimenDescription.class)){ + rowWrapper = createSpecimenRowWrapper(HibernateProxyHelper.deproxy(description, SpecimenDescription.class), descriptiveDataSet, false); + } + if(rowWrapper!=null){ + wrappers.add(rowWrapper); + } monitor.worked(1); } return wrappers; @@ -120,69 +139,112 @@ public class DescriptiveDataSetService @Override public Collection loadSpecimens(DescriptiveDataSet descriptiveDataSet){ - //set filter parameters + List filteredNodes = findFilteredTaxonNodes(descriptiveDataSet); + return occurrenceService.listUuidAndTitleCacheByAssociatedTaxon(filteredNodes, null, null); + } + + @Override + public List findFilteredTaxonNodes(DescriptiveDataSet descriptiveDataSet){ TaxonNodeFilter filter = TaxonNodeFilter.NewRankInstance(descriptiveDataSet.getMinRank(), descriptiveDataSet.getMaxRank()); descriptiveDataSet.getGeoFilter().forEach(area -> filter.orArea(area.getUuid())); descriptiveDataSet.getTaxonSubtreeFilter().forEach(node -> filter.orSubtree(node)); filter.setIncludeUnpublished(true); - List filteredNodes = taxonNodeService.uuidList(filter); - return occurrenceService.listUuidAndTitleCacheByAssociatedTaxon(filteredNodes, null, null); + return taxonNodeService.uuidList(filter); } @Override - public RowWrapperDTO createRowWrapper(DescriptionBase description, DescriptiveDataSet descriptiveDataSet){ - return createRowWrapper(null, description, null, descriptiveDataSet); + public List loadFilteredTaxonNodes(DescriptiveDataSet descriptiveDataSet, List propertyPaths){ + return taxonNodeService.load(findFilteredTaxonNodes(descriptiveDataSet), propertyPaths); + } + + private TaxonNode findTaxonNodeForDescription(TaxonNode taxonNode, SpecimenOrObservationBase specimen){ + Collection nodeWrapper = occurrenceService.listUuidAndTitleCacheByAssociatedTaxon(Arrays.asList(taxonNode.getUuid()), null, null); + for (SpecimenNodeWrapper specimenNodeWrapper : nodeWrapper) { + if(specimenNodeWrapper.getUuidAndTitleCache().getId().equals(specimen.getId())){ + return taxonNode; + } + } + return null; } @Override - public RowWrapperDTO createRowWrapper(SpecimenOrObservationBase specimen, DescriptiveDataSet descriptiveDataSet){ - return createRowWrapper(specimen, null, null, descriptiveDataSet); + public TaxonRowWrapperDTO createTaxonRowWrapper(TaxonDescription description, + DescriptiveDataSet descriptiveDataSet) { + TaxonNode taxonNode = null; + Classification classification = null; + Optional first = descriptiveDataSet.getTaxonSubtreeFilter().stream() + .filter(node->node.getClassification()!=null).findFirst(); + Optional classificationOptional = first.map(node->node.getClassification()); + if(classificationOptional.isPresent()){ + classification = classificationOptional.get(); + Taxon taxon = (Taxon) taxonService.load(description.getTaxon().getId(), Arrays.asList("taxonNodes", "taxonNodes.classification")); + taxonNode = taxon.getTaxonNode(classification); + } + return new TaxonRowWrapperDTO(description, taxonNode); } - private RowWrapperDTO createRowWrapper(SpecimenOrObservationBase specimen, DescriptionBase description, TaxonNode taxonNode, DescriptiveDataSet descriptiveDataSet){ - if(description!=null){ - specimen = description.getDescribedSpecimenOrObservation(); - } + @Override + public SpecimenRowWrapperDTO createSpecimenRowWrapper(SpecimenDescription description, DescriptiveDataSet descriptiveDataSet, + boolean createDefaultTaxonDescription){ + SpecimenOrObservationBase specimen = description.getDescribedSpecimenOrObservation(); + TaxonNode taxonNode = null; FieldUnit fieldUnit = null; String identifier = null; NamedArea country = null; //supplemental information - if(specimen!=null){ - if(taxonNode==null){ - Collection> associatedTaxa = occurrenceService.listAssociatedTaxa(specimen, null, null, null, - Arrays.asList(new String[]{ - "taxonNodes", - "taxonNodes.classification", - })); - if(associatedTaxa!=null && !associatedTaxa.isEmpty()){ - //FIXME: what about multiple associated taxa - Set taxonSubtreeFilter = descriptiveDataSet.getTaxonSubtreeFilter(); - if(taxonSubtreeFilter!=null && !taxonSubtreeFilter.isEmpty()){ - Taxon taxon = HibernateProxyHelper.deproxy(associatedTaxa.iterator().next(), Taxon.class); - taxonNode = taxon.getTaxonNode(taxonSubtreeFilter.iterator().next().getClassification()); - } - } - } - Collection fieldUnits = occurrenceService.findFieldUnits(specimen.getUuid(), - Arrays.asList(new String[]{ - "gatheringEvent", - "gatheringEvent.country" - })); - if(fieldUnits.size()!=1){ - logger.error("More than one or no field unit found for specimen"); //$NON-NLS-1$ + //get taxon node + Set taxonSubtreeFilter = descriptiveDataSet.getTaxonSubtreeFilter(); + for (TaxonNode node : taxonSubtreeFilter) { + //check for node + node = taxonNodeService.load(node.getId(), Arrays.asList("taxon")); + taxonNode = findTaxonNodeForDescription(node, specimen); + if(taxonNode!=null){ + break; } else{ - fieldUnit = fieldUnits.iterator().next(); - } - if(specimen instanceof DerivedUnit){ - identifier = occurrenceService.getMostSignificantIdentifier(HibernateProxyHelper.deproxy(specimen, DerivedUnit.class)); - } - if(fieldUnit!=null && fieldUnit.getGatheringEvent()!=null){ - country = fieldUnit.getGatheringEvent().getCountry(); + //check for child nodes + List allChildren = taxonNodeService.loadChildNodesOfTaxonNode(node, Arrays.asList("taxon"), true, true, null); + for (TaxonNode child : allChildren) { + taxonNode = findTaxonNodeForDescription(child, specimen); + if(taxonNode!=null){ + break; + } + } } } - return new RowWrapperDTO(description, specimen, taxonNode, fieldUnit, identifier, country); + if(taxonNode==null){ + return null; + } + //taxon node was found + + //get field unit + Collection fieldUnits = occurrenceService.findFieldUnits(specimen.getUuid(), + Arrays.asList(new String[]{ + "gatheringEvent", + "gatheringEvent.country" + })); + if(fieldUnits.size()!=1){ + logger.error("More than one or no field unit found for specimen"); //$NON-NLS-1$ + return null; + } + else{ + fieldUnit = fieldUnits.iterator().next(); + } + //get identifier + if(specimen instanceof DerivedUnit){ + identifier = occurrenceService.getMostSignificantIdentifier(HibernateProxyHelper.deproxy(specimen, DerivedUnit.class)); + } + //get country + if(fieldUnit!=null && fieldUnit.getGatheringEvent()!=null){ + country = fieldUnit.getGatheringEvent().getCountry(); + } + //get default taxon description + TaxonDescription defaultTaxonDescription = findDefaultTaxonDescription(descriptiveDataSet.getUuid(), + taxonNode.getUuid(), createDefaultTaxonDescription); + TaxonRowWrapperDTO taxonRowWrapper = defaultTaxonDescription != null + ? createTaxonRowWrapper(defaultTaxonDescription, descriptiveDataSet) : null; + return new SpecimenRowWrapperDTO(description, taxonNode, fieldUnit, identifier, country, taxonRowWrapper); } @Override @@ -196,7 +258,41 @@ public class DescriptiveDataSetService } @Override - public SpecimenDescription findDescriptionForDescriptiveDataSet(UUID descriptiveDataSetUuid, UUID specimenUuid){ + public TaxonDescription findDefaultTaxonDescription(UUID descriptiveDataSetUuid, UUID taxonNodeUuid, boolean create){ + DescriptiveDataSet dataSet = load(descriptiveDataSetUuid); + TaxonNode taxonNode = taxonNodeService.load(taxonNodeUuid, Arrays.asList("taxon", "taxon.descriptions", "taxon.descriptions.markers")); + Set dataSetDescriptions = dataSet.getDescriptions(); + //filter out COMPUTED descriptions + List nonComputedDescriptions = taxonNode.getTaxon().getDescriptions().stream() + .filter(desc -> desc.getMarkers().stream() + .anyMatch(marker -> marker.getMarkerType().equals(MarkerType.COMPUTED()))) + .collect(Collectors.toList()); + for (TaxonDescription taxonDescription : nonComputedDescriptions) { + for (DescriptionBase description : dataSetDescriptions) { + if(description.getUuid().equals(taxonDescription.getUuid())){ + return taxonDescription; + } + } + } + if(!create){ + return null; + } + //description not yet added to dataset -> create a new one + TaxonDescription newTaxonDescription = TaxonDescription.NewInstance(taxonNode.getTaxon()); + newTaxonDescription.setTitleCache("Dataset "+dataSet.getLabel()+": "+newTaxonDescription.generateTitle(), true); //$NON-NLS-2$ + dataSet.getDescriptiveSystem().getDistinctFeatures().forEach(wsFeature->{ + if(wsFeature.isSupportsCategoricalData()){ + newTaxonDescription.addElement(CategoricalData.NewInstance(wsFeature)); + } + else if(wsFeature.isSupportsQuantitativeData()){ + newTaxonDescription.addElement(QuantitativeData.NewInstance(wsFeature)); + } + }); + return newTaxonDescription; + } + + @Override + public SpecimenDescription findSpecimenDescription(UUID descriptiveDataSetUuid, UUID specimenUuid){ DescriptiveDataSet dataSet = load(descriptiveDataSetUuid); SpecimenOrObservationBase specimen = occurrenceService.load(specimenUuid); @@ -304,12 +400,21 @@ public class DescriptiveDataSetService } + //TODO: this should either be solved in the model class itself + //OR this should cover all possibilities including modifiers for example private class DescriptionElementCompareWrapper { private DescriptionElementBase element; private Set stateUuids = new HashSet<>(); - private Float min = null; - private Float max = null; + private Set avgs = new HashSet<>(); + private Set exacts = new HashSet<>(); + private Set maxs = new HashSet<>(); + private Set mins = new HashSet<>(); + private Set sampleSizes = new HashSet<>(); + private Set standardDevs = new HashSet<>(); + private Set lowerBounds = new HashSet<>(); + private Set upperBounds = new HashSet<>(); + private Set variances = new HashSet<>(); public DescriptionElementCompareWrapper(DescriptionElementBase element) { this.element = element; @@ -319,22 +424,57 @@ public class DescriptiveDataSetService } else if(element.isInstanceOf(QuantitativeData.class)){ QuantitativeData elementData = (QuantitativeData)element; - min = elementData.getMin(); - max = elementData.getMax(); - } - } + elementData.getStatisticalValues().forEach(value->{ + if(value.getType().equals(StatisticalMeasure.AVERAGE())){ + avgs.add(value.getValue()); + } + else if(value.getType().equals(StatisticalMeasure.EXACT_VALUE())){ + exacts.add(value.getValue()); + + } + else if(value.getType().equals(StatisticalMeasure.MAX())){ + maxs.add(value.getValue()); + } + else if(value.getType().equals(StatisticalMeasure.MIN())){ + mins.add(value.getValue()); + } + else if(value.getType().equals(StatisticalMeasure.SAMPLE_SIZE())){ + sampleSizes.add(value.getValue()); - public DescriptionElementBase unwrap() { - return element; + } + else if(value.getType().equals(StatisticalMeasure.STANDARD_DEVIATION())){ + standardDevs.add(value.getValue()); + } + else if(value.getType().equals(StatisticalMeasure.TYPICAL_LOWER_BOUNDARY())){ + lowerBounds.add(value.getValue()); + + } + else if(value.getType().equals(StatisticalMeasure.TYPICAL_UPPER_BOUNDARY())){ + upperBounds.add(value.getValue()); + } + else if(value.getType().equals(StatisticalMeasure.VARIANCE())){ + variances.add(value.getValue()); + } + }); + } } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((max == null) ? 0 : max.hashCode()); - result = prime * result + ((min == null) ? 0 : min.hashCode()); + result = prime * result + getOuterType().hashCode(); + result = prime * result + ((avgs == null) ? 0 : avgs.hashCode()); + result = prime * result + ((element == null) ? 0 : element.hashCode()); + result = prime * result + ((exacts == null) ? 0 : exacts.hashCode()); + result = prime * result + ((lowerBounds == null) ? 0 : lowerBounds.hashCode()); + result = prime * result + ((maxs == null) ? 0 : maxs.hashCode()); + result = prime * result + ((mins == null) ? 0 : mins.hashCode()); + result = prime * result + ((sampleSizes == null) ? 0 : sampleSizes.hashCode()); + result = prime * result + ((standardDevs == null) ? 0 : standardDevs.hashCode()); result = prime * result + ((stateUuids == null) ? 0 : stateUuids.hashCode()); + result = prime * result + ((upperBounds == null) ? 0 : upperBounds.hashCode()); + result = prime * result + ((variances == null) ? 0 : variances.hashCode()); return result; } @@ -350,18 +490,63 @@ public class DescriptiveDataSetService return false; } DescriptionElementCompareWrapper other = (DescriptionElementCompareWrapper) obj; - if (max == null) { - if (other.max != null) { + if (!getOuterType().equals(other.getOuterType())) { + return false; + } + if (avgs == null) { + if (other.avgs != null) { return false; } - } else if (!max.equals(other.max)) { + } else if (!avgs.equals(other.avgs)) { return false; } - if (min == null) { - if (other.min != null) { + if (element == null) { + if (other.element != null) { return false; } - } else if (!min.equals(other.min)) { + } else if (!element.equals(other.element)) { + return false; + } + if (exacts == null) { + if (other.exacts != null) { + return false; + } + } else if (!exacts.equals(other.exacts)) { + return false; + } + if (lowerBounds == null) { + if (other.lowerBounds != null) { + return false; + } + } else if (!lowerBounds.equals(other.lowerBounds)) { + return false; + } + if (maxs == null) { + if (other.maxs != null) { + return false; + } + } else if (!maxs.equals(other.maxs)) { + return false; + } + if (mins == null) { + if (other.mins != null) { + return false; + } + } else if (!mins.equals(other.mins)) { + return false; + } + if (sampleSizes == null) { + if (other.sampleSizes != null) { + return false; + } + } else if (!sampleSizes.equals(other.sampleSizes)) { + return false; + } + if (standardDevs == null) { + if (other.standardDevs != null) { + return false; + } + } else if (!standardDevs.equals(other.standardDevs)) { return false; } if (stateUuids == null) { @@ -371,8 +556,27 @@ public class DescriptiveDataSetService } else if (!stateUuids.equals(other.stateUuids)) { return false; } + if (upperBounds == null) { + if (other.upperBounds != null) { + return false; + } + } else if (!upperBounds.equals(other.upperBounds)) { + return false; + } + if (variances == null) { + if (other.variances != null) { + return false; + } + } else if (!variances.equals(other.variances)) { + return false; + } return true; } + + private DescriptiveDataSetService getOuterType() { + return DescriptiveDataSetService.this; + } + } }