diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml
index 46cc7a2483..91ff7f93eb 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml
@@ -32,4 +32,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml
index 7fdded0880..f3e8e1f0c1 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml
@@ -211,7 +211,7 @@
-
+
@@ -340,4 +340,16 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
index c884558fad..a17e7410f5 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
@@ -1039,6 +1039,7 @@
+
@@ -1100,6 +1101,7 @@
org.alfresco.module.org_alfresco_module_rm.record.RecordService.addRecordType=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.makeRecord=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.link=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.record.RecordService.moveRecord=RM.Write.0
org.alfresco.module.org_alfresco_module_rm.record.RecordService.*=RM_DENY
]]>
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml
index 96be6476a8..1c1cb4115c 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml
@@ -860,7 +860,7 @@
-
+
@@ -871,4 +871,15 @@
+
+
+
+
+
+ RECORD
+
+
+
+
\ No newline at end of file
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/HideRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/HideRecordAction.java
index b3e50912ac..9eef3871f7 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/HideRecordAction.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/HideRecordAction.java
@@ -39,7 +39,7 @@ import org.apache.commons.logging.LogFactory;
* @since 2.1
*/
public class HideRecordAction extends AuditableActionExecuterAbstractBase
- implements RecordsManagementModel
+ implements RecordsManagementModel
{
/** Logger */
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/MoveDmRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/MoveDmRecordAction.java
new file mode 100644
index 0000000000..adc33c01e7
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/MoveDmRecordAction.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * 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 .
+ */
+package org.alfresco.module.org_alfresco_module_rm.action.dm;
+
+import java.util.List;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.module.org_alfresco_module_rm.action.AuditableActionExecuterAbstractBase;
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.action.ParameterDefinition;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Moves a record within a collaboration site.
+ * The record can be moved only within the collaboration site where it was declared.
+ *
+ * @author Tuna Aksoy
+ * @since 2.3
+ */
+public class MoveDmRecordAction extends AuditableActionExecuterAbstractBase implements RecordsManagementModel
+{
+ /** Logger */
+ private static Log logger = LogFactory.getLog(MoveDmRecordAction.class);
+
+ /** Action name */
+ public static final String NAME = "move-dm-record";
+
+ /** Constant for target node reference parameter */
+ public static final String PARAM_TARGET_NODE_REF = "targetNodeRef";
+
+ /** Node service */
+ private NodeService nodeService;
+
+ /** Record service */
+ private RecordService recordService;
+
+ /**
+ * Gets the node service
+ *
+ * @return Node service
+ */
+ protected NodeService getNodeService()
+ {
+ return this.nodeService;
+ }
+
+ /**
+ * Sets the node service
+ *
+ * @param nodeService Node service
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Gets the record service
+ *
+ * @return Record service
+ */
+ protected RecordService getRecordService()
+ {
+ return this.recordService;
+ }
+
+ /**
+ * Sets the record service
+ *
+ * @param recordService Record service
+ */
+ public void setRecordService(RecordService recordService)
+ {
+ this.recordService = recordService;
+ }
+
+ /**
+ * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override
+ protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
+ {
+ // Cannot move a document which is not a record
+ if (!getNodeService().hasAspect(actionedUponNodeRef, ASPECT_RECORD) && logger.isDebugEnabled())
+ {
+ logger.debug("Cannot move the document, because '" + actionedUponNodeRef.toString() + "' is not a record.");
+ }
+ else
+ {
+ // Move the record within the collaboration site
+ getRecordService().moveRecord(actionedUponNodeRef, getTargetNodeRef(action));
+ }
+ }
+
+ /**
+ * Helper method to get the target node reference from the action parameter
+ *
+ * @param action The action
+ * @return Node reference of the target
+ */
+ private NodeRef getTargetNodeRef(Action action)
+ {
+ String targetNodeRef = (String) action.getParameterValue(PARAM_TARGET_NODE_REF);
+
+ if (StringUtils.isBlank(targetNodeRef))
+ {
+ throw new AlfrescoRuntimeException("Could not find target node reference.");
+ }
+
+ return new NodeRef(targetNodeRef);
+ }
+
+ /**
+ * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List)
+ */
+ @Override
+ protected void addParameterDefinitions(List paramList)
+ {
+ // Intentionally empty
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java
index 92a17e9b86..d1705b3ea0 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java
@@ -56,10 +56,10 @@ public interface RecordService
* Disables the property editable check.
*/
void disablePropertyEditableCheck();
-
+
/**
* Disables the property editable check for a given node in this transaction only.
- *
+ *
* @param nodeRef node reference
* @since 2.2
*/
@@ -231,4 +231,12 @@ public interface RecordService
* @param folder The folder in which the link will be created
*/
void link(NodeRef nodeRef, NodeRef folder);
+
+ /**
+ * Moves a record within a collaboration site
+ *
+ * @param nodeRef The record which should be moved
+ * @param targetNodeRef The target node reference where it should be moved to
+ */
+ void moveRecord(NodeRef nodeRef, NodeRef targetNodeRef);
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
index 0cc4cd45f2..a1f5bf7033 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
@@ -80,6 +80,8 @@ import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService;
+import org.alfresco.service.cmr.site.SiteInfo;
+import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
@@ -194,6 +196,9 @@ public class RecordServiceImpl extends BaseBehaviourBean
/** Permission service */
private PermissionService permissionService;
+ /** Site service */
+ private SiteService siteService;
+
/** list of available record meta-data aspects and the file plan types the are applicable to */
private Map> recordMetaDataAspects;
@@ -315,6 +320,14 @@ public class RecordServiceImpl extends BaseBehaviourBean
this.permissionService = permissionService;
}
+ /**
+ * @param siteService site service
+ */
+ public void setSiteService(SiteService siteService)
+ {
+ this.siteService = siteService;
+ }
+
/**
* Init method
*/
@@ -1475,4 +1488,68 @@ public class RecordServiceImpl extends BaseBehaviourBean
nodeService.addChild(folder, nodeRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, nodeService.getProperty(nodeRef, ContentModel.PROP_NAME).toString()));
}
}
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#moveRecord(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override
+ public void moveRecord(final NodeRef nodeRef, final NodeRef targetNodeRef)
+ {
+ ParameterCheck.mandatory("nodeRef", nodeRef);
+ ParameterCheck.mandatory("targetNodeRef", targetNodeRef);
+
+ NodeRef sourceParentNodeRef = null;
+
+ NodeRef originatingLocation = (NodeRef) nodeService.getProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION);
+ for (ChildAssociationRef parentAssoc : nodeService.getParentAssocs(nodeRef))
+ {
+ if (!parentAssoc.isPrimary() && parentAssoc.getParentRef().equals(originatingLocation))
+ {
+ sourceParentNodeRef = parentAssoc.getParentRef();
+ break;
+ }
+ }
+
+ if (sourceParentNodeRef == null)
+ {
+ throw new AlfrescoRuntimeException("Could not find source parent node reference.");
+ }
+
+ SiteInfo sourceSite = siteService.getSite(sourceParentNodeRef);
+ SiteInfo targetSite = siteService.getSite(targetNodeRef);
+
+ if (!sourceSite.equals(targetSite))
+ {
+ throw new AlfrescoRuntimeException("The record can only be moved within the same collaboration site.");
+ }
+
+ if (!sourceSite.getSitePreset().equals("site-dashboard"))
+ {
+ throw new AlfrescoRuntimeException("Only records within a collaboration site can be moved.");
+ }
+
+ final NodeRef source = sourceParentNodeRef;
+
+ AuthenticationUtil.runAsSystem(new RunAsWork()
+ {
+ @Override
+ public Void doWork()
+ {
+ try
+ {
+ // Move the record
+ fileFolderService.moveFrom(nodeRef, source, targetNodeRef, null);
+
+ // Update the originating location property
+ nodeService.setProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION, targetNodeRef);
+ }
+ catch (FileExistsException | FileNotFoundException ex)
+ {
+ throw new AlfrescoRuntimeException("Can't move node: " + ex);
+ }
+
+ return null;
+ }
+ });
+ }
}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/HideRecordActionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/HideRecordActionTest.java
index db2d00e3d4..8660f761b5 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/HideRecordActionTest.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/HideRecordActionTest.java
@@ -21,9 +21,7 @@ package org.alfresco.module.org_alfresco_module_rm.test.legacy.action;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction;
import org.alfresco.module.org_alfresco_module_rm.action.dm.HideRecordAction;
-import org.alfresco.module.org_alfresco_module_rm.role.Role;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -49,19 +47,6 @@ public class HideRecordActionTest extends BaseRMTestCase
public void testHideRecordAction()
{
- doTestInTransaction(new Test()
- {
- public Void run()
- {
- // The user must have the appropriate rights
- Role role = filePlanRoleService.getRole(filePlan, "RecordsManager");
- authorityService.addAuthority(role.getRoleGroupName(), dmCollaborator);
-
- return null;
- }
- },
- AuthenticationUtil.getAdminUserName());
-
doTestInTransaction(new Test()
{
public Void run()
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/MoveRecordActionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/MoveRecordActionTest.java
new file mode 100644
index 0000000000..71c7a50c81
--- /dev/null
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/MoveRecordActionTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * 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 .
+ */
+package org.alfresco.module.org_alfresco_module_rm.test.legacy.action;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction;
+import org.alfresco.module.org_alfresco_module_rm.action.dm.MoveDmRecordAction;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+
+/**
+ * Move Record Action Unit Test.
+ *
+ * @author Tuna Aksoy
+ * @since 2.2
+ */
+public class MoveRecordActionTest extends BaseRMTestCase
+{
+ @Override
+ protected boolean isUserTest()
+ {
+ return true;
+ }
+
+ @Override
+ protected boolean isCollaborationSiteTest()
+ {
+ return true;
+ }
+
+ public void testMoveRecordAction()
+ {
+ doTestInTransaction(new Test()
+ {
+ public Void run()
+ {
+ // Create a new folder in a collaboration site
+ NodeRef testFolder = fileFolderService.create(dmFolder, "myTestFolder", ContentModel.TYPE_FOLDER).getNodeRef();
+
+ // Create a document so that the user has the write permissions for that document
+ NodeRef document = fileFolderService.create(testFolder, "moveFile.txt", ContentModel.TYPE_CONTENT).getNodeRef();
+
+ // Create destination folder
+ String destination = fileFolderService.create(testFolder, "newDest", ContentModel.TYPE_FOLDER).getNodeRef().toString();
+
+ // Create a record from that document
+ Action createAction = actionService.createAction(CreateRecordAction.NAME);
+ createAction.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan);
+ actionService.executeAction(createAction, document);
+
+ // Check if the document is a record now
+ assertTrue(recordService.isRecord(document));
+
+ // The record should have the original location information
+ assertNotNull(nodeService.getProperty(document, PROP_RECORD_ORIGINATING_LOCATION));
+
+ // Check the parents. In this case the document should have two parents (doclib and fileplan)
+ assertEquals(nodeService.getParentAssocs(document).size(), 2);
+
+ // Check the number of children of dmFolder before move
+ assertEquals(nodeService.getChildAssocs(testFolder).size(), 2);
+
+ // Move the record
+ Action moveRecordAction = actionService.createAction(MoveDmRecordAction.NAME);
+ moveRecordAction.setParameterValue(MoveDmRecordAction.PARAM_TARGET_NODE_REF, destination);
+ actionService.executeAction(moveRecordAction, document);
+
+ // Check the number of children of dmFolder after move
+ assertEquals(nodeService.getChildAssocs(testFolder).size(), 1);
+
+ // Check the new document parent
+ ChildAssociationRef parent1 = nodeService.getParentAssocs(document).get(0);
+ ChildAssociationRef parent2 = nodeService.getParentAssocs(document).get(1);
+ NodeRef newDocParent = (parent1.isPrimary() ? parent2 : parent1).getParentRef();
+ assertEquals(destination, newDocParent.toString());
+
+ // Check if the original location information has been updated
+ assertEquals((NodeRef) nodeService.getProperty(document, PROP_RECORD_ORIGINATING_LOCATION), newDocParent);
+
+ return null;
+ }
+ },
+ dmCollaborator);
+ }
+}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java
index 38ba4304e0..1683e05449 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java
@@ -723,7 +723,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
{
// create collaboration site
collabSiteId = GUID.generate();
- collaborationSite = siteService.createSite("preset", collabSiteId, "title", "description", SiteVisibility.PRIVATE);
+ collaborationSite = siteService.createSite("site-dashboard", collabSiteId, "title", "description", SiteVisibility.PRIVATE);
documentLibrary = SiteServiceImpl.getSiteContainer(
collabSiteId,
SiteService.DOCUMENT_LIBRARY,
@@ -818,7 +818,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
protected abstract class BehaviourDrivenTest
{
protected boolean runInTransactionTests = true;
-
+
protected Class> expectedException;
public BehaviourDrivenTest()
@@ -829,7 +829,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
{
this.expectedException = expectedException;
}
-
+
public BehaviourDrivenTest(boolean runInTransactionTests)
{
this.runInTransactionTests = runInTransactionTests;
@@ -875,7 +875,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
when();
}
});
-
+
doTestInTransaction(new VoidTest()
{
@Override