-// $Id$\r
-/**\r
-* Copyright (C) 2007 EDIT\r
-* European Distributed Institute of Taxonomy\r
-* http://www.e-taxonomy.eu\r
-*\r
-* The contents of this file are subject to the Mozilla Public License Version 1.1\r
-* See LICENSE.TXT at the top of this package for the full license terms.\r
-*/\r
-\r
-package eu.etaxonomy.cdm.api.service;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.Comparator;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.UUID;\r
-\r
-import org.apache.log4j.Logger;\r
-import org.springframework.beans.factory.annotation.Autowired;\r
-import org.springframework.stereotype.Service;\r
-import org.springframework.transaction.annotation.Transactional;\r
-\r
-import eu.etaxonomy.cdm.api.service.UpdateResult.Status;\r
-import eu.etaxonomy.cdm.api.service.config.NodeDeletionConfigurator.ChildHandling;\r
-import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;\r
-import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator;\r
-import eu.etaxonomy.cdm.api.service.dto.CdmEntityIdentifier;\r
-import eu.etaxonomy.cdm.api.service.pager.Pager;\r
-import eu.etaxonomy.cdm.api.service.pager.PagerUtils;\r
-import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;\r
-import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;\r
-import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
-import eu.etaxonomy.cdm.model.name.HomotypicalGroup;\r
-import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
-import eu.etaxonomy.cdm.model.reference.Reference;\r
-import eu.etaxonomy.cdm.model.taxon.Classification;\r
-import eu.etaxonomy.cdm.model.taxon.Synonym;\r
-import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;\r
-import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;\r
-import eu.etaxonomy.cdm.model.taxon.Taxon;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonNaturalComparator;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonNode;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonNodeAgentRelation;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonNodeByNameComparator;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonNodeByRankAndNameComparator;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;\r
-import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;\r
-import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;\r
-import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;\r
-\r
-/**\r
- * @author n.hoffmann\r
- * @created Apr 9, 2010\r
- * @version 1.0\r
- */\r
-@Service\r
-@Transactional(readOnly = true)\r
-public class TaxonNodeServiceImpl extends AnnotatableServiceBase<TaxonNode, ITaxonNodeDao> implements ITaxonNodeService{\r
- private static final Logger logger = Logger.getLogger(TaxonNodeServiceImpl.class);\r
-\r
- @Autowired\r
- private IBeanInitializer defaultBeanInitializer;\r
-\r
- private final Comparator<? super TaxonNode> taxonNodeComparator = new TaxonNodeByNameComparator();\r
-\r
- @Autowired\r
- private ITaxonService taxonService;\r
-\r
- @Autowired\r
- private IClassificationService classService;\r
-\r
- @Autowired\r
- private IDefinedTermDao termDao;\r
-\r
- @Override\r
- public List<TaxonNode> loadChildNodesOfTaxonNode(TaxonNode taxonNode,\r
- List<String> propertyPaths, boolean recursive, NodeSortMode sortMode) {\r
- taxonNode = dao.load(taxonNode.getUuid());\r
- List<TaxonNode> childNodes;\r
- if (recursive == true){\r
- childNodes = dao.listChildrenOf(taxonNode, null, null, null, recursive);\r
- }else{\r
- childNodes = new ArrayList<TaxonNode>(taxonNode.getChildNodes());\r
- }\r
- if (sortMode != null){\r
- Comparator<TaxonNode> comparator = null;\r
- if (sortMode.equals(NodeSortMode.NaturalOrder)){\r
- comparator = new TaxonNaturalComparator();\r
- } else if (sortMode.equals(NodeSortMode.AlphabeticalOrder)){\r
- comparator = new TaxonNodeByNameComparator();\r
- } else if (sortMode.equals(NodeSortMode.RankAndAlphabeticalOrder)){\r
- comparator = new TaxonNodeByRankAndNameComparator();\r
- }\r
- Collections.sort(childNodes, comparator);\r
- }\r
- defaultBeanInitializer.initializeAll(childNodes, propertyPaths);\r
- return childNodes;\r
- }\r
-\r
- @Override\r
- @Autowired\r
- protected void setDao(ITaxonNodeDao dao) {\r
- this.dao = dao;\r
- }\r
-\r
- @Override\r
- @Transactional(readOnly = false)\r
- public DeleteResult makeTaxonNodeASynonymOfAnotherTaxonNode(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode, SynonymRelationshipType synonymRelationshipType, Reference citation, String citationMicroReference) {\r
-\r
-\r
- // TODO at the moment this method only moves synonym-, concept relations and descriptions to the new accepted taxon\r
- // in a future version we also want to move cdm data like annotations, marker, so., but we will need a policy for that\r
- if (oldTaxonNode == null || newAcceptedTaxonNode == null || oldTaxonNode.getTaxon().getName() == null){\r
- throw new IllegalArgumentException("A mandatory parameter was null.");\r
- }\r
-\r
- if(oldTaxonNode.equals(newAcceptedTaxonNode)){\r
- throw new IllegalArgumentException("Taxon can not be made synonym of its own.");\r
- }\r
-\r
-\r
- Classification classification = oldTaxonNode.getClassification();\r
- Taxon oldTaxon = (Taxon) HibernateProxyHelper.deproxy(oldTaxonNode.getTaxon());\r
- Taxon newAcceptedTaxon = (Taxon)this.taxonService.load(newAcceptedTaxonNode.getTaxon().getUuid());\r
- // Move oldTaxon to newTaxon\r
- //TaxonNameBase<?,?> synonymName = oldTaxon.getName();\r
- TaxonNameBase<?,?> synonymName = (TaxonNameBase)HibernateProxyHelper.deproxy(oldTaxon.getName());\r
- HomotypicalGroup group = synonymName.getHomotypicalGroup();\r
- group = HibernateProxyHelper.deproxy(group, HomotypicalGroup.class);\r
- if (synonymRelationshipType == null){\r
- if (synonymName.isHomotypic(newAcceptedTaxon.getName())){\r
- synonymRelationshipType = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();\r
- }else{\r
- synonymRelationshipType = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();\r
- }\r
- }\r
-\r
- //set homotypic group\r
- HomotypicalGroup newAcceptedTaxonHomotypicalgroup = newAcceptedTaxon.getHomotypicGroup();\r
- newAcceptedTaxonHomotypicalgroup = HibernateProxyHelper.deproxy(newAcceptedTaxonHomotypicalgroup, HomotypicalGroup.class);\r
- TaxonNameBase newAcceptedTaxonName = HibernateProxyHelper.deproxy(newAcceptedTaxon.getName(), TaxonNameBase.class);\r
- // Move Synonym Relations to new Taxon\r
- SynonymRelationship synonmyRelationship = newAcceptedTaxon.addSynonymName(synonymName,\r
- synonymRelationshipType, citation, citationMicroReference);\r
- HomotypicalGroup homotypicalGroupAcceptedTaxon = synonmyRelationship.getSynonym().getHomotypicGroup();\r
- // Move Synonym Relations to new Taxon\r
- // From ticket 3163 we can move taxon with accepted name having homotypic synonyms\r
- List<Synonym> synonymsInHomotypicalGroup = null;\r
-\r
- //the synonyms of the homotypical group of the old taxon\r
- if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){\r
- synonymsInHomotypicalGroup = oldTaxon.getSynonymsInGroup(group);\r
- }\r
-\r
- for(SynonymRelationship synRelation : oldTaxon.getSynonymRelations()){\r
- SynonymRelationshipType srt;\r
- if(synRelation.getSynonym().getName().getHomotypicalGroup()!= null\r
- && synRelation.getSynonym().getName().getHomotypicalGroup().equals(newAcceptedTaxonName.getHomotypicalGroup())) {\r
- srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();\r
- } else if(synRelation.getType() != null && synRelation.getType().equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())) {\r
- if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){\r
- srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();\r
- } else{\r
- srt = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();\r
- }\r
- } else {\r
- srt = synRelation.getType();\r
-\r
- }\r
-\r
- newAcceptedTaxon.addSynonym(synRelation.getSynonym(),\r
- srt,\r
- synRelation.getCitation(),\r
- synRelation.getCitationMicroReference());\r
-\r
- /*if (synonymsInHomotypicalGroup.contains(synRelation.getSynonym()) && srt.equals(SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF())){\r
- homotypicalGroupAcceptedTaxon.addTypifiedName(synRelation.getSynonym().getName());\r
- }*/\r
-\r
- }\r
-\r
-\r
-\r
-\r
-\r
- // CHILD NODES\r
- if(oldTaxonNode.getChildNodes() != null && oldTaxonNode.getChildNodes().size() != 0){\r
- List<TaxonNode> childNodes = new ArrayList<TaxonNode>();\r
- for (TaxonNode childNode : oldTaxonNode.getChildNodes()){\r
- childNodes.add(childNode);\r
- }\r
- for(TaxonNode childNode :childNodes){\r
- newAcceptedTaxonNode.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference()); // childNode.getSynonymToBeUsed()\r
- }\r
- }\r
-\r
- //Move Taxon RelationShips to new Taxon\r
- Set<TaxonRelationship> obsoleteTaxonRelationships = new HashSet<TaxonRelationship>();\r
- for(TaxonRelationship taxonRelationship : oldTaxon.getTaxonRelations()){\r
- Taxon fromTaxon = (Taxon) HibernateProxyHelper.deproxy(taxonRelationship.getFromTaxon());\r
- Taxon toTaxon = (Taxon) HibernateProxyHelper.deproxy(taxonRelationship.getToTaxon());\r
- if (fromTaxon == oldTaxon){\r
- newAcceptedTaxon.addTaxonRelation(taxonRelationship.getToTaxon(), taxonRelationship.getType(),\r
- taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());\r
-\r
- }else if(toTaxon == oldTaxon){\r
- fromTaxon.addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(),\r
- taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());\r
- taxonService.saveOrUpdate(fromTaxon);\r
-\r
- }else{\r
- logger.warn("Taxon is not part of its own Taxonrelationship");\r
- }\r
- // Remove old relationships\r
-\r
- fromTaxon.removeTaxonRelation(taxonRelationship);\r
- toTaxon.removeTaxonRelation(taxonRelationship);\r
- taxonRelationship.setToTaxon(null);\r
- taxonRelationship.setFromTaxon(null);\r
- }\r
-\r
-\r
- //Move descriptions to new taxon\r
- List<TaxonDescription> descriptions = new ArrayList<TaxonDescription>( oldTaxon.getDescriptions()); //to avoid concurrent modification errors (newAcceptedTaxon.addDescription() modifies also oldtaxon.descritpions())\r
- for(TaxonDescription description : descriptions){\r
- String message = "Description copied from former accepted taxon: %s (Old title: %s)";\r
- message = String.format(message, oldTaxon.getTitleCache(), description.getTitleCache());\r
- description.setTitleCache(message, true);\r
- //oldTaxon.removeDescription(description, false);\r
- newAcceptedTaxon.addDescription(description);\r
- }\r
- oldTaxon.clearDescriptions();\r
-\r
- taxonService.update(newAcceptedTaxon);\r
-\r
- taxonService.update(oldTaxon);\r
-\r
- TaxonDeletionConfigurator conf = new TaxonDeletionConfigurator();\r
- conf.setDeleteSynonymsIfPossible(false);\r
- DeleteResult result = taxonService.isDeletable(oldTaxon, conf);\r
- conf.setDeleteNameIfPossible(false);\r
-\r
- if (result.isOk()){\r
- result = taxonService.deleteTaxon(oldTaxon.getUuid(), conf, classification.getUuid());\r
- }else{\r
- result.setStatus(Status.OK);\r
- TaxonNodeDeletionConfigurator config = new TaxonNodeDeletionConfigurator();\r
- config.setDeleteElement(false);\r
- conf.setTaxonNodeConfig(config);\r
- result.includeResult(deleteTaxonNode(oldTaxonNode, conf));\r
- }\r
- result.addUpdatedObject(newAcceptedTaxon);\r
- result.addUpdatedObject(oldTaxon);\r
-\r
- //oldTaxonNode.delete();\r
- return result;\r
- }\r
-\r
-\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#makeTaxonNodeASynonymOfAnotherTaxonNode(java.util.UUID, java.util.UUID, java.util.UUID, java.util.UUID, java.lang.String)\r
- */\r
- @Override\r
- @Transactional(readOnly = false)\r
- public UpdateResult makeTaxonNodeASynonymOfAnotherTaxonNode(UUID oldTaxonNodeUuid,\r
- UUID newAcceptedTaxonNodeUUID,\r
- SynonymRelationshipType synonymRelationshipType,\r
- Reference citation,\r
- String citationMicroReference) {\r
-\r
- TaxonNode oldTaxonNode = dao.load(oldTaxonNodeUuid);\r
- TaxonNode oldTaxonParentNode = oldTaxonNode.getParent();\r
- TaxonNode newTaxonNode = dao.load(newAcceptedTaxonNodeUUID);\r
-\r
- UpdateResult result = makeTaxonNodeASynonymOfAnotherTaxonNode(oldTaxonNode,\r
- newTaxonNode,\r
- synonymRelationshipType,\r
- citation,\r
- citationMicroReference);\r
- result.addUpdatedCdmId(new CdmEntityIdentifier(oldTaxonParentNode.getId(), TaxonNode.class));\r
- result.addUpdatedCdmId(new CdmEntityIdentifier(newTaxonNode.getId(), TaxonNode.class));\r
- result.setCdmEntity(oldTaxonParentNode);\r
- return result;\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#deleteTaxonNodes(java.util.List)\r
- */\r
- @Override\r
- @Transactional(readOnly = false)\r
- public DeleteResult deleteTaxonNodes(List<TaxonNode> list, TaxonDeletionConfigurator config) {\r
-\r
- if (config == null){\r
- config = new TaxonDeletionConfigurator();\r
- }\r
- DeleteResult result = new DeleteResult();\r
- List<UUID> deletedUUIDs = new ArrayList<UUID>();\r
- Classification classification = null;\r
- List<TaxonNode> taxonNodes = new ArrayList<TaxonNode>(list);\r
- for (TaxonNode treeNode:taxonNodes){\r
- if (treeNode != null){\r
-\r
- TaxonNode taxonNode;\r
- taxonNode = HibernateProxyHelper.deproxy(treeNode, TaxonNode.class);\r
- TaxonNode parent = taxonNode.getParent();\r
- //check whether the node has children or the children are already deleted\r
- if(taxonNode.hasChildNodes()) {\r
- List<TaxonNode> children = new ArrayList<TaxonNode> ();\r
- List<TaxonNode> childNodesList = taxonNode.getChildNodes();\r
- children.addAll(childNodesList);\r
- int compare = config.getTaxonNodeConfig().getChildHandling().compareTo(ChildHandling.DELETE);\r
- boolean childHandling = (compare == 0)? true: false;\r
- if (childHandling){\r
- boolean changeDeleteTaxon = false;\r
- if (!config.getTaxonNodeConfig().isDeleteTaxon()){\r
- config.getTaxonNodeConfig().setDeleteTaxon(true);\r
- changeDeleteTaxon = true;\r
- }\r
- DeleteResult resultNodes = deleteTaxonNodes(children, config);\r
- if (!resultNodes.isOk()){\r
- result.addExceptions(resultNodes.getExceptions());\r
- result.setStatus(resultNodes.getStatus());\r
- }\r
- if (changeDeleteTaxon){\r
- config.getTaxonNodeConfig().setDeleteTaxon(false);\r
- }\r
-\r
- } else {\r
- //move the children to the parent\r
-\r
- for (TaxonNode child: childNodesList){\r
- parent.addChildNode(child, child.getReference(), child.getMicroReference());\r
- }\r
-\r
- }\r
- }\r
-\r
- classification = taxonNode.getClassification();\r
-\r
- if (classification.getRootNode().equals(taxonNode)){\r
- classification.removeRootNode();\r
- classification = null;\r
- }else if (classification.getChildNodes().contains(taxonNode)){\r
- Taxon taxon = taxonNode.getTaxon();\r
- classification.deleteChildNode(taxonNode);\r
-\r
- //node is rootNode\r
- if (taxon != null){\r
-\r
- if (config.getTaxonNodeConfig().isDeleteTaxon()){\r
- taxonService.saveOrUpdate(taxon);\r
- saveOrUpdate(taxonNode);\r
-\r
- TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();\r
- DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, classification.getUuid());\r
- if (!resultTaxon.isOk()){\r
- result.addExceptions(resultTaxon.getExceptions());\r
- result.setStatus(resultTaxon.getStatus());\r
- }\r
-\r
- }\r
- }\r
- classification = null;\r
-\r
- } else {\r
- classification = null;\r
- Taxon taxon = taxonNode.getTaxon();\r
- taxon = HibernateProxyHelper.deproxy(taxon, Taxon.class);\r
- if (taxon != null){\r
- taxon.removeTaxonNode(taxonNode);\r
- if (config.getTaxonNodeConfig().isDeleteTaxon()){\r
- TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();\r
- saveOrUpdate(taxonNode);\r
- taxonService.saveOrUpdate(taxon);\r
- DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, null);\r
-\r
- if (!resultTaxon.isOk()){\r
- result.addExceptions(resultTaxon.getExceptions());\r
- result.setStatus(resultTaxon.getStatus());\r
- }\r
- }\r
- }\r
-\r
- }\r
-\r
- result.addUpdatedObject(parent);\r
- if(result.getCdmEntity() == null){\r
- result.setCdmEntity(taxonNode);\r
- }\r
- UUID uuid = dao.delete(taxonNode);\r
- logger.debug("Deleted node " +uuid.toString());\r
-\r
- }\r
- }\r
- /*if (classification != null){\r
- result.addUpdatedObject(classification);\r
- DeleteResult resultClassification = classService.delete(classification);\r
- if (!resultClassification.isOk()){\r
- result.addExceptions(resultClassification.getExceptions());\r
- result.setStatus(resultClassification.getStatus());\r
- }\r
- }*/\r
- return result;\r
-\r
- }\r
-\r
-\r
- @Override\r
- @Transactional(readOnly = false)\r
- public DeleteResult deleteTaxonNodes(Collection<UUID> nodeUuids, TaxonDeletionConfigurator config) {\r
- List<TaxonNode> nodes = new ArrayList<TaxonNode>();\r
- for(UUID nodeUuid : nodeUuids) {\r
- nodes.add(dao.load(nodeUuid));\r
- }\r
- return deleteTaxonNodes(nodes, config);\r
- }\r
-\r
-\r
-\r
- @Override\r
- @Transactional(readOnly = false)\r
- public DeleteResult deleteTaxonNode(UUID nodeUUID, TaxonDeletionConfigurator config) {\r
-\r
- TaxonNode node = HibernateProxyHelper.deproxy(dao.load(nodeUUID), TaxonNode.class);\r
- return deleteTaxonNode(node, config);\r
- }\r
-\r
- @Override\r
- @Transactional(readOnly = false)\r
- public DeleteResult deleteTaxonNode(TaxonNode node, TaxonDeletionConfigurator config) {\r
- DeleteResult result = new DeleteResult();\r
- if (node == null){\r
- result.setAbort();\r
- result.addException(new Exception("The TaxonNode was already deleted."));\r
- return result;\r
- }\r
- Taxon taxon = null;\r
- try{\r
- taxon = (Taxon)HibernateProxyHelper.deproxy(node.getTaxon());\r
- }catch(NullPointerException e){\r
- result.setAbort();\r
- result.addException(new Exception("The Taxon was already deleted."));\r
-\r
- }\r
- TaxonNode parent = HibernateProxyHelper.deproxy(node.getParent(), TaxonNode.class);\r
- if (config == null){\r
- config = new TaxonDeletionConfigurator();\r
- }\r
-\r
-\r
-\r
- if (config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.MOVE_TO_PARENT)){\r
- Object[] children = node.getChildNodes().toArray();\r
- TaxonNode childNode;\r
- for (Object child: children){\r
- childNode = (TaxonNode) child;\r
- parent.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference());\r
- }\r
- }else{\r
- deleteTaxonNodes(node.getChildNodes(), config);\r
- }\r
-\r
- if (taxon != null){\r
- if (config.getTaxonNodeConfig().isDeleteTaxon() && (config.isDeleteInAllClassifications() || taxon.getTaxonNodes().size() == 1)){\r
- result = taxonService.deleteTaxon(taxon.getUuid(), config, node.getClassification().getUuid());\r
- result.addUpdatedObject(parent);\r
- if (result.isOk()){\r
- return result;\r
- }\r
- } else {\r
- result.addUpdatedObject(taxon);\r
- }\r
- }\r
- result.setCdmEntity(node);\r
- boolean success = taxon.removeTaxonNode(node);\r
- dao.save(parent);\r
- taxonService.saveOrUpdate(taxon);\r
- result.addUpdatedObject(parent);\r
-\r
- if (success){\r
- result.setStatus(Status.OK);\r
- parent = HibernateProxyHelper.deproxy(parent, TaxonNode.class);\r
- int index = parent.getChildNodes().indexOf(node);\r
- if (index > -1){\r
- parent.removeChild(index);\r
- }\r
- if (!dao.delete(node, config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.DELETE)).equals(null)){\r
- return result;\r
- } else {\r
- result.setError();\r
- return result;\r
- }\r
- }else{\r
- if (dao.findByUuid(node.getUuid()) != null){\r
- result.setError();\r
- result.addException(new Exception("The node can not be removed from the taxon."));\r
- }\r
- return result;\r
- }\r
-\r
-\r
-\r
- }\r
-\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#listAllNodesForClassification(eu.etaxonomy.cdm.model.taxon.Classification, int, int)\r
- */\r
- @Override\r
- public List<TaxonNode> listAllNodesForClassification(Classification classification, Integer start, Integer end) {\r
- return dao.getTaxonOfAcceptedTaxaByClassification(classification, start, end);\r
- }\r
-\r
- @Override\r
- public int countAllNodesForClassification(Classification classification) {\r
- return dao.countTaxonOfAcceptedTaxaByClassification(classification);\r
- }\r
-\r
- @Override\r
- @Transactional\r
- public UpdateResult moveTaxonNode(UUID taxonNodeUuid, UUID targetNodeUuid, boolean isParent){\r
- TaxonNode taxonNode = dao.load(taxonNodeUuid);\r
- TaxonNode targetNode = dao.load(targetNodeUuid);\r
- return moveTaxonNode(taxonNode, targetNode, isParent);\r
- }\r
-\r
- @Override\r
- @Transactional\r
- public UpdateResult moveTaxonNode(TaxonNode taxonNode, TaxonNode newParent, boolean isParent){\r
- UpdateResult result = new UpdateResult();\r
-\r
- Integer sortIndex;\r
- if (isParent){\r
-\r
- sortIndex = newParent.getChildNodes().size();\r
- }else{\r
- sortIndex = newParent.getSortIndex() +1;\r
- newParent = newParent.getParent();\r
- }\r
- result.addUpdatedObject(newParent);\r
- result.addUpdatedObject(taxonNode.getParent());\r
- result.setCdmEntity(taxonNode);\r
- newParent.addChildNode(taxonNode, sortIndex, taxonNode.getReference(), taxonNode.getMicroReference());\r
- dao.saveOrUpdate(newParent);\r
-\r
- return result;\r
- }\r
-\r
-\r
-\r
- @Override\r
- @Transactional\r
- public UpdateResult moveTaxonNodes(Set<UUID> taxonNodeUuids, UUID newParentNodeUuid, boolean isParent){\r
- UpdateResult result = new UpdateResult();\r
- TaxonNode targetNode = dao.load(newParentNodeUuid);\r
- for (UUID taxonNodeUuid: taxonNodeUuids){\r
- TaxonNode taxonNode = dao.load(taxonNodeUuid);\r
- result.includeResult(moveTaxonNode(taxonNode,targetNode, isParent));\r
- }\r
- return result;\r
- }\r
-\r
- @Override\r
- public Pager<TaxonNodeAgentRelation> pageTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid,\r
- UUID agentUuid, UUID rankUuid, UUID relTypeUuid, Integer pageSize, Integer pageIndex, List<String> propertyPaths) {\r
-\r
-\r
- List<TaxonNodeAgentRelation> records = null;\r
-\r
- long count = dao.countTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid);\r
- if(PagerUtils.hasResultsInRange(count, pageIndex, pageSize)) {\r
- records = dao.listTaxonNodeAgentRelations(taxonUuid, classificationUuid,\r
- agentUuid, rankUuid, relTypeUuid, PagerUtils.startFor(pageSize, pageIndex), PagerUtils.limitFor(pageSize), propertyPaths);\r
- }\r
-\r
- Pager<TaxonNodeAgentRelation> pager = new DefaultPagerImpl<TaxonNodeAgentRelation>(pageIndex, count, pageSize, records);\r
- return pager;\r
- }\r
-\r
- @Override\r
- @Transactional\r
- public UpdateResult createNewTaxonNode(UUID parentNodeUuid, Taxon newTaxon, Reference ref, String microref){\r
- UpdateResult result = new UpdateResult();\r
- TaxonNode parent = dao.load(parentNodeUuid);\r
- TaxonNode child = null;\r
- try{\r
- child = parent.addChildTaxon(newTaxon, parent.getReference(), parent.getMicroReference());\r
- }catch(Exception e){\r
- logger.error("TaxonNode could not be created.");\r
- }\r
-// child = dao.save(child);\r
-\r
- dao.saveOrUpdate(parent);\r
- result.addUpdatedObject(parent);\r
- result.setCdmEntity(child);\r
- return result;\r
-\r
- }\r
-\r
-}\r
+// $Id$
+/**
+* Copyright (C) 2007 EDIT
+* 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.etaxonomy.cdm.api.service.UpdateResult.Status;
+import eu.etaxonomy.cdm.api.service.config.NodeDeletionConfigurator.ChildHandling;
+import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;
+import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator;
+import eu.etaxonomy.cdm.api.service.dto.CdmEntityIdentifier;
+import eu.etaxonomy.cdm.api.service.pager.Pager;
+import eu.etaxonomy.cdm.api.service.pager.PagerUtils;
+import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
+import eu.etaxonomy.cdm.hibernate.HHH_9751_Util;
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
+import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.common.DefinedTerm;
+import eu.etaxonomy.cdm.model.description.TaxonDescription;
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.name.TaxonNameBase;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.taxon.Classification;
+import eu.etaxonomy.cdm.model.taxon.HomotypicGroupTaxonComparator;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
+import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.model.taxon.TaxonNodeAgentRelation;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
+import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
+import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
+import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
+
+/**
+ * @author n.hoffmann
+ * @created Apr 9, 2010
+ * @version 1.0
+ */
+@Service
+@Transactional(readOnly = true)
+public class TaxonNodeServiceImpl extends AnnotatableServiceBase<TaxonNode, ITaxonNodeDao> implements ITaxonNodeService{
+ private static final Logger logger = Logger.getLogger(TaxonNodeServiceImpl.class);
+
+ @Autowired
+ private IBeanInitializer defaultBeanInitializer;
+
+ @Autowired
+ private ITaxonService taxonService;
+
+ @Autowired
+ private IAgentService agentService;
+
+ @Override
+ public List<TaxonNode> loadChildNodesOfTaxonNode(TaxonNode taxonNode,
+ List<String> propertyPaths, boolean recursive, NodeSortMode sortMode) {
+
+ getSession().refresh(taxonNode);
+ List<TaxonNode> childNodes;
+ if (recursive == true){
+ childNodes = dao.listChildrenOf(taxonNode, null, null, null, recursive);
+ }else{
+ childNodes = new ArrayList<TaxonNode>(taxonNode.getChildNodes());
+ }
+
+ HHH_9751_Util.removeAllNull(childNodes);
+
+ if (sortMode != null){
+ Comparator<TaxonNode> comparator = sortMode.newComparator();
+ Collections.sort(childNodes, comparator);
+ }
+ defaultBeanInitializer.initializeAll(childNodes, propertyPaths);
+ return childNodes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Pager<TaxonNodeDto> pageChildNodesDTOs(UUID taxonNodeUuid, boolean recursive,
+ boolean doSynonyms, NodeSortMode sortMode,
+ Integer pageSize, Integer pageIndex) {
+
+ TaxonNode parentNode = dao.load(taxonNodeUuid);
+
+ List<CdmBase> allRecords = new ArrayList<>();
+
+ //acceptedTaxa
+ List<TaxonNode> childNodes = loadChildNodesOfTaxonNode(parentNode, null, recursive, sortMode);
+ allRecords.addAll(childNodes);
+
+ //add synonyms if pager is not yet full synonyms
+ List<Synonym> synList = new ArrayList<>(parentNode.getTaxon().getSynonyms());
+ Collections.sort(synList, new HomotypicGroupTaxonComparator(null));
+ //TODO: test sorting
+
+ allRecords.addAll(synList);
+
+
+ List<TaxonNodeDto> dtos = new ArrayList<>(pageSize);
+ int start = PagerUtils.startFor(pageSize, pageIndex);
+ int limit = PagerUtils.limitFor(pageSize);
+ Long totalCount = Long.valueOf(allRecords.size());
+
+ if(PagerUtils.hasResultsInRange(totalCount, pageIndex, pageSize)) {
+ TaxonNameBase<?,?> parentName = null;
+
+ for(int i = start; i < Math.min(totalCount, start + limit); i++) {
+ CdmBase record = allRecords.get(i);
+
+ if (record.isInstanceOf(TaxonNode.class)){
+ dtos.add(new TaxonNodeDto(CdmBase.deproxy(record, TaxonNode.class)));
+ }else if (record.isInstanceOf(Synonym.class)){
+ Synonym synonym = CdmBase.deproxy(record, Synonym.class);
+ parentName = parentName == null? parentNode.getTaxon().getName(): parentName;
+ boolean isHomotypic = synonym.getName().isHomotypic(parentName);
+ dtos.add(new TaxonNodeDto(synonym, isHomotypic));
+ }
+ }
+ }
+
+ return new DefaultPagerImpl<TaxonNodeDto>(pageIndex, totalCount, pageSize , dtos);
+ }
+
+ @Override
+ public TaxonNodeDto parentDto(UUID taxonNodeUuid) {
+ TaxonNode taxonNode = dao.load(taxonNodeUuid);
+ if(taxonNode.getParent() != null) {
+ return new TaxonNodeDto(taxonNode.getParent());
+ }
+ return null;
+ }
+
+ @Override
+ @Autowired
+ protected void setDao(ITaxonNodeDao dao) {
+ this.dao = dao;
+ }
+
+ @Override
+ @Transactional(readOnly = false)
+ public DeleteResult makeTaxonNodeASynonymOfAnotherTaxonNode(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode, SynonymRelationshipType synonymRelationshipType, Reference citation, String citationMicroReference) {
+
+
+ // TODO at the moment this method only moves synonym-, concept relations and descriptions to the new accepted taxon
+ // in a future version we also want to move cdm data like annotations, marker, so., but we will need a policy for that
+ if (oldTaxonNode == null || newAcceptedTaxonNode == null || oldTaxonNode.getTaxon().getName() == null){
+ throw new IllegalArgumentException("A mandatory parameter was null.");
+ }
+
+ if(oldTaxonNode.equals(newAcceptedTaxonNode)){
+ throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
+ }
+
+
+ Classification classification = oldTaxonNode.getClassification();
+ Taxon oldTaxon = HibernateProxyHelper.deproxy(oldTaxonNode.getTaxon());
+ Taxon newAcceptedTaxon = (Taxon)this.taxonService.load(newAcceptedTaxonNode.getTaxon().getUuid());
+ // Move oldTaxon to newTaxon
+ //TaxonNameBase<?,?> synonymName = oldTaxon.getName();
+ TaxonNameBase<?,?> synonymName = HibernateProxyHelper.deproxy(oldTaxon.getName());
+ HomotypicalGroup group = synonymName.getHomotypicalGroup();
+ group = HibernateProxyHelper.deproxy(group, HomotypicalGroup.class);
+ if (synonymRelationshipType == null){
+ if (synonymName.isHomotypic(newAcceptedTaxon.getName())){
+ synonymRelationshipType = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
+ }else{
+ synonymRelationshipType = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
+ }
+ }
+
+ //set homotypic group
+ HomotypicalGroup newAcceptedTaxonHomotypicalgroup = newAcceptedTaxon.getHomotypicGroup();
+ newAcceptedTaxonHomotypicalgroup = HibernateProxyHelper.deproxy(newAcceptedTaxonHomotypicalgroup, HomotypicalGroup.class);
+ TaxonNameBase newAcceptedTaxonName = HibernateProxyHelper.deproxy(newAcceptedTaxon.getName(), TaxonNameBase.class);
+ // Move Synonym Relations to new Taxon
+ SynonymRelationship synonmyRelationship = newAcceptedTaxon.addSynonymName(synonymName,
+ synonymRelationshipType, citation, citationMicroReference);
+ HomotypicalGroup homotypicalGroupAcceptedTaxon = synonmyRelationship.getSynonym().getHomotypicGroup();
+ // Move Synonym Relations to new Taxon
+ // From ticket 3163 we can move taxon with accepted name having homotypic synonyms
+ List<Synonym> synonymsInHomotypicalGroup = null;
+
+ //the synonyms of the homotypical group of the old taxon
+ if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
+ synonymsInHomotypicalGroup = oldTaxon.getSynonymsInGroup(group);
+ }
+
+ for(SynonymRelationship synRelation : oldTaxon.getSynonymRelations()){
+ SynonymRelationshipType srt;
+ if(synRelation.getSynonym().getName().getHomotypicalGroup()!= null
+ && synRelation.getSynonym().getName().getHomotypicalGroup().equals(newAcceptedTaxonName.getHomotypicalGroup())) {
+ srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
+ } else if(synRelation.getType() != null && synRelation.getType().equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())) {
+ if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
+ srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
+ } else{
+ srt = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
+ }
+ } else {
+ srt = synRelation.getType();
+
+ }
+
+ newAcceptedTaxon.addSynonym(synRelation.getSynonym(),
+ srt,
+ synRelation.getCitation(),
+ synRelation.getCitationMicroReference());
+
+ /*if (synonymsInHomotypicalGroup.contains(synRelation.getSynonym()) && srt.equals(SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF())){
+ homotypicalGroupAcceptedTaxon.addTypifiedName(synRelation.getSynonym().getName());
+ }*/
+
+ }
+
+
+
+
+
+ // CHILD NODES
+ if(oldTaxonNode.getChildNodes() != null && oldTaxonNode.getChildNodes().size() != 0){
+ List<TaxonNode> childNodes = new ArrayList<TaxonNode>();
+ for (TaxonNode childNode : oldTaxonNode.getChildNodes()){
+ childNodes.add(childNode);
+ }
+ for(TaxonNode childNode :childNodes){
+ newAcceptedTaxonNode.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference()); // childNode.getSynonymToBeUsed()
+ }
+ }
+
+ //Move Taxon RelationShips to new Taxon
+ Set<TaxonRelationship> obsoleteTaxonRelationships = new HashSet<TaxonRelationship>();
+ for(TaxonRelationship taxonRelationship : oldTaxon.getTaxonRelations()){
+ Taxon fromTaxon = HibernateProxyHelper.deproxy(taxonRelationship.getFromTaxon());
+ Taxon toTaxon = HibernateProxyHelper.deproxy(taxonRelationship.getToTaxon());
+ if (fromTaxon == oldTaxon){
+ newAcceptedTaxon.addTaxonRelation(taxonRelationship.getToTaxon(), taxonRelationship.getType(),
+ taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
+
+ }else if(toTaxon == oldTaxon){
+ fromTaxon.addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(),
+ taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
+ taxonService.saveOrUpdate(fromTaxon);
+
+ }else{
+ logger.warn("Taxon is not part of its own Taxonrelationship");
+ }
+ // Remove old relationships
+
+ fromTaxon.removeTaxonRelation(taxonRelationship);
+ toTaxon.removeTaxonRelation(taxonRelationship);
+ taxonRelationship.setToTaxon(null);
+ taxonRelationship.setFromTaxon(null);
+ }
+
+
+ //Move descriptions to new taxon
+ List<TaxonDescription> descriptions = new ArrayList<TaxonDescription>( oldTaxon.getDescriptions()); //to avoid concurrent modification errors (newAcceptedTaxon.addDescription() modifies also oldtaxon.descritpions())
+ for(TaxonDescription description : descriptions){
+ String message = "Description copied from former accepted taxon: %s (Old title: %s)";
+ message = String.format(message, oldTaxon.getTitleCache(), description.getTitleCache());
+ description.setTitleCache(message, true);
+ //oldTaxon.removeDescription(description, false);
+ newAcceptedTaxon.addDescription(description);
+ }
+ oldTaxon.clearDescriptions();
+
+ taxonService.update(newAcceptedTaxon);
+
+ taxonService.update(oldTaxon);
+
+ TaxonDeletionConfigurator conf = new TaxonDeletionConfigurator();
+ conf.setDeleteSynonymsIfPossible(false);
+ DeleteResult result = taxonService.isDeletable(oldTaxon, conf);
+ conf.setDeleteNameIfPossible(false);
+
+ if (result.isOk()){
+ result = taxonService.deleteTaxon(oldTaxon.getUuid(), conf, classification.getUuid());
+ }else{
+ result.setStatus(Status.OK);
+ TaxonNodeDeletionConfigurator config = new TaxonNodeDeletionConfigurator();
+ config.setDeleteElement(false);
+ conf.setTaxonNodeConfig(config);
+ result.includeResult(deleteTaxonNode(oldTaxonNode, conf));
+ }
+ result.addUpdatedObject(newAcceptedTaxon);
+ result.addUpdatedObject(oldTaxon);
+
+ //oldTaxonNode.delete();
+ return result;
+ }
+
+
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#makeTaxonNodeASynonymOfAnotherTaxonNode(java.util.UUID, java.util.UUID, java.util.UUID, java.util.UUID, java.lang.String)
+ */
+ @Override
+ @Transactional(readOnly = false)
+ public UpdateResult makeTaxonNodeASynonymOfAnotherTaxonNode(UUID oldTaxonNodeUuid,
+ UUID newAcceptedTaxonNodeUUID,
+ SynonymRelationshipType synonymRelationshipType,
+ Reference citation,
+ String citationMicroReference) {
+
+ TaxonNode oldTaxonNode = dao.load(oldTaxonNodeUuid);
+ TaxonNode oldTaxonParentNode = oldTaxonNode.getParent();
+ TaxonNode newTaxonNode = dao.load(newAcceptedTaxonNodeUUID);
+
+ UpdateResult result = makeTaxonNodeASynonymOfAnotherTaxonNode(oldTaxonNode,
+ newTaxonNode,
+ synonymRelationshipType,
+ citation,
+ citationMicroReference);
+ result.addUpdatedCdmId(new CdmEntityIdentifier(oldTaxonParentNode.getId(), TaxonNode.class));
+ result.addUpdatedCdmId(new CdmEntityIdentifier(newTaxonNode.getId(), TaxonNode.class));
+ result.setCdmEntity(oldTaxonParentNode);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#deleteTaxonNodes(java.util.List)
+ */
+ @Override
+ @Transactional(readOnly = false)
+ public DeleteResult deleteTaxonNodes(List<TaxonNode> list, TaxonDeletionConfigurator config) {
+
+ if (config == null){
+ config = new TaxonDeletionConfigurator();
+ }
+ DeleteResult result = new DeleteResult();
+ List<UUID> deletedUUIDs = new ArrayList<UUID>();
+ Classification classification = null;
+ List<TaxonNode> taxonNodes = new ArrayList<TaxonNode>(list);
+ for (TaxonNode treeNode:taxonNodes){
+ if (treeNode != null){
+
+ TaxonNode taxonNode;
+ taxonNode = HibernateProxyHelper.deproxy(treeNode, TaxonNode.class);
+ TaxonNode parent = taxonNode.getParent();
+ //check whether the node has children or the children are already deleted
+ if(taxonNode.hasChildNodes()) {
+ List<TaxonNode> children = new ArrayList<TaxonNode> ();
+ List<TaxonNode> childNodesList = taxonNode.getChildNodes();
+ children.addAll(childNodesList);
+ int compare = config.getTaxonNodeConfig().getChildHandling().compareTo(ChildHandling.DELETE);
+ boolean childHandling = (compare == 0)? true: false;
+ if (childHandling){
+ boolean changeDeleteTaxon = false;
+ if (!config.getTaxonNodeConfig().isDeleteTaxon()){
+ config.getTaxonNodeConfig().setDeleteTaxon(true);
+ changeDeleteTaxon = true;
+ }
+ DeleteResult resultNodes = deleteTaxonNodes(children, config);
+ if (!resultNodes.isOk()){
+ result.addExceptions(resultNodes.getExceptions());
+ result.setStatus(resultNodes.getStatus());
+ }
+ if (changeDeleteTaxon){
+ config.getTaxonNodeConfig().setDeleteTaxon(false);
+ }
+
+ } else {
+ //move the children to the parent
+
+ for (TaxonNode child: childNodesList){
+ parent.addChildNode(child, child.getReference(), child.getMicroReference());
+ }
+
+ }
+ }
+
+ classification = taxonNode.getClassification();
+
+ if (classification.getRootNode().equals(taxonNode)){
+ classification.removeRootNode();
+ classification = null;
+ }else if (classification.getChildNodes().contains(taxonNode)){
+ Taxon taxon = taxonNode.getTaxon();
+ classification.deleteChildNode(taxonNode);
+
+ //node is rootNode
+ if (taxon != null){
+
+ if (config.getTaxonNodeConfig().isDeleteTaxon()){
+ taxonService.saveOrUpdate(taxon);
+ saveOrUpdate(taxonNode);
+
+ TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
+ DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, classification.getUuid());
+ if (!resultTaxon.isOk()){
+ result.addExceptions(resultTaxon.getExceptions());
+ result.setStatus(resultTaxon.getStatus());
+ }
+
+ }
+ }
+ classification = null;
+
+ } else {
+ classification = null;
+ Taxon taxon = taxonNode.getTaxon();
+ taxon = HibernateProxyHelper.deproxy(taxon, Taxon.class);
+ if (taxon != null){
+ taxon.removeTaxonNode(taxonNode);
+ if (config.getTaxonNodeConfig().isDeleteTaxon()){
+ TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
+ saveOrUpdate(taxonNode);
+ taxonService.saveOrUpdate(taxon);
+ DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, null);
+
+ if (!resultTaxon.isOk()){
+ result.addExceptions(resultTaxon.getExceptions());
+ result.setStatus(resultTaxon.getStatus());
+ }
+ }
+ }
+
+ }
+
+ result.addUpdatedObject(parent);
+ if(result.getCdmEntity() == null){
+ result.setCdmEntity(taxonNode);
+ }
+ UUID uuid = dao.delete(taxonNode);
+ logger.debug("Deleted node " +uuid.toString());
+
+ }
+ }
+ /*if (classification != null){
+ result.addUpdatedObject(classification);
+ DeleteResult resultClassification = classService.delete(classification);
+ if (!resultClassification.isOk()){
+ result.addExceptions(resultClassification.getExceptions());
+ result.setStatus(resultClassification.getStatus());
+ }
+ }*/
+ return result;
+
+ }
+
+
+ @Override
+ @Transactional(readOnly = false)
+ public DeleteResult deleteTaxonNodes(Collection<UUID> nodeUuids, TaxonDeletionConfigurator config) {
+ List<TaxonNode> nodes = new ArrayList<TaxonNode>();
+ for(UUID nodeUuid : nodeUuids) {
+ nodes.add(dao.load(nodeUuid));
+ }
+ return deleteTaxonNodes(nodes, config);
+ }
+
+
+
+ @Override
+ @Transactional(readOnly = false)
+ public DeleteResult deleteTaxonNode(UUID nodeUUID, TaxonDeletionConfigurator config) {
+
+ TaxonNode node = HibernateProxyHelper.deproxy(dao.load(nodeUUID), TaxonNode.class);
+ return deleteTaxonNode(node, config);
+ }
+
+ @Override
+ @Transactional(readOnly = false)
+ public DeleteResult deleteTaxonNode(TaxonNode node, TaxonDeletionConfigurator config) {
+ DeleteResult result = new DeleteResult();
+ if (node == null){
+ result.setAbort();
+ result.addException(new Exception("The TaxonNode was already deleted."));
+ return result;
+ }
+ Taxon taxon = null;
+ try{
+ taxon = HibernateProxyHelper.deproxy(node.getTaxon());
+ }catch(NullPointerException e){
+ result.setAbort();
+ result.addException(new Exception("The Taxon was already deleted."));
+
+ }
+ TaxonNode parent = HibernateProxyHelper.deproxy(node.getParent(), TaxonNode.class);
+ if (config == null){
+ config = new TaxonDeletionConfigurator();
+ }
+
+
+
+ if (config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.MOVE_TO_PARENT)){
+ Object[] children = node.getChildNodes().toArray();
+ TaxonNode childNode;
+ for (Object child: children){
+ childNode = (TaxonNode) child;
+ parent.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference());
+ }
+ }else{
+ deleteTaxonNodes(node.getChildNodes(), config);
+ }
+
+ if (taxon != null){
+ if (config.getTaxonNodeConfig().isDeleteTaxon() && (config.isDeleteInAllClassifications() || taxon.getTaxonNodes().size() == 1)){
+ result = taxonService.deleteTaxon(taxon.getUuid(), config, node.getClassification().getUuid());
+ result.addUpdatedObject(parent);
+ if (result.isOk()){
+ return result;
+ }
+ } else {
+ result.addUpdatedObject(taxon);
+ }
+ }
+ result.setCdmEntity(node);
+ boolean success = taxon.removeTaxonNode(node);
+ dao.save(parent);
+ taxonService.saveOrUpdate(taxon);
+ result.addUpdatedObject(parent);
+
+ if (success){
+ result.setStatus(Status.OK);
+ parent = HibernateProxyHelper.deproxy(parent, TaxonNode.class);
+ int index = parent.getChildNodes().indexOf(node);
+ if (index > -1){
+ parent.removeChild(index);
+ }
+ if (!dao.delete(node, config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.DELETE)).equals(null)){
+ return result;
+ } else {
+ result.setError();
+ return result;
+ }
+ }else{
+ if (dao.findByUuid(node.getUuid()) != null){
+ result.setError();
+ result.addException(new Exception("The node can not be removed from the taxon."));
+ }
+ return result;
+ }
+
+
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#listAllNodesForClassification(eu.etaxonomy.cdm.model.taxon.Classification, int, int)
+ */
+ @Override
+ public List<TaxonNode> listAllNodesForClassification(Classification classification, Integer start, Integer end) {
+ return dao.getTaxonOfAcceptedTaxaByClassification(classification, start, end);
+ }
+
+ @Override
+ public int countAllNodesForClassification(Classification classification) {
+ return dao.countTaxonOfAcceptedTaxaByClassification(classification);
+ }
+
+ @Override
+ @Transactional
+ public UpdateResult moveTaxonNode(UUID taxonNodeUuid, UUID targetNodeUuid, int movingType){
+ TaxonNode taxonNode = HibernateProxyHelper.deproxy(dao.load(taxonNodeUuid), TaxonNode.class);
+ TaxonNode targetNode = HibernateProxyHelper.deproxy(dao.load(targetNodeUuid), TaxonNode.class);
+ return moveTaxonNode(taxonNode, targetNode, movingType);
+ }
+
+ @Override
+ @Transactional
+ public UpdateResult moveTaxonNode(TaxonNode taxonNode, TaxonNode newParent, int movingType){
+ UpdateResult result = new UpdateResult();
+
+ TaxonNode parentParent = HibernateProxyHelper.deproxy(newParent.getParent(), TaxonNode.class);
+
+ Integer sortIndex = -1;
+ if (movingType == 0){
+ sortIndex = 0;
+ }else if (movingType == 1){
+ sortIndex = newParent.getSortIndex();
+ newParent = parentParent;
+ } else if (movingType == 2){
+ sortIndex = newParent.getSortIndex() +1;
+ newParent = parentParent;
+ } else{
+ result.setAbort();
+ result.addException(new Exception("The moving type "+ movingType +" is not supported."));
+ }
+ result.addUpdatedObject(newParent);
+ result.addUpdatedObject(taxonNode.getParent());
+ result.setCdmEntity(taxonNode);
+
+ newParent.addChildNode(taxonNode, sortIndex, taxonNode.getReference(), taxonNode.getMicroReference());
+
+ dao.saveOrUpdate(newParent);
+
+ return result;
+ }
+
+
+
+ @Override
+ @Transactional
+ public UpdateResult moveTaxonNodes(Set<UUID> taxonNodeUuids, UUID newParentNodeUuid, int movingType){
+ UpdateResult result = new UpdateResult();
+ TaxonNode targetNode = dao.load(newParentNodeUuid);
+ for (UUID taxonNodeUuid: taxonNodeUuids){
+ TaxonNode taxonNode = dao.load(taxonNodeUuid);
+ result.includeResult(moveTaxonNode(taxonNode,targetNode, movingType));
+ }
+ return result;
+ }
+
+ @Override
+ public Pager<TaxonNodeAgentRelation> pageTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid,
+ UUID agentUuid, UUID rankUuid, UUID relTypeUuid, Integer pageSize, Integer pageIndex, List<String> propertyPaths) {
+
+
+ List<TaxonNodeAgentRelation> records = null;
+
+ long count = dao.countTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid);
+ if(PagerUtils.hasResultsInRange(count, pageIndex, pageSize)) {
+ records = dao.listTaxonNodeAgentRelations(taxonUuid, classificationUuid,
+ agentUuid, rankUuid, relTypeUuid, PagerUtils.startFor(pageSize, pageIndex), PagerUtils.limitFor(pageSize), propertyPaths);
+ }
+
+ Pager<TaxonNodeAgentRelation> pager = new DefaultPagerImpl<TaxonNodeAgentRelation>(pageIndex, count, pageSize, records);
+ return pager;
+ }
+
+ @Override
+ @Transactional
+ public UpdateResult createNewTaxonNode(UUID parentNodeUuid, Taxon newTaxon, Reference ref, String microref){
+ UpdateResult result = new UpdateResult();
+
+ UUID taxonUUID = taxonService.saveOrUpdate(newTaxon);
+ newTaxon = (Taxon) taxonService.load(taxonUUID);
+
+ TaxonNode parent = dao.load(parentNodeUuid);
+ TaxonNode child = null;
+ try{
+ child = parent.addChildTaxon(newTaxon, parent.getReference(), parent.getMicroReference());
+ }catch(Exception e){
+ result.addException(e);
+ result.setError();
+ return result;
+ }
+// child = dao.save(child);
+
+ dao.saveOrUpdate(parent);
+ result.addUpdatedObject(parent);
+ if (child != null){
+ result.setCdmEntity(child);
+ }
+ return result;
+
+ }
+ @Override
+ @Transactional
+ public UpdateResult createNewTaxonNode(UUID parentNodeUuid, UUID taxonUuid, Reference ref, String microref){
+ UpdateResult result = new UpdateResult();
+ TaxonNode parent = dao.load(parentNodeUuid);
+ Taxon taxon = (Taxon) taxonService.load(taxonUuid);
+ TaxonNode child = null;
+ try{
+ child = parent.addChildTaxon(taxon, parent.getReference(), parent.getMicroReference());
+ }catch(Exception e){
+ result.addException(e);
+ result.setError();
+ return result;
+ }
+// child = dao.save(child);
+
+ dao.saveOrUpdate(parent);
+ result.addUpdatedObject(parent);
+ if (child != null){
+ result.setCdmEntity(child);
+ }
+ return result;
+
+ }
+
+ @Override
+ @Transactional
+ public UpdateResult addTaxonNodeAgentRelation(UUID taxonNodeUUID, UUID agentUUID, DefinedTerm relationshipType){
+ UpdateResult result = new UpdateResult();
+ TaxonNode node = dao.load(taxonNodeUUID);
+ TeamOrPersonBase agent = (TeamOrPersonBase) agentService.load(agentUUID);
+ node.addAgentRelation(relationshipType, agent);
+ try{
+ dao.merge(node, true);
+ }catch (Exception e){
+ result.setError();
+ result.addException(e);
+ }
+ result.setCdmEntity(node);
+ return result;
+ }
+
+
+}