revert small changes
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / TaxonNodeServiceImpl.java
index 7d84ac4c08db6c25bd343780d455dc6723265627..9fdf1cd3fdd2ed3f70ad746547626d792b0b11d4 100644 (file)
@@ -17,12 +17,14 @@ import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
 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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
@@ -34,7 +36,9 @@ import eu.etaxonomy.cdm.api.service.config.SecundumForSubtreeConfigurator;
 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.dto.CreateTaxonDTO;
 import eu.etaxonomy.cdm.api.service.dto.TaxonDistributionDTO;
+import eu.etaxonomy.cdm.api.service.dto.TaxonDistributionDTOComparator;
 import eu.etaxonomy.cdm.api.service.pager.Pager;
 import eu.etaxonomy.cdm.api.service.pager.PagerUtils;
 import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
@@ -49,11 +53,15 @@ import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.Language;
 import eu.etaxonomy.cdm.model.common.LanguageString;
 import eu.etaxonomy.cdm.model.common.TreeIndex;
+import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
+import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
 import eu.etaxonomy.cdm.model.description.DescriptiveDataSet;
 import eu.etaxonomy.cdm.model.description.TaxonDescription;
 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
 import eu.etaxonomy.cdm.model.name.HybridRelationship;
+import eu.etaxonomy.cdm.model.name.Rank;
 import eu.etaxonomy.cdm.model.name.TaxonName;
+import eu.etaxonomy.cdm.model.permission.Operation;
 import eu.etaxonomy.cdm.model.reference.Reference;
 import eu.etaxonomy.cdm.model.taxon.Classification;
 import eu.etaxonomy.cdm.model.taxon.HomotypicGroupTaxonComparator;
@@ -65,14 +73,17 @@ import eu.etaxonomy.cdm.model.taxon.TaxonBase;
 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.model.taxon.TaxonRelationshipType;
 import eu.etaxonomy.cdm.model.term.DefinedTerm;
 import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
 import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeFilterDao;
+import eu.etaxonomy.cdm.persistence.dto.MergeResult;
 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
-import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
+import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
 import eu.etaxonomy.cdm.persistence.query.OrderHint;
+import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
 
 /**
  * @author n.hoffmann
@@ -112,6 +123,8 @@ public class TaxonNodeServiceImpl
     @Autowired
     IProgressMonitorService progressMonitorService;
 
+    @Autowired
+    private ICdmPermissionEvaluator permissionEvaluator;
 
     @Override
     public List<TaxonNode> loadChildNodesOfTaxonNode(TaxonNode taxonNode,
@@ -149,72 +162,48 @@ public class TaxonNodeServiceImpl
         return dao.listChildrenOf(node, pageSize, pageIndex, recursive, includeUnpublished, propertyPaths);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public UuidAndTitleCache<TaxonNode> getParentUuidAndTitleCache(ITaxonTreeNode child) {
+    public TaxonNodeDto getParentUuidAndTitleCache(ITaxonTreeNode child) {
         UUID uuid = child.getUuid();
         int id = child.getId();
-        UuidAndTitleCache<TaxonNode> uuidAndTitleCache = new UuidAndTitleCache<>(uuid, id, null);
+        TaxonNodeDto uuidAndTitleCache = new TaxonNodeDto(uuid, id, null);
         return getParentUuidAndTitleCache(uuidAndTitleCache);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public UuidAndTitleCache<TaxonNode> getParentUuidAndTitleCache(UuidAndTitleCache<TaxonNode> child) {
+    public TaxonNodeDto getParentUuidAndTitleCache(TaxonNodeDto child) {
         return dao.getParentUuidAndTitleCache(child);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public List<TaxonNodeDto> listChildNodesAsTaxonNodeDto(UuidAndTitleCache<TaxonNode> parent) {
+    public List<TaxonNodeDto> listChildNodesAsTaxonNodeDto(TaxonNodeDto parent) {
         return dao.listChildNodesAsTaxonNodeDto(parent);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public List<UuidAndTitleCache<TaxonNode>> listChildNodesAsUuidAndTitleCache(UuidAndTitleCache<TaxonNode> parent) {
-        return dao.listChildNodesAsUuidAndTitleCache(parent);
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public List<UuidAndTitleCache<TaxonNode>> getUuidAndTitleCache(Integer limit, String pattern, UUID classificationUuid) {
+    public List<TaxonNodeDto> getUuidAndTitleCache(Integer limit, String pattern, UUID classificationUuid) {
         return dao.getUuidAndTitleCache(limit, pattern, classificationUuid);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public List<TaxonNodeDto> listChildNodesAsTaxonNodeDto(ITaxonTreeNode parent) {
-        UUID uuid = parent.getUuid();
-        int id = parent.getId();
-        UuidAndTitleCache<TaxonNode> uuidAndTitleCache = new UuidAndTitleCache<>(uuid, id, null);
+        List<String> propertyPaths = new ArrayList<>();
+        propertyPaths.add("parent");
+        parent = dao.load(parent.getId(), propertyPaths);
+        TaxonNodeDto uuidAndTitleCache = new TaxonNodeDto(parent);
         return listChildNodesAsTaxonNodeDto(uuidAndTitleCache);
     }
 
     @Override
-    public List<UuidAndTitleCache<TaxonNode>> listChildNodesAsUuidAndTitleCache(ITaxonTreeNode parent) {
-        UUID uuid = parent.getUuid();
-        int id = parent.getId();
-        UuidAndTitleCache<TaxonNode> uuidAndTitleCache = new UuidAndTitleCache<>(uuid, id, null);
-        return listChildNodesAsUuidAndTitleCache(uuidAndTitleCache);
+    public List<TaxonNodeDto> taxonNodeDtoParentRank(Classification classification, Rank rank, TaxonName name) {
+       return dao.getParentTaxonNodeDtoForRank(classification, rank, name);
+    }
+
+    @Override
+    public List<TaxonNodeDto> taxonNodeDtoParentRank(Classification classification, Rank rank, TaxonBase<?> taxonBase) {
+        return dao.getParentTaxonNodeDtoForRank(classification, rank, taxonBase);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public Pager<TaxonNodeDto> pageChildNodesDTOs(UUID taxonNodeUuid, boolean recursive,  boolean includeUnpublished,
             boolean doSynonyms, NodeSortMode sortMode,
@@ -257,6 +246,9 @@ public class TaxonNodeServiceImpl
 
     @Override
     public TaxonNodeDto parentDto(UUID taxonNodeUuid) {
+        if (taxonNodeUuid == null){
+            return null;
+        }
         TaxonNode taxonNode = dao.load(taxonNodeUuid);
         if(taxonNode.getParent() != null) {
             return new TaxonNodeDto(taxonNode.getParent());
@@ -266,8 +258,11 @@ public class TaxonNodeServiceImpl
 
     @Override
     public TaxonNodeDto dto(UUID taxonNodeUuid) {
+        if (taxonNodeUuid == null){
+            return null;
+        }
         TaxonNode taxonNode = dao.load(taxonNodeUuid);
-        if(taxonNode.getParent() != null) {
+        if (taxonNode != null){
             return new TaxonNodeDto(taxonNode);
         }
         return null;
@@ -282,7 +277,7 @@ public class TaxonNodeServiceImpl
     @Override
     @Transactional(readOnly = false)
     public DeleteResult makeTaxonNodeASynonymOfAnotherTaxonNode(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode,
-            SynonymType synonymType, Reference citation, String citationMicroReference)  {
+            SynonymType synonymType, Reference citation, String citationMicroReference, boolean setNameInSource)  {
 
         // 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
@@ -390,13 +385,21 @@ public class TaxonNodeServiceImpl
             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);
+            if (setNameInSource) {
+                for (DescriptionElementBase element: description.getElements()){
+                    for (DescriptionElementSource source: element.getSources()){
+                        if (source.getNameUsedInSource() == null){
+                            source.setNameUsedInSource(newSynonymName);
+                        }
+                    }
+                }
+            }
             //oldTaxon.removeDescription(description, false);
             newAcceptedTaxon.addDescription(description);
         }
@@ -436,10 +439,11 @@ public class TaxonNodeServiceImpl
             UUID newAcceptedTaxonNodeUUIDs,
             SynonymType synonymType,
             Reference citation,
-            String citationMicroReference) {
+            String citationMicroReference,
+            boolean setNameInSource) {
        UpdateResult result = new UpdateResult();
        for (UUID nodeUuid: oldTaxonNodeUuids) {
-               result.includeResult(makeTaxonNodeASynonymOfAnotherTaxonNode(nodeUuid, newAcceptedTaxonNodeUUIDs, synonymType, citation, citationMicroReference));
+               result.includeResult(makeTaxonNodeASynonymOfAnotherTaxonNode(nodeUuid, newAcceptedTaxonNodeUUIDs, synonymType, citation, citationMicroReference, setNameInSource));
        }
        return result;
     }
@@ -450,7 +454,8 @@ public class TaxonNodeServiceImpl
             UUID newAcceptedTaxonNodeUUID,
             SynonymType synonymType,
             Reference citation,
-            String citationMicroReference) {
+            String citationMicroReference,
+            boolean setNameInSource) {
 
         TaxonNode oldTaxonNode = dao.load(oldTaxonNodeUuid);
         TaxonNode oldTaxonParentNode = oldTaxonNode.getParent();
@@ -460,7 +465,7 @@ public class TaxonNodeServiceImpl
                 newTaxonNode,
                 synonymType,
                 citation,
-                citationMicroReference);
+                citationMicroReference, setNameInSource);
         result.addUpdatedCdmId(new CdmEntityIdentifier(oldTaxonParentNode.getId(), TaxonNode.class));
         result.addUpdatedCdmId(new CdmEntityIdentifier(newTaxonNode.getId(), TaxonNode.class));
         result.setCdmEntity(oldTaxonParentNode);
@@ -482,11 +487,11 @@ public class TaxonNodeServiceImpl
                if (treeNode != null){
 
                        TaxonNode taxonNode;
-                   taxonNode = HibernateProxyHelper.deproxy(treeNode, TaxonNode.class);
+                   taxonNode = CdmBase.deproxy(treeNode);
                    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> children = new ArrayList<> ();
                        List<TaxonNode> childNodesList = taxonNode.getChildNodes();
                                children.addAll(childNodesList);
                                //To avoid NPE when child is also in list of taxonNodes, remove it from the list
@@ -542,6 +547,7 @@ public class TaxonNodeServiceImpl
                                    saveOrUpdate(taxonNode);
 
                                        TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
+                                       configNew.setClassificationUuid(classification.getUuid());
                                        DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, classification.getUuid());
                                        if (!resultTaxon.isOk()){
                                 result.addExceptions(resultTaxon.getExceptions());
@@ -553,16 +559,16 @@ public class TaxonNodeServiceImpl
                        classification = null;
 
                    } else {
-                       classification = null;
+                       //classification = null;
                        Taxon taxon = taxonNode.getTaxon();
-                       taxon = HibernateProxyHelper.deproxy(taxon, Taxon.class);
+                       taxon = CdmBase.deproxy(taxon);
                        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);
+                                       DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, classification.getUuid());
 
                             if (!resultTaxon.isOk()){
                                 result.addExceptions(resultTaxon.getExceptions());
@@ -609,7 +615,7 @@ public class TaxonNodeServiceImpl
     @Transactional(readOnly = false)
     public DeleteResult deleteTaxonNode(UUID nodeUUID, TaxonDeletionConfigurator config) {
 
-       TaxonNode node = HibernateProxyHelper.deproxy(dao.load(nodeUUID), TaxonNode.class);
+       TaxonNode node = CdmBase.deproxy(dao.load(nodeUUID));
        return deleteTaxonNode(node, config);
     }
 
@@ -719,8 +725,8 @@ public class TaxonNodeServiceImpl
     @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);
+        TaxonNode taxonNode = HibernateProxyHelper.deproxy(dao.load(taxonNodeUuid));
+       TaxonNode targetNode = HibernateProxyHelper.deproxy(dao.load(targetNodeUuid));
        UpdateResult result = moveTaxonNode(taxonNode, targetNode, movingType);
        return result;
     }
@@ -731,7 +737,6 @@ public class TaxonNodeServiceImpl
         UpdateResult result = new UpdateResult();
 
         TaxonNode parentParent = HibernateProxyHelper.deproxy(newParent.getParent());
-        TaxonNode oldParent = HibernateProxyHelper.deproxy(taxonNode.getParent());
         Integer sortIndex = -1;
         if (movingType == 0){
             sortIndex = 0;
@@ -752,8 +757,6 @@ public class TaxonNodeServiceImpl
         return result;
     }
 
-
-
     @Override
     @Transactional
     public UpdateResult moveTaxonNodes(Set<UUID> taxonNodeUuids, UUID newParentNodeUuid, int movingType, IProgressMonitor monitor){
@@ -765,7 +768,6 @@ public class TaxonNodeServiceImpl
 
         TaxonNode targetNode = dao.load(newParentNodeUuid);
         List<TaxonNode> nodes = dao.list(taxonNodeUuids, null, null, null, null);
-        boolean hasPermission = true;
 
         monitor.beginTask("Move Taxonnodes", nodes.size()*2);
         monitor.subTask("move taxon nodes");
@@ -811,13 +813,23 @@ public class TaxonNodeServiceImpl
 
     @Override
     @Transactional
-    public UpdateResult createNewTaxonNode(UUID parentNodeUuid, Taxon newTaxon, Reference ref, String microref){
+    public UpdateResult createNewTaxonNode(UUID parentNodeUuid, CreateTaxonDTO taxonDto, UUID refUuid, String microref, boolean unplaced, boolean doubtful, boolean excluded, Map<Language,LanguageString> excludedNote){
         UpdateResult result = new UpdateResult();
-        if (newTaxon.getName().getId() != 0){
-            TaxonName name = nameService.load(newTaxon.getName().getUuid());
-            newTaxon.setName(name);
+        TaxonName name = null;
+        if (taxonDto.getNameUuid() != null){
+            name = nameService.load(taxonDto.getNameUuid());
+
         }else{
-            for (HybridRelationship rel : newTaxon.getName().getHybridChildRelations()){
+            NonViralNameParserImpl nonViralNameParser = NonViralNameParserImpl.NewInstance();
+            name = (TaxonName) nonViralNameParser.parseFullName(taxonDto.getTaxonNameString());
+        }
+        Reference sec = null;
+        if (taxonDto.getSecUuid() != null ){
+            sec = referenceService.load(taxonDto.getSecUuid());
+
+        }
+        if (!name.isPersited()){
+            for (HybridRelationship rel : name.getHybridChildRelations()){
                 if (!rel.getHybridName().isPersited()) {
                     nameService.save(rel.getHybridName());
                 }
@@ -826,13 +838,25 @@ public class TaxonNodeServiceImpl
                 }
             }
         }
-        UUID taxonUUID = taxonService.saveOrUpdate(newTaxon);
-        newTaxon = (Taxon) taxonService.load(taxonUUID);
 
-        TaxonNode parent = dao.load(parentNodeUuid);
-        TaxonNode child = null;
-        try{
-            child = parent.addChildTaxon(newTaxon,ref, microref);
+       Taxon newTaxon = Taxon.NewInstance(name, sec);
+//       UUID taxonUuid = taxonService.saveOrUpdate(newTaxon);
+//       newTaxon = (Taxon) taxonService.load(taxonUuid);
+
+       TaxonNode parent = dao.load(parentNodeUuid);
+       TaxonNode child = null;
+       Reference ref = null;
+       if (refUuid != null){
+           ref = referenceService.load(refUuid);
+       }
+
+       try{
+           child = parent.addChildTaxon(newTaxon, ref, microref);
+           child.setDoubtful(doubtful);
+           child.setExcluded(excluded);
+           child.setUnplaced(unplaced);
+           child.getExcludedNote().putAll(excludedNote);
+
         }catch(Exception e){
             result.addException(e);
             result.setError();
@@ -845,10 +869,8 @@ public class TaxonNodeServiceImpl
             result.setCdmEntity(child);
         }
         return result;
-
     }
 
-
     @Override
     @Transactional
     public UpdateResult saveNewTaxonNode(TaxonNode newTaxonNode){
@@ -856,14 +878,14 @@ public class TaxonNodeServiceImpl
         UUID parentUuid = newTaxonNode.getParent().getUuid();
         Taxon taxon = null;
 
-        if (newTaxonNode.getTaxon().getId() != 0){
+        if (newTaxonNode.getTaxon().isPersited()){
             taxon = (Taxon)taxonService.load(newTaxonNode.getTaxon().getUuid());
-            //newTaxonNode.setTaxon(taxon);
-        }else if (newTaxonNode.getTaxon().getName().getId() != 0){
+        }else if (newTaxonNode.getTaxon().getName().isPersited()){
             TaxonName name = nameService.load(newTaxonNode.getTaxon().getName().getUuid());
             taxon = newTaxonNode.getTaxon();
             taxon.setName(name);
         }else{
+            //taxon and name is not persisted, persist possible related names
             for (HybridRelationship rel : newTaxonNode.getTaxon().getName().getHybridChildRelations()){
                 if (!rel.getHybridName().isPersited()) {
                     nameService.save(rel.getHybridName());
@@ -882,26 +904,26 @@ public class TaxonNodeServiceImpl
             Reference sec = referenceService.load(taxon.getSec().getUuid());
             taxon.setSec(sec);
         }
-        if (taxon.getId() == 0){
-            UUID taxonUUID = taxonService.saveOrUpdate(taxon);
-            taxon = (Taxon) taxonService.load(taxonUUID);
+        if (!taxon.isPersited()){
+            MergeResult<TaxonBase> mergeResult = taxonService.merge(taxon, true);
+            taxon = (Taxon) mergeResult.getMergedEntity();
 
         }
 
-
         TaxonNode parent = dao.load(parentUuid);
         TaxonNode child = null;
         try{
             child = parent.addChildTaxon(taxon, newTaxonNode.getReference(), newTaxonNode.getMicroReference());
-
         }catch(Exception e){
             result.addException(e);
             result.setError();
             return result;
         }
 
+        //TODO can't we work with clone method here?
         child.setUnplaced(newTaxonNode.isUnplaced());
         child.setExcluded(newTaxonNode.isExcluded());
+        child.setDoubtful(newTaxonNode.isDoubtful());
         for (TaxonNodeAgentRelation agentRel :newTaxonNode.getAgentRelations()){
             child.addAgentRelation(agentRel.getType(), agentRel.getAgent());
         }
@@ -910,22 +932,16 @@ public class TaxonNodeServiceImpl
         }
 
         newTaxonNode = null;
-        dao.saveOrUpdate(child);
-
+        MergeResult<TaxonNode> mergeNode = dao.merge(child,true);
+        child = mergeNode.getMergedEntity();
         result.addUpdatedObject(child.getParent());
-        if (child != null){
-            result.setCdmEntity(child);
-        }
+        result.setCdmEntity(child);
         return result;
-
-
     }
 
-
-
     @Override
     @Transactional
-    public UpdateResult createNewTaxonNode(UUID parentNodeUuid, UUID taxonUuid, Reference ref, String microref){
+    public UpdateResult createNewTaxonNode(UUID parentNodeUuid, UUID taxonUuid, UUID refUuid, String microref){
         UpdateResult result = new UpdateResult();
         TaxonNode parent = dao.load(parentNodeUuid);
         Taxon taxon = (Taxon) taxonService.load(taxonUuid);
@@ -945,7 +961,6 @@ public class TaxonNodeServiceImpl
             result.setCdmEntity(child);
         }
         return result;
-
     }
 
     @Override
@@ -1017,7 +1032,6 @@ public class TaxonNodeServiceImpl
         return result;
     }
 
-
     @Override
     @Transactional(readOnly=false)
     public UpdateResult setPublishForSubtree(PublishForSubtreeConfigurator config){
@@ -1039,6 +1053,8 @@ public class TaxonNodeServiceImpl
         boolean publish = config.isPublish();
         boolean includeSynonyms = config.isIncludeSynonyms();
         boolean includeSharedTaxa = config.isIncludeSharedTaxa();
+        boolean includeHybrids = config.isIncludeHybrids();
+        boolean includeRelatedTaxa = config.isIncludeProParteSynonyms() || config.isIncludeMisapplications();
         if (subTree == null){
             result.setError();
             result.addException(new NullPointerException("Subtree does not exist"));
@@ -1046,37 +1062,44 @@ public class TaxonNodeServiceImpl
             return result;
         }else{
             subTreeIndex = TreeIndex.NewInstance(subTree.treeIndex());
-            int count = includeAcceptedTaxa ? dao.countPublishForSubtreeAcceptedTaxa(subTreeIndex, publish, includeSharedTaxa):0;
-            count += includeSynonyms ? dao.countPublishForSubtreeSynonyms(subTreeIndex, publish, includeSharedTaxa):0;
+            int count = includeAcceptedTaxa ? dao.countPublishForSubtreeAcceptedTaxa(subTreeIndex, publish, includeSharedTaxa, includeHybrids):0;
+            count += includeSynonyms ? dao.countPublishForSubtreeSynonyms(subTreeIndex, publish, includeSharedTaxa, includeHybrids):0;
+            count += includeRelatedTaxa ? dao.countPublishForSubtreeRelatedTaxa(subTreeIndex, publish, includeSharedTaxa, includeHybrids):0;
             monitor.beginTask("Update publish flag", count);
         }
 
 
         if (includeAcceptedTaxa){
             monitor.subTask("Update Accepted Taxa");
-            Set<TaxonBase> updatedTaxa = dao.setPublishForSubtreeAcceptedTaxa(subTreeIndex, publish, includeSharedTaxa, monitor);
+            @SuppressWarnings("rawtypes")
+            Set<TaxonBase> updatedTaxa = dao.setPublishForSubtreeAcceptedTaxa(subTreeIndex, publish, includeSharedTaxa, includeHybrids, monitor);
             result.addUpdatedObjects(updatedTaxa);
         }
         if (includeSynonyms){
             monitor.subTask("Update Synonyms");
-            Set<TaxonBase> updatedSynonyms = dao.setPublishForSubtreeSynonyms(subTreeIndex, publish, includeSharedTaxa, monitor);
+            @SuppressWarnings("rawtypes")
+            Set<TaxonBase> updatedSynonyms = dao.setPublishForSubtreeSynonyms(subTreeIndex, publish, includeSharedTaxa, includeHybrids, monitor);
             result.addUpdatedObjects(updatedSynonyms);
         }
-
+        if (includeRelatedTaxa){
+            monitor.subTask("Update Related Taxa");
+            Set<UUID> relationTypes = new HashSet<>();
+            if (config.isIncludeMisapplications()){
+                relationTypes.addAll(TaxonRelationshipType.misappliedNameUuids());
+            }
+            if (config.isIncludeProParteSynonyms()){
+                relationTypes.addAll(TaxonRelationshipType.proParteOrPartialSynonymUuids());
+            }
+            @SuppressWarnings("rawtypes")
+            Set<TaxonBase> updatedTaxa = dao.setPublishForSubtreeRelatedTaxa(subTreeIndex, publish,
+                    relationTypes, includeSharedTaxa, includeHybrids, monitor);
+            result.addUpdatedObjects(updatedTaxa);
+        }
 
         monitor.done();
         return result;
     }
 
-    @Override
-    @Transactional(readOnly=false)
-    @Deprecated
-    public UpdateResult setPublishForSubtree(UUID subtreeUuid, boolean publish, boolean includeAcceptedTaxa,
-            boolean includeSynonyms, boolean includeSharedTaxa, IProgressMonitor monitor) {
-        PublishForSubtreeConfigurator configurator = new PublishForSubtreeConfigurator(subtreeUuid, publish, monitor);
-        return setPublishForSubtree(configurator);
-    }
-
     @Override
     public long count(TaxonNodeFilter filter){
         return nodeFilterDao.count(filter);
@@ -1137,23 +1160,36 @@ public class TaxonNodeServiceImpl
     }
 
     @Override
-    public List<TaxonDistributionDTO> getTaxonDistributionDTOForSubtree(UUID parentNodeUuid, List<String> propertyPaths){
-        List<TaxonNode> nodes = listChildrenOf(load(parentNodeUuid), null, null,
-               true, true, propertyPaths);
+    public List<TaxonDistributionDTO> getTaxonDistributionDTO(List<UUID> nodeUuids, List<String> propertyPaths, Authentication authentication, boolean openChildren){
+        Set<TaxonNode> nodes = new HashSet<>();
+        if (openChildren){
+            List<TaxonNode> parentNodes = load(nodeUuids, propertyPaths);
+            for (TaxonNode node: parentNodes){
+                nodes.addAll(listChildrenOf(node, null, null, true, true, propertyPaths));
+            }
+            nodes.addAll(parentNodes);
+
+        }
         List<TaxonDistributionDTO> result = new ArrayList<>();
+        boolean hasPermission = false;
+        //TaxonDescription instance = TaxonDescription.NewInstance();
+        //hasPermission = permissionEvaluator.hasPermission(authentication, instance, Operation.UPDATE);
         for(TaxonNode node:nodes){
-            if (node.getTaxon() != null){
+            if (authentication != null ) {
+                hasPermission = permissionEvaluator.hasPermission(authentication, node, Operation.UPDATE);
+            }else {
+                hasPermission = true;
+            }
+            if (node.getTaxon() != null && hasPermission){
                 try{
                     TaxonDistributionDTO dto = new TaxonDistributionDTO(node.getTaxon());
                     result.add(dto);
                 }catch(Exception e){
-                    System.err.println(node.getTaxon().getTitleCache());
+                    logger.error(e.getMessage(), e);
                 }
-
             }
-
         }
-
+        result.sort(new TaxonDistributionDTOComparator());
         return result;
     }
 
@@ -1178,5 +1214,15 @@ public class TaxonNodeServiceImpl
         return pager;
     }
 
+//    @Override
+//    public List<TaxonDistributionDTO> getTaxonDistributionDTOForSubtree(UUID parentNodeUuid,
+//            List<String> propertyPaths, boolean openChildren) {
+//        return getTaxonDistributionDTOForSubtree(parentNodeUuid, propertyPaths, null, openChildren);
+//    }
 
+    @Override
+    public List<TaxonDistributionDTO> getTaxonDistributionDTO(List<UUID> nodeUuids,
+            List<String> propertyPaths, boolean openChildren) {
+        return getTaxonDistributionDTO(nodeUuids, propertyPaths, null, openChildren);
+    }
 }