Implemented persistence for the WorkflowFormProcessor.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21258 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
N Smith 2010-07-19 10:46:11 +00:00
parent 2bfa74df80
commit 18f23482b6
15 changed files with 516 additions and 107 deletions

View File

@ -1252,7 +1252,8 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
fields.add("bpm:workflowDueDate");
fields.add("packageItems");
String workflowDefName = "jbpm$wf:adhoc";
// Use URL-friendly format.
String workflowDefName = "jbpm_wf_adhoc";
Form form = this.formService.getForm(new Item(WORKFLOW_FORM_ITEM_KIND, workflowDefName), fields);
// check a form got returned
@ -1310,7 +1311,7 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
assertTrue("Expecting there to be more tasks", tasksAfter > tasksBefore);
// check workflow instance details
assertEquals(workflowDefName, workflow.definition.name);
assertEquals("jbpm$wf:adhoc", workflow.definition.name);
}
public void testNoForm() throws Exception

View File

@ -33,9 +33,7 @@ public abstract class AbstractFieldProcessor<Data> implements FieldProcessor
public Field generateField(String fieldName, FormCreationData data)
{
Data typedData = checkDataType(data.getItemData());
Field field = generateTypedField(fieldName, data, typedData);
logIfFieldNotFound(field, fieldName);
return field;
return generateTypedField(fieldName, data, typedData);
}
@SuppressWarnings("unchecked")
@ -53,18 +51,6 @@ public abstract class AbstractFieldProcessor<Data> implements FieldProcessor
}
}
protected void logIfFieldNotFound(Field fieldInfo, String fieldName)
{
if (fieldInfo == null)
{
Log logger = getLogger();
if (logger!=null && logger.isDebugEnabled())
{
logger.debug("Ignoring unrecognised field \"" + fieldName + "\"");
}
}
}
/**
* Registers this {@link FieldProcessor} with the supplied registry.
*

View File

@ -24,4 +24,5 @@ import org.alfresco.repo.forms.Field;
public interface FieldProcessor
{
Field generateField(String fieldName, FormCreationData data);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2005-2010 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.forms.processor;
/**
* @author Nick Smith
*/
public interface FormPersister<PersistType>
{
PersistType persist();
}

View File

@ -31,14 +31,12 @@ import java.util.regex.Pattern;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.forms.Field;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.Form;
import org.alfresco.repo.forms.FormData;
import org.alfresco.repo.forms.FormException;
import org.alfresco.repo.forms.PropertyFieldDefinition;
import org.alfresco.repo.forms.FormData.FieldData;
import org.alfresco.repo.forms.processor.FilteredFormProcessor;
import org.alfresco.repo.forms.processor.FormCreationData;
import org.alfresco.repo.forms.processor.workflow.DataKeyMatcher;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
@ -146,6 +144,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
*/
protected Pattern associationNamePattern = Pattern.compile(ASSOC_DATA_PREFIX + "([a-zA-Z0-9]+)_(.*)(_[a-zA-Z]+)");
private DataKeyMatcher keyMatcher;
/**
* Sets the node service
*
@ -184,6 +184,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
this.keyMatcher = new DataKeyMatcher(namespaceService);
}
/**
@ -807,6 +808,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
return mimetype;
}
}
/**

View File

@ -21,7 +21,6 @@ package org.alfresco.repo.forms.processor.node;
import org.alfresco.repo.forms.Field;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.PropertyFieldDefinition;
import org.alfresco.repo.forms.processor.AbstractFieldProcessor;
import org.alfresco.repo.forms.processor.FormCreationData;

View File

@ -27,14 +27,14 @@ import org.alfresco.service.namespace.QName;
*/
public class DataKeyInfo
{
private final String dataKey;
private final String fieldName;
private final QName qName;
private final FieldType fieldType;
private final boolean isAdd;
private DataKeyInfo(String dataKey, QName qName, FieldType fieldType, boolean isAdd)
{
this.dataKey = dataKey;
this.fieldName = dataKey;
this.qName = qName;
this.fieldType = fieldType;
this.isAdd = isAdd;
@ -50,23 +50,28 @@ public class DataKeyInfo
return new DataKeyInfo(dataKey, qName, FieldType.PROPERTY, true);
}
public static DataKeyInfo makeTransientDataKeyInfo(String dataKey)
public static DataKeyInfo makeTransientPropertyDataKeyInfo(String dataKey)
{
return new DataKeyInfo(dataKey, null, FieldType.TRANSIENT, true);
return new DataKeyInfo(dataKey, null, FieldType.TRANSIENT_PROPERTY, true);
}
public static DataKeyInfo makeTransientAssociationDataKeyInfo(String dataKey, boolean isAdd)
{
return new DataKeyInfo(dataKey, null, FieldType.TRANSIENT_ASSOCIATION, isAdd);
}
/**
* @return the dataKey
* @return the fieldName
*/
public String getDataKey()
public String getFieldName()
{
return dataKey;
return fieldName;
}
/**
* @return the qName
*/
public QName getqName()
public QName getQName()
{
return qName;
}
@ -87,5 +92,25 @@ public class DataKeyInfo
{
return isAdd;
}
/**
* Implements the visitor pattern. Takes a DataKeyInfoVisitor and calls the
* appropriate visit method based on the fieldType.
*
* @param <T>
* @param visitor
* @return
*/
public <T> T visit(DataKeyInfoVisitor<T> visitor)
{
switch(fieldType)
{
case ASSOCIATION: return visitor.visitAssociation(this);
case PROPERTY: return visitor.visitProperty(this);
case TRANSIENT_ASSOCIATION: return visitor.visitTransientAssociation(this);
case TRANSIENT_PROPERTY: return visitor.visitTransientProperty(this);
default: return null; //Should never be reached.
}
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2005-2010 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.forms.processor.workflow;
/**
* Visitor interface used to enable the visitor pattern on {@link DataKeyInfo}
* instances. Implementations of this interface can call
* <code>DataKeyInfo.visit(DataKeyInfoVisitor)</code> to have the appropriate
* visit method called on the visitor, based on the fieldType of the
* {@link DataKeyInfo} instance.
*
* @author Nick Smith
*/
public interface DataKeyInfoVisitor<T>
{
/**
* Called for {@link DataKeyInfo} instances with a field type of ASSOCIATION.
* @param info
* @return
*/
T visitAssociation(DataKeyInfo info);
/**
* Called for {@link DataKeyInfo} instances with a field type of PROPERTY.
* @param info
* @return
*/
T visitProperty(DataKeyInfo info);
/**
* Called for {@link DataKeyInfo} instances with a field type of TRANSIENT_ASSOCIATION.
* @param info
* @return
*/
T visitTransientAssociation(DataKeyInfo info);
/**
* Called for {@link DataKeyInfo} instances with a field type of TRANSIENT_PROPERTY.
* @param info
* @return
*/
T visitTransientProperty(DataKeyInfo info);
}

View File

@ -40,11 +40,6 @@ public class DataKeyMatcher
*/
private final static Pattern propertyNamePattern = Pattern.compile("(^[a-zA-Z0-9]+)_([a-zA-Z0-9_]+$)");
public DataKeyMatcher(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* A regular expression which can be used to match association names. These
* names will look like <code>"assoc_cm_references_added"</code>. The
@ -53,12 +48,20 @@ public class DataKeyMatcher
*/
private final static Pattern associationNamePattern = Pattern.compile("(^[a-zA-Z0-9]+)_([a-zA-Z0-9_]+)(_[a-zA-Z]+$)");
private final static Pattern transientAssociationPattern = Pattern.compile("(^[a-zA-Z0-9]+)(_[a-zA-Z]+$)");
private final NamespaceService namespaceService;
public DataKeyMatcher(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
*
* @param dataKey
* @return
* Attempts to match the <code>dataKey</code> to either a property or association pattern.
* If no match can be found then returns <code>null</code>.
* @param dataKey the dataKey to be matched.
* @return a {@link DataKeyInfo} representation or <code>null</code>.
*/
public DataKeyInfo match(String dataKey)
{
@ -70,7 +73,6 @@ public class DataKeyMatcher
{
return matchAssociation(dataKey);
}
// No match found.
return null;
}
@ -79,14 +81,33 @@ public class DataKeyMatcher
{
String keyName = dataKey.substring(ASSOC_DATA_PREFIX.length());
Matcher matcher = associationNamePattern.matcher(keyName);
if (!matcher.matches())
if (matcher.matches())
{
return null;
QName qName = getQName(matcher);
boolean isAdd = isAdd(matcher, 3);
String name = qName.toPrefixString(namespaceService);
return DataKeyInfo.makeAssociationDataKeyInfo(name, qName, isAdd);
}
QName qName = getQName(matcher);
String suffix = matcher.group(3);
return matchTransientAssociation(keyName);
}
private DataKeyInfo matchTransientAssociation(String keyName)
{
Matcher matcher = transientAssociationPattern.matcher(keyName);
if(matcher.matches())
{
boolean isAdd = isAdd(matcher, 2);
String name = matcher.group(1);
return DataKeyInfo.makeTransientAssociationDataKeyInfo(name, isAdd);
}
return null;
}
private boolean isAdd(Matcher matcher, int suffixPos)
{
String suffix = matcher.group(suffixPos);
boolean isAdd = !(ASSOC_DATA_REMOVED_SUFFIX.equals(suffix));
return DataKeyInfo.makeAssociationDataKeyInfo(keyName, qName, isAdd);
return isAdd;
}
private DataKeyInfo matchProperty(String dataKey)
@ -96,9 +117,10 @@ public class DataKeyMatcher
if (matcher.matches())
{
QName qName = getQName(matcher);
return DataKeyInfo.makePropertyDataKeyInfo(keyName, qName);
String name = qName.toPrefixString(namespaceService);
return DataKeyInfo.makePropertyDataKeyInfo(name, qName);
}
return DataKeyInfo.makeTransientDataKeyInfo(keyName);
return DataKeyInfo.makeTransientPropertyDataKeyInfo(keyName);
}
private QName getQName(Matcher matcher)

View File

@ -27,5 +27,6 @@ public enum FieldType
{
ASSOCIATION,
PROPERTY,
TRANSIENT;
TRANSIENT_ASSOCIATION,
TRANSIENT_PROPERTY;
}

View File

@ -51,11 +51,11 @@ import org.apache.commons.logging.LogFactory;
public class TaskFormProcessor extends ContentModelFormProcessor<WorkflowTask, WorkflowTask>
{
/** Logger */
private static final Log LOGGER = LogFactory.getLog(TaskFormProcessor.class);
private static final TypedPropertyValueGetter valueGetter = new TypedPropertyValueGetter();
private DataKeyMatcher keyMatcher;
private WorkflowService workflowService;
private static final Log LOGGER = LogFactory.getLog(TaskFormProcessor.class);
private TypedPropertyValueGetter valueGetter;
private DataKeyMatcher keyMatcher;
private WorkflowService workflowService;
// Constructor for Spring
public TaskFormProcessor()
@ -72,6 +72,7 @@ public class TaskFormProcessor extends ContentModelFormProcessor<WorkflowTask, W
this.dictionaryService = dictionaryService;
this.fieldProcessorRegistry = fieldProcessorRegistry;
this.keyMatcher = new DataKeyMatcher(namespaceService);
this.valueGetter = new TypedPropertyValueGetter(dictionaryService);
}
@Override
@ -101,31 +102,30 @@ public class TaskFormProcessor extends ContentModelFormProcessor<WorkflowTask, W
{
String name = fieldData.getName();
DataKeyInfo keyInfo = keyMatcher.match(name);
if ((keyInfo == null || FieldType.TRANSIENT == keyInfo.getFieldType()) &&
LOGGER.isWarnEnabled())
if (keyInfo == null ||
FieldType.TRANSIENT_PROPERTY == keyInfo.getFieldType() )
{
LOGGER.warn("Ignoring unrecognized field: " + name);
if(LOGGER.isDebugEnabled())
LOGGER.debug("Ignoring unrecognized field: " + name);
return;
}
if (keyInfo != null)
QName fullName = keyInfo.getQName();
Object rawValue = fieldData.getValue();
if (FieldType.PROPERTY == keyInfo.getFieldType())
{
QName fullName = keyInfo.getqName();
Object rawValue = fieldData.getValue();
if (FieldType.PROPERTY == keyInfo.getFieldType())
Serializable propValue = getPropertyValueToPersist(fullName, rawValue, itemData);
// TODO What if the user wants to set prop to null?
if (propValue != null)
{
Serializable propValue = getPropertyValueToPersist(fullName, rawValue, itemData);
// TODO What if the user wants to set prop to null?
if (propValue != null)
{
updater.addProperty(fullName, propValue);
}
updater.addProperty(fullName, propValue);
}
else if (FieldType.ASSOCIATION == keyInfo.getFieldType())
}
else if (FieldType.ASSOCIATION == keyInfo.getFieldType())
{
if (rawValue instanceof String)
{
if (rawValue instanceof String)
{
updater.changeAssociation(fullName, (String) rawValue, keyInfo.isAdd());
}
updater.changeAssociation(fullName, (String) rawValue, keyInfo.isAdd());
}
}
}
@ -143,7 +143,7 @@ public class TaskFormProcessor extends ContentModelFormProcessor<WorkflowTask, W
{
return valueGetter.getValue(value, propDef);
}
return null;
return (Serializable) value;
}
/*
@ -232,4 +232,13 @@ public class TaskFormProcessor extends ContentModelFormProcessor<WorkflowTask, W
this.keyMatcher = new DataKeyMatcher(namespaceService);
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#setDictionaryService(org.alfresco.service.cmr.dictionary.DictionaryService)
*/
@Override
public void setDictionaryService(DictionaryService dictionaryService)
{
super.setDictionaryService(dictionaryService);
this.valueGetter = new TypedPropertyValueGetter(dictionaryService);
}
}

View File

@ -26,7 +26,6 @@
package org.alfresco.repo.forms.processor.workflow;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -88,7 +87,7 @@ public class TaskUpdater
public boolean changeAssociation(QName name, String nodeRefs, boolean isAdd)
{
List<NodeRef> value = getNodeRefs(nodeRefs);
List<NodeRef> value = NodeRef.getNodeRefs(nodeRefs, LOGGER);
if (value == null)
{
return false;
@ -120,34 +119,4 @@ public class TaskUpdater
return map;
}
private List<NodeRef> getNodeRefs(Object value)
{
String[] nodeRefIds = ((String) value).split(",");
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(nodeRefIds.length);
for (String nodeRefString : nodeRefIds)
{
String nodeRefId = nodeRefString.trim();
if (NodeRef.isNodeRef(nodeRefId))
{
NodeRef nodeRef = new NodeRef(nodeRefId);
nodeRefs.add(nodeRef);
}
else
{
logNodeRefError(nodeRefId);
}
}
return nodeRefs;
}
private void logNodeRefError(String nodeRefId)
{
if (LOGGER.isWarnEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Target Node: ").append(nodeRefId);
msg.append(" is not a valid NodeRef and has been ignored.");
LOGGER.warn(msg.toString());
}
}
}

View File

@ -31,8 +31,11 @@ import java.util.Arrays;
import java.util.List;
import org.alfresco.repo.forms.FormException;
import org.alfresco.repo.forms.processor.node.ItemData;
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.namespace.QName;
import org.json.JSONArray;
import org.json.JSONException;
import org.springframework.extensions.surf.util.I18NUtil;
@ -44,6 +47,27 @@ public class TypedPropertyValueGetter
{
public static final String ON = "on";
private final DictionaryService dictionaryService;
public TypedPropertyValueGetter(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
public Serializable getPropertyValueToPersist(QName fullName, Object value, ItemData<?> itemData)
{
PropertyDefinition propDef = itemData.getPropertyDefinition(fullName);
if (propDef == null)
{
propDef = dictionaryService.getProperty(fullName);
}
if (propDef != null)
{
return getValue(value, propDef);
}
return (Serializable) value;
}
public Serializable getValue(Object value, PropertyDefinition propDef)
{
if (value == null)

View File

@ -0,0 +1,165 @@
/*
* Copyright (C) 2005-2010 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.forms.processor.workflow;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* A helper class used to start workflows. The builder accumuates all the
* changes to be made to the list of parameters and package items, then starts a
* new workflow once the build() method is called.
*
* @author Nick Smith
*/
public class WorkflowBuilder
{
private final WorkflowService workflowService;
private final WorkflowDefinition definition;
private final NodeService nodeService;
private final Map<QName, Serializable> params = new HashMap<QName, Serializable>();
private final Set<NodeRef> packageItems = new HashSet<NodeRef>();
private NodeRef packageNode = null;
public WorkflowBuilder(WorkflowDefinition definition, WorkflowService workflowService, NodeService nodeService)
{
this.workflowService = workflowService;
this.nodeService = nodeService;
this.definition = definition;
}
public void addParameter(QName name, Serializable value)
{
params.put(name, value);
}
public void addAssociationParameter(QName name, Serializable value)
{
params.put(name, value);
}
public void addPackageItems(List<NodeRef> items)
{
packageItems.addAll(items);
}
/**
* Takes a comma-separated list of {@link NodeRef} ids and adds the
* specified NodeRefs to the package.
*
* @param items
*/
public void addPackageItems(String items)
{
List<NodeRef> nodes = NodeRef.getNodeRefs(items);
addPackageItems(nodes);
}
public void addPackageItemsAsStrings(List<String> itemStrs)
{
for (String itemStr : itemStrs)
{
addPackageItem(itemStr);
}
}
public void addPackageItem(NodeRef item)
{
packageItems.add(item);
}
public void addPackageItem(String itemStr)
{
packageItems.add(new NodeRef(itemStr));
}
/**
* @param packageNode the packageNode to set
*/
public void setPackageNode(NodeRef packageNode)
{
this.packageNode = packageNode;
}
public WorkflowInstance build()
{
buildPackage();
WorkflowPath path = workflowService.startWorkflow(definition.id, params);
signalStartTask(path);
return path.instance;
}
private void signalStartTask(WorkflowPath path)
{
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(path.id);
if(tasks.size() == 1)
{
WorkflowTask startTask = tasks.get(0);
workflowService.endTask(startTask.id, null);
}
else
throw new WorkflowException("Start task not found! Expected 1 task but found: " + tasks.size());
}
private void buildPackage()
{
final NodeRef packageRef = workflowService.createPackage(packageNode);
final String url = NamespaceService.CONTENT_MODEL_1_0_URI;
final QName packageContains = WorkflowModel.ASSOC_PACKAGE_CONTAINS;
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
for (NodeRef item : packageItems)
{
String name =
(String) nodeService.getProperty(item, ContentModel.PROP_NAME);
String localName = QName.createValidLocalName(name);
QName qName = QName.createQName(url, localName);
nodeService.addChild(packageRef, item, packageContains, qName);
}
return null;
}
}, AuthenticationUtil.getSystemUserName());
params.put(WorkflowModel.ASSOC_PACKAGE, packageRef);
}
}

View File

@ -28,11 +28,14 @@ import java.util.regex.Matcher;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.forms.FormData;
import org.alfresco.repo.forms.FormException;
import org.alfresco.repo.forms.FormNotFoundException;
import org.alfresco.repo.forms.Item;
import org.alfresco.repo.forms.FormData.FieldData;
import org.alfresco.repo.forms.processor.node.ContentModelFormProcessor;
import org.alfresco.repo.forms.processor.node.ItemData;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@ -66,6 +69,10 @@ public class WorkflowFormProcessor extends ContentModelFormProcessor<WorkflowDef
/** Unprotected Node Service */
private NodeService unprotectedNodeService;
/** TyepdPropertyValueGetter */
private TypedPropertyValueGetter valueGetter;
private DataKeyMatcher keyMatcher;
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#getAssociationValues(java.lang.Object)
*/
@ -188,13 +195,39 @@ public class WorkflowFormProcessor extends ContentModelFormProcessor<WorkflowDef
return defName;
}
/*
* @see
* org.alfresco.repo.forms.processor.node.NodeFormProcessor#internalPersist
* (java.lang.Object, org.alfresco.repo.forms.FormData)
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#internalPersist(java.lang.Object, org.alfresco.repo.forms.FormData)
*/
@Override
protected WorkflowInstance internalPersist(WorkflowDefinition workflowDef, final FormData data)
protected WorkflowInstance internalPersist(WorkflowDefinition definition, FormData data)
{
WorkflowBuilder builder = new WorkflowBuilder(definition, workflowService, nodeService);
ItemData<WorkflowDefinition> itemData = makeItemData(definition);
for (FieldData fieldData : data)
{
addFieldToSerialize(builder, itemData, fieldData);
}
return builder.build();
}
private void addFieldToSerialize(WorkflowBuilder builder, ItemData<WorkflowDefinition> itemData, FieldData fieldData)
{
String dataKeyName = fieldData.getName();
DataKeyInfo keyInfo = keyMatcher.match(dataKeyName);
if (keyInfo == null ||
FieldType.TRANSIENT_PROPERTY == keyInfo.getFieldType() )
{
if(logger.isDebugEnabled())
logger.debug("Ignoring unrecognized field: " + dataKeyName);
return;
}
WorkflowDataKeyInfoVisitor visitor = new WorkflowDataKeyInfoVisitor(fieldData.getValue(), builder, itemData);
keyInfo.visit(visitor);
}
protected WorkflowInstance oldInternalPersist(WorkflowDefinition workflowDef, final FormData data)
{
if (logger.isDebugEnabled()) logger.debug("Persisting form for: " + workflowDef);
@ -285,4 +318,88 @@ public class WorkflowFormProcessor extends ContentModelFormProcessor<WorkflowDef
{
this.workflowService = workflowService;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#setNamespaceService(org.alfresco.service.namespace.NamespaceService)
*/
@Override
public void setNamespaceService(NamespaceService namespaceService)
{
super.setNamespaceService(namespaceService);
this.keyMatcher = new DataKeyMatcher(namespaceService);
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#setDictionaryService(org.alfresco.service.cmr.dictionary.DictionaryService)
*/
@Override
public void setDictionaryService(DictionaryService dictionaryService)
{
super.setDictionaryService(dictionaryService);
this.valueGetter = new TypedPropertyValueGetter(dictionaryService);
}
private class WorkflowDataKeyInfoVisitor implements DataKeyInfoVisitor<Void>
{
private final Object rawValue;
private final WorkflowBuilder builder;
private final ItemData<WorkflowDefinition> itemData;
public WorkflowDataKeyInfoVisitor(Object rawValue, WorkflowBuilder builder,
ItemData<WorkflowDefinition> itemData)
{
this.rawValue = rawValue;
this.builder = builder;
this.itemData = itemData;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.workflow.DataKeyInfoVisitor#visitAssociation(org.alfresco.repo.forms.processor.workflow.DataKeyInfo)
*/
public Void visitAssociation(DataKeyInfo info)
{
QName qName = info.getQName();
if (rawValue instanceof String)
{
Serializable nodes = (Serializable) NodeRef.getNodeRefs((String) rawValue);
builder.addParameter(qName, nodes);
}
return null;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.workflow.DataKeyInfoVisitor#visitProperty(org.alfresco.repo.forms.processor.workflow.DataKeyInfo)
*/
public Void visitProperty(DataKeyInfo info)
{
QName qName = info.getQName();
Serializable propValue = valueGetter.getPropertyValueToPersist(qName, rawValue, itemData);
builder.addParameter(qName, propValue);
return null;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.workflow.DataKeyInfoVisitor#visitTransientAssociation(org.alfresco.repo.forms.processor.workflow.DataKeyInfo)
*/
public Void visitTransientAssociation(DataKeyInfo info)
{
if(PackageItemsFieldProcessor.KEY.equals(info.getFieldName()))
{
if(rawValue instanceof String)
{
builder.addPackageItems((String)rawValue);
}
}
return null;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.workflow.DataKeyInfoVisitor#visitTransientProperty(org.alfresco.repo.forms.processor.workflow.DataKeyInfo)
*/
public Void visitTransientProperty(DataKeyInfo info)
{
throw new FormException("This methdo should never be called!");
}
}
}