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:
Mark Hibbins
2014-03-27 10:53:58 +00:00
parent a0b11a7377
commit 9d66d4f6b2
8 changed files with 427 additions and 282 deletions

View File

@@ -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

View File

@@ -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">

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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)