X-Git-Url: https://dev.e-taxonomy.eu/gitweb/cdmlib.git/blobdiff_plain/39d18e25817e6e2f158d07c9c228df22262dcc33..e1c0af0a692e6a2d9668ea7096e2b04665c0d590:/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TaxonServiceImpl.java?ds=sidebyside diff --git a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TaxonServiceImpl.java b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TaxonServiceImpl.java index fad4d77910..dcb0b8f279 100644 --- a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TaxonServiceImpl.java +++ b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TaxonServiceImpl.java @@ -21,6 +21,8 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import javax.persistence.EntityNotFoundException; + import org.apache.log4j.Logger; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.queryParser.ParseException; @@ -35,11 +37,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase; import eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator; +import eu.etaxonomy.cdm.api.service.config.IncludedTaxonConfiguration; import eu.etaxonomy.cdm.api.service.config.MatchingTaxonConfigurator; import eu.etaxonomy.cdm.api.service.config.SynonymDeletionConfigurator; import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator; import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator.ChildHandling; +import eu.etaxonomy.cdm.api.service.dto.IncludedTaxaDTO; import eu.etaxonomy.cdm.api.service.exception.DataChangeNoRollbackException; import eu.etaxonomy.cdm.api.service.exception.HomotypicalGroupChangeException; import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException; @@ -62,7 +67,6 @@ import eu.etaxonomy.cdm.hibernate.search.GroupByTaxonClassBridge; import eu.etaxonomy.cdm.hibernate.search.MultilanguageTextFieldBridge; import eu.etaxonomy.cdm.model.CdmBaseType; import eu.etaxonomy.cdm.model.common.CdmBase; -import eu.etaxonomy.cdm.model.common.ITreeNode; import eu.etaxonomy.cdm.model.common.IdentifiableEntity; import eu.etaxonomy.cdm.model.common.IdentifiableSource; import eu.etaxonomy.cdm.model.common.Language; @@ -92,13 +96,16 @@ 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.HomotypicalGroup; +import eu.etaxonomy.cdm.model.name.NameRelationship; import eu.etaxonomy.cdm.model.name.Rank; import eu.etaxonomy.cdm.model.name.TaxonNameBase; import eu.etaxonomy.cdm.model.name.ZoologicalName; import eu.etaxonomy.cdm.model.occurrence.DerivedUnit; +import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent; import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase; import eu.etaxonomy.cdm.model.reference.Reference; import eu.etaxonomy.cdm.model.taxon.Classification; +import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode; import eu.etaxonomy.cdm.model.taxon.Synonym; import eu.etaxonomy.cdm.model.taxon.SynonymRelationship; import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType; @@ -112,6 +119,7 @@ import eu.etaxonomy.cdm.persistence.dao.common.IOrderedTermVocabularyDao; import eu.etaxonomy.cdm.persistence.dao.initializer.AbstractBeanInitializer; import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao; import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao; +import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao; import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao; import eu.etaxonomy.cdm.persistence.fetch.CdmFetch; import eu.etaxonomy.cdm.persistence.query.MatchMode; @@ -146,7 +154,6 @@ public class TaxonServiceImpl extends IdentifiableServiceBase getAllSynonyms(int limit, int start) { - return dao.getAllSynonyms(limit, start); - } - - /** - * FIXME Candidate for harmonization - * list(Taxon.class, ...) - * (non-Javadoc) - * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int) - */ - @Override - public List getAllTaxa(int limit, int start) { - return dao.getAllTaxa(limit, start); - } - /** * FIXME Candidate for harmonization * merge with getRootTaxa(Reference sec, ..., ...) @@ -217,18 +205,11 @@ public class TaxonServiceImpl extends IdentifiableServiceBase getRootTaxa(Rank rank, Reference sec, boolean onlyWithChildren,boolean withMisapplications, List propertyPaths) { return dao.getRootTaxa(rank, sec, null, onlyWithChildren, withMisapplications, propertyPaths); } - /* (non-Javadoc) - * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllRelationships(int, int) - */ @Override public List getAllRelationships(int limit, int start){ return dao.getAllRelationships(limit, start); @@ -295,10 +276,12 @@ public class TaxonServiceImpl extends IdentifiableServiceBase heteroSynonyms = acceptedTaxon.getSynonymsInGroup(synonymHomotypicGroup); + Set basionymsAndReplacedSynonyms = synonymHomotypicGroup.getBasionymAndReplacedSynonymRelations(); for (Synonym heteroSynonym : heteroSynonyms){ if (synonym.equals(heteroSynonym)){ acceptedTaxon.removeSynonym(heteroSynonym, false); + }else{ //move synonyms in same homotypic group to new accepted taxon heteroSynonym.replaceAcceptedTaxon(newAcceptedTaxon, relTypeForGroup, copyCitationInfo, citation, microCitation); @@ -311,7 +294,9 @@ public class TaxonServiceImpl extends IdentifiableServiceBase synonymName = synonym.getName(); - // remove synonym from taxon + /* // remove synonym from taxon toTaxon.removeSynonym(synonym); - +*/ // Create a taxon with synonym name Taxon fromTaxon = Taxon.NewInstance(synonymName, null); @@ -339,7 +324,8 @@ public class TaxonServiceImpl extends IdentifiableServiceBase(pageNumber, numberOfResults, pageSize, results); } + @Override + public List listAcceptedTaxaFor(UUID synonymUuid, UUID classificationUuid, Integer pageSize, Integer pageNumber, + List orderHints, List propertyPaths){ + return pageAcceptedTaxaFor(synonymUuid, classificationUuid, pageSize, pageNumber, orderHints, propertyPaths).getRecords(); + } + + @Override + public Pager pageAcceptedTaxaFor(UUID synonymUuid, UUID classificationUuid, Integer pageSize, Integer pageNumber, + List orderHints, List propertyPaths){ + + List list = new ArrayList(); + Long count = 0l; + + Synonym synonym = null; + + try { + synonym = (Synonym) dao.load(synonymUuid); + } catch (ClassCastException e){ + throw new EntityNotFoundException("The TaxonBase entity referenced by " + synonymUuid + " is not a Synonmy"); + } catch (NullPointerException e){ + throw new EntityNotFoundException("No TaxonBase entity found for " + synonymUuid); + } + + Classification classificationFilter = null; + if(classificationUuid != null){ + try { + classificationFilter = classificationDao.load(classificationUuid); + } catch (NullPointerException e){ + throw new EntityNotFoundException("No Classification entity found for " + classificationUuid); + } + if(classificationFilter == null){ + + } + } + + count = dao.countAcceptedTaxaFor(synonym, classificationFilter) ; + if(count > (pageSize * pageNumber)){ + list = dao.listAcceptedTaxaFor(synonym, classificationFilter, pageSize, pageNumber, orderHints, propertyPaths); + } + + return new DefaultPagerImpl(pageNumber, count.intValue(), pageSize, list); + } + + /** * @param taxon * @param includeRelationships @@ -549,6 +579,10 @@ public class TaxonServiceImpl extends IdentifiableServiceBase(pageNumber, numberOfResults, pageSize, results); } + /* (non-Javadoc) + * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List) + */ + @Override + public List> getSynonymsByHomotypicGroup(Taxon taxon, List propertyPaths){ + List> result = new ArrayList>(); + Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths); + + //homotypic + result.add(t.getHomotypicSynonymsByHomotypicGroup()); + + //heterotypic + List homotypicalGroups = t.getHeterotypicSynonymyGroups(); + for(HomotypicalGroup homotypicalGroup : homotypicalGroups){ + result.add(t.getSynonymsInGroup(homotypicalGroup)); + } + + return result; + + } + /* (non-Javadoc) * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List) */ @@ -737,10 +792,8 @@ public class TaxonServiceImpl extends IdentifiableServiceBase configurator.getPageSize() * configurator.getPageNumber()){ - List commonNameResults = dao.getTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath()); - for( Object[] entry : commonNameResults ) { - taxa.add((TaxonBase) entry[0]); - } + List commonNameResults = dao.getTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath()); + taxa.addAll(commonNameResults); } if(taxa != null){ results.addAll(taxa); @@ -796,21 +849,26 @@ public class TaxonServiceImpl extends IdentifiableServiceBase propertyPath) { + logger.trace("listMedia() - START"); + Set taxa = new HashSet(); List taxonMedia = new ArrayList(); + List nonImageGalleryImages = new ArrayList(); if (limitToGalleries == null) { limitToGalleries = false; } // --- resolve related taxa - if (includeRelationships != null) { + if (includeRelationships != null && ! includeRelationships.isEmpty()) { + logger.trace("listMedia() - resolve related taxa"); taxa = listRelatedTaxa(taxon, includeRelationships, null, null, null, null); } taxa.add((Taxon) dao.load(taxon.getUuid())); if(includeTaxonDescriptions != null && includeTaxonDescriptions){ + logger.trace("listMedia() - includeTaxonDescriptions"); List taxonDescriptions = new ArrayList(); // --- TaxonDescriptions for (Taxon t : taxa) { @@ -820,14 +878,23 @@ public class TaxonServiceImpl extends IdentifiableServiceBase specimensOrObservations = new HashSet(); // --- Specimens for (Taxon t : taxa) { @@ -881,6 +948,7 @@ public class TaxonServiceImpl extends IdentifiableServiceBase nameDescriptions = new HashSet(); for (Taxon t : taxa) { @@ -898,7 +966,12 @@ public class TaxonServiceImpl extends IdentifiableServiceBase referencedObjects = isDeletable(taxon, config); + + if (referencedObjects.isEmpty()){ // --- DeleteSynonymRelations if (config.isDeleteSynonymRelations()){ boolean removeSynonymNameFromHomotypicalGroup = false; @@ -981,7 +1058,7 @@ public class TaxonServiceImpl extends IdentifiableServiceBase 0){ String message = "Taxon can't be deleted as it is related to another taxon. " + "Remove taxon from all relations to other taxa prior to deletion."; - throw new ReferencedObjectUndeletableException(message); + // throw new ReferencedObjectUndeletableException(message); } } else{ for (TaxonRelationship taxRel: taxon.getTaxonRelations()){ @@ -1013,32 +1090,36 @@ public class TaxonServiceImpl extends IdentifiableServiceBase descriptions = taxon.getDescriptions(); - + List removeDescriptions = new ArrayList(); for (TaxonDescription desc: descriptions){ //TODO use description delete configurator ? //FIXME check if description is ALWAYS deletable if (desc.getDescribedSpecimenOrObservation() != null){ String message = "Taxon can't be deleted as it is used in a TaxonDescription" + " which also describes specimens or abservations"; - throw new ReferencedObjectUndeletableException(message); + //throw new ReferencedObjectUndeletableException(message); } + removeDescriptions.add(desc); descriptionService.delete(desc); + + } + for (TaxonDescription desc: removeDescriptions){ taxon.removeDescription(desc); } } - //check references with only reverse mapping + /* //check references with only reverse mapping String message = checkForReferences(taxon); if (message != null){ - throw new ReferencedObjectUndeletableException(message.toString()); - } + //throw new ReferencedObjectUndeletableException(message.toString()); + }*/ if (! config.isDeleteTaxonNodes() || (!config.isDeleteInAllClassifications() && classification == null )){ - if (taxon.getTaxonNodes().size() > 0){ - message = "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion or define a classification where it should be deleted or adapt the taxon deletion configurator."; - throw new ReferencedObjectUndeletableException(message); - } + //if (taxon.getTaxonNodes().size() > 0){ + // message = "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion or define a classification where it should be deleted or adapt the taxon deletion configurator."; + // throw new ReferencedObjectUndeletableException(message); + //} }else{ if (taxon.getTaxonNodes().size() != 0){ Set nodes = taxon.getTaxonNodes(); @@ -1063,14 +1144,14 @@ public class TaxonServiceImpl extends IdentifiableServiceBase nodesList = new HashSet(); + Set nodesList = new HashSet(); nodesList.addAll(taxon.getTaxonNodes()); - for (ITreeNode treeNode: nodesList){ + for (ITaxonTreeNode treeNode: nodesList){ TaxonNode taxonNode = (TaxonNode) treeNode; if(!deleteChildren){ /* Object[] childNodes = taxonNode.getChildNodes().toArray(); @@ -1098,33 +1179,47 @@ public class TaxonServiceImpl extends IdentifiableServiceBase exceptions = new ArrayList(); + for (String message: referencedObjects){ + ReferencedObjectUndeletableException exception = new ReferencedObjectUndeletableException(message); + exceptions.add(exception); + } + result.addExceptions(exceptions); + result.setError(); + } + return result; } @@ -1170,22 +1279,39 @@ public class TaxonServiceImpl extends IdentifiableServiceBase list = genericDao.getCdmBasesByFieldAndClass(PolytomousKeyNode.class, "taxon", taxon); + if (!list.isEmpty()) { + result = true; + } + return result; + } + @Transactional(readOnly = false) public UUID delete(Synonym syn){ UUID result = syn.getUuid(); @@ -1193,13 +1319,15 @@ public class TaxonServiceImpl extends IdentifiableServiceBase messages = isDeletable(synonym, config); - //remove synonymRelationship - Set taxonSet = new HashSet(); - if (taxon != null){ - taxonSet.add(taxon); - }else{ - taxonSet.addAll(synonym.getAcceptedTaxa()); - } - for (Taxon relatedTaxon : taxonSet){ -// dao.deleteSynonymRelationships(synonym, relatedTaxon); - relatedTaxon.removeSynonym(synonym, config.isNewHomotypicGroupIfNeeded()); - } - this.saveOrUpdate(synonym); - //TODO remove name from homotypical group? + if (messages.isEmpty()){ + synonym = CdmBase.deproxy(dao.merge(synonym), Synonym.class); - //remove synonym (if necessary) + //remove synonymRelationship + Set taxonSet = new HashSet(); + if (taxon != null){ + taxonSet.add(taxon); + }else{ + taxonSet.addAll(synonym.getAcceptedTaxa()); + } + for (Taxon relatedTaxon : taxonSet){ + // dao.deleteSynonymRelationships(synonym, relatedTaxon); + relatedTaxon.removeSynonym(synonym, config.isNewHomotypicGroupIfNeeded()); + } + this.saveOrUpdate(synonym); + //TODO remove name from homotypical group? - if (synonym.getSynonymRelations().isEmpty()){ - TaxonNameBase name = synonym.getName(); - synonym.setName(null); - dao.delete(synonym); + //remove synonym (if necessary) + + UUID uuid = null; + if (synonym.getSynonymRelations().isEmpty()){ + TaxonNameBase name = synonym.getName(); + synonym.setName(null); + uuid = dao.delete(synonym); + + //remove name if possible (and required) + if (name != null && config.isDeleteNameIfPossible()){ + + nameService.delete(name, config.getNameDeletionConfig()); - //remove name if possible (and required) - if (name != null && config.isDeleteNameIfPossible()){ - try{ - nameService.delete(name, config.getNameDeletionConfig()); - }catch (ReferencedObjectUndeletableException ex){ - if (logger.isDebugEnabled()) { - logger.debug("Name wasn't deleted as it is referenced"); - } } + + }else { + result.setError(); + result.addException(new ReferencedObjectUndeletableException("Synonym can not be deleted it is used in a synonymRelationship.")); + return result; } + + return result; + }else{ + List exceptions = new ArrayList(); + for (String message :messages){ + exceptions.add(new ReferencedObjectUndeletableException(message)); + } + result.setError(); + result.addExceptions(exceptions); + return result; } + + } @@ -2263,7 +2412,7 @@ public class TaxonServiceImpl extends IdentifiableServiceBase nodes = taxon.getTaxonNodes(); - List taxonNames = new ArrayList(); + List taxonNames = new ArrayList(); for (TaxonNode node: nodes){ // HashMap synonymsGenus = new HashMap(); // Changed this to be able to store the idInSource to a genusName @@ -2616,8 +2765,6 @@ public class TaxonServiceImpl extends IdentifiableServiceBase listClassifications(TaxonBase taxonBase, Integer limit, Integer start, List propertyPaths) { @@ -2904,9 +3044,257 @@ public class TaxonServiceImpl extends IdentifiableServiceBase synonymName = fromTaxon.getName(); + Synonym synonym = Synonym.NewInstance(synonymName, fromTaxon.getSec()); + + // Remove concept relation from taxon + toTaxon.removeTaxon(fromTaxon, oldRelationshipType); + + + + + // Create a new synonym for the taxon + SynonymRelationship synonymRelationship; + if (synonymRelationshipType != null + && synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){ + synonymRelationship = toTaxon.addHomotypicSynonym(synonym, null, null); + } else{ + synonymRelationship = toTaxon.addHeterotypicSynonymName(synonymName); + } + + this.saveOrUpdate(toTaxon); + //TODO: configurator and classification + TaxonDeletionConfigurator config = new TaxonDeletionConfigurator(); + config.setDeleteNameIfPossible(false); + this.deleteTaxon(fromTaxon, config, null); + return synonymRelationship.getSynonym(); + + } + @Override + public List isDeletable(TaxonBase taxonBase, DeleteConfiguratorBase config){ + List result = new ArrayList(); + Set references = commonService.getReferencingObjectsForDeletion(taxonBase); + if (taxonBase instanceof Taxon){ + TaxonDeletionConfigurator taxonConfig = (TaxonDeletionConfigurator) config; + result = isDeletableForTaxon(references, taxonConfig); + }else{ + SynonymDeletionConfigurator synonymConfig = (SynonymDeletionConfigurator) config; + result = isDeletableForSynonym(references, synonymConfig); + } + return result; + } + + private List isDeletableForSynonym(Set references, SynonymDeletionConfigurator config){ + String message; + List result = new ArrayList(); + for (CdmBase ref: references){ + if (!(ref instanceof SynonymRelationship || ref instanceof Taxon || ref instanceof TaxonNameBase )){ + message = "The Synonym can't be deleted as long as it is referenced by " + ref.getClass().getSimpleName() + " with id "+ ref.getId(); + result.add(message); + } + } + + return result; + } + private List isDeletableForTaxon(Set references, TaxonDeletionConfigurator config){ + String message; + List result = new ArrayList(); + for (CdmBase ref: references){ + if (!(ref instanceof TaxonNameBase)){ + if (!config.isDeleteSynonymRelations() && (ref instanceof SynonymRelationship)){ + message = "The Taxon can't be deleted as long as it has synonyms."; + result.add(message); + } + if (!config.isDeleteDescriptions() && (ref instanceof DescriptionBase)){ + message = "The Taxon can't be deleted as long as it has factual data."; + result.add(message); + } + + if (!config.isDeleteTaxonNodes() && (ref instanceof TaxonNode)){ + message = "The Taxon can't be deleted as long as it belongs to a taxon node."; + result.add(message); + } + if (!config.isDeleteTaxonRelationships() && (ref instanceof TaxonNode)){ + if (!config.isDeleteMisappliedNamesAndInvalidDesignations() && (((TaxonRelationship)ref).getType().equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())|| ((TaxonRelationship)ref).getType().equals(TaxonRelationshipType.INVALID_DESIGNATION_FOR()))){ + message = "The Taxon can't be deleted as long as it has misapplied names or invalid designations."; + result.add(message); + } else{ + message = "The Taxon can't be deleted as long as it belongs to a taxon node."; + result.add(message); + } + } + if (ref instanceof PolytomousKeyNode){ + message = "The Taxon can't be deleted as long as it is referenced by a polytomous key node."; + result.add(message); + } + + if (HibernateProxyHelper.isInstanceOf(ref, IIdentificationKey.class)){ + message = "Taxon can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name"; + result.add(message); + + } + + /* //PolytomousKeyNode + if (referencingObject.isInstanceOf(PolytomousKeyNode.class)){ + String message = "Taxon" + taxon.getTitleCache() + " can't be deleted as it is used in polytomous key node"; + return message; + }*/ + //TaxonInteraction + if (ref.isInstanceOf(TaxonInteraction.class)){ + message = "Taxon can't be deleted as it is used in taxonInteraction#taxon2"; + result.add(message); + } + //TaxonInteraction + if (ref.isInstanceOf(DeterminationEvent.class)){ + message = "Taxon can't be deleted as it is used in a determination event"; + result.add(message); + } + + } + + } + + return result; + } + + @Override + public IncludedTaxaDTO listIncludedTaxa(UUID taxonUuid, IncludedTaxonConfiguration config) { + IncludedTaxaDTO result = new IncludedTaxaDTO(taxonUuid); + + //preliminary implementation + + Set taxa = new HashSet(); + TaxonBase taxonBase = find(taxonUuid); + if (taxonBase == null){ + return new IncludedTaxaDTO(); + }else if (taxonBase.isInstanceOf(Taxon.class)){ + Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class); + taxa.add(taxon); + }else if (taxonBase.isInstanceOf(Synonym.class)){ + //TODO partial synonyms ?? + //TODO synonyms in general + Synonym syn = CdmBase.deproxy(taxonBase, Synonym.class); + taxa.addAll(syn.getAcceptedTaxa()); + }else{ + throw new IllegalArgumentException("Unhandled class " + taxonBase.getClass().getSimpleName()); + } + + Set related = makeRelatedIncluded(taxa, result, config); + int i = 0; + while((! related.isEmpty()) && i++ < 100){ //to avoid + related = makeRelatedIncluded(related, result, config); + } + + return result; + } + + /** + * Computes all children and conceptually congruent and included taxa and adds them to the existingTaxa + * data structure. + * @return the set of conceptually related taxa for further use + */ + /** + * @param uncheckedTaxa + * @param existingTaxa + * @param config + * @return + */ + private Set makeRelatedIncluded(Set uncheckedTaxa, IncludedTaxaDTO existingTaxa, IncludedTaxonConfiguration config) { + + //children + Set taxonNodes = new HashSet(); + for (Taxon taxon: uncheckedTaxa){ + taxonNodes.addAll(taxon.getTaxonNodes()); + } + + Set children = new HashSet(); + if (! config.onlyCongruent){ + for (TaxonNode node: taxonNodes){ + List childNodes = nodeService.loadChildNodesOfTaxonNode(node, null, true, false); + for (TaxonNode child : childNodes){ + children.add(child.getTaxon()); + } + } + children.remove(null); // just to be on the save side + } + + Iterator it = children.iterator(); + while(it.hasNext()){ + UUID uuid = it.next().getUuid(); + if (existingTaxa.contains(uuid)){ + it.remove(); + }else{ + existingTaxa.addIncludedTaxon(uuid, new ArrayList(), false); + } + } + + //concept relations + Set uncheckedAndChildren = new HashSet(uncheckedTaxa); + uncheckedAndChildren.addAll(children); + + Set relatedTaxa = makeConceptIncludedTaxa(uncheckedAndChildren, existingTaxa, config); + + + Set result = new HashSet(relatedTaxa); + return result; + } + + /** + * Computes all conceptually congruent or included taxa and adds them to the existingTaxa data structure. + * @return the set of these computed taxa + */ + private Set makeConceptIncludedTaxa(Set unchecked, IncludedTaxaDTO existingTaxa, IncludedTaxonConfiguration config) { + Set result = new HashSet(); + + for (Taxon taxon : unchecked){ + Set fromRelations = taxon.getRelationsFromThisTaxon(); + Set toRelations = taxon.getRelationsToThisTaxon(); + + for (TaxonRelationship fromRel : fromRelations){ + if (config.includeDoubtful == false && fromRel.isDoubtful()){ + continue; + } + if (fromRel.getType().equals(TaxonRelationshipType.CONGRUENT_TO()) || + !config.onlyCongruent && fromRel.getType().equals(TaxonRelationshipType.INCLUDES()) || + !config.onlyCongruent && fromRel.getType().equals(TaxonRelationshipType.CONGRUENT_OR_INCLUDES()) + ){ + result.add(fromRel.getToTaxon()); + } + } + + for (TaxonRelationship toRel : toRelations){ + if (config.includeDoubtful == false && toRel.isDoubtful()){ + continue; + } + if (toRel.getType().equals(TaxonRelationshipType.CONGRUENT_TO())){ + result.add(toRel.getFromTaxon()); + } + } + } + + Iterator it = result.iterator(); + while(it.hasNext()){ + UUID uuid = it.next().getUuid(); + if (existingTaxa.contains(uuid)){ + it.remove(); + }else{ + existingTaxa.addIncludedTaxon(uuid, new ArrayList(), false); + } + } + return result; + } + @Override + public List findTaxaByName(MatchingTaxonConfigurator config){ + List taxonList = dao.getTaxaByName(true, false, false, config.getTaxonNameTitle(), null, MatchMode.EXACT, null, 0, 0, config.getPropertyPath()); + return taxonList; + } }