mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
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
This commit is contained in:
@@ -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
|
||||
|
@@ -855,6 +855,62 @@
|
||||
<property name="allowParameterSubstitutions" value="true"/>
|
||||
</bean>
|
||||
|
||||
<!-- Copy To -->
|
||||
|
||||
<bean id="copyTo_proxy" parent="rmProxyAction">
|
||||
<property name="target" ref="copyTo"/>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref bean="copyTo_security"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="copyTo_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor" parent="actionSecurity">
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
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
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="copyTo" class="org.alfresco.module.org_alfresco_module_rm.action.impl.CopyToAction" parent="rmAction">
|
||||
<property name="fileFolderService" ref="FileFolderService"/>
|
||||
<property name="filePlanService" ref="FilePlanService" />
|
||||
<property name="publicAction" value="true"/>
|
||||
<property name="allowParameterSubstitutions" value="true"/>
|
||||
</bean>
|
||||
|
||||
<!-- Move To -->
|
||||
|
||||
<bean id="moveTo_proxy" parent="rmProxyAction">
|
||||
<property name="target" ref="moveTo"/>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref bean="moveTo_security"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="moveTo_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor" parent="actionSecurity">
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
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
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="moveTo" class="org.alfresco.module.org_alfresco_module_rm.action.impl.MoveToAction" parent="rmAction">
|
||||
<property name="fileFolderService" ref="FileFolderService"/>
|
||||
<property name="filePlanService" ref="FilePlanService" />
|
||||
<property name="publicAction" value="true"/>
|
||||
<property name="allowParameterSubstitutions" value="true"/>
|
||||
</bean>
|
||||
|
||||
<!-- RequestInfo action -->
|
||||
|
||||
<bean id="requestInfo_proxy" parent="rmProxyAction">
|
||||
|
@@ -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<ParameterDefinition> 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<Void>()
|
||||
{
|
||||
@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<String> 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<ChildAssociationRef> 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;
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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<ParameterDefinition> 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<Void>()
|
||||
{
|
||||
@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<String> pathValueList = new ArrayList<String>(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<String> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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<String> substitutionSuggestions = new ArrayList<String>();
|
||||
|
||||
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<String> getSubPathSuggestions(WebScriptRequest req, final String path, final String fragment) {
|
||||
private List<String> getSubPathSuggestions(WebScriptRequest req, final String path, final String fragment, boolean unfiled) {
|
||||
List<String> pathSuggestions = new ArrayList<String>();
|
||||
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;
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user