diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
index 4cb71d28e0..ddd303c982 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
@@ -143,7 +143,6 @@
-
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
index 01ac11f766..de5519decd 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
@@ -45,6 +45,7 @@
+
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java
index b59181191b..441af631bb 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java
@@ -51,13 +51,9 @@ import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
-import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.quickshare.QuickShareService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
-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 org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.service.namespace.QName;
@@ -98,9 +94,6 @@ public class RecordAspect extends AbstractDisposableItem
/** quickShare service */
private QuickShareService quickShareService;
- /** File folder service */
- private FileFolderService fileFolderService;
-
/** I18N */
private static final String MSG_CANNOT_UPDATE_RECORD_CONTENT = "rm.service.update-record-content";
@@ -137,15 +130,6 @@ public class RecordAspect extends AbstractDisposableItem
this.quickShareService = quickShareService;
}
- /**
- *
- * @param fileFolderService file folder service
- */
- public void setFileFolderService(FileFolderService fileFolderService)
- {
- this.fileFolderService = fileFolderService;
- }
-
/**
* Behaviour to ensure renditions have the appropriate extended security.
*
@@ -351,11 +335,7 @@ public class RecordAspect extends AbstractDisposableItem
/**
* On copy complete behaviour for record aspect.
*
- * @param classRef
- * @param sourceNodeRef
- * @param targetNodeRef
- * @param copyToNewNode
- * @param copyMap
+ * @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyCompletePolicy#onCopyComplete(QName, NodeRef, NodeRef, boolean, Map)
*/
@Override
@Behaviour
@@ -376,12 +356,7 @@ public class RecordAspect extends AbstractDisposableItem
extendedSecurityService.remove(targetNodeRef);
//create a new content URL for the copy
- ContentReader reader = fileFolderService.getReader(targetNodeRef);
- if (reader != null)
- {
- ContentWriter writer = fileFolderService.getWriter(targetNodeRef);
- writer.putContent(reader);
- }
+ createNewContentURL(targetNodeRef);
}
}
@@ -402,6 +377,7 @@ public class RecordAspect extends AbstractDisposableItem
/**
* Behaviour to remove the shared link before declare a record
+ * and to create new bin if the node is a copy or has copies
*
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeAddAspectPolicy#beforeAddAspect(org.alfresco.service.cmr.repository.NodeRef,
* org.alfresco.service.namespace.QName)
@@ -421,6 +397,26 @@ public class RecordAspect extends AbstractDisposableItem
quickShareService.unshareContent(sharedId);
}
+ // if the node has a copy or is a copy of an existing node
+ if (!nodeService.getTargetAssocs(nodeRef, ContentModel.ASSOC_ORIGINAL).isEmpty() ||
+ !nodeService.getSourceAssocs(nodeRef, ContentModel.ASSOC_ORIGINAL).isEmpty())
+ {
+ //disable versioning and auditing
+ behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
+ behaviourFilter.disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
+ try
+ {
+ //create a new content URL for the copy/original node
+ createNewContentURL(nodeRef);
+ }
+ finally
+ {
+ //enable versioning and auditing
+ behaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
+ behaviourFilter.enableBehaviour(ContentModel.ASPECT_VERSIONABLE);
+ }
+ }
+
return null;
}
}, AuthenticationUtil.getSystemUserName());
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspect.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspect.java
index 9437c6c6ef..f4712a8995 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspect.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspect.java
@@ -34,12 +34,14 @@ import org.alfresco.module.org_alfresco_module_rm.relationship.Relationship;
import org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService;
import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
+import org.alfresco.service.namespace.QName;
/**
* rmv:versionRecord behaviour bean
@@ -52,14 +54,15 @@ import org.alfresco.service.cmr.version.Version;
defaultType = "rmv:versionRecord"
)
public class VersionRecordAspect extends BaseBehaviourBean
- implements NodeServicePolicies.BeforeDeleteNodePolicy
+ implements NodeServicePolicies.BeforeAddAspectPolicy,
+ NodeServicePolicies.BeforeDeleteNodePolicy
{
/** recordable version service */
private RecordableVersionService recordableVersionService;
/** relationship service */
private RelationshipService relationshipService;
-
+
/**
* @param recordableVersionService recordable version service
*/
@@ -75,7 +78,7 @@ public class VersionRecordAspect extends BaseBehaviourBean
{
this.relationshipService = relationshipService;
}
-
+
/**
* If the record is a version record then delete the associated version entry
*
@@ -129,4 +132,18 @@ public class VersionRecordAspect extends BaseBehaviourBean
});
}
}
+
+ /**
+ * Behaviour to duplicate the bin before declaring a version record
+ *
+ * @see org.alfresco.repo.node.NodeServicePolicies.BeforeAddAspectPolicy#beforeAddAspect(org.alfresco.service.cmr.repository.NodeRef,
+ * org.alfresco.service.namespace.QName)
+ */
+ @Override
+ @Behaviour(kind = BehaviourKind.CLASS, notificationFrequency = NotificationFrequency.FIRST_EVENT)
+ public void beforeAddAspect(NodeRef nodeRef, QName qName)
+ {
+ //create a new content URL for the version record
+ createNewContentURL(nodeRef);
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java
index 8f45c69441..8fc5094b05 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java
@@ -31,6 +31,7 @@ import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
+import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
@@ -38,6 +39,9 @@ import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
+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 org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
@@ -71,9 +75,12 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
/** authentication helper */
protected AuthenticationUtil authenticationUtil;
-
+
/** transactional resource helper */
- protected TransactionalResourceHelper transactionalResourceHelper;
+ protected TransactionalResourceHelper transactionalResourceHelper;
+
+ /** Content service */
+ protected ContentService contentService;
/**
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
@@ -124,6 +131,16 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
this.transactionalResourceHelper = transactionalResourceHelper;
}
+ /**
+ * Set the content service
+ *
+ * @param contentService content service
+ */
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
/**
* Helper to get internal node service.
*
@@ -537,4 +554,30 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
result.add(nodeService.getType(nodeRef));
return result;
}
+
+ /**
+ * Helper to update the given content property for the node
+ *
+ * @param nodeRef the node
+ * @param contentProperty the property to be updated
+ */
+ protected void updateContentProperty(NodeRef nodeRef, QName contentProperty)
+ {
+ ContentReader reader = contentService.getReader(nodeRef, contentProperty);
+ if (reader != null)
+ {
+ ContentWriter writer = contentService.getWriter(nodeRef, contentProperty, true);
+ writer.putContent(reader);
+ }
+ }
+
+ /**
+ * Helper to create a new content URL for the node
+ *
+ * @param nodeRef the node
+ */
+ protected void createNewContentURL(NodeRef nodeRef)
+ {
+ updateContentProperty(nodeRef, ContentModel.PROP_CONTENT);
+ }
}
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/RecordableVersionsBaseTest.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/RecordableVersionsBaseTest.java
index c75997e0e1..2727c0b730 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/RecordableVersionsBaseTest.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/RecordableVersionsBaseTest.java
@@ -238,7 +238,16 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
if (frozenProperties.containsKey(beforePropertyName))
{
Serializable frozenValue = frozenProperties.get(beforePropertyName);
- assertEquals("Frozen property " + beforePropertyName.getLocalName() + " value is incorrect.", entry.getValue(), frozenValue);
+ if(beforePropertyName.equals(ContentModel.PROP_CONTENT))
+ {
+ assertTrue("Content property value should be different.",
+ entry.getValue() != frozenValue);
+ }
+ else
+ {
+ assertEquals("Frozen property " + beforePropertyName.getLocalName() + " value is incorrect.",
+ entry.getValue(), frozenValue);
+ }
cloneFrozenProperties.remove(beforePropertyName);
}
else if (!PROP_FILE_PLAN.equals(beforePropertyName) &&
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspectUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspectUnitTest.java
new file mode 100644
index 0000000000..730da904f3
--- /dev/null
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspectUnitTest.java
@@ -0,0 +1,176 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASPECT_RECORD;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
+import org.alfresco.repo.policy.BehaviourFilter;
+import org.alfresco.service.cmr.repository.AssociationRef;
+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 org.alfresco.service.cmr.repository.NodeService;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+/**
+ * Unit tests for the {@link RecordAspect}.
+ *
+ * @author Claudia Agache
+ */
+public class RecordAspectUnitTest
+{
+ private static final NodeRef NODE_REF = new NodeRef("node://Ref/");
+ private static final NodeRef COPY_REF = new NodeRef("node://Copy/");
+ private static final AssociationRef SOURCE_ASSOC_REF = new AssociationRef(COPY_REF, ContentModel.ASSOC_ORIGINAL,
+ NODE_REF);
+ private static final AssociationRef TARGET_ASSOC_REF = new AssociationRef(NODE_REF, ContentModel.ASSOC_ORIGINAL,
+ COPY_REF);
+
+ @InjectMocks
+ private RecordAspect recordAspect;
+ @Mock
+ private NodeService mockNodeService;
+ @Mock
+ private BehaviourFilter mockBehaviorFilter;
+ @Mock
+ private ContentService mockContentService;
+ @Mock
+ private ContentReader mockContentReader;
+ @Mock
+ private ContentWriter mockContentWriter;
+ @Mock
+ private ExtendedSecurityService mockExtendedSecurityService;
+
+ @Before
+ public void setUp()
+ {
+ initMocks(this);
+ }
+
+ /** Check that the bin is duplicated before adding the aspect if the file has a copy. */
+ @Test
+ public void testDuplicateBinBeforeAddingAspectForFileWithCopy()
+ {
+ when(mockNodeService.getSourceAssocs(NODE_REF, ContentModel.ASSOC_ORIGINAL)).thenReturn(asList(SOURCE_ASSOC_REF));
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
+ when(mockContentService.getWriter(NODE_REF, ContentModel.PROP_CONTENT, true)).thenReturn(mockContentWriter);
+
+ recordAspect.beforeAddAspect(NODE_REF, ASPECT_RECORD);
+
+ verifyBeforeAddAspectMethodsInvocations(1);
+ }
+
+ /** Check that the bin is duplicated before adding the aspect if the file is a copy. */
+ @Test
+ public void testDuplicateBinBeforeAddingAspectForCopy()
+ {
+ when(mockNodeService.getTargetAssocs(NODE_REF, ContentModel.ASSOC_ORIGINAL)).thenReturn(asList(TARGET_ASSOC_REF));
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
+ when(mockContentService.getWriter(NODE_REF, ContentModel.PROP_CONTENT, true)).thenReturn(mockContentWriter);
+
+ recordAspect.beforeAddAspect(NODE_REF, ASPECT_RECORD);
+
+ verifyBeforeAddAspectMethodsInvocations(1);
+ }
+
+ /** Check that no content bin is created if the file does not have content. */
+ @Test
+ public void testBeforeAddAspectOnFileWithNoContent()
+ {
+ when(mockNodeService.getTargetAssocs(NODE_REF, ContentModel.ASSOC_ORIGINAL)).thenReturn(asList(TARGET_ASSOC_REF));
+ when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(null);
+
+ recordAspect.beforeAddAspect(NODE_REF, ASPECT_RECORD);
+
+ verify(mockBehaviorFilter, times(1)).disableBehaviour(eq(ContentModel.ASPECT_AUDITABLE));
+ verify(mockBehaviorFilter, times(1)).disableBehaviour(eq(ContentModel.ASPECT_VERSIONABLE));
+ verify(mockContentService, times(1)).getReader(NODE_REF, ContentModel.PROP_CONTENT);
+ verify(mockContentService, never()).getWriter(NODE_REF, ContentModel.PROP_CONTENT, true);
+ verify(mockBehaviorFilter, times(1)).enableBehaviour(eq(ContentModel.ASPECT_AUDITABLE));
+ verify(mockBehaviorFilter, times(1)).enableBehaviour(eq(ContentModel.ASPECT_VERSIONABLE));
+ }
+
+ /** Check that the bin is not duplicated before adding the aspect if the node has no copies. */
+ @Test
+ public void testNotDuplicateBinForFileWithNoCopies()
+ {
+ when(mockNodeService.getSourceAssocs(NODE_REF, ContentModel.ASSOC_ORIGINAL)).thenReturn(emptyList());
+ when(mockNodeService.getTargetAssocs(NODE_REF, ContentModel.ASSOC_ORIGINAL)).thenReturn(emptyList());
+
+ recordAspect.beforeAddAspect(NODE_REF, ASPECT_RECORD);
+
+ verifyBeforeAddAspectMethodsInvocations(0);
+ }
+
+ /** Check that the bin is duplicated when copying a record. */
+ @Test
+ public void testDuplicateBinWhenCopyingRecord()
+ {
+ when(mockNodeService.exists(COPY_REF)).thenReturn(true);
+ when(mockNodeService.hasAspect(COPY_REF, ASPECT_RECORD)).thenReturn(true);
+ when(mockContentService.getReader(COPY_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
+ when(mockContentService.getWriter(COPY_REF, ContentModel.PROP_CONTENT, true)).thenReturn(mockContentWriter);
+
+ recordAspect.onCopyComplete(null, NODE_REF, COPY_REF, true, null);
+
+ verify(mockExtendedSecurityService, times(1)).remove(COPY_REF);
+ verify(mockContentService, times(1)).getReader(COPY_REF, ContentModel.PROP_CONTENT);
+ verify(mockContentService, times(1)).getWriter(COPY_REF, ContentModel.PROP_CONTENT, true);
+ verify(mockContentWriter, times(1)).putContent(mockContentReader);
+ }
+
+ /**
+ * Helper to verify beforeAddAspect methods invocations
+ *
+ * @param wantedNumberOfInvocations wanted number of invocations for each method
+ */
+ private void verifyBeforeAddAspectMethodsInvocations(int wantedNumberOfInvocations)
+ {
+ verify(mockBehaviorFilter, times(wantedNumberOfInvocations)).disableBehaviour(eq(ContentModel.ASPECT_AUDITABLE));
+ verify(mockBehaviorFilter, times(wantedNumberOfInvocations)).disableBehaviour(eq(ContentModel.ASPECT_VERSIONABLE));
+ verify(mockContentService, times(wantedNumberOfInvocations)).getReader(NODE_REF, ContentModel.PROP_CONTENT);
+ verify(mockContentService, times(wantedNumberOfInvocations)).getWriter(NODE_REF, ContentModel.PROP_CONTENT, true);
+ verify(mockContentWriter, times(wantedNumberOfInvocations)).putContent(mockContentReader);
+ verify(mockBehaviorFilter, times(wantedNumberOfInvocations)).enableBehaviour(eq(ContentModel.ASPECT_AUDITABLE));
+ verify(mockBehaviorFilter, times(wantedNumberOfInvocations)).enableBehaviour(eq(ContentModel.ASPECT_VERSIONABLE));
+ }
+}