From 9d66d4f6b23519777cc6b70096f7691f65a1cec6 Mon Sep 17 00:00:00 2001 From: Mark Hibbins Date: Thu, 27 Mar 2014 10:53:58 +0000 Subject: [PATCH] RM-1198 & RM-1199 - Added functionality for Copy-to and Move-to rule actions git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@65697 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../messages/actions.properties | 10 + .../rm-action-context.xml | 56 ++++ .../action/impl/CopyMoveFileToBaseAction.java | 290 ++++++++++++++++++ .../action/impl/CopyToAction.java | 21 ++ .../action/impl/FileToAction.java | 268 +--------------- .../action/impl/MoveToAction.java | 21 ++ .../RmSubstitutionSuggestionsGet.java | 25 +- .../test/action/FileToActionTest.java | 18 +- 8 files changed, 427 insertions(+), 282 deletions(-) create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveFileToBaseAction.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyToAction.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/MoveToAction.java diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/actions.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/actions.properties index 1d32068d9c..1311a35201 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/actions.properties +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/actions.properties @@ -79,6 +79,16 @@ fileTo.title=File to fileTo.description=Files a record to the specified record folder. fileTo.path.display-label=Path to Record Folder fileTo.createRecordPath.display-label=Create Record Path +# Copy to +copyTo.title=Copy to +copyTo.description=Copies a record to the specified record folder. +copyTo.path.display-label=Path to Record Folder +copyTo.createRecordPath.display-label=Create Record Path +# Move to +moveTo.title=Move to +moveTo.description=Moves a record to the specified record folder. +moveTo.path.display-label=Path to Record Folder +moveTo.createRecordPath.display-label=Create Record Path # Reject reject.title=Reject reject.description=Rejects a record and moves the document to its original location diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml index 16e705a25a..821b6c5330 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml @@ -855,6 +855,62 @@ + + + + + + + + + + + + + + + org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.execute=RM_CAP.0.rma:filePlanComponent.CreateModifyDestroyEvents + org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.*=RM_ALLOW + org.alfresco.repo.action.executer.ActionExecuter.*=RM_ALLOW + + + + + + + + + + + + + + + + + + + + + + + + + + org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.execute=RM_CAP.0.rma:filePlanComponent.CreateModifyDestroyEvents + org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.*=RM_ALLOW + org.alfresco.repo.action.executer.ActionExecuter.*=RM_ALLOW + + + + + + + + + + + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveFileToBaseAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveFileToBaseAction.java new file mode 100644 index 0000000000..5f3dc616a6 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveFileToBaseAction.java @@ -0,0 +1,290 @@ +package org.alfresco.module.org_alfresco_module_rm.action.impl; + +import java.util.Arrays; +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; +import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.repo.action.ParameterDefinitionImpl; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileNotFoundException; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.springframework.util.StringUtils; + +/** + * File To action implementation. + * + * @author Mark Hibbins + * @since 2.2 + */ +public abstract class CopyMoveFileToBaseAction extends RMActionExecuterAbstractBase +{ + /** action parameters */ + public static final String PARAM_DESTINATION_RECORD_FOLDER = "destinationRecordFolder"; + public static final String PARAM_PATH = "path"; + public static final String PARAM_CREATE_RECORD_PATH = "createRecordPath"; + public static final String ACTION_FILETO = "fileTo"; + + /** file folder service */ + private FileFolderService fileFolderService; + + /** file plan service */ + private FilePlanService filePlanService; + + /** action modes */ + public enum CopyMoveFileToActionMode + { + COPY, MOVE + }; + protected CopyMoveFileToActionMode mode; + + /** + * @param fileFolderService file folder service + */ + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } + + /** + * @param filePlanService file plan service + */ + public void setFilePlanService(FilePlanService filePlanService) + { + this.filePlanService = filePlanService; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#addParameterDefinitions(java.util.List) + */ + @Override + protected void addParameterDefinitions(List paramList) + { + paramList.add(new ParameterDefinitionImpl(PARAM_PATH, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_PATH))); + paramList.add(new ParameterDefinitionImpl(PARAM_CREATE_RECORD_PATH, DataTypeDefinition.BOOLEAN, false, getParamDisplayLabel(PARAM_CREATE_RECORD_PATH))); + } + + /** + * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + protected void executeImpl(final Action action, final NodeRef actionedUponNodeRef) + { + if (nodeService.exists(actionedUponNodeRef) && + (freezeService.isFrozen(actionedUponNodeRef) == false) && + (!ACTION_FILETO.equals(action.getActionDefinitionName()) || !recordService.isFiled(actionedUponNodeRef)) && + (!(ACTION_FILETO.equals(action.getActionDefinitionName()) && RecordsManagementModel.TYPE_UNFILED_RECORD_CONTAINER.equals(nodeService.getType(actionedUponNodeRef))))) + { + boolean targetIsUnfiledRecord = + !ACTION_FILETO.equals(action.getActionDefinitionName()) && ( + ((ContentModel.TYPE_CONTENT.equals(nodeService.getType(actionedUponNodeRef)) || RecordsManagementModel.TYPE_NON_ELECTRONIC_DOCUMENT.equals(nodeService.getType(actionedUponNodeRef))) && + !recordService.isFiled(actionedUponNodeRef)) || + RecordsManagementModel.TYPE_UNFILED_RECORD_CONTAINER.equals(nodeService.getType(actionedUponNodeRef)) + ); + + // first look to see if the destination record folder has been specified + NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); + if (recordFolder == null) + { + // get the reference to the record folder based on the relative path + recordFolder = createOrResolvePath(action, actionedUponNodeRef, targetIsUnfiledRecord); + } + + if (recordFolder == null) + { + throw new AlfrescoRuntimeException("Unable to execute file to action, because the destination record folder could not be determined."); + } + + final NodeRef finalRecordFolder = recordFolder; + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + try + { + if(mode == CopyMoveFileToActionMode.MOVE) + { + fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null); + } + else + { + fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null); + } + } + catch (FileNotFoundException fileNotFound) + { + throw new AlfrescoRuntimeException( + "Unable to execute file to action, because the " + (mode == CopyMoveFileToActionMode.MOVE ? "move" : "copy") + " operation failed.", + fileNotFound + ); + } + + return null; + } + }); + } + } + + /** + * Create or resolve the path specified in the action's path parameter + * + * @param action + * @param actionedUponNodeRef + * @param targetisUnfiledRecords true is the target is in unfiled records + * @return + */ + private NodeRef createOrResolvePath(Action action, NodeRef actionedUponNodeRef, boolean targetisUnfiledRecords) + { + // get the starting context + NodeRef context = getContext(action, actionedUponNodeRef, targetisUnfiledRecords); + NodeRef path = context; + + // get the path we wish to resolve + String pathParameter = (String)action.getParameterValue(PARAM_PATH); + String[] pathElementsArray = StringUtils.tokenizeToStringArray(pathParameter, "/", false, true); + if((pathElementsArray != null) && (pathElementsArray.length > 0)) + { + // get the create parameter + Boolean createValue = (Boolean)action.getParameterValue(PARAM_CREATE_RECORD_PATH); + boolean create = createValue == null ? false : createValue.booleanValue(); + + // create or resolve the specified path + path = createOrResolvePath(action, context, actionedUponNodeRef, Arrays.asList(pathElementsArray), targetisUnfiledRecords, create, false); + } + return path; + } + + /** + * Create or resolve the specified path + * + * @param action Action to use for reporting if anything goes wrong + * @param parent Parent of path to be created + * @param actionedUponNodeRef The node subject to the file/move/copy action + * @param pathElements The elements of the path to be created + * @param targetisUnfiledRecords true if the target is within unfiled records + * @param create true if the path should be creeated if it does not exist + * @param creating true if we have already created the parent and therefore can skip the check to see if the next path element already exists + * @return + */ + private NodeRef createOrResolvePath(Action action, NodeRef parent, NodeRef actionedUponNodeRef, List pathElements, boolean targetisUnfiledRecords, boolean create, boolean creating) + { + NodeRef nodeRef = null; + String childName = pathElements.get(0); + boolean lastPathElement = pathElements.size() == 1; + if(!creating) + { + nodeRef = getChild(parent, childName); + } + if(nodeRef == null) + { + if(create) + { + creating = true; + nodeRef = createChild( + action, + parent, + childName, + targetisUnfiledRecords, + lastPathElement && (ContentModel.TYPE_CONTENT.equals(nodeService.getType(actionedUponNodeRef)) || RecordsManagementModel.TYPE_NON_ELECTRONIC_DOCUMENT.equals(nodeService.getType(actionedUponNodeRef)))); + } + else + { + throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the destination path could not be determined."); + } + } + if(pathElements.size() > 1) + { + nodeRef = createOrResolvePath(action, nodeRef, actionedUponNodeRef, pathElements.subList(1, pathElements.size()), targetisUnfiledRecords, create, creating); + } + return nodeRef; + } + + /** + * Get the specified child node ref of the specified parent if it exists, otherwise return null + * + * @param parent + * @param childName + * @return + */ + private NodeRef getChild(NodeRef parent, String childName) + { + NodeRef child = null; + List children = nodeService.getChildAssocs(parent); + for (ChildAssociationRef childAssoc : children) { + NodeRef childNodeRef = childAssoc.getChildRef(); + String existingChildName = (String)nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME); + if(existingChildName.equals(childName)) + { + child = childNodeRef; + break; + } + } + return child; + } + + /** + * Create the specified child of the specified parent + * + * @param action Action to use for reporting if anything goes wrong + * @param parent Parent of the child to be created + * @param childName The name of the child to be created + * @param targetisUnfiledRecords true if the child is being created in the unfiled directory (determines type as unfiled container child) + * @param lastAsFolder true if this is the last element of the pathe being created and it should be created as a folder. ignored if targetIsUnfiledRecords is true + * @return + */ + private NodeRef createChild(Action action, NodeRef parent, String childName, boolean targetisUnfiledRecords, boolean lastAsFolder) + { + NodeRef child = null; + if(targetisUnfiledRecords) + { + child = this.fileFolderService.create(parent, childName, RecordsManagementModel.TYPE_UNFILED_RECORD_CONTAINER).getNodeRef(); + } + else if(lastAsFolder) + { + child = recordFolderService.createRecordFolder(parent, childName); + } + else + { + if(RecordsManagementModel.TYPE_RECORD_FOLDER.equals(nodeService.getType(parent))) + { + throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the destination path could not be created."); + } + child = this.filePlanService.createRecordCategory(parent, childName); + } + return child; + + } + + /** + * Return the context. This will be the unfiled records container of the context if targetisUnfiledRecords is true + * + * @param action + * @param actionedUponNodeRef + * @param targetisUnfiledRecords + * @return + */ + private NodeRef getContext(Action action, NodeRef actionedUponNodeRef, boolean targetisUnfiledRecords) + { + NodeRef context = filePlanService.getFilePlan(actionedUponNodeRef); + if(targetisUnfiledRecords && (context != null) && nodeService.exists(context)) + { + context = filePlanService.getUnfiledContainer(context); + } + if((context == null) || (!nodeService.exists(context))) + { + throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the path resolution context could not be determined."); + } + return context; + } + +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyToAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyToAction.java new file mode 100644 index 0000000000..23da848210 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyToAction.java @@ -0,0 +1,21 @@ +package org.alfresco.module.org_alfresco_module_rm.action.impl; + + +/** + * File To action implementation. + * + * @author Mark Hibbins + * @since 2.2 + */ +public class CopyToAction extends CopyMoveFileToBaseAction +{ + /** action name */ + public static final String NAME = "copyTo"; + + @Override + public void init() + { + super.init(); + this.mode = CopyMoveFileToActionMode.COPY; + } +} \ No newline at end of file diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/FileToAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/FileToAction.java index 9d7212b628..fe365d48da 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/FileToAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/FileToAction.java @@ -1,24 +1,5 @@ package org.alfresco.module.org_alfresco_module_rm.action.impl; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; -import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; -import org.alfresco.repo.action.ParameterDefinitionImpl; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.service.cmr.action.Action; -import org.alfresco.service.cmr.action.ParameterDefinition; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.model.FileNotFoundException; -import org.alfresco.service.cmr.repository.NodeRef; -import org.apache.commons.lang.ArrayUtils; -import org.springframework.util.StringUtils; /** * File To action implementation. @@ -26,256 +7,15 @@ import org.springframework.util.StringUtils; * @author Roy Wetherall * @since 2.1 */ -public class FileToAction extends RMActionExecuterAbstractBase +public class FileToAction extends CopyMoveFileToBaseAction { /** action name */ public static final String NAME = "fileTo"; - /** action parameters */ - public static final String PARAM_DESTINATION_RECORD_FOLDER = "destinationRecordFolder"; - public static final String PARAM_PATH = "path"; - public static final String PARAM_CREATE_RECORD_PATH = "createRecordPath"; - - /** file folder service */ - private FileFolderService fileFolderService; - - /** file plan service */ - private FilePlanService filePlanService; - - /** - * @param fileFolderService file folder service - */ - public void setFileFolderService(FileFolderService fileFolderService) - { - this.fileFolderService = fileFolderService; - } - - /** - * @param filePlanService file plan service - */ - public void setFilePlanService(FilePlanService filePlanService) - { - this.filePlanService = filePlanService; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#addParameterDefinitions(java.util.List) - */ @Override - protected void addParameterDefinitions(List paramList) + public void init() { - paramList.add(new ParameterDefinitionImpl(PARAM_PATH, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_PATH))); - paramList.add(new ParameterDefinitionImpl(PARAM_CREATE_RECORD_PATH, DataTypeDefinition.BOOLEAN, false, getParamDisplayLabel(PARAM_CREATE_RECORD_PATH))); + super.init(); + this.mode = CopyMoveFileToActionMode.MOVE; } - - /** - * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) - */ - @Override - protected void executeImpl(final Action action, final NodeRef actionedUponNodeRef) - { - if (nodeService.exists(actionedUponNodeRef) && - !freezeService.isFrozen(actionedUponNodeRef) && - !recordService.isFiled(actionedUponNodeRef)) - { - // first look to see if the destination record folder has been specified - NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); - if (recordFolder == null) - { - // get the reference to the record folder based on the relative path - recordFolder = createOrResolveRecordFolder(action, actionedUponNodeRef); - } - - if (recordFolder == null) - { - throw new AlfrescoRuntimeException("Unable to execute file to action, because the destination record folder could not be determined."); - } - - if (recordFolderService.isRecordFolder(recordFolder)) - { - final NodeRef finalRecordFolder = recordFolder; - - AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public Void doWork() throws Exception - { - try - { - fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null); - } - catch (FileNotFoundException fileNotFound) - { - throw new AlfrescoRuntimeException("Unable to execute file to action, because the move operation failed.", fileNotFound); - } - - return null; - } - }); - } - else - { - throw new AlfrescoRuntimeException("Unable to execute file to action, becuase the destination was not a record folder."); - } - } - } - - /** - * - * @param action - * @param actionedUponNodeRef - * @return - */ - private NodeRef createOrResolveRecordFolder(Action action, NodeRef actionedUponNodeRef) - { - // TODO check the action for a context node reference - // the file plan node always provides the context - NodeRef context = filePlanService.getFilePlan(actionedUponNodeRef); - if (context == null) - { - throw new AlfrescoRuntimeException("Unable to execute fileTo action, because the path resolution context could not be found."); - } - else if (!nodeService.exists(context)) - { - throw new AlfrescoRuntimeException("Unable to execute fileTo action, because the context for the relative path does not exist."); - } - - // look for the path parameter - String path = (String)action.getParameterValue(PARAM_PATH); - String[] pathValues = ArrayUtils.EMPTY_STRING_ARRAY; - - if (path != null && !path.isEmpty()) - { - pathValues = StringUtils.tokenizeToStringArray(path, "/", false, true); - } - - // look for the creation strategy - boolean create = false; - Boolean createValue = (Boolean)action.getParameterValue(PARAM_CREATE_RECORD_PATH); - if (createValue != null) - { - create = createValue.booleanValue(); - } - - // try and get child - NodeRef recordFolder = resolvePath(context, pathValues); - - if (recordFolder == null) - { - if (create) - { - // get the parent into which we are going to create the new record folder - NodeRef parent = resolveParent(context, pathValues, create); - if (parent == null) - { - throw new AlfrescoRuntimeException("Unable to create new record folder, because destination parent could not be found."); - } - - // ensure we are trying to create a record folder in a record category - if (!filePlanService.isRecordCategory(parent)) - { - throw new AlfrescoRuntimeException("Unable to create nre record folder, beacuse the parent is not a record category."); - } - - // get the new record folders name - String recordFolderName = pathValues[pathValues.length-1]; - recordFolder = recordFolderService.createRecordFolder(parent, recordFolderName); - } - else - { - throw new AlfrescoRuntimeException("Unable to execute FileTo action, because the destination record folder does not exist."); - } - } - - return recordFolder; - } - - /** - * - * @param context - * @param pathValues - * @return - */ - private NodeRef resolvePath(final NodeRef context, final String[] pathValues) - { - return resolvePath(context, pathValues, false); - } - - /** - * - * @param context - * @param pathValues - * @param create Create any missing path elements - * @return - */ - private NodeRef resolvePath(final NodeRef context, final String[] pathValues, boolean create) - { - NodeRef result = null; - FileInfo fileInfo = null; - try - { - List pathValueList = new ArrayList(Arrays.asList(pathValues)); - fileInfo = fileFolderService.resolveNamePath(context, pathValueList, false); - if((fileInfo == null) && create) - { - NodeRef parent = this.filePlanService.getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID); - for(int i = 1; i <= pathValueList.size(); i++) - { - List partialPathValueList = pathValueList.subList(0, i); - fileInfo = fileFolderService.resolveNamePath(context, partialPathValueList, false); - if(fileInfo == null) - { - parent = this.filePlanService.createRecordCategory(parent, partialPathValueList.get(partialPathValueList.size() - 1)); - } - else - { - parent = fileInfo.getNodeRef(); - } - } - result = parent; - } - } - catch (FileNotFoundException e) - { - // ignore, checking for null - } - if (fileInfo != null) - { - result = fileInfo.getNodeRef(); - } - return result; - } - - /** - * - * @param context - * @param pathValues - * @param create Create any missing path elements - * @return - */ - private NodeRef resolveParent(NodeRef context, String[] pathValues, boolean create) - { - NodeRef result = null; - - if (ArrayUtils.isEmpty(pathValues)) - { - // this should never occur since if the path is empty then the context it the resolution of the - // path .. the context must already exist - throw new AlfrescoRuntimeException("Unable to resolve the parent, because no valid path was specified."); - } - else if (pathValues.length == 1) - { - // the context is the parent - result = context; - } - else - { - pathValues = (String[])ArrayUtils.remove(pathValues, pathValues.length-1); - result = resolvePath(context, pathValues, create); - } - - return result; - } - - } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/MoveToAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/MoveToAction.java new file mode 100644 index 0000000000..114cd099f0 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/MoveToAction.java @@ -0,0 +1,21 @@ +package org.alfresco.module.org_alfresco_module_rm.action.impl; + + +/** + * File To action implementation. + * + * @author Mark Hibbins + * @since 2.2 + */ +public class MoveToAction extends CopyMoveFileToBaseAction +{ + /** action name */ + public static final String NAME = "moveTo"; + + @Override + public void init() + { + super.init(); + this.mode = CopyMoveFileToActionMode.MOVE; + } +} \ No newline at end of file diff --git a/rm-server/source/java/org/alfresco/repo/web/scripts/substitutionsuggestions/RmSubstitutionSuggestionsGet.java b/rm-server/source/java/org/alfresco/repo/web/scripts/substitutionsuggestions/RmSubstitutionSuggestionsGet.java index 2075b9973c..aa6cf967d3 100644 --- a/rm-server/source/java/org/alfresco/repo/web/scripts/substitutionsuggestions/RmSubstitutionSuggestionsGet.java +++ b/rm-server/source/java/org/alfresco/repo/web/scripts/substitutionsuggestions/RmSubstitutionSuggestionsGet.java @@ -51,11 +51,14 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript { private final static String FRAGMENT_PARAMETER = "fragment"; private final static String PATH_PARAMETER = "path"; + private final static String UNFILED_PARAMETER = "unfiled"; + private final static String UNFILED = "true"; private final static String SUBSTITUTIONS_MODEL_KEY = "substitutions"; private final static String RECORD_FOLDER_TYPE = "recordFolder"; private final static String RECORD_CATEGORY_TYPE = "recordCategory"; + private final static String UNFILED_RECORD_FOLDER_TYPE = "unfiledRecordContainerChild"; private final static String CREATE_CAPABILITY = "Create"; private final static String VIEW_CAPABILITY = "ViewRecords"; @@ -139,12 +142,14 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript { String fragment = req.getParameter(FRAGMENT_PARAMETER); String path = req.getParameter(PATH_PARAMETER); + String unfiledString = req.getParameter(UNFILED_PARAMETER); + boolean unfiled = (unfiledString != null) && UNFILED.equals(unfiledString); List substitutionSuggestions = new ArrayList(); if((fragment != null) && (fragment.length() >= this.substitutionMinimumFragmentSize)) { - substitutionSuggestions.addAll(getSubPathSuggestions(req, path, fragment)); + substitutionSuggestions.addAll(getSubPathSuggestions(req, path, fragment, unfiled)); substitutionSuggestions.addAll(this.parameterProcessorComponent.getSubstitutionSuggestions(fragment)); } @@ -161,13 +166,13 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript * @param fragment * @return */ - private List getSubPathSuggestions(WebScriptRequest req, final String path, final String fragment) { + private List getSubPathSuggestions(WebScriptRequest req, final String path, final String fragment, boolean unfiled) { List pathSuggestions = new ArrayList(); if((path != null) && path.startsWith("/") && (fragment != null)) { String[] pathFragments = path.split("/"); - NodeRef currentNode = getFilePlan(req); + NodeRef currentNode = getFilePlan(req, unfiled); for(String pathFragment : pathFragments) { // ignore empty elements of the path produced by split @@ -178,7 +183,7 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript for (ChildAssociationRef childAssoc : children) { NodeRef childNodeRef = childAssoc.getChildRef(); String fileName = (String) nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME); - if(fileName.equals(pathFragment) && isNodeRefAppropriateForPathSuggestion(childNodeRef)) + if(fileName.equals(pathFragment) && isNodeRefAppropriateForPathSuggestion(childNodeRef, unfiled)) { foundThisPathFragment = true; currentNode = childNodeRef; @@ -200,7 +205,7 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript for (ChildAssociationRef childAssoc : children) { NodeRef childNodeRef = childAssoc.getChildRef(); String fileName = (String) nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME); - if((fragment.isEmpty() || fileName.toLowerCase().startsWith(lowerCaseFragment)) && isNodeRefAppropriateForPathSuggestion(childNodeRef)) + if((fragment.isEmpty() || fileName.toLowerCase().startsWith(lowerCaseFragment)) && isNodeRefAppropriateForPathSuggestion(childNodeRef, unfiled)) { pathSuggestions.add("/" + fileName); if(pathSuggestions.size() >= pathSubstitutionMaximumNumberSuggestions) @@ -220,7 +225,7 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript * @param req * @return */ - protected NodeRef getFilePlan(WebScriptRequest req) + protected NodeRef getFilePlan(WebScriptRequest req, boolean unfiled) { NodeRef filePlan = null; @@ -256,7 +261,7 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript filePlan = filePlanService.getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID); } - return filePlan; + return unfiled ? filePlanService.getUnfiledContainer(filePlan) : filePlan; } /** @@ -265,12 +270,14 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript * @param nodeRef Instance of NodeRef to be tested * @return True if the passed NodeRef instance is a record category or record folder */ - private boolean isNodeRefAppropriateForPathSuggestion(NodeRef nodeRef) + private boolean isNodeRefAppropriateForPathSuggestion(NodeRef nodeRef, boolean unfiled) { // check node type QName type = nodeService.getType(nodeRef); String typeLocalName = type.getLocalName(); - boolean isCorrectType = (RECORD_FOLDER_TYPE.equals(typeLocalName) || RECORD_CATEGORY_TYPE.equals(typeLocalName)); + boolean isCorrectType = + (!unfiled && (RECORD_FOLDER_TYPE.equals(typeLocalName) || RECORD_CATEGORY_TYPE.equals(typeLocalName)) || + (unfiled && UNFILED_RECORD_FOLDER_TYPE.equals(typeLocalName))); // check permissions boolean canView = false; diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/action/FileToActionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/action/FileToActionTest.java index e0456dec54..d2359c577e 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/action/FileToActionTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/action/FileToActionTest.java @@ -42,13 +42,13 @@ import org.springframework.util.StringUtils; */ public class FileToActionTest extends BaseRMTestCase { - private static final String PATH = "rmcontainer/rmfolder"; - private static final String PATH2 = "/rmcontainer/rmfolder"; - private static final String PATH_BAD = "monkey/rmfolder"; - private static final String PATH_CREATE = "rmcontainer/newrmfolder"; - private static final String LONG_PATH_CREATE = "/rmcontainer/one/two/three/four/newrmfolder"; + private static final String PATH = "rmContainer/rmFolder"; + private static final String PATH2 = "/rmContainer/rmFolder"; + private static final String PATH_BAD = "monkey/rmFolder"; + private static final String PATH_CREATE = "rmContainer/newRmFolder"; + private static final String LONG_PATH_CREATE = "/rmContainer/one/two/three/four/newRmFolder"; - private static final String PATH_SUB1 = "rmcontainer/${node.cm:title}"; + private static final String PATH_SUB1 = "rmContainer/${node.cm:title}"; @Override protected boolean isCollaborationSiteTest() @@ -181,19 +181,19 @@ public class FileToActionTest extends BaseRMTestCase public void testCreate() throws Exception { initRecord(); - createRecord(PATH_CREATE, "newrmfolder"); + createRecord(PATH_CREATE, "newRmFolder"); } public void testCreateSub() throws Exception { initRecord(); - createRecord(PATH_SUB1, "mytestvalue", "rmcontainer/mytestvalue"); + createRecord(PATH_SUB1, "mytestvalue", "rmContainer/mytestvalue"); } public void testCreatePath() throws Exception { initRecord(); - createRecord(LONG_PATH_CREATE, "newrmfolder", "rmcontainer/one/two/three/four/newrmfolder"); + createRecord(LONG_PATH_CREATE, "newRmFolder", "rmContainer/one/two/three/four/newRmFolder"); } private void createRecord(String path, String name)