cleanup and allow merge with objectsToRemove in all services
authorAndreas Müller <a.mueller@bgbm.org>
Thu, 28 Jul 2022 17:20:05 +0000 (19:20 +0200)
committerAndreas Müller <a.mueller@bgbm.org>
Thu, 28 Jul 2022 17:20:05 +0000 (19:20 +0200)
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/common/ICdmEntityDao.java
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/common/ICdmGenericDao.java
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/hibernate/common/CdmEntityDaoBase.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IPolytomousKeyNodeService.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IPolytomousKeyService.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IService.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/PolytomousKeyServiceImpl.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/ServiceBase.java

index 7438eff75d85fbdb16351af03190d7a1616cee19..25d8465f067d4dee26e4ed3d7d81fe0b0d67dce5 100644 (file)
@@ -40,7 +40,15 @@ public interface ICdmEntityDao<T extends CdmBase> {
 
     public <S extends T> S save(S newInstance) throws DataAccessException;
 
-    public T merge(T transientObject) throws DataAccessException;
+    public T merge(T transientEntity) throws DataAccessException;
+
+    /**
+     * Same as {@link #merge(CdmBase)} but with the possibility to fully remove
+     * further objects from the database during the same session.
+     * This may become necessary if these objects were deleted from the detached object graph
+     * and are not handled via Cascade.REMOVE or orphanRemoval.
+     */
+    public T merge(T transientEntity, Collection<CdmBase> removedObjects) throws DataAccessException;
 
     /**
      * This method allows for the possibility of returning the input transient
@@ -53,12 +61,12 @@ public interface ICdmEntityDao<T extends CdmBase> {
      * This method returns the root merged transient entity as well as all newly merged
      * persistent entities within the return object.
      *
-     * @param transientObject
+     * @param transientEntity
      * @param returnTransientEntity
      * @return transient or persistent object depending on the value of returnTransientEntity
      * @throws DataAccessException
      */
-    public MergeResult<T> merge(T transientObject, boolean returnTransientEntity) throws DataAccessException;
+    public MergeResult<T> merge(T transientEntity, boolean returnTransientEntity) throws DataAccessException;
 
     /**
      * Obtains the specified LockMode on the supplied object
index e0d8d0d8c8c266e918afb2ce943b15a10566505e..6fb12e1da095b3e2bdb12bbfe792c3b40d0da1bf 100644 (file)
@@ -99,7 +99,7 @@ public interface ICdmGenericDao {
         * @throws NullPointerException
         * @throws MergeException
         */
-       public <T extends CdmBase> void   merge(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException;
+       public <T extends CdmBase> void merge(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException;
 
        /**
         * Computes if cdmBase2 can be merged into cdmBase1. This is usually the case when both
@@ -118,7 +118,7 @@ public interface ICdmGenericDao {
         * @throws NullPointerException
         * @throws MergeException
         */
-       public <T extends CdmBase> boolean  isMergeable(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException;
+       public <T extends CdmBase> boolean isMergeable(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException;
 
        /**
      * Returns a list of matching persistent objects according to the match strategy
index 75a422871b2fb0e85e7670c01ebf41863d5a5956..2342b09cf0fcb467620a55cf586e45557beba8b4 100644 (file)
@@ -60,6 +60,7 @@ import eu.etaxonomy.cdm.model.common.VersionableEntity;
 import eu.etaxonomy.cdm.model.permission.User;
 import eu.etaxonomy.cdm.model.view.AuditEvent;
 import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
+import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
 import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
 import eu.etaxonomy.cdm.persistence.dao.common.Restriction.Operator;
 import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
@@ -78,10 +79,13 @@ public abstract class CdmEntityDaoBase<T extends CdmBase>
         extends DaoBase
         implements ICdmEntityDao<T> {
 
-    private static final Logger logger = LogManager.getLogger(CdmEntityDaoBase.class);
+    private static final Logger logger = LogManager.getLogger();
+
+    @Autowired
+    private ICdmGenericDao genericDao;
 
     protected int flushAfterNo = 1000; // large numbers may cause synchronisation errors
-                                        // when commiting the session
+                                        // when committing the session
     protected Class<T> type;
 
     @Autowired
@@ -311,6 +315,18 @@ public abstract class CdmEntityDaoBase<T extends CdmBase>
         return persistentObject;
     }
 
+    @Override
+    public T merge(T transientEntity, Collection<CdmBase> detachedObjectsToRemove) throws DataAccessException{
+        T result = merge(transientEntity);
+        for (CdmBase detachedObject : detachedObjectsToRemove) {
+            CdmBase persistedObject = genericDao.find(CdmBase.deproxy(detachedObject.getClass()), detachedObject.getUuid());
+            if (persistedObject != null) {
+                genericDao.delete(persistedObject);
+            }
+        }
+        return result;
+    }
+
     @Override
     public UUID saveOrUpdate(T transientObject) throws DataAccessException {
         if (transientObject == null) {
index 221b2208bbf0e9dd260b4a8866afdc8b6ec4d419..31ffde6ac9795e9c640864bf664951032ac6b546 100644 (file)
@@ -1,25 +1,23 @@
-/**\r
-* Copyright (C) 2009 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
-package eu.etaxonomy.cdm.api.service;\r
-\r
-import java.util.UUID;\r
-\r
-import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;\r
-\r
-/**\r
- * @author a.kohlbecker\r
- * @since 24.03.2011\r
- *\r
- */\r
-public interface IPolytomousKeyNodeService extends IVersionableService<PolytomousKeyNode> {\r
-\r
-    public DeleteResult delete(UUID nodeUuid, boolean deleteChildren);\r
-\r
-\r
-}\r
+/**
+* Copyright (C) 2009 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.UUID;
+
+import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;
+
+/**
+ * @author a.kohlbecker
+ * @since 24.03.2011
+ */
+public interface IPolytomousKeyNodeService extends IVersionableService<PolytomousKeyNode> {
+
+    public DeleteResult delete(UUID nodeUuid, boolean deleteChildren);
+
+}
index c360fe38ff2c521568aa2bfcbc7a0189be7a8ba8..c3059e1d36af0522ac79a595df0f79f25fab24d7 100644 (file)
@@ -1,50 +1,50 @@
-/**\r
-* Copyright (C) 2009 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.List;\r
-import java.util.UUID;\r
-\r
-import eu.etaxonomy.cdm.api.service.pager.Pager;\r
-import eu.etaxonomy.cdm.model.description.PolytomousKey;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
-\r
-public interface IPolytomousKeyService extends IIdentifiableEntityService<PolytomousKey> {\r
-\r
-       /**\r
-        * Loads a polytomous key including all of its nodes (all the way down to the tips of the tree).\r
-        * Because this method automatically adds key nodes recursively, adding "root" to property paths\r
-        * is superfluous - the propertyPaths argument should be used to initialize property paths <i>in addition</i>\r
-        * to the key nodes. The nodePaths argument is applied to each node in turn, so again, adding "children"\r
-        * is also superfluous. The nodePaths argument should be used to specify additional properties of the\r
-        * key node to initialize.\r
-        *\r
-        */\r
-       public PolytomousKey loadWithNodes(UUID uuid, List<String> propertyPaths, List<String> nodePaths);\r
-\r
-       public Pager<PolytomousKey> findByTaxonomicScope(TaxonBase taxon, Integer pageSize,\r
-                       Integer pageNumber, List<String> propertyPaths, List<String> nodePaths);\r
-\r
-    /**\r
-     * Refreshes all node numberings recursively from the root node downwards.\r
-     *\r
-     * @param polytomousKeyUuid\r
-     * @return\r
-     */\r
-   public UpdateResult updateAllNodeNumberings(UUID polytomousKeyUuid);\r
-\r
-    /**\r
-     * Refreshes all node numberings for all polytomous keys recursively from the root node downwards.\r
-     *\r
-     * @return\r
-     */\r
-    public UpdateResult updateAllNodeNumberings();\r
-\r
-}\r
+/**
+* Copyright (C) 2009 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.List;
+import java.util.UUID;
+
+import eu.etaxonomy.cdm.api.service.pager.Pager;
+import eu.etaxonomy.cdm.model.description.PolytomousKey;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+
+public interface IPolytomousKeyService extends IIdentifiableEntityService<PolytomousKey> {
+
+       /**
+        * Loads a polytomous key including all of its nodes (all the way down to the tips of the tree).
+        * Because this method automatically adds key nodes recursively, adding "root" to property paths
+        * is superfluous - the propertyPaths argument should be used to initialize property paths <i>in addition</i>
+        * to the key nodes. The nodePaths argument is applied to each node in turn, so again, adding "children"
+        * is also superfluous. The nodePaths argument should be used to specify additional properties of the
+        * key node to initialize.
+        *
+        */
+       public PolytomousKey loadWithNodes(UUID uuid, List<String> propertyPaths, List<String> nodePaths);
+
+       public Pager<PolytomousKey> findByTaxonomicScope(TaxonBase taxon, Integer pageSize,
+                       Integer pageNumber, List<String> propertyPaths, List<String> nodePaths);
+
+    /**
+     * Refreshes all node numberings recursively from the root node downwards.
+     *
+     * @param polytomousKeyUuid
+     * @return
+     */
+   public UpdateResult updateAllNodeNumberings(UUID polytomousKeyUuid);
+
+    /**
+     * Refreshes all node numberings for all polytomous keys recursively from the root node downwards.
+     *
+     * @return
+     */
+    public UpdateResult updateAllNodeNumberings();
+
+}
index 32c063b3c5f5e2c8264bae8ad81c5d94465f8165..34571ed13f8d680f6a5266f7c8d62fe1d42b9bca 100644 (file)
@@ -22,6 +22,7 @@ import org.hibernate.criterion.Criterion;
 import org.hibernate.event.spi.MergeEvent;
 
 import eu.etaxonomy.cdm.api.service.pager.Pager;
+import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.ICdmBase;
 import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
 import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
@@ -273,6 +274,8 @@ public interface IService<T extends ICdmBase>{
      */
     public T merge(T detachedObject);
 
+    public T merge(T detachedObject, CdmBase... removedObjects);
+
     /**
      * Returns a paged list of entities of type <T> optionally restricted
      * to objects belonging to a class that that extends <T>
index 19618701b7f18d53e15368954f7bbdc528a3bd6b..7c3c6dd1c28821bb42bb3a04288c4786a8a0466d 100644 (file)
@@ -6,7 +6,6 @@
 * 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;
@@ -36,7 +35,9 @@ import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
 
 @Service
 @Transactional(readOnly = false)
-public class PolytomousKeyServiceImpl extends IdentifiableServiceBase<PolytomousKey, IPolytomousKeyDao> implements IPolytomousKeyService {
+public class PolytomousKeyServiceImpl
+        extends IdentifiableServiceBase<PolytomousKey, IPolytomousKeyDao>
+        implements IPolytomousKeyService {
 
        private IIdentificationKeyDao identificationKeyDao;
 
index 0af7204980fb360c25d67497ca8d4ad730a99157..ffd1bcb1f67534c90d29e7bd94ca05d646f8c7c6 100644 (file)
@@ -10,6 +10,7 @@
 package eu.etaxonomy.cdm.api.service;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -232,6 +233,18 @@ public abstract class ServiceBase<T extends CdmBase, DAO extends ICdmEntityDao<T
         return dao.merge(newInstance);
     }
 
+    /**
+     * Same as #merge(T) but with the possibility to fully remove further entities
+     * from the database during the same session. This may become necessary if these
+     * entities were deleted from the detached object graph and are not handled
+     * via Cascade.REMOVE or orphanRemoval, e.g. when children were removed
+     * from its parents and not used elsewhere anymore.
+     */
+    @Override
+    public T merge(T detachedObject, CdmBase... removedObjects) {
+        return dao.merge(detachedObject, Arrays.asList(removedObjects));
+    }
+
     @Override
     @Transactional(readOnly = false)
     public MergeResult<T> merge(T newInstance, boolean returnTransientEntity) {