ref #9481: move the descriptions to the new taxon to avoid DDS when deleting the...
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / TaxonServiceImpl.java
index ac30060871104e556b8b0d8c2907332f3a5f60f5..8162c1fbf33f0b85c83f8e24c2e34ba7f774edca 100644 (file)
@@ -11,6 +11,7 @@ package eu.etaxonomy.cdm.api.service;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -66,6 +67,8 @@ import eu.etaxonomy.cdm.api.service.search.SearchResult;
 import eu.etaxonomy.cdm.api.service.search.SearchResultBuilder;
 import eu.etaxonomy.cdm.api.service.util.TaxonRelationshipEdge;
 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
+import eu.etaxonomy.cdm.compare.taxon.HomotypicGroupTaxonComparator;
+import eu.etaxonomy.cdm.compare.taxon.TaxonComparator;
 import eu.etaxonomy.cdm.exception.UnpublishedException;
 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
 import eu.etaxonomy.cdm.hibernate.search.AcceptedTaxonBridge;
@@ -94,6 +97,7 @@ import eu.etaxonomy.cdm.model.description.TaxonInteraction;
 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
 import eu.etaxonomy.cdm.model.location.NamedArea;
 import eu.etaxonomy.cdm.model.media.Media;
+import eu.etaxonomy.cdm.model.metadata.SecReferenceHandlingEnum;
 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
 import eu.etaxonomy.cdm.model.name.IZoologicalName;
 import eu.etaxonomy.cdm.model.name.Rank;
@@ -105,7 +109,6 @@ import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
 import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
 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.ITaxonTreeNode;
 import eu.etaxonomy.cdm.model.taxon.Synonym;
 import eu.etaxonomy.cdm.model.taxon.SynonymType;
@@ -165,6 +168,9 @@ public class TaxonServiceImpl
 
     @Autowired
     private IDescriptionService descriptionService;
+
+    @Autowired
+    private IReferenceService referenceService;
 //
 //    @Autowired
 //    private IOrderedTermVocabularyDao orderedVocabularyDao;
@@ -204,11 +210,12 @@ public class TaxonServiceImpl
         UpdateResult result = new UpdateResult();
        acceptedTaxon.removeSynonym(synonym);
        TaxonName synonymName = synonym.getName();
-       boolean sameHomotypicGroup = synonymName.getHomotypicalGroup().equals(acceptedTaxon.getName().getHomotypicalGroup());
+       TaxonName taxonName = HibernateProxyHelper.deproxy(acceptedTaxon.getName());
+
+       boolean sameHomotypicGroup = synonymName.getHomotypicalGroup().equals(taxonName.getHomotypicalGroup());
 
         synonymName.removeTaxonBase(synonym);
 
-        TaxonName taxonName = HibernateProxyHelper.deproxy(acceptedTaxon.getName(), TaxonName.class);
         //taxonName.removeTaxonBase(acceptedTaxon);
 
         List<Synonym> synonyms = new ArrayList<>();
@@ -219,9 +226,18 @@ public class TaxonServiceImpl
         for (Synonym syn: synonyms){
             acceptedTaxon.removeSynonym(syn);
         }
-        Taxon newTaxon = (Taxon)acceptedTaxon.clone();
+        Taxon newTaxon = acceptedTaxon.clone();
+        newTaxon.getDescriptions().clear();
+        Set<TaxonDescription> descriptionsToCopy = new HashSet<>();
+        for (TaxonDescription desc: acceptedTaxon.getDescriptions()){
+            descriptionsToCopy.add(desc);
+        }
+        for (TaxonDescription description: descriptionsToCopy){
+            newTaxon.addDescription(description);
+        }
         newTaxon.setName(synonymName);
         newTaxon.setSec(synonym.getSec());
+        newTaxon.setPublish(synonym.isPublish());
         for (Synonym syn: synonyms){
             if (!syn.getName().equals(newTaxon.getName())){
                 newTaxon.addSynonym(syn, syn.getType());
@@ -286,9 +302,10 @@ public class TaxonServiceImpl
             }
 
         }
-        Synonym newSynonym = (Synonym)synonym.clone();
+        Synonym newSynonym = synonym.clone();
         newSynonym.setName(taxonName);
         newSynonym.setSec(acceptedTaxon.getSec());
+        newSynonym.setPublish(acceptedTaxon.isPublish());
         if (sameHomotypicGroup){
             newTaxon.addSynonym(newSynonym, SynonymType.HOMOTYPIC_SYNONYM_OF());
         }else{
@@ -313,7 +330,7 @@ public class TaxonServiceImpl
 
     @Override
     @Transactional(readOnly = false)
-    public UpdateResult changeSynonymToAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon, boolean deleteSynonym) {
+    public UpdateResult changeSynonymToAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon, Reference newSecRef, String microRef, boolean deleteSynonym) {
         UpdateResult result = new UpdateResult();
         TaxonName acceptedName = acceptedTaxon.getName();
         TaxonName synonymName = synonym.getName();
@@ -326,8 +343,8 @@ public class TaxonServiceImpl
             result.setAbort();
             return result;
         }
-
-        Taxon newAcceptedTaxon = Taxon.NewInstance(synonymName, acceptedTaxon.getSec());
+        Taxon newAcceptedTaxon = Taxon.NewInstance(synonymName, newSecRef, microRef);
+        newAcceptedTaxon.setPublish(synonym.isPublish());
         dao.save(newAcceptedTaxon);
         result.setCdmEntity(newAcceptedTaxon);
         SynonymType relTypeForGroup = SynonymType.HOMOTYPIC_SYNONYM_OF();
@@ -364,19 +381,51 @@ public class TaxonServiceImpl
     public UpdateResult changeSynonymToAcceptedTaxon(UUID synonymUuid,
             UUID acceptedTaxonUuid,
             UUID newParentNodeUuid,
+            UUID newSec,
+            String microReference,
+            SecReferenceHandlingEnum secHandling,
             boolean deleteSynonym)  {
         UpdateResult result = new UpdateResult();
         Synonym synonym = CdmBase.deproxy(dao.load(synonymUuid), Synonym.class);
         Taxon acceptedTaxon = CdmBase.deproxy(dao.load(acceptedTaxonUuid), Taxon.class);
-        result =  changeSynonymToAcceptedTaxon(synonym, acceptedTaxon, deleteSynonym);
-        Taxon newTaxon = (Taxon)result.getCdmEntity();
         TaxonNode newParentNode = taxonNodeDao.load(newParentNodeUuid);
+        Reference newSecRef = null;
+        switch (secHandling){
+            case AlwaysDelete:
+                newSecRef = null;
+                break;
+            case KeepAlways:
+                newSecRef = synonym.getSec();
+                break;
+            case UseNewParentSec:
+                newSecRef = newParentNode.getTaxon() != null? newParentNode.getTaxon().getSec(): null;
+                break;
+            case KeepWhenSame:
+                Reference parentSec = newParentNode.getTaxon() != null? newParentNode.getTaxon().getSec(): null;
+                Reference synSec = synonym.getSec();
+                if (parentSec != null && synSec != null && parentSec.equals(synSec)){
+                    newSecRef = synonym.getSec();
+                }else{
+                    newSecRef = CdmBase.deproxy(referenceService.load(newSec));
+                }
+            case WarningSelect:
+                newSecRef = CdmBase.deproxy(referenceService.load(newSec));
+
+            default:
+                break;
+        }
+
+
+        result =  changeSynonymToAcceptedTaxon(synonym, acceptedTaxon, newSecRef, microReference, deleteSynonym);
+        Taxon newTaxon = (Taxon)result.getCdmEntity();
+
         TaxonNode newNode = newParentNode.addChildTaxon(newTaxon, null, null);
         taxonNodeDao.save(newNode);
         result.addUpdatedObject(newTaxon);
         result.addUpdatedObject(acceptedTaxon);
         result.setCdmEntity(newNode);
         return result;
+
     }
 
     @Override
@@ -415,6 +464,7 @@ public class TaxonServiceImpl
 */
         // Create a taxon with synonym name
         Taxon fromTaxon = Taxon.NewInstance(synonymName, null);
+        fromTaxon.setPublish(synonym.isPublish());
         save(fromTaxon);
         fromTaxon.setAppendedPhrase(synonym.getAppendedPhrase());
 
@@ -1028,8 +1078,8 @@ public class TaxonServiceImpl
                 configRelTaxon.setDeleteConceptRelationships(true);
 
                 for (TaxonRelationship taxRel: taxon.getTaxonRelations()){
-                    if (config.isDeleteMisappliedNamesAndInvalidDesignations()
-                            && taxRel.getType().isMisappliedNameOrInvalidDesignation()
+                    if (config.isDeleteMisappliedNames()
+                            && taxRel.getType().isMisappliedName()
                             && taxon.equals(taxRel.getToTaxon())){
                         this.deleteTaxon(taxRel.getFromTaxon().getUuid(), config, classificationUuid);
                     } else if (config.isDeleteConceptRelationships() && taxRel.getType().isConceptRelationship()){
@@ -1449,7 +1499,8 @@ public class TaxonServiceImpl
     }
 
     @Override
-    public <T extends TaxonBase> List<UuidAndTitleCache<T>> getUuidAndTitleCache(Class<T> clazz, Integer limit, String pattern) {
+    public <T extends TaxonBase>List<UuidAndTitleCache<T>> getUuidAndTitleCache(Class<T> clazz, Integer limit, String pattern) {
+
         return dao.getUuidAndTitleCache(clazz, limit, pattern);
     }
 
@@ -1490,15 +1541,15 @@ public class TaxonServiceImpl
     @Override
     public <S extends TaxonBase> Pager<S> findByTitleWithRestrictions(Class<S> clazz, String queryString, MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
          long numberOfResults = dao.countByTitleWithRestrictions(clazz, queryString, matchmode, restrictions);
-         numberOfResults = numberOfResults + dao.countByTitleWithRestrictions(clazz, "?".concat(queryString), matchmode, restrictions);
 
+         long numberOfResults_doubtful = dao.countByTitleWithRestrictions(clazz, "?".concat(queryString), matchmode, restrictions);
          List<S> results = new ArrayList<>();
-         if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+         if(numberOfResults > 0 || numberOfResults_doubtful > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
 
              results = dao.findByTitleWithRestrictions(clazz, queryString, matchmode, restrictions, pageSize, pageNumber, orderHints, propertyPaths);
              results.addAll(dao.findByTitleWithRestrictions(clazz, "?".concat(queryString), matchmode, restrictions, pageSize, pageNumber, orderHints, propertyPaths));
          }
-
+         Collections.sort(results, new TaxonComparator());
          return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
     }
 
@@ -1519,7 +1570,7 @@ public class TaxonServiceImpl
                    results.addAll(dao.findByTitle(clazz, "?".concat(queryString), matchmode,  criteria, pageSize, pageNumber, orderHints, propertyPaths));
                }
         }
-
+        Collections.sort(results, new TaxonComparator());
         return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
     }
 
@@ -2981,10 +3032,27 @@ public class TaxonServiceImpl
             Taxon taxon = (Taxon)load(taxonBaseUuid, propertyPaths);
 
             result = isDeletableForTaxon(references, taxonConfig );
+
+            if (taxonConfig.isDeleteNameIfPossible()){
+                if (taxonBase.getName() != null){
+                    DeleteResult nameResult = nameService.isDeletable(taxonBase.getName().getUuid(), taxonConfig.getNameDeletionConfig(), taxon.getUuid());
+                    if (!nameResult.isOk()){
+                        result.addExceptions(nameResult.getExceptions());
+                    }
+                }
+
+            }
         }else{
             SynonymDeletionConfigurator synonymConfig = (SynonymDeletionConfigurator) config;
             result = isDeletableForSynonym(references, synonymConfig);
+            if (synonymConfig.isDeleteNameIfPossible()){
+                DeleteResult nameResult = nameService.isDeletable(taxonBase.getName().getUuid(), synonymConfig.getNameDeletionConfig(), taxonBase.getUuid());
+                if (!nameResult.isOk()){
+                    result.addExceptions(nameResult.getExceptions());
+                }
+            }
         }
+
         return result;
     }
 
@@ -2998,6 +3066,7 @@ public class TaxonServiceImpl
                 result.addRelatedObject(ref);
                 result.setAbort();
             }
+
         }
 
         return result;
@@ -3025,8 +3094,8 @@ public class TaxonServiceImpl
 
                 }
                 if (!config.isDeleteTaxonRelationships() && (ref instanceof TaxonRelationship)){
-                    if (!config.isDeleteMisappliedNamesAndInvalidDesignations() &&
-                            (((TaxonRelationship)ref).getType().isMisappliedNameOrInvalidDesignation())){
+                    if (!config.isDeleteMisappliedNames() &&
+                            (((TaxonRelationship)ref).getType().isMisappliedName())){
                         message = "The taxon can't be deleted as long as it has misapplied names or invalid designations.";
                     } else{
                         message = "The taxon can't be deleted as long as it belongs to taxon relationship.";
@@ -3274,7 +3343,7 @@ public class TaxonServiceImpl
                return result;
        }
 
-       @Override
+    @Override
        public UpdateResult moveFactualDateToAnotherTaxon(UUID fromTaxonUuid, UUID toTaxonUuid){
                UpdateResult result = new UpdateResult();