diff --git a/build.xml b/build.xml
index 326ea9708b..9b1a065d48 100644
--- a/build.xml
+++ b/build.xml
@@ -114,4 +114,7 @@
-
\ No newline at end of file
+
+
+
+
diff --git a/rm-server/build.xml b/rm-server/build.xml
index 85e3ad8c55..d4ecc2401f 100644
--- a/rm-server/build.xml
+++ b/rm-server/build.xml
@@ -1,28 +1,29 @@
-
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
-
\ No newline at end of file
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 3a8f03b462..1d32068d9c 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
@@ -78,7 +78,7 @@ unfreeze.description=Unfreezes a record.
fileTo.title=File to
fileTo.description=Files a record to the specified record folder.
fileTo.path.display-label=Path to Record Folder
-fileTo.createRecordFolder.display-label=Create Record Folder
+fileTo.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-webscript-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml
index 4d964f0686..9d786a52df 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml
@@ -566,4 +566,11 @@
+
+
+
+
+
\ 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 e2ccffcc00..9a88255d2c 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
@@ -15,6 +15,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.alfresco.service.cmr.search.CategoryService;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.util.StringUtils;
@@ -32,14 +33,14 @@ public class FileToAction 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_FOLDER = "createRecordFolder";
+ 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
*/
@@ -63,7 +64,7 @@ public class FileToAction extends RMActionExecuterAbstractBase
protected void addParameterDefinitions(List paramList)
{
paramList.add(new ParameterDefinitionImpl(PARAM_PATH, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_PATH)));
- paramList.add(new ParameterDefinitionImpl(PARAM_CREATE_RECORD_FOLDER, DataTypeDefinition.BOOLEAN, false, getParamDisplayLabel(PARAM_CREATE_RECORD_FOLDER)));
+ paramList.add(new ParameterDefinitionImpl(PARAM_CREATE_RECORD_PATH, DataTypeDefinition.BOOLEAN, false, getParamDisplayLabel(PARAM_CREATE_RECORD_PATH)));
}
/**
@@ -141,7 +142,7 @@ public class FileToAction extends RMActionExecuterAbstractBase
// look for the creation strategy
boolean create = false;
- Boolean createValue = (Boolean)action.getParameterValue(PARAM_CREATE_RECORD_FOLDER);
+ Boolean createValue = (Boolean)action.getParameterValue(PARAM_CREATE_RECORD_PATH);
if (createValue != null)
{
create = createValue.booleanValue();
@@ -155,7 +156,7 @@ public class FileToAction extends RMActionExecuterAbstractBase
if (create == true)
{
// get the parent into which we are going to create the new record folder
- NodeRef parent = resolveParent(context, pathValues);
+ 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.");
@@ -187,12 +188,43 @@ public class FileToAction extends RMActionExecuterAbstractBase
* @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
{
- fileInfo = fileFolderService.resolveNamePath(context, new ArrayList(Arrays.asList(pathValues)), false);
+ 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)
{
@@ -212,6 +244,18 @@ public class FileToAction extends RMActionExecuterAbstractBase
* @return
*/
private NodeRef resolveParent(NodeRef context, String[] pathValues)
+ {
+ return resolveParent(context, pathValues, false);
+ }
+
+ /**
+ *
+ * @param context
+ * @param pathValues
+ * @param create Create any missing path elements
+ * @return
+ */
+ private NodeRef resolveParent(NodeRef context, String[] pathValues, boolean create)
{
NodeRef result = null;
@@ -229,7 +273,7 @@ public class FileToAction extends RMActionExecuterAbstractBase
else
{
pathValues = (String[])ArrayUtils.remove(pathValues, pathValues.length-1);
- result = resolvePath(context, pathValues);
+ result = resolvePath(context, pathValues, create);
}
return result;
diff --git a/rm-server/source/java/org/alfresco/repo/action/parameter/DateParameterProcessor.java b/rm-server/source/java/org/alfresco/repo/action/parameter/DateParameterProcessor.java
index 45eb13f38f..3810258297 100644
--- a/rm-server/source/java/org/alfresco/repo/action/parameter/DateParameterProcessor.java
+++ b/rm-server/source/java/org/alfresco/repo/action/parameter/DateParameterProcessor.java
@@ -19,7 +19,9 @@
package org.alfresco.repo.action.parameter;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -30,7 +32,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
* @author Roy Wetherall
* @since 2.1
*/
-public class DateParameterProcessor extends ParameterProcessor
+public class DateParameterProcessor extends ParameterProcessor implements ParameterSubstitutionSuggester
{
private static final String DAY = "day";
private static final String WEEK = "week";
@@ -39,6 +41,27 @@ public class DateParameterProcessor extends ParameterProcessor
private static final String SHORT = "short";
private static final String LONG = "long";
private static final String NUMBER = "number";
+
+ private static final String SEP = ".";
+
+ private static final String[] ALL_FIELDS_FOR_SUBSTITUTION_QUERY = {
+ DAY,
+ DAY + SEP + SHORT,
+ DAY + SEP + LONG,
+ DAY + SEP + NUMBER,
+ WEEK,
+ WEEK + SEP + SHORT,
+ WEEK + SEP + LONG,
+ WEEK + SEP + NUMBER,
+ MONTH,
+ MONTH + SEP + SHORT,
+ MONTH + SEP + LONG,
+ MONTH + SEP + NUMBER,
+ YEAR,
+ YEAR + SEP + SHORT,
+ YEAR + SEP + LONG,
+ YEAR + SEP + NUMBER
+ };
/**
* @see org.alfresco.repo.action.parameter.ParameterProcessor#process(java.lang.String, org.alfresco.service.cmr.repository.NodeRef)
@@ -172,4 +195,28 @@ public class DateParameterProcessor extends ParameterProcessor
return style;
}
+
+ @Override
+ public List getSubstitutionSuggestions(String substitutionFragment)
+ {
+ List suggestions = new ArrayList();
+ String namePrefix = this.getName() + ".";
+ if(this.getName().toLowerCase().contains(substitutionFragment.toLowerCase()))
+ {
+ for(String field: ALL_FIELDS_FOR_SUBSTITUTION_QUERY) {
+ suggestions.add(namePrefix + field);
+ }
+ }
+ else
+ {
+ for(String field: ALL_FIELDS_FOR_SUBSTITUTION_QUERY) {
+ String prefixFieldName = namePrefix + field;
+ if(prefixFieldName.toLowerCase().contains(substitutionFragment.toLowerCase()))
+ {
+ suggestions.add(namePrefix + field);
+ }
+ }
+ }
+ return suggestions;
+ }
}
diff --git a/rm-server/source/java/org/alfresco/repo/action/parameter/ParameterProcessorComponent.java b/rm-server/source/java/org/alfresco/repo/action/parameter/ParameterProcessorComponent.java
index dff8451d11..91e28c0afa 100644
--- a/rm-server/source/java/org/alfresco/repo/action/parameter/ParameterProcessorComponent.java
+++ b/rm-server/source/java/org/alfresco/repo/action/parameter/ParameterProcessorComponent.java
@@ -19,7 +19,9 @@
package org.alfresco.repo.action.parameter;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -28,6 +30,7 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.action.ParameterizedItem;
import org.alfresco.service.cmr.action.ParameterizedItemDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
+import org.apache.commons.lang.StringUtils;
/**
* Parameter processor component
@@ -35,13 +38,15 @@ import org.alfresco.service.cmr.repository.NodeRef;
* @author Roy Wetherall
* @since 2.1
*/
-public class ParameterProcessorComponent
+public class ParameterProcessorComponent implements ParameterSubstitutionSuggester
{
/** regex used to parse parameters */
- private static final String REG_EX = "\\$\\{([^\\$\\{]+)\\}";
+ private static final String REG_EX_OLD = "\\$\\{([^\\$\\{]+)\\}";
+ private static final String REG_EX = "\\{([^\\{]+)\\}";
/** registry of parameter processors */
private Map processors = new HashMap(5);
+ private List subtitutionSuggesterProcessors = new ArrayList(5);
/**
* Register parameter processor
@@ -51,6 +56,10 @@ public class ParameterProcessorComponent
public void register(ParameterProcessor processor)
{
this.processors.put(processor.getName(), processor);
+ if(processor instanceof ParameterSubstitutionSuggester)
+ {
+ this.subtitutionSuggesterProcessors.add((ParameterSubstitutionSuggester)processor);
+ }
}
/**
@@ -83,9 +92,14 @@ public class ParameterProcessorComponent
* @return String resulting value
*/
public String process(String value, NodeRef nodeRef)
+ {
+ return process(process(value, nodeRef, REG_EX_OLD), nodeRef, REG_EX);
+ }
+
+ public String process(String value, NodeRef nodeRef, String regExp)
{
// match the substitution pattern
- Pattern patt = Pattern.compile(REG_EX);
+ Pattern patt = Pattern.compile(regExp);
Matcher m = patt.matcher(value);
StringBuffer sb = new StringBuffer(value.length());
@@ -112,6 +126,25 @@ public class ParameterProcessorComponent
return sb.toString();
}
+ /**
+ * Return a list of substitution suggestions for the passed string fragment.
+ *
+ * @param subtitutionFragment Text fragment to search on.
+ * @return A list of substitutions that match the substitution fragment.
+ */
+ public List getSubstitutionSuggestions(final String substitutionFragment)
+ {
+ List suggestions = new ArrayList();
+ if (StringUtils.isNotBlank(substitutionFragment))
+ {
+ for (ParameterSubstitutionSuggester suggestor : this.subtitutionSuggesterProcessors)
+ {
+ suggestions.addAll(suggestor.getSubstitutionSuggestions(substitutionFragment.toLowerCase()));
+ }
+ }
+ return suggestions;
+ }
+
/**
* Look up parameter processor
*
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/AllTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/AllTestSuite.java
index 0a3a9e7273..897357ab5f 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/AllTestSuite.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/AllTestSuite.java
@@ -18,6 +18,7 @@
*/
package org.alfresco.module.org_alfresco_module_rm.test;
+import org.alfresco.repo.ParameterProcessorTestSuite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@@ -36,7 +37,8 @@ import org.junit.runners.Suite.SuiteClasses;
CapabilitiesTestSuite.class,
ServicesTestSuite.class,
WebScriptTestSuite.class,
- IssueTestSuite.class
+ IssueTestSuite.class,
+ ParameterProcessorTestSuite.class
})
public class AllTestSuite
{
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/WebScriptTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/WebScriptTestSuite.java
index cb3163fbc5..0c8cc7289a 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/WebScriptTestSuite.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/WebScriptTestSuite.java
@@ -31,6 +31,7 @@ import org.alfresco.module.org_alfresco_module_rm.test.webscript.RmAuthoritiesRe
import org.alfresco.module.org_alfresco_module_rm.test.webscript.RmClassesRestApiTest;
import org.alfresco.module.org_alfresco_module_rm.test.webscript.RmPropertiesRestApiTest;
import org.alfresco.module.org_alfresco_module_rm.test.webscript.RoleRestApiTest;
+import org.alfresco.repo.web.scripts.SubstitutionSuggestionsRestApiTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@@ -56,7 +57,8 @@ import org.junit.runners.Suite.SuiteClasses;
ActionDefinitionsRestApiTest.class,
RmClassesRestApiTest.class,
RmPropertiesRestApiTest.class,
- RmAuthoritiesRestApiTest.class
+ RmAuthoritiesRestApiTest.class,
+ SubstitutionSuggestionsRestApiTest.class
})
public class WebScriptTestSuite
{
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 e540e905b7..e0456dec54 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
@@ -46,6 +46,7 @@ public class FileToActionTest extends BaseRMTestCase
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}";
@@ -189,6 +190,12 @@ public class FileToActionTest extends BaseRMTestCase
createRecord(PATH_SUB1, "mytestvalue", "rmcontainer/mytestvalue");
}
+ public void testCreatePath() throws Exception
+ {
+ initRecord();
+ createRecord(LONG_PATH_CREATE, "newrmfolder", "rmcontainer/one/two/three/four/newrmfolder");
+ }
+
private void createRecord(String path, String name)
{
createRecord(path, name, path);
@@ -209,7 +216,7 @@ public class FileToActionTest extends BaseRMTestCase
// set parameters
Map params = new HashMap(1);
params.put(FileToAction.PARAM_PATH, path);
- params.put(FileToAction.PARAM_CREATE_RECORD_FOLDER, true);
+ params.put(FileToAction.PARAM_CREATE_RECORD_PATH, true);
// execute file-to action
rmActionService.executeRecordsManagementAction(dmDocument, FileToAction.NAME, params);