RM-591: A records manager can define a rule that creates folders based on a creation strategy

* RM actions can be configured to allow parmater level substitution
 * Paramater processor component added .. resposibile for processing parameters of an RM action and selecting the correct processor
 * Parameter processor framework added .. new processors can be sprung in using the usual pattern
 * 'node' processor added .. allows simple property value substitution based on the actioned upon node
 * 'date' processor added .. allows simple date value substituation
 * 'message' processor added .. allows message bundle value substitution
 * an example substitution parameter could be .. "/${message.my-company.name}/invoices/${date.month.short}"
 * fileTo action is configured to allow parameter substitution .. with the relative path and auto create features as well it is possible to define a rule that creates records folders based on a simple creation strategy .. for example always file into a record folder for this month



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@47262 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2013-02-28 07:21:26 +00:00
parent c626585c1a
commit 81806ae2f9
16 changed files with 770 additions and 126 deletions

View File

@@ -157,6 +157,27 @@
</property> </property>
</bean> </bean>
<bean id="parameterProcessorComponent" class="org.alfresco.repo.action.parameter.ParameterProcessorComponent"/>
<bean id="baseParamenterProcessor" abstract="true" init-method="init">
<property name="parameterProcessorComponent" ref="parameterProcessorComponent"/>
</bean>
<bean id="nodeParameterProcessor" parent="baseParamenterProcessor" class="org.alfresco.repo.action.parameter.NodeParameterProcessor" >
<property name="name" value="node" />
<property name="nodeService" ref="NodeService" />
<property name="dictionaryService" ref="DictionaryService" />
<property name="namespaceService" ref="NamespaceService" />
</bean>
<bean id="dateParameterProcessor" parent="baseParamenterProcessor" class="org.alfresco.repo.action.parameter.DateParameterProcessor">
<property name="name" value="date" />
</bean>
<bean id="messageParameterProcessor" parent="baseParamenterProcessor" class="org.alfresco.repo.action.parameter.MessageParameterProcessor">
<property name="name" value="message" />
</bean>
<!-- Rule Service --> <!-- Rule Service -->
<bean id="ruleService" class="org.alfresco.repo.rule.ExtendedRuleServiceImpl" init-method="init"> <bean id="ruleService" class="org.alfresco.repo.rule.ExtendedRuleServiceImpl" init-method="init">

View File

@@ -32,6 +32,7 @@
<property name="ownableService" ref="ownableService"/> <property name="ownableService" ref="ownableService"/>
<property name="freezeService" ref="freezeService"/> <property name="freezeService" ref="freezeService"/>
<property name="recordService" ref="recordService"/> <property name="recordService" ref="recordService"/>
<property name="parameterProcessorComponent" ref="parameterProcessorComponent"/>
</bean> </bean>
<bean id="rmProxyAction" <bean id="rmProxyAction"
@@ -696,6 +697,7 @@
<bean id="fileTo" class="org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction" parent="rmAction"> <bean id="fileTo" class="org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction" parent="rmAction">
<property name="fileFolderService" ref="FileFolderService"/> <property name="fileFolderService" ref="FileFolderService"/>
<property name="publicAction" value="true"/> <property name="publicAction" value="true"/>
<property name="allowParameterSubstitutions" value="true"/>
</bean> </bean>
</beans> </beans>

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.action;
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.repo.action.parameter.ParameterProcessorComponent;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Extension to action implementation hierarchy to insert parameter substitution processing.
*
* @author Roy Wetherall
* @since 2.1
*/
public abstract class PropertySubActionExecuterAbstractBase extends ActionExecuterAbstractBase
{
private ParameterProcessorComponent parameterProcessorComponent;
protected boolean allowParameterSubstitutions = false;
public void setParameterProcessorComponent(ParameterProcessorComponent parameterProcessorComponent)
{
this.parameterProcessorComponent = parameterProcessorComponent;
}
public void setAllowParameterSubstitutions(boolean allowParameterSubstitutions)
{
this.allowParameterSubstitutions = allowParameterSubstitutions;
}
@Override
public void execute(Action action, NodeRef actionedUponNodeRef)
{
if (allowParameterSubstitutions == true)
{
parameterProcessorComponent.process(action, getActionDefinition(), actionedUponNodeRef);
}
super.execute(action, actionedUponNodeRef);
}
}

View File

@@ -69,7 +69,7 @@ import org.springframework.util.StringUtils;
* *
* @author Roy Wetherall * @author Roy Wetherall
*/ */
public abstract class RMActionExecuterAbstractBase extends ActionExecuterAbstractBase public abstract class RMActionExecuterAbstractBase extends PropertySubActionExecuterAbstractBase
implements RecordsManagementAction, implements RecordsManagementAction,
RecordsManagementModel, RecordsManagementModel,
BeanNameAware BeanNameAware
@@ -392,8 +392,6 @@ public abstract class RMActionExecuterAbstractBase extends ActionExecuterAbstra
*/ */
public RecordsManagementActionResult execute(NodeRef filePlanComponent, Map<String, Serializable> parameters) public RecordsManagementActionResult execute(NodeRef filePlanComponent, Map<String, Serializable> parameters)
{ {
//isExecutableImpl(filePlanComponent, parameters, true);
// Create the action // Create the action
Action action = this.actionService.createAction(name); Action action = this.actionService.createAction(name);
action.setParameterValues(parameters); action.setParameterValues(parameters);
@@ -440,22 +438,6 @@ public abstract class RMActionExecuterAbstractBase extends ActionExecuterAbstra
// No parameters // No parameters
} }
// /**
// * @see org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction#isExecutable(org.alfresco.service.cmr.repository.NodeRef, java.util.Map)
// */
// public boolean isExecutable(NodeRef filePlanComponent, Map<String, Serializable> parameters)
// {
// return isExecutableImpl(filePlanComponent, parameters, false);
// }
//
// /**
// * @param filePlanComponent
// * @param parameters
// * @param throwException
// * @return
// */
// protected abstract boolean isExecutableImpl(NodeRef filePlanComponent, Map<String, Serializable> parameters, boolean throwException);
/** /**
* By default, rmActions do not provide an implicit target nodeRef. * By default, rmActions do not provide an implicit target nodeRef.
*/ */

View File

@@ -6,9 +6,7 @@ import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.ParameterDefinitionImpl; import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
@@ -84,24 +82,14 @@ public class FileToAction extends RMActionExecuterAbstractBase
// TODO .. what if a record of the same name already exists in the destination record folder?? // TODO .. what if a record of the same name already exists in the destination record folder??
final NodeRef finalRecordFolder = recordFolder; final NodeRef finalRecordFolder = recordFolder;
// AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
// {
// @Override
// public Void doWork() throws Exception
// {
try try
{ {
// TODO .. why do I have to execute this as system .. I should have permission to do this!!!
fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null); fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null);
} }
catch (FileNotFoundException fileNotFound) catch (FileNotFoundException fileNotFound)
{ {
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 move operation failed.", fileNotFound);
} }
//
// return null;
// }
// });
} }
else else
{ {
@@ -138,6 +126,7 @@ public class FileToAction extends RMActionExecuterAbstractBase
// look for the path parameter // look for the path parameter
String path = (String)action.getParameterValue(PARAM_PATH); String path = (String)action.getParameterValue(PARAM_PATH);
String[] pathValues = ArrayUtils.EMPTY_STRING_ARRAY; String[] pathValues = ArrayUtils.EMPTY_STRING_ARRAY;
if (path != null && path.isEmpty() == false) if (path != null && path.isEmpty() == false)
{ {
pathValues = StringUtils.tokenizeToStringArray(path, "/", false, true); pathValues = StringUtils.tokenizeToStringArray(path, "/", false, true);
@@ -193,12 +182,6 @@ public class FileToAction extends RMActionExecuterAbstractBase
private NodeRef resolvePath(final NodeRef context, final String[] pathValues) private NodeRef resolvePath(final NodeRef context, final String[] pathValues)
{ {
NodeRef result = null; NodeRef result = null;
//FileInfo fileInfo = AuthenticationUtil.runAsSystem(new RunAsWork<FileInfo>()
//{
// @Override
// public FileInfo doWork() throws Exception
// {
FileInfo fileInfo = null; FileInfo fileInfo = null;
try try
{ {
@@ -208,10 +191,6 @@ public class FileToAction extends RMActionExecuterAbstractBase
{ {
// ignore, checking for null // ignore, checking for null
} }
// return fileInfo;
// }
//});
if (fileInfo != null) if (fileInfo != null)
{ {
result = fileInfo.getNodeRef(); result = fileInfo.getNodeRef();

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.action.parameter;
import java.util.Calendar;
import java.util.Locale;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Date parameter processor.
*
* @author Roy Wetherall
* @since 2.1
*/
public class DateParameterProcessor extends ParameterProcessor
{
private static final String MONTH = "month";
private static final String YEAR = "year";
private static final String SHORT = "short";
private static final String LONG = "long";
/**
* @see org.alfresco.repo.action.parameter.ParameterProcessor#process(java.lang.String, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public String process(String value, NodeRef actionedUponNodeRef)
{
// the default position is to return the value un-changed
String result = value;
// strip the processor name from the value
value = stripName(value);
if (value.isEmpty() == false)
{
String[] values = value.split("\\.", 2);
Calendar calendar = Calendar.getInstance();
int field = getField(values);
if (Calendar.YEAR == field)
{
result = Integer.toString(calendar.get(field));
}
else
{
result = calendar.getDisplayName(field, getStyle(values), Locale.getDefault());
}
}
return result;
}
private int getField(String[] values)
{
int result = 0;
String field = values[0];
if (MONTH.equals(field) == true)
{
result = Calendar.MONTH;
}
else if (YEAR.equals(field) == true)
{
result = Calendar.YEAR;
}
else
{
throw new AlfrescoRuntimeException("Date component " + field + " is not supported by parameter substitution.");
}
return result;
}
private int getStyle(String[] values)
{
int result = Calendar.SHORT;
if (values.length == 2)
{
String style = values[1];
if (LONG.equals(style) == true)
{
result = Calendar.LONG;
}
else if (SHORT.equals(style) == true)
{
result = Calendar.SHORT;
}
else
{
throw new AlfrescoRuntimeException("Style component " + style + " is not supported by parameter substitution.");
}
}
return result;
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.action.parameter;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Message parameter processor.
*
* @author Roy Wetherall
* @since 2.1
*/
public class MessageParameterProcessor extends ParameterProcessor
{
/**
* @see org.alfresco.repo.action.parameter.ParameterProcessor#process(java.lang.String, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public String process(String value, NodeRef actionedUponNodeRef)
{
// the default position is to return the value un-changed
String result = value;
// strip the processor name from the value
value = stripName(value);
if (value.isEmpty() == false)
{
result = I18NUtil.getMessage(value);
if (result == null)
{
throw new AlfrescoRuntimeException("The message parameter processor could not resolve the message for the id " + value);
}
}
return result;
}
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.action.parameter;
import java.io.Serializable;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.lang.ArrayUtils;
/**
* Node parameter processor.
*
* @author Roy Wetherall
* @since 2.1
*/
public class NodeParameterProcessor extends ParameterProcessor
{
/** Supported data types */
private QName[] supportedDataTypes =
{
DataTypeDefinition.TEXT,
DataTypeDefinition.BOOLEAN,
DataTypeDefinition.DATE,
DataTypeDefinition.DATETIME,
DataTypeDefinition.DOUBLE,
DataTypeDefinition.FLOAT,
DataTypeDefinition.INT
};
/** Node service */
private NodeService nodeService;
/** Namespace service */
private NamespaceService namespaceService;
/** Dictionary service */
private DictionaryService dictionaryService;
/**
* @param nodeService node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param namespaceService namespace service
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @param dictionaryService dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @see org.alfresco.repo.action.parameter.ParameterProcessor#process(java.lang.String, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public String process(String value, NodeRef actionedUponNodeRef)
{
// the default position is to return the value un-changed
String result = value;
// strip the processor name from the value
value = stripName(value);
if (value.isEmpty() == false)
{
QName qname = QName.createQName(value, namespaceService);
PropertyDefinition propertyDefinition = dictionaryService.getProperty(qname);
if (propertyDefinition == null)
{
throw new AlfrescoRuntimeException("The property " + value + " does not have a property definition.");
}
QName type = propertyDefinition.getDataType().getName();
if (ArrayUtils.contains(supportedDataTypes, type) == true)
{
Serializable propertyValue = nodeService.getProperty(actionedUponNodeRef, qname);
result = propertyValue.toString();
}
else
{
throw new AlfrescoRuntimeException("The property " + value + " is of type " + type.toString() + " which is not supported by parameter substitution.");
}
}
return result;
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.action.parameter;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Abstract parameter processor implementation.
*
* @author Roy Wetherall
* @since 2.1
*/
public abstract class ParameterProcessor
{
/** Processor name */
private String name;
/** Parameter processor component */
private ParameterProcessorComponent parameterProcessorComponent;
/**
* @return parameter processor name
*/
public String getName()
{
return name;
}
/**
* @param name parameter processor name
*/
public void setName(String name)
{
this.name = name;
}
/**
* @param parameterProcessorComponent parameter processor component
*/
public void setParameterProcessorComponent(ParameterProcessorComponent parameterProcessorComponent)
{
this.parameterProcessorComponent = parameterProcessorComponent;
}
/**
* Init method
*/
public void init()
{
parameterProcessorComponent.register(this);
}
/**
* Process the parameter value.
*
* @param value substitution value
* @param actionedUponNodeRef actioned upon node reference
* @return String processed string, original string if subs string invalid
*/
public abstract String process(String value, NodeRef actionedUponNodeRef);
/**
* Strips the name of the processor from the subs value.
*
* @param value subs value
* @return String subs value with the name and '.' delimiter removed
*/
protected String stripName(String value)
{
String result = "";
String[] values = value.split("\\.", 2);
if (values.length == 2)
{
result = values[1];
}
return result;
}
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.action.parameter;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.action.ParameterizedItem;
import org.alfresco.service.cmr.action.ParameterizedItemDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
/**
*
*
* @author Roy Wetherall
* @since 2.1
*/
public class ParameterProcessorComponent
{
private static final String REG_EX = "\\$\\{([^\\$\\{]+)\\}";
private Map<String, ParameterProcessor> processors = new HashMap<String, ParameterProcessor>(5);
/**
*
* @param processor
*/
public void register(ParameterProcessor processor)
{
this.processors.put(processor.getName(), processor);
}
/**
*
* @param ruleItem
* @param ruleItemDefinition
* @param actionedUponNodeRef
*/
public void process(ParameterizedItem ruleItem, ParameterizedItemDefinition ruleItemDefinition, NodeRef actionedUponNodeRef)
{
for (Map.Entry<String, Serializable> entry : ruleItem.getParameterValues().entrySet())
{
String parameterName = entry.getKey();
// get the parameter definition
ParameterDefinition def = ruleItemDefinition.getParameterDefintion(parameterName);
if (def != null)
{
if (DataTypeDefinition.TEXT.equals(def.getType()) == true)
{
String parameterValue = (String)entry.getValue();
// match the substitution pattern
Pattern patt = Pattern.compile(REG_EX);
Matcher m = patt.matcher(parameterValue);
StringBuffer sb = new StringBuffer(parameterValue.length());
while (m.find())
{
String text = m.group(1);
// lookup parameter processor to use
ParameterProcessor processor = lookupProcessor(text);
if (processor == null)
{
throw new AlfrescoRuntimeException("A parameter processor has not been found for the substitution string " + text);
}
else
{
// process each substitution value
text = processor.process(text, actionedUponNodeRef);
}
// append new value
m.appendReplacement(sb, Matcher.quoteReplacement(text));
}
m.appendTail(sb);
// set the updated parameter value
ruleItem.setParameterValue(parameterName, sb.toString());
}
}
}
}
private ParameterProcessor lookupProcessor(String value)
{
ParameterProcessor result = null;
if (value != null && value.isEmpty() == false)
{
String[] values = value.split("\\.", 2);
if (values.length != 0)
{
// get the processor from the registered map
result = processors.get(values[0]);
}
}
return result;
}
}

View File

@@ -47,6 +47,8 @@ public class FileToActionTest extends BaseRMTestCase
private static final String PATH_BAD = "monkey/rmfolder"; private static final String PATH_BAD = "monkey/rmfolder";
private static final String PATH_CREATE = "rmcontainer/newrmfolder"; private static final String PATH_CREATE = "rmcontainer/newrmfolder";
private static final String PATH_SUB1 = "rmcontainer/${node.name}";
protected ActionService dmActionService; protected ActionService dmActionService;
@Override @Override
@@ -70,24 +72,7 @@ public class FileToActionTest extends BaseRMTestCase
public void testFileToNodeRef() public void testFileToNodeRef()
{ {
doTestInTransaction(new Test<Void>() initRecord();
{
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<Void>() doTestInTransaction(new Test<Void>()
{ {
@@ -119,10 +104,9 @@ public class FileToActionTest extends BaseRMTestCase
return null; return null;
} }
}, rmAdminName); }, rmAdminName);
} }
public void testFileToPath() private void initRecord()
{ {
doTestInTransaction(new Test<Void>() doTestInTransaction(new Test<Void>()
{ {
@@ -142,6 +126,11 @@ public class FileToActionTest extends BaseRMTestCase
return null; return null;
} }
}, dmCollaborator); }, dmCollaborator);
}
public void testFileToPath()
{
initRecord();
doTestInTransaction(new Test<Void>() doTestInTransaction(new Test<Void>()
{ {
@@ -169,24 +158,7 @@ public class FileToActionTest extends BaseRMTestCase
public void testFileToPath2() public void testFileToPath2()
{ {
doTestInTransaction(new Test<Void>() initRecord();
{
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<Void>() doTestInTransaction(new Test<Void>()
{ {
@@ -214,38 +186,36 @@ public class FileToActionTest extends BaseRMTestCase
public void testCreate() throws Exception public void testCreate() throws Exception
{ {
doTestInTransaction(new Test<Void>() initRecord();
{ createRecord(PATH_CREATE, "newrmfolder");
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);
public void testCreateSub() throws Exception
{
initRecord();
createRecord(PATH_SUB1, "collabDocument.txt", "rmcontainer/collabDocument.txt");
}
private void createRecord(String path, String name)
{
createRecord(path, name, path);
}
private void createRecord(final String path, final String name, final String resolvedPath)
{
doTestInTransaction(new Test<Void>() doTestInTransaction(new Test<Void>()
{ {
public Void run() throws Exception public Void run() throws Exception
{ {
String[] pathValues = StringUtils.tokenizeToStringArray(PATH_CREATE, "/"); String[] pathValues = StringUtils.tokenizeToStringArray(resolvedPath, "/");
// show the folder doesn' exist to begin with // show the folder doesn't exist to begin with
FileInfo createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList<String>(Arrays.asList(pathValues)), false); FileInfo createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList<String>(Arrays.asList(pathValues)), false);
assertNull(createdRecordFolder); assertNull(createdRecordFolder);
// set parameters // set parameters
Map<String, Serializable> params = new HashMap<String, Serializable>(1); Map<String, Serializable> params = new HashMap<String, Serializable>(1);
params.put(FileToAction.PARAM_PATH, PATH_CREATE); params.put(FileToAction.PARAM_PATH, path);
params.put(FileToAction.PARAM_CREATE_RECORD_FOLDER, true); params.put(FileToAction.PARAM_CREATE_RECORD_FOLDER, true);
// execute file-to action // execute file-to action
@@ -254,7 +224,7 @@ public class FileToActionTest extends BaseRMTestCase
// show the folder has now been created // show the folder has now been created
createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList<String>(Arrays.asList(pathValues)), false); createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList<String>(Arrays.asList(pathValues)), false);
assertNotNull(createdRecordFolder); assertNotNull(createdRecordFolder);
assertEquals("newrmfolder", createdRecordFolder.getName()); assertEquals(name, createdRecordFolder.getName());
NodeRef createdRecordFolderNodeRef = createdRecordFolder.getNodeRef(); NodeRef createdRecordFolderNodeRef = createdRecordFolder.getNodeRef();
// check things have gone according to plan // check things have gone according to plan
@@ -268,7 +238,6 @@ public class FileToActionTest extends BaseRMTestCase
return null; return null;
} }
}, rmAdminName); }, rmAdminName);
} }
public void failureTests() throws Exception public void failureTests() throws Exception

View File

@@ -21,6 +21,8 @@ package org.alfresco.module.org_alfresco_module_rm.test.service;
import java.util.List; import java.util.List;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.module.org_alfresco_module_rm.test.util.TestActionPropertySubs;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionDefinition; import org.alfresco.service.cmr.action.ActionDefinition;
import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
@@ -142,4 +144,29 @@ public class ExtendedActionServiceTest extends BaseRMTestCase
return result; return result;
} }
public void testActionPropertySubstitution() throws Exception
{
doTestInTransaction(new Test<Void>()
{
public Void run()
{
Action action = dmActionService.createAction(TestActionPropertySubs.NAME);
action.setParameterValue("longMonth", "${date.month.long}");
action.setParameterValue("shortMonth", "${date.month}");
action.setParameterValue("year", "${date.year}");
action.setParameterValue("name", "${node.cm:name}");
action.setParameterValue("company", "${message.test.company}");
action.setParameterValue("combo", "${date.year}/${date.month.short}/${node.cm:name}-${message.test.company}.txt");
dmActionService.executeAction(action, rmFolder);
return null;
}
});
}
} }

View File

@@ -34,7 +34,7 @@ public class TestActionParams extends RMActionExecuterAbstractBase
Object dateValue = action.getParameterValue(PARAM_DATE); Object dateValue = action.getParameterValue(PARAM_DATE);
if ((dateValue instanceof java.util.Date) == false) if ((dateValue instanceof java.util.Date) == false)
{ {
throw new AlfrescoRuntimeException("Param we not a Date as expected."); throw new AlfrescoRuntimeException("Param was not a Date as expected.");
} }
} }
} }

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.test.util;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase;
import org.alfresco.repo.action.ParameterDefinitionImpl;
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.repository.NodeRef;
import org.springframework.extensions.surf.util.I18NUtil;
public class TestActionPropertySubs extends RMActionExecuterAbstractBase
{
public static final String NAME = "testActionPropertySubs";
@Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
{
paramList.add(new ParameterDefinitionImpl("shortMonth", DataTypeDefinition.TEXT, false, ""));
paramList.add(new ParameterDefinitionImpl("longMonth", DataTypeDefinition.TEXT, false, ""));
paramList.add(new ParameterDefinitionImpl("year", DataTypeDefinition.TEXT, false, ""));
paramList.add(new ParameterDefinitionImpl("name", DataTypeDefinition.TEXT, false, ""));
paramList.add(new ParameterDefinitionImpl("company", DataTypeDefinition.TEXT, false, ""));
paramList.add(new ParameterDefinitionImpl("combo", DataTypeDefinition.TEXT, false, ""));
}
@Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{
Calendar myToday = Calendar.getInstance();
String shortMonth = myToday.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault());
String longMonth = myToday.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
String year = Integer.toString(myToday.get(Calendar.YEAR));
String name = (String)nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_NAME);
String company = I18NUtil.getMessage("test.company");
assertEquals(shortMonth, (String)action.getParameterValue("shortMonth"));
assertEquals(longMonth, (String)action.getParameterValue("longMonth"));
assertEquals(year, (String)action.getParameterValue("year"));
assertEquals(name, (String)action.getParameterValue("name"));
assertEquals(company, (String)action.getParameterValue("company"));
assertEquals(year + "/" + shortMonth + "/" + name + "-" + company +".txt", (String)action.getParameterValue("combo"));
}
private void assertEquals(String expected, String actual)
{
if (expected.equals(actual) == false)
{
throw new AlfrescoRuntimeException("Expected value " + expected + " does not match actual value " + actual);
}
}
}

View File

@@ -4,7 +4,7 @@
<beans> <beans>
<!-- test model --> <!-- test model -->
<bean id="org_alfresco_module_dod5015_rmTestdictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap"> <bean id="org_alfresco_module_rm_rmTestdictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
<property name="models"> <property name="models">
<list> <list>
<value>test-model.xml</value> <value>test-model.xml</value>
@@ -12,6 +12,16 @@
</property> </property>
</bean> </bean>
<!-- test messages -->
<bean id="org_alfresco_module_rm_testResourceBundles" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
<property name="resourceBundles">
<list>
<value>test</value>
</list>
</property>
</bean>
<!-- Test actions --> <!-- Test actions -->
<bean id="testAction_proxy" class="org.alfresco.module.org_alfresco_module_rm.capability.RMActionProxyFactoryBean" parent="rmProxyAction" init-method="registerAction"> <bean id="testAction_proxy" class="org.alfresco.module.org_alfresco_module_rm.capability.RMActionProxyFactoryBean" parent="rmProxyAction" init-method="registerAction">
<property name="target"> <property name="target">
@@ -19,6 +29,7 @@
</property> </property>
</bean> </bean>
<bean id="testAction" class="org.alfresco.module.org_alfresco_module_rm.test.util.TestAction" parent="rmAction"/> <bean id="testAction" class="org.alfresco.module.org_alfresco_module_rm.test.util.TestAction" parent="rmAction"/>
<bean id="testAction2_proxy" class="org.alfresco.module.org_alfresco_module_rm.capability.RMActionProxyFactoryBean" parent="rmProxyAction" init-method="registerAction"> <bean id="testAction2_proxy" class="org.alfresco.module.org_alfresco_module_rm.capability.RMActionProxyFactoryBean" parent="rmProxyAction" init-method="registerAction">
<property name="target"> <property name="target">
<ref bean="testAction2"/> <ref bean="testAction2"/>
@@ -27,6 +38,7 @@
<bean id="testAction2" class="org.alfresco.module.org_alfresco_module_rm.test.util.TestAction2" parent="rmAction"> <bean id="testAction2" class="org.alfresco.module.org_alfresco_module_rm.test.util.TestAction2" parent="rmAction">
<property name="publicAction" value="true"/> <property name="publicAction" value="true"/>
</bean> </bean>
<bean id="testActionParams_proxy" class="org.alfresco.module.org_alfresco_module_rm.capability.RMActionProxyFactoryBean" parent="rmProxyAction" init-method="registerAction"> <bean id="testActionParams_proxy" class="org.alfresco.module.org_alfresco_module_rm.capability.RMActionProxyFactoryBean" parent="rmProxyAction" init-method="registerAction">
<property name="target"> <property name="target">
<ref bean="testActionParams"/> <ref bean="testActionParams"/>
@@ -34,6 +46,16 @@
</bean> </bean>
<bean id="testActionParams" class="org.alfresco.module.org_alfresco_module_rm.test.util.TestActionParams" parent="rmAction"/> <bean id="testActionParams" class="org.alfresco.module.org_alfresco_module_rm.test.util.TestActionParams" parent="rmAction"/>
<bean id="testActionPropertySubs_proxy" class="org.alfresco.module.org_alfresco_module_rm.capability.RMActionProxyFactoryBean" parent="rmProxyAction" init-method="registerAction">
<property name="target">
<ref bean="testActionPropertySubs"/>
</property>
</bean>
<bean id="testActionPropertySubs" class="org.alfresco.module.org_alfresco_module_rm.test.util.TestActionPropertySubs" parent="rmAction">
<property name="allowParameterSubstitutions" value="true"/>
</bean>
<!-- Applicability tests --> <!-- Applicability tests -->
<bean id="recordOnlyAction_proxy" class="org.alfresco.module.org_alfresco_module_rm.capability.RMActionProxyFactoryBean" parent="rmProxyAction" init-method="registerAction"> <bean id="recordOnlyAction_proxy" class="org.alfresco.module.org_alfresco_module_rm.capability.RMActionProxyFactoryBean" parent="rmProxyAction" init-method="registerAction">

View File

@@ -0,0 +1 @@
test.company=Alfresco