diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java
index d1b5d5f907..2306424f57 100644
--- a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java
+++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java
@@ -702,6 +702,7 @@ public abstract class BaseAPI
public enum RM_ACTIONS
{
EDIT_DISPOSITION_DATE("editDispositionActionAsOfDate"),
+ END_RETENTION("retain"),
CUT_OFF("cutoff"),
UNDO_CUT_OFF("undoCutoff"),
TRANSFER("transfer"),
diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/PreventActionsOnFrozenContentTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/PreventActionsOnFrozenContentTests.java
index a21d2b69f4..6abe3d69b9 100644
--- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/PreventActionsOnFrozenContentTests.java
+++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/hold/PreventActionsOnFrozenContentTests.java
@@ -47,6 +47,7 @@ import java.io.File;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.core.JsonBodyGenerator;
+import org.alfresco.rest.core.v0.BaseAPI.RM_ACTIONS;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.common.ReviewPeriod;
import org.alfresco.rest.rm.community.model.record.Record;
@@ -55,6 +56,7 @@ import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.rm.community.model.recordfolder.RecordFolder;
import org.alfresco.rest.rm.community.model.recordfolder.RecordFolderProperties;
import org.alfresco.rest.v0.HoldsAPI;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.service.DispositionScheduleService;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
@@ -81,6 +83,7 @@ public class PreventActionsOnFrozenContentTests extends BaseRMRestTest
private static FolderModel folderModel;
private static RecordCategoryChild recordFolder;
private static Record recordFrozen, recordNotHeld;
+ private static RecordCategory categoryWithRS;
@Autowired
private HoldsAPI holdsAPI;
@@ -88,6 +91,9 @@ public class PreventActionsOnFrozenContentTests extends BaseRMRestTest
@Autowired
private DispositionScheduleService dispositionScheduleService;
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+
@BeforeClass (alwaysRun = true)
public void preconditionForPreventActionsOnFrozenContent() throws Exception
{
@@ -276,12 +282,52 @@ public class PreventActionsOnFrozenContentTests extends BaseRMRestTest
assertNotNull(folderWithRS.getProperties().getRecordSearchDispositionInstructions());
}
+
+ /**
+ * Given a record category with a disposition schedule applied to records
+ * And the disposition schedule has a retain step immediately and destroy step immediately
+ * And a complete record added to one hold
+ * When I execute the retain action
+ * Then the action is executed
+ * And the record search disposition schedule properties are updated
+ *
+ * @throws Exception
+ */
+ @Test
+ @AlfrescoTest (jira = "RM-6931")
+ public void retainActionOnFrozenHeldRecords() throws Exception
+ {
+ STEP("Add a category with a disposition schedule.");
+ categoryWithRS = createRootCategory(getRandomName("CategoryWithRS"));
+ dispositionScheduleService.createCategoryRetentionSchedule(categoryWithRS.getName(), true);
+ dispositionScheduleService.addRetainAfterPeriodStep(categoryWithRS.getName(), "immediately");
+ dispositionScheduleService.addDestroyWithGhostingAfterPeriodStep(categoryWithRS.getName(), "immediately");
+
+ STEP("Create record folder with a record.");
+ RecordCategoryChild folder = createFolder(categoryWithRS.getId(), getRandomName("RecFolder"));
+ Record record = createElectronicRecord(folder.getId(), getRandomName("elRecord"));
+ completeRecord(record.getId());
+
+ STEP("Add the record to the hold");
+ holdsAPI.addItemToHold(getAdminUser().getUsername(), getAdminUser().getPassword(), record.getId(), HOLD_ONE);
+
+ STEP("Execute the retain action");
+ rmRolesAndActionsAPI.executeAction(getAdminUser().getUsername(), getAdminUser().getPassword(), record.getName(),
+ RM_ACTIONS.END_RETENTION);
+
+ STEP("Check the record search disposition properties");
+ Record recordUpdated = getRestAPIFactory().getRecordsAPI().getRecord(record.getId());
+ assertTrue(recordUpdated.getProperties().getRecordSearchDispositionActionName().contains(RM_ACTIONS.DESTROY.getAction()));
+ assertTrue(recordUpdated.getProperties().getRecordSearchDispositionPeriod().contains("immediately"));
+ }
+
@AfterClass (alwaysRun = true)
public void cleanUpPreventActionsOnFrozenContent() throws Exception
{
holdsAPI.deleteHold(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD_ONE);
dataSite.usingAdmin().deleteSite(testSite);
getRestAPIFactory().getRecordCategoryAPI().deleteRecordCategory(recordFolder.getParentId());
+ getRestAPIFactory().getRecordCategoryAPI().deleteRecordCategory(categoryWithRS.getId());
}
}
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/content-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/content-context.xml
index 7e9807e15b..d8e94ea0ba 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/content-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/content-context.xml
@@ -18,6 +18,7 @@
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/log4j.properties b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/log4j.properties
index 76742abc10..f5ecef752f 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/log4j.properties
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/log4j.properties
@@ -56,4 +56,5 @@ log4j.logger.org.alfresco.module.org_alfresco_module_rm.patch=info
# Job debug
#
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.job=debug
-log4j.logger.org.alfresco.repo.web.scripts.roles.DynamicAuthoritiesGet=info
\ No newline at end of file
+log4j.logger.org.alfresco.repo.web.scripts.roles.DynamicAuthoritiesGet=info
+log4j.logger.org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAOImpl=info
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml
index f182740df2..d999b109d7 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml
@@ -251,6 +251,8 @@
+
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml
index 766c80c519..457b70432e 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml
@@ -7,6 +7,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMapConfig.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMapConfig.xml
index 8144e44bf6..fd97f207cb 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMapConfig.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMapConfig.xml
@@ -2,6 +2,11 @@
+
+
+
+
+
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/ContentDestructionComponent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/ContentDestructionComponent.java
index fb77f3efb6..b86b1b0c2a 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/ContentDestructionComponent.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/ContentDestructionComponent.java
@@ -33,6 +33,7 @@ import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.model.RenditionModel;
+import org.alfresco.module.org_alfresco_module_rm.util.ContentBinDuplicationUtility;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -63,6 +64,9 @@ public class ContentDestructionComponent
/** behaviour filter */
private BehaviourFilter behaviourFilter;
+ /** Utility class for duplicating content */
+ private ContentBinDuplicationUtility contentBinDuplicationUtility;
+
/** indicates whether cleansing is enabled or not */
private boolean cleansingEnabled = false;
@@ -138,6 +142,15 @@ public class ContentDestructionComponent
this.behaviourFilter = behaviourFilter;
}
+ /**
+ * Setter for content duplication utility class
+ * @param contentBinDuplicationUtility ContentBinDuplicationUtility
+ */
+ public void setContentBinDuplicationUtility(ContentBinDuplicationUtility contentBinDuplicationUtility)
+ {
+ this.contentBinDuplicationUtility = contentBinDuplicationUtility;
+ }
+
/**
* @param cleansingEnabled true if cleansing enabled, false otherwise
*/
@@ -214,16 +227,19 @@ public class ContentDestructionComponent
// get content data
ContentData dataContent = (ContentData)entry.getValue();
- // if enabled cleanse content
- if (isCleansingEnabled())
+ if (!contentBinDuplicationUtility.hasAtLeastOneOtherReference(nodeRef))
{
- // register for cleanse then immediate destruction
- getEagerContentStoreCleaner().registerOrphanedContentUrlForCleansing(dataContent.getContentUrl());
- }
- else
- {
- // register for immediate destruction
- getEagerContentStoreCleaner().registerOrphanedContentUrl(dataContent.getContentUrl(), true);
+ // if enabled cleanse content
+ if (isCleansingEnabled())
+ {
+ // register for cleanse then immediate destruction
+ getEagerContentStoreCleaner().registerOrphanedContentUrlForCleansing(dataContent.getContentUrl());
+ }
+ else
+ {
+ // register for immediate destruction
+ getEagerContentStoreCleaner().registerOrphanedContentUrl(dataContent.getContentUrl(), true);
+ }
}
// clear the property
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java
index b6e778e094..ed9f0ce31b 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java
@@ -587,7 +587,16 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel
}
}
- nodeService.setProperties(record, props);
+ try
+ {
+ //disable on properties update policy for the frozen aspect
+ frozenAspect.disableOnPropUpdateFrozenAspect();
+ nodeService.setProperties(record, props);
+ }
+ finally
+ {
+ frozenAspect.enableOnPropUpdateFrozenAspect();
+ }
if (logger.isDebugEnabled())
{
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java
index 88c29d63cd..a3c041fc9e 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java
@@ -61,4 +61,10 @@ public interface RecordsManagementQueryDAO
* @return list of distinct property values
*/
public Set getChildrenStringPropertyValues(NodeRef parent, QName property);
+
+ /**
+ * @param contentUrl the URL of the content url entity
+ * @return Set a set of nodes that reference the given content url
+ */
+ Set getNodeRefsWhichReferenceContentUrl(String contentUrl);
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java
index 57e879cc0b..a13a6fcd44 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java
@@ -30,17 +30,22 @@ package org.alfresco.module.org_alfresco_module_rm.query;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.repo.domain.contentdata.ContentUrlEntity;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.qname.QNameDAO;
import org.alfresco.repo.tenant.TenantService;
+import org.alfresco.repo.version.Version2Model;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.mybatis.spring.SqlSessionTemplate;
/**
@@ -51,8 +56,14 @@ import org.mybatis.spring.SqlSessionTemplate;
*/
public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, RecordsManagementModel
{
+ /** logger */
+ @SuppressWarnings ("unused")
+ private static final Log logger = LogFactory.getLog(RecordsManagementQueryDAOImpl.class);
+
+ /** query names */
private static final String COUNT_IDENTIFIER = "alfresco.query.rm.select_CountRMIndentifier";
private static final String GET_CHILDREN_PROPERTY_VALUES = "select_GetStringPropertyValuesOfChildren";
+ private static final String SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL = "select_NodeIdsWhichReferenceContentUrl";
/** SQL session template */
protected SqlSessionTemplate template;
@@ -143,4 +154,90 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
return new HashSet<>(template.selectList(GET_CHILDREN_PROPERTY_VALUES, queryParams));
}
+
+ /**
+ * Get a set of node reference which reference the provided content URL
+ *
+ * @return Set set of nodes that reference the provided content URL
+ * @param String contentUrl content URL
+ */
+ @Override
+ public Set getNodeRefsWhichReferenceContentUrl(String contentUrl)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Getting nodes that reference content URL = " + contentUrl);
+ }
+
+ // create the content URL entity used to query for nodes
+ ContentUrlEntity contentUrlEntity = new ContentUrlEntity();
+ contentUrlEntity.setContentUrl(contentUrl.toLowerCase());
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Executing query " + SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL);
+ }
+
+ // Get all the node ids which reference the given content url
+ List nodeIds = template.selectList(SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL, contentUrlEntity);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Query " + SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL + " returned " + nodeIds.size() + " results");
+ }
+
+ // create a set of uuids which reference the content url
+ Set nodesReferencingContentUrl = new HashSet(nodeIds.size());
+ for (Long nodeId : nodeIds)
+ {
+ StringBuilder logMessage = null;
+ NodeRef nodeRefToAdd;
+
+ if (nodeId != null && nodeDAO.exists(nodeId))
+ {
+ if (logger.isDebugEnabled())
+ {
+ logMessage = new StringBuilder("Adding noderef ");
+ }
+
+ // if the referencing node is a version2Store reference to the content url, add the version 2 frozen node ref
+ NodeRef version2FrozenNodeRef = (NodeRef) nodeDAO.getNodeProperty(nodeId, Version2Model.PROP_QNAME_FROZEN_NODE_REF);
+ if (version2FrozenNodeRef != null && nodeDAO.exists(version2FrozenNodeRef))
+ {
+ nodeRefToAdd = version2FrozenNodeRef;
+
+ if (logger.isDebugEnabled())
+ {
+ logMessage.append(nodeRefToAdd).append(" (from version)");
+ }
+ }
+
+ // add the node ref of the referencing node
+ else
+ {
+ nodeRefToAdd = nodeDAO.getNodeIdStatus(nodeId).getNodeRef();
+ if (logger.isDebugEnabled())
+ {
+ logMessage.append(nodeRefToAdd);
+ }
+ }
+
+ nodesReferencingContentUrl.add(nodeRefToAdd);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(logMessage.toString());
+ }
+ }
+ else
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Not adding " + nodeId + " (exist==false)");
+ }
+ }
+ }
+
+ return nodesReferencingContentUrl;
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtility.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtility.java
index 417bd924a2..c1d6f31643 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtility.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtility.java
@@ -27,11 +27,15 @@
package org.alfresco.module.org_alfresco_module_rm.util;
import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
+import java.util.Set;
+
/**
* Utility class to duplicate the content of a node without triggering the audit or versioning behaviours
* @author Ross Gale
@@ -44,6 +48,14 @@ public class ContentBinDuplicationUtility extends ServiceBaseImpl
*/
private BehaviourFilter behaviourFilter;
+ /**
+ * Provides methods for accessing and transforming content.
+ */
+ private ContentService contentService;
+
+ /** Records Management Query DAO */
+ private RecordsManagementQueryDAO recordsManagementQueryDAO;
+
/**
* Setter for behaviour filter
* @param behaviourFilter BehaviourFilter
@@ -53,6 +65,44 @@ public class ContentBinDuplicationUtility extends ServiceBaseImpl
this.behaviourFilter = behaviourFilter;
}
+ /**
+ * Setter for content service
+ * @param contentService ContentService
+ */
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
+ /**
+ * Setter for the Records Management QueryDAO
+ *
+ * @param recordsManagementQueryDAO The RM query DAO to set
+ */
+ public void setRecordsManagementQueryDAO(RecordsManagementQueryDAO recordsManagementQueryDAO)
+ {
+ this.recordsManagementQueryDAO = recordsManagementQueryDAO;
+ }
+
+ /**
+ * Determines whether the bin file for a given node has at least one other reference to it
+ * Will return true if the binary exists and is referenced by at least one other node
+ * @param nodeRef Node with the binary in question
+ * @return boolean for if the bin has at least one other reference to it
+ */
+ public boolean hasAtLeastOneOtherReference(NodeRef nodeRef)
+ {
+ boolean hasAtLeastOneOtherReference = false;
+ String contentUrl = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT).getContentUrl();
+
+ Set referencesToContentNode = recordsManagementQueryDAO.getNodeRefsWhichReferenceContentUrl(contentUrl);
+ if (referencesToContentNode.size() > 1)
+ {
+ hasAtLeastOneOtherReference = true;
+ }
+ return hasAtLeastOneOtherReference;
+ }
+
/**
* Duplicate the content of a node without triggering the audit or versioning behaviours
*
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtilityUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtilityUnitTest.java
index b5dcd55d56..df5844b62d 100644
--- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtilityUnitTest.java
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtilityUnitTest.java
@@ -28,11 +28,18 @@
package org.alfresco.module.org_alfresco_module_rm.util;
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASPECT_ARCHIVED;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
@@ -52,6 +59,9 @@ import org.mockito.MockitoAnnotations;
*/
public class ContentBinDuplicationUtilityUnitTest
{
+ private final static NodeRef NODE_REF = new NodeRef("some://test/noderef");
+ private final static NodeRef NODE_REF2 = new NodeRef("some://test/anothernoderef");
+ private final static String CONTENT_URL = "someContentUrl";
@Mock
private ContentService mockContentService;
@@ -67,6 +77,9 @@ public class ContentBinDuplicationUtilityUnitTest
@Mock
private NodeService mockNodeService;
+ @Mock
+ private RecordsManagementQueryDAO recordsManagementQueryDAO;
+
@InjectMocks
private ContentBinDuplicationUtility contentBinDuplicationUtility;
@@ -82,10 +95,9 @@ public class ContentBinDuplicationUtilityUnitTest
@Test
public void testContentUrlIsUpdated()
{
- NodeRef nodeRef = new NodeRef("some://test/noderef");
- when(mockContentService.getReader(nodeRef, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
- when(mockContentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true)).thenReturn(mockContentWriter);
- contentBinDuplicationUtility.duplicate(nodeRef);
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
+ when(mockContentService.getWriter(NODE_REF, ContentModel.PROP_CONTENT, true)).thenReturn(mockContentWriter);
+ contentBinDuplicationUtility.duplicate(NODE_REF);
verify(mockContentWriter, times(1)).putContent(mockContentReader);
checkBehaviours(1);
}
@@ -96,9 +108,8 @@ public class ContentBinDuplicationUtilityUnitTest
@Test
public void testDuplicationDoesntHappenWithNoContent()
{
- NodeRef nodeRef = new NodeRef("some://test/noderef");
- when(mockContentService.getReader(nodeRef, ContentModel.PROP_CONTENT)).thenReturn(null);
- contentBinDuplicationUtility.duplicate(nodeRef);
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(null);
+ contentBinDuplicationUtility.duplicate(NODE_REF);
verify(mockContentWriter, times(0)).putContent(mockContentReader);
checkBehaviours(1);
}
@@ -118,6 +129,52 @@ public class ContentBinDuplicationUtilityUnitTest
verify(mockContentReader, times(0)).getReader();
checkBehaviours(0);
}
+ /**
+ * Test hasAtLeastOneOtherReference returns true when node has another reference to it
+ */
+ @Test
+ public void testHasAtLeastOneOtherReference()
+ {
+ Set multipleReferences = new HashSet<>();
+ Collections.addAll(multipleReferences, NODE_REF, NODE_REF2);
+
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT).getContentUrl()).thenReturn(CONTENT_URL);
+ when(recordsManagementQueryDAO.getNodeRefsWhichReferenceContentUrl(CONTENT_URL)).thenReturn(multipleReferences);
+
+ assertTrue(contentBinDuplicationUtility.hasAtLeastOneOtherReference(NODE_REF));
+ }
+
+ /**
+ * Test hasAtLeastOneOtherReference returns false when node has no other reference to it other than its own content ref
+ */
+ @Test
+ public void testHasNoOtherReference()
+ {
+ Set singleReference = Collections.singleton(NODE_REF);
+
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT).getContentUrl()).thenReturn(CONTENT_URL);
+ when(recordsManagementQueryDAO.getNodeRefsWhichReferenceContentUrl(CONTENT_URL)).thenReturn(singleReference);
+
+ assertFalse(contentBinDuplicationUtility.hasAtLeastOneOtherReference(NODE_REF));
+ }
+
+ /**
+ * Test hasAtLeastOneOtherReference returns false when node has no references to it at all
+ */
+ @Test
+ public void testHasNoReferences()
+ {
+ Set noReferences = Collections. emptySet();
+
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT).getContentUrl()).thenReturn(CONTENT_URL);
+ when(recordsManagementQueryDAO.getNodeRefsWhichReferenceContentUrl(CONTENT_URL)).thenReturn(noReferences);
+
+ assertFalse(contentBinDuplicationUtility.hasAtLeastOneOtherReference(NODE_REF));
+ }
+
/**
* Check that the behaviours are disabled and re-enabled the correct number of times
* @param times the times the behaviours should be called