From 017efecda95dbad2f1563565035792504a68e644 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Mon, 18 Feb 2013 00:47:11 +0000 Subject: [PATCH] RM: FileTo action will create a record folder if it can not be found by the provided relative path * this is not the default behaviour and needs to be specified via a action property * only executable as the RMAdmin atm * not yet available via the UI git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@46726 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../action/impl/FileToAction.java | 180 ++++++++++++++---- .../test/action/FileToActionTest.java | 126 +++++++++++- 2 files changed, 263 insertions(+), 43 deletions(-) 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 ff4c318128..c37c801c88 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 @@ -10,6 +10,7 @@ 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; /** @@ -24,6 +25,7 @@ public class FileToAction extends RMActionExecuterAbstractBase public static final String PARAM_DESTINATION_RECORD_FOLDER = "destinationRecordFolder"; public static final String PARAM_PATH = "path"; + public static final String PARAM_CREATE_RECORD_FOLDER = "createRecordFolder"; private FileFolderService fileFolderService; @@ -38,76 +40,170 @@ public class FileToAction extends RMActionExecuterAbstractBase @Override protected void executeImpl(Action action, NodeRef actionedUponNodeRef) { - if (recordService.isFiled(actionedUponNodeRef) == false) + if (nodeService.exists(actionedUponNodeRef) == true) { - // first look to see if the destination record folder has been specified - NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); - if (recordFolder == null) + if (recordService.isFiled(actionedUponNodeRef) == false) { - // get the reference to the record folder based on the relative path - recordFolder = resolvePath(action, actionedUponNodeRef); - } - - if (recordFolder == null) - { - throw new AlfrescoRuntimeException("Unable to execute file to action, because the destination record folder could not be determined."); - } - - if (recordsManagementService.isRecordFolder(recordFolder) == true) - { - // TODO .. what if a record of the same name already exists in the destination record folder?? - try + // first look to see if the destination record folder has been specified + NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); + if (recordFolder == null) { - fileFolderService.move(actionedUponNodeRef, recordFolder, null); + // get the reference to the record folder based on the relative path + recordFolder = createOrResolveRecordFolder(action, actionedUponNodeRef); } - catch (FileNotFoundException fileNotFound) + + if (recordFolder == null) { - throw new AlfrescoRuntimeException("Unable to execute file to action, because the move operation failed.", fileNotFound); + throw new AlfrescoRuntimeException("Unable to execute file to action, because the destination record folder could not be determined."); + } + + if (recordsManagementService.isRecordFolder(recordFolder) == true) + { + // TODO .. what if a record of the same name already exists in the destination record folder?? + try + { + fileFolderService.move(actionedUponNodeRef, recordFolder, null); + } + catch (FileNotFoundException fileNotFound) + { + throw new AlfrescoRuntimeException("Unable to execute file to action, because the move operation failed.", fileNotFound); + } + } + else + { + throw new AlfrescoRuntimeException("Unable to execute file to action, becuase the destination was not a record folder."); } } else { - throw new AlfrescoRuntimeException("Unable to execute file to action, becuase the destination was not a record folder."); + throw new AlfrescoRuntimeException("Unable to execute file to action, because the actioned upon node is not an unfiled record."); } } - else - { - throw new AlfrescoRuntimeException("Unable to execute file to action, because the actioned upon node is not an unfiled record."); - } } - private NodeRef resolvePath(Action action, NodeRef actionedUponNodeRef) + /** + * + * @param action + * @param actionedUponNodeRef + * @return + */ + private NodeRef createOrResolveRecordFolder(Action action, NodeRef actionedUponNodeRef) { - // TODO we could provide a parameter to override the file plan as the path context - + // TODO check the action for a context node reference // the file plan node always provides the context - NodeRef context = recordsManagementService.getFilePlan(actionedUponNodeRef); + NodeRef context = recordsManagementService.getFilePlan(actionedUponNodeRef); if (context == null) { - throw new AlfrescoRuntimeException("Unable to execute file to action, because the path resolution context could not be found."); + throw new AlfrescoRuntimeException("Unable to execute fileTo action, because the path resolution context could not be found."); + } + else if (nodeService.exists(context) == false) + { + throw new AlfrescoRuntimeException("Unable to execute fileTo action, because the context for the relative path does not exist."); } - - // assume by default the result is the context - NodeRef result = context; // look for the path parameter String path = (String)action.getParameterValue(PARAM_PATH); + String[] pathValues = ArrayUtils.EMPTY_STRING_ARRAY; if (path != null && path.isEmpty() == false) { - String[] pathValues = StringUtils.tokenizeToStringArray(path, "/", false, true); - try + pathValues = StringUtils.tokenizeToStringArray(path, "/", false, true); + } + + // look for the creation strategy + boolean create = false; + Boolean createValue = (Boolean)action.getParameterValue(PARAM_CREATE_RECORD_FOLDER); + if (createValue != null) + { + create = createValue.booleanValue(); + } + + // try and get child + NodeRef recordFolder = resolvePath(context, pathValues); + + if (recordFolder == null) + { + if (create == true) { - FileInfo fileInfo = fileFolderService.resolveNamePath(context, new ArrayList(Arrays.asList(pathValues))); - result = fileInfo.getNodeRef(); - } - catch (FileNotFoundException fileNotFound) - { - // TODO .. handle this exception by possibly creating the missing record folder ??? + // get the parent into which we are going to create the new record folder + NodeRef parent = resolveParent(context, pathValues); + if (parent == null) + { + throw new AlfrescoRuntimeException("Unable to create new record folder, because destination parent could not be found."); + } - throw new AlfrescoRuntimeException("Unable to execute file to action, because destination path could not be resolved."); + // ensure we are trying to create a record folder in a record category + if (recordsManagementService.isRecordCategory(parent) == false) + { + 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 = recordsManagementService.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(NodeRef context, String[] pathValues) + { + NodeRef result = null; + FileInfo fileInfo = null; + try + { + fileInfo = fileFolderService.resolveNamePath(context, new ArrayList(Arrays.asList(pathValues)), false); + } + catch (FileNotFoundException e) + { + // ignore, checking for null + } + if (fileInfo != null) + { + result = fileInfo.getNodeRef(); + } + return result; + } + + /** + * + * @param context + * @param pathValues + * @return + */ + private NodeRef resolveParent(NodeRef context, String[] pathValues) + { + NodeRef result = null; + + if (ArrayUtils.isEmpty(pathValues) == true) + { + // 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); } return result; } + + } 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 a67e5b411b..f23b2babf9 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 @@ -19,6 +19,8 @@ package org.alfresco.module.org_alfresco_module_rm.test.action; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -27,8 +29,10 @@ import org.alfresco.module.org_alfresco_module_rm.capability.Capability; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.service.cmr.action.ActionService; +import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessStatus; +import org.springframework.util.StringUtils; /** * FileTo action unit test @@ -40,6 +44,8 @@ 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"; protected ActionService dmActionService; @@ -164,7 +170,7 @@ public class FileToActionTest extends BaseRMTestCase public void testFileToPath2() { doTestInTransaction(new Test() - { + { public Void run() { // create record from document @@ -205,5 +211,123 @@ public class FileToActionTest extends BaseRMTestCase } }, rmAdminName); } + + public void testCreate() throws Exception + { + doTestInTransaction(new Test() + { + public Void run() + { + // create record from document + recordService.createRecord(filePlan, dmDocument); + + // check things have gone according to plan + assertTrue(recordService.isRecord(dmDocument)); + assertFalse(recordService.isFiled(dmDocument)); + + // is the unfiled container the primary parent of the filed record + NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef(); + assertEquals(filePlanService.getUnfiledContainer(filePlan), parent); + + return null; + } + }, dmCollaborator); + + doTestInTransaction(new Test() + { + public Void run() throws Exception + { + String[] pathValues = StringUtils.tokenizeToStringArray(PATH_CREATE, "/"); + + // show the folder doesn' exist to begin with + FileInfo createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList(Arrays.asList(pathValues)), false); + assertNull(createdRecordFolder); + + // set parameters + Map params = new HashMap(1); + params.put(FileToAction.PARAM_PATH, PATH_CREATE); + params.put(FileToAction.PARAM_CREATE_RECORD_FOLDER, true); + + // execute file-to action + actionService.executeRecordsManagementAction(dmDocument, FileToAction.NAME, params); + + // show the folder has now been created + createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList(Arrays.asList(pathValues)), false); + assertNotNull(createdRecordFolder); + assertEquals("newrmfolder", createdRecordFolder.getName()); + NodeRef createdRecordFolderNodeRef = createdRecordFolder.getNodeRef(); + + // check things have gone according to plan + assertTrue(recordService.isRecord(dmDocument)); + assertTrue(recordService.isFiled(dmDocument)); + + // is the record folder the primary parent of the filed record + NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef(); + assertEquals(createdRecordFolderNodeRef, parent); + + return null; + } + }, rmAdminName); + + } + + public void failureTests() throws Exception + { + doTestInTransaction(new Test() + { + public Void run() + { + // create record from document + recordService.createRecord(filePlan, dmDocument); + + // check things have gone according to plan + assertTrue(recordService.isRecord(dmDocument)); + assertFalse(recordService.isFiled(dmDocument)); + + // is the unfiled container the primary parent of the filed record + NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef(); + assertEquals(filePlanService.getUnfiledContainer(filePlan), parent); + + return null; + } + }, dmCollaborator); + + doTestInTransaction(new FailureTest + ( + "Path is invalid and record create not set." + ) + { + @Override + public void run() throws Exception + { + // set parameters + Map params = new HashMap(1); + params.put(FileToAction.PARAM_PATH, PATH_BAD); + + // execute file-to action + actionService.executeRecordsManagementAction(dmDocument, FileToAction.NAME, params); + + } + }); + + doTestInTransaction(new FailureTest + ( + "Path is for a new folder, but create not set." + ) + { + @Override + public void run() throws Exception + { + // set parameters + Map params = new HashMap(1); + params.put(FileToAction.PARAM_PATH, PATH_CREATE); + + // execute file-to action + actionService.executeRecordsManagementAction(dmDocument, FileToAction.NAME, params); + + } + }); + + } }