Created the new WorkflowFormProcessor which processes forms based on a workflow definition name.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21172 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
N Smith
2010-07-14 15:10:17 +00:00
parent d6fdc2fb03
commit 650f4e4b8d
12 changed files with 411 additions and 1007 deletions

View File

@@ -17,22 +17,23 @@
<value>org.alfresco.repo.forms.FormService</value> <value>org.alfresco.repo.forms.FormService</value>
</property> </property>
<property name="target"> <property name="target">
<ref bean="formService"/> <ref bean="formService" />
</property> </property>
<property name="interceptorNames"> <property name="interceptorNames">
<list> <list>
<idref local="FormService_transaction"/> <idref local="FormService_transaction" />
<idref bean="AuditMethodInterceptor"/> <idref bean="AuditMethodInterceptor" />
<idref bean="exceptionTranslator"/> <idref bean="exceptionTranslator" />
<idref local="FormService_security"/> <idref local="FormService_security" />
</list> </list>
</property> </property>
</bean> </bean>
<!-- Form service transaction bean --> <!-- Form service transaction bean -->
<bean id="FormService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <bean id="FormService_transaction"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager"> <property name="transactionManager">
<ref bean="transactionManager"/> <ref bean="transactionManager" />
</property> </property>
<property name="transactionAttributes"> <property name="transactionAttributes">
<props> <props>
@@ -42,7 +43,8 @@
</bean> </bean>
<!-- Form service security bean --> <!-- Form service security bean -->
<bean id="FormService_security" class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" /> <bean id="FormService_security"
class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
<bean id="formService" class="org.alfresco.repo.forms.FormServiceImpl"> <bean id="formService" class="org.alfresco.repo.forms.FormServiceImpl">
<property name="processorRegistry" ref="formProcessorRegistry" /> <property name="processorRegistry" ref="formProcessorRegistry" />
@@ -52,37 +54,26 @@
<bean id="formProcessorRegistry" <bean id="formProcessorRegistry"
class="org.alfresco.repo.forms.processor.FormProcessorRegistry" /> class="org.alfresco.repo.forms.processor.FormProcessorRegistry" />
<bean id="nodeFilterRegistry" <bean id="nodeFilterRegistry" class="org.alfresco.repo.forms.processor.FilterRegistry" />
class="org.alfresco.repo.forms.processor.FilterRegistry" />
<bean id="typeFilterRegistry" <bean id="typeFilterRegistry" class="org.alfresco.repo.forms.processor.FilterRegistry" />
class="org.alfresco.repo.forms.processor.FilterRegistry" />
<bean id="workflowFilterRegistry"
class="org.alfresco.repo.forms.processor.FilterRegistry" />
<!-- Form processors --> <!-- Form processors -->
<bean id="baseFormProcessor" abstract="true" init-method="register" <bean id="baseFormProcessor" abstract="true" init-method="register"
class="org.alfresco.repo.forms.processor.AbstractFormProcessor"> class="org.alfresco.repo.forms.processor.node.ContentModelFormProcessor">
<property name="processorRegistry" ref="formProcessorRegistry" /> <property name="processorRegistry" ref="formProcessorRegistry" />
</bean> <property name="nodeService" ref="NodeService" />
<property name="contentService" ref="ContentService" />
<bean id="filteredFormProcessor" abstract="true" <property name="dictionaryService" ref="DictionaryService" />
class="org.alfresco.repo.forms.processor.FilteredFormProcessor" <property name="fileFolderService" ref="FileFolderService" />
parent="baseFormProcessor" > <property name="namespaceService" ref="NamespaceService" />
<property name="fieldProcessorRegistry" ref="fieldProcessorRegistry" /> <property name="fieldProcessorRegistry" ref="fieldProcessorRegistry" />
</bean> </bean>
<bean id="nodeFormProcessor" <bean id="nodeFormProcessor"
class="org.alfresco.repo.forms.processor.node.NodeFormProcessor" class="org.alfresco.repo.forms.processor.node.NodeFormProcessor"
parent="filteredFormProcessor"> parent="baseFormProcessor">
<property name="filterRegistry" ref="nodeFilterRegistry" /> <property name="filterRegistry" ref="nodeFilterRegistry" />
<property name="nodeService" ref="NodeService" />
<property name="fileFolderService" ref="FileFolderService" />
<property name="dictionaryService" ref="DictionaryService" />
<property name="namespaceService" ref="NamespaceService" />
<property name="contentService" ref="ContentService" />
<property name="matchPattern"> <property name="matchPattern">
<value>node</value> <value>node</value>
</property> </property>
@@ -90,34 +81,13 @@
<bean id="typeFormProcessor" <bean id="typeFormProcessor"
class="org.alfresco.repo.forms.processor.node.TypeFormProcessor" class="org.alfresco.repo.forms.processor.node.TypeFormProcessor"
parent="filteredFormProcessor"> parent="baseFormProcessor">
<property name="filterRegistry" ref="typeFilterRegistry" /> <property name="filterRegistry" ref="typeFilterRegistry" />
<property name="nodeService" ref="NodeService" />
<property name="fileFolderService" ref="FileFolderService" />
<property name="dictionaryService" ref="DictionaryService" />
<property name="namespaceService" ref="NamespaceService" />
<property name="contentService" ref="ContentService" />
<property name="matchPattern"> <property name="matchPattern">
<value>type</value> <value>type</value>
</property> </property>
</bean> </bean>
<bean id="workflowFormProcessor"
class="org.alfresco.repo.forms.processor.workflow.WorkflowFormProcessor"
parent="filteredFormProcessor">
<property name="filterRegistry" ref="workflowFilterRegistry" />
<property name="nodeService" ref="NodeService" />
<property name="smallNodeService" ref="nodeService" />
<property name="fileFolderService" ref="FileFolderService" />
<property name="dictionaryService" ref="DictionaryService" />
<property name="namespaceService" ref="NamespaceService" />
<property name="contentService" ref="ContentService" />
<property name="workflowService" ref="WorkflowService" />
<property name="matchPattern">
<value>workflow</value>
</property>
</bean>
<!-- Filters --> <!-- Filters -->
<bean id="baseFormFilter" abstract="true" init-method="register" <bean id="baseFormFilter" abstract="true" init-method="register"
class="org.alfresco.repo.forms.processor.AbstractFilter" /> class="org.alfresco.repo.forms.processor.AbstractFilter" />
@@ -125,16 +95,16 @@
<!-- <!--
<bean id="imageAspectFormFilter" <bean id="imageAspectFormFilter"
class="org.alfresco.repo.forms.processor.node.ImageAspectFilter" class="org.alfresco.repo.forms.processor.node.ImageAspectFilter"
parent="baseFormFilter"> parent="baseFormFilter"> <property name="filterRegistry"
<property name="filterRegistry" ref="nodeFilterRegistry" /> ref="nodeFilterRegistry" /> </bean>
</bean>
--> -->
<bean id="formServiceScript" parent="baseJavaScriptExtension" class="org.alfresco.repo.forms.script.ScriptFormService"> <bean id="formServiceScript" parent="baseJavaScriptExtension"
class="org.alfresco.repo.forms.script.ScriptFormService">
<property name="extensionName"> <property name="extensionName">
<value>formService</value> <value>formService</value>
</property> </property>
<property name="formService" ref="FormService"/> <property name="formService" ref="FormService" />
</bean> </bean>
<!-- Field Processor Config --> <!-- Field Processor Config -->
@@ -182,4 +152,35 @@
class="org.alfresco.repo.forms.processor.node.DefaultFieldProcessor" class="org.alfresco.repo.forms.processor.node.DefaultFieldProcessor"
parent="qnameFieldProcessor" /> parent="qnameFieldProcessor" />
<!-- Workflow Form Processor Config -->
<bean id="workflowFormProcessor"
class="org.alfresco.repo.forms.processor.workflow.WorkflowFormProcessor"
parent="baseFormProcessor">
<property name="filterRegistry" ref="workflowFilterRegistry" />
<property name="smallNodeService" ref="nodeService" />
<property name="workflowService" ref="WorkflowService" />
<property name="matchPattern">
<value>workflow</value>
</property>
</bean>
<bean id="taskFormProcessor"
class="org.alfresco.repo.forms.processor.workflow.TaskFormProcessor"
parent="baseFormProcessor">
<property name="filterRegistry" ref="taskFilterRegistry" />
<property name="workflowService" ref="workflowServiceImpl" />
<property name="matchPattern">
<value>task</value>
</property>
</bean>
<bean id="workflowFilterRegistry" class="org.alfresco.repo.forms.processor.FilterRegistry" />
<bean id="taskFilterRegistry" class="org.alfresco.repo.forms.processor.FilterRegistry" />
<bean id="packageItemsFieldProcessor"
class="org.alfresco.repo.forms.processor.workflow.PackageItemsFieldProcessor"
parent="baseFieldProcessor" />
</beans> </beans>

View File

@@ -6,3 +6,6 @@ form_service.encoding.label=Encoding
form_service.encoding.description=Encoding of the content form_service.encoding.description=Encoding of the content
form_service.size.label=Size form_service.size.label=Size
form_service.size.description=Size of the content in bytes form_service.size.description=Size of the content in bytes
form_service.package.items.label=Items
form_service.package.items.description=Items that are part of the workflow

View File

@@ -35,13 +35,11 @@ public class ContentField implements Field
{ {
private final FieldDefinition fieldDefinition; private final FieldDefinition fieldDefinition;
private final ClassAttributeDefinition classDefinition; private final ClassAttributeDefinition classDefinition;
private final boolean isProperty;
private final Object value; private final Object value;
public ContentField(PropertyDefinition propertyDefinition, public ContentField(PropertyDefinition propertyDefinition,
PropertyFieldDefinition fieldDef, Object value) PropertyFieldDefinition fieldDef, Object value)
{ {
this.isProperty = true;
this.classDefinition = propertyDefinition; this.classDefinition = propertyDefinition;
this.fieldDefinition = fieldDef; this.fieldDefinition = fieldDef;
this.value = value; this.value = value;
@@ -50,7 +48,6 @@ public class ContentField implements Field
public ContentField(AssociationDefinition assocDefinition, public ContentField(AssociationDefinition assocDefinition,
AssociationFieldDefinition fieldDef, Object value) AssociationFieldDefinition fieldDef, Object value)
{ {
this.isProperty = false;
this.classDefinition = assocDefinition; this.classDefinition = assocDefinition;
this.fieldDefinition = fieldDef; this.fieldDefinition = fieldDef;
this.value = value; this.value = value;
@@ -60,10 +57,9 @@ public class ContentField implements Field
* This constructor should only be used to create FieldInfo for transient properties such as encoding, mimetype or size. * This constructor should only be used to create FieldInfo for transient properties such as encoding, mimetype or size.
* @param fieldDef The PropertyFieldDefinition for the transient property. * @param fieldDef The PropertyFieldDefinition for the transient property.
*/ */
public ContentField(PropertyFieldDefinition fieldDef, Object value) public ContentField(FieldDefinition fieldDef, Object value)
{ {
this.classDefinition = null; this.classDefinition = null;
this.isProperty = true;
this.fieldDefinition = fieldDef; this.fieldDefinition = fieldDef;
this.value = value; this.value = value;
} }
@@ -76,6 +72,14 @@ public class ContentField implements Field
return classDefinition == null; return classDefinition == null;
} }
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.task.Field#isTransient()
*/
public boolean isProperty()
{
return fieldDefinition instanceof PropertyFieldDefinition;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.task.Field#getFieldDefinition() * @see org.alfresco.repo.forms.processor.task.Field#getFieldDefinition()
*/ */
@@ -112,7 +116,7 @@ public class ContentField implements Field
public String toString() public String toString()
{ {
String type = isTransient()?"Transient ":""; String type = isTransient()?"Transient ":"";
type += isProperty ? "Property" : "Association"; type += isProperty() ? "Property" : "Association";
return "Field: " + getFieldName() + " Type: " + type; return "Field: " + getFieldName() + " Type: " + type;
} }

View File

@@ -244,108 +244,6 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
protected abstract TypeDefinition getBaseType(ItemType item); protected abstract TypeDefinition getBaseType(ItemType item);
/**
* Generates the field definition for the transient mimetype property
*
* @param content The ContentData object to generate the field from
* @param form The Form instance to populate
*/
protected void generateMimetypePropertyField(ContentData content, Form form)
{
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_MIMETYPE;
PropertyFieldDefinition mimetypeField = new PropertyFieldDefinition(TRANSIENT_MIMETYPE, DataTypeDefinition.TEXT
.getLocalName());
mimetypeField.setLabel(I18NUtil.getMessage(MSG_MIMETYPE_LABEL));
mimetypeField.setDescription(I18NUtil.getMessage(MSG_MIMETYPE_DESC));
mimetypeField.setDataKeyName(dataKeyName);
form.addFieldDefinition(mimetypeField);
if (content != null)
{
form.addData(dataKeyName, content.getMimetype());
}
}
/**
* Generates the field definition for the transient encoding property
*
* @param content The ContentData object to generate the field from
* @param form The Form instance to populate
*/
protected void generateEncodingPropertyField(ContentData content, Form form)
{
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_ENCODING;
PropertyFieldDefinition encodingField = new PropertyFieldDefinition(TRANSIENT_ENCODING, DataTypeDefinition.TEXT
.getLocalName());
encodingField.setLabel(I18NUtil.getMessage(MSG_ENCODING_LABEL));
encodingField.setDescription(I18NUtil.getMessage(MSG_ENCODING_DESC));
encodingField.setDataKeyName(dataKeyName);
form.addFieldDefinition(encodingField);
if (content != null)
{
form.addData(dataKeyName, content.getEncoding());
}
}
/**
* Generates the field definition for the transient size property
*
* @param content The ContentData object to generate the field from
* @param form The Form instance to populate
*/
protected void generateSizePropertyField(ContentData content, Form form)
{
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_SIZE;
PropertyFieldDefinition sizeField = new PropertyFieldDefinition(TRANSIENT_SIZE, DataTypeDefinition.LONG
.getLocalName());
sizeField.setLabel(I18NUtil.getMessage(MSG_SIZE_LABEL));
sizeField.setDescription(I18NUtil.getMessage(MSG_SIZE_DESC));
sizeField.setDataKeyName(dataKeyName);
sizeField.setProtectedField(true);
form.addFieldDefinition(sizeField);
if (content != null)
{
form.addData(dataKeyName, new Long(content.getSize()));
}
}
/**
* Determines whether the given node represents a working copy, if it does
* the name field is searched for and set to protected as the name field
* should not be edited for a working copy.
*
* If the node is not a working copy this method has no effect.
*
* @param nodeRef NodeRef of node to check and potentially process
* @param form The generated form
*/
protected void processWorkingCopy(NodeRef nodeRef, Form form)
{
// if the node is a working copy ensure that the name field (id present)
// is set to be protected as it can not be edited
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY))
{
// go through fields looking for name field
for (FieldDefinition fieldDef : form.getFieldDefinitions())
{
if (fieldDef.getName().equals(ContentModel.PROP_NAME.toPrefixString(this.namespaceService)))
{
fieldDef.setProtectedField(true);
if (getLogger().isDebugEnabled())
{
getLogger().debug("Set " + ContentModel.PROP_NAME.toPrefixString(this.namespaceService) +
"field to protected as it is a working copy");
}
break;
}
}
}
}
/** /**
* Retrieves the values of the given association definition on the given * Retrieves the values of the given association definition on the given
* node. * node.

View File

@@ -27,6 +27,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.Form;
import org.alfresco.repo.forms.FormData; import org.alfresco.repo.forms.FormData;
import org.alfresco.repo.forms.FormNotFoundException; import org.alfresco.repo.forms.FormNotFoundException;
import org.alfresco.repo.forms.Item; import org.alfresco.repo.forms.Item;
@@ -223,6 +225,52 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
return content; return content;
} }
/**
* Determines whether the given node represents a working copy, if it does
* the name field is searched for and set to protected as the name field
* should not be edited for a working copy.
*
* If the node is not a working copy this method has no effect.
*
* @param nodeRef NodeRef of node to check and potentially process
* @param form The generated form
*/
protected void processWorkingCopy(NodeRef nodeRef, Form form)
{
// if the node is a working copy ensure that the name field (id present)
// is set to be protected as it can not be edited
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY))
{
// go through fields looking for name field
for (FieldDefinition fieldDef : form.getFieldDefinitions())
{
if (fieldDef.getName().equals(ContentModel.PROP_NAME.toPrefixString(this.namespaceService)))
{
fieldDef.setProtectedField(true);
if (getLogger().isDebugEnabled())
{
getLogger().debug("Set " + ContentModel.PROP_NAME.toPrefixString(this.namespaceService) +
"field to protected as it is a working copy");
}
break;
}
}
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#internalGenerate(java.lang.Object, java.util.List, java.util.List, org.alfresco.repo.forms.Form, java.util.Map)
*/
@Override
protected void internalGenerate(NodeRef item, List<String> fields, List<String> forcedFields, Form form,
Map<String, Object> context)
{
super.internalGenerate(item, fields, forcedFields, form, context);
processWorkingCopy(item, form);
}
/* /*
* @see * @see
* org.alfresco.repo.forms.processor.FilteredFormProcessor#internalPersist * org.alfresco.repo.forms.processor.FilteredFormProcessor#internalPersist

View File

@@ -22,6 +22,7 @@ package org.alfresco.repo.forms.processor.node;
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.PROP_DATA_PREFIX; import static org.alfresco.repo.forms.processor.node.FormFieldConstants.PROP_DATA_PREFIX;
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.TRANSIENT_ENCODING; import static org.alfresco.repo.forms.processor.node.FormFieldConstants.TRANSIENT_ENCODING;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.PropertyFieldDefinition; import org.alfresco.repo.forms.PropertyFieldDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@@ -42,7 +43,7 @@ public class TransientEncodingFieldProcessor extends TransientFieldProcessor
} }
@Override @Override
protected PropertyFieldDefinition makeTransientPropertyDefinition() protected FieldDefinition makeTransientPropertyDefinition()
{ {
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_ENCODING; String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_ENCODING;
PropertyFieldDefinition encodingField = new PropertyFieldDefinition(TRANSIENT_ENCODING, PropertyFieldDefinition encodingField = new PropertyFieldDefinition(TRANSIENT_ENCODING,

View File

@@ -20,6 +20,7 @@
package org.alfresco.repo.forms.processor.node; package org.alfresco.repo.forms.processor.node;
import org.alfresco.repo.forms.Field; import org.alfresco.repo.forms.Field;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.PropertyFieldDefinition; import org.alfresco.repo.forms.PropertyFieldDefinition;
import org.alfresco.repo.forms.processor.AbstractFieldProcessor; import org.alfresco.repo.forms.processor.AbstractFieldProcessor;
import org.alfresco.repo.forms.processor.FormCreationData; import org.alfresco.repo.forms.processor.FormCreationData;
@@ -32,7 +33,7 @@ public abstract class TransientFieldProcessor extends AbstractFieldProcessor<Tra
@Override @Override
protected Field generateTypedField(String fieldName, FormCreationData formData, TransientValueGetter typedData) protected Field generateTypedField(String fieldName, FormCreationData formData, TransientValueGetter typedData)
{ {
PropertyFieldDefinition transientPropDef = makeTransientPropertyDefinition(); FieldDefinition transientPropDef = makeTransientPropertyDefinition();
Field fieldInfo = null; Field fieldInfo = null;
Object value = getValue(fieldName, typedData); Object value = getValue(fieldName, typedData);
if (transientPropDef != null) if (transientPropDef != null)
@@ -59,5 +60,5 @@ public abstract class TransientFieldProcessor extends AbstractFieldProcessor<Tra
return TransientValueGetter.class; return TransientValueGetter.class;
} }
protected abstract PropertyFieldDefinition makeTransientPropertyDefinition(); protected abstract FieldDefinition makeTransientPropertyDefinition();
} }

View File

@@ -22,6 +22,7 @@ package org.alfresco.repo.forms.processor.node;
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.PROP_DATA_PREFIX; import static org.alfresco.repo.forms.processor.node.FormFieldConstants.PROP_DATA_PREFIX;
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.TRANSIENT_MIMETYPE; import static org.alfresco.repo.forms.processor.node.FormFieldConstants.TRANSIENT_MIMETYPE;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.PropertyFieldDefinition; import org.alfresco.repo.forms.PropertyFieldDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@@ -40,7 +41,7 @@ public class TransientMimetypeFieldProcessor extends TransientFieldProcessor
} }
@Override @Override
protected PropertyFieldDefinition makeTransientPropertyDefinition() { protected FieldDefinition makeTransientPropertyDefinition() {
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_MIMETYPE; String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_MIMETYPE;
PropertyFieldDefinition mimetypeField = new PropertyFieldDefinition(TRANSIENT_MIMETYPE, DataTypeDefinition.TEXT PropertyFieldDefinition mimetypeField = new PropertyFieldDefinition(TRANSIENT_MIMETYPE, DataTypeDefinition.TEXT
.getLocalName()); .getLocalName());

View File

@@ -22,6 +22,7 @@ package org.alfresco.repo.forms.processor.node;
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.PROP_DATA_PREFIX; import static org.alfresco.repo.forms.processor.node.FormFieldConstants.PROP_DATA_PREFIX;
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.TRANSIENT_SIZE; import static org.alfresco.repo.forms.processor.node.FormFieldConstants.TRANSIENT_SIZE;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.PropertyFieldDefinition; import org.alfresco.repo.forms.PropertyFieldDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@@ -41,7 +42,7 @@ public class TransientSizeFieldProcessor extends TransientFieldProcessor
} }
@Override @Override
protected PropertyFieldDefinition makeTransientPropertyDefinition() protected FieldDefinition makeTransientPropertyDefinition()
{ {
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_SIZE; String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_SIZE;
PropertyFieldDefinition sizeField = new PropertyFieldDefinition(TRANSIENT_SIZE, PropertyFieldDefinition sizeField = new PropertyFieldDefinition(TRANSIENT_SIZE,

View File

@@ -0,0 +1,85 @@
/*
* 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 org.alfresco.repo.forms.AssociationFieldDefinition;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.AssociationFieldDefinition.Direction;
import org.alfresco.repo.forms.processor.FieldProcessor;
import org.alfresco.repo.forms.processor.node.TransientFieldProcessor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.ASSOC_DATA_PREFIX;
/**
* {@link FieldProcessor} for handling package contents when displaying Workflow and Task Forms.
* @author Nick Smith
*/
public class PackageItemsFieldProcessor extends TransientFieldProcessor
{
/** Logger */
private final static Log logger = LogFactory.getLog(PackageItemsFieldProcessor.class);
public static final String KEY = "packageItems";
private static final String MSG_LABEL = "form_service.package.items.label";
private static final String MSG_DESCRIPTION = "form_service.package.items.description";
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.node.TransientFieldProcessor#makeTransientPropertyDefinition()
*/
@Override
protected FieldDefinition makeTransientPropertyDefinition()
{
AssociationFieldDefinition fieldDef = new AssociationFieldDefinition(
KEY, "cm:content", Direction.TARGET);
fieldDef.setLabel(I18NUtil.getMessage(MSG_LABEL));
fieldDef.setDescription(I18NUtil.getMessage(MSG_DESCRIPTION));
fieldDef.setProtectedField(false);
fieldDef.setEndpointMandatory(false);
fieldDef.setEndpointMany(true);
// define the data key name and set
String dataKey = ASSOC_DATA_PREFIX + KEY;
fieldDef.setDataKeyName(dataKey);
return fieldDef;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.AbstractFieldProcessor#getLogger()
*/
@Override
protected Log getLogger()
{
return logger;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.AbstractFieldProcessor#getRegistryKey()
*/
@Override
protected String getRegistryKey()
{
return KEY;
}
}

View File

@@ -24,40 +24,22 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.forms.AssociationFieldDefinition;
import org.alfresco.repo.forms.FieldGroup;
import org.alfresco.repo.forms.Form;
import org.alfresco.repo.forms.FormData; import org.alfresco.repo.forms.FormData;
import org.alfresco.repo.forms.FormNotFoundException; import org.alfresco.repo.forms.FormNotFoundException;
import org.alfresco.repo.forms.Item; import org.alfresco.repo.forms.Item;
import org.alfresco.repo.forms.PropertyFieldDefinition;
import org.alfresco.repo.forms.AssociationFieldDefinition.Direction;
import org.alfresco.repo.forms.PropertyFieldDefinition.FieldConstraint;
import org.alfresco.repo.forms.processor.node.ContentModelFormProcessor; import org.alfresco.repo.forms.processor.node.ContentModelFormProcessor;
import org.alfresco.repo.forms.processor.node.PeriodDataTypeParameters;
import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.Constraint;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Period;
import org.alfresco.service.cmr.workflow.WorkflowDefinition; 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.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath; import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask; import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
import org.alfresco.service.cmr.workflow.WorkflowTaskState; import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
@@ -69,39 +51,78 @@ import org.springframework.util.StringUtils;
* Temporary FormProcessor implementation that can generate and persist * Temporary FormProcessor implementation that can generate and persist
* Form objects for workflow definitions. * Form objects for workflow definitions.
* *
* @author Gavin Cornwell * @author Nick Smith
*/ */
public class WorkflowFormProcessor extends ContentModelFormProcessor<WorkflowDefinition, WorkflowInstance> public class WorkflowFormProcessor extends ContentModelFormProcessor<WorkflowDefinition, WorkflowInstance>
{ {
/** Logger */ /** Logger */
private static Log logger = LogFactory.getLog(WorkflowFormProcessor.class); private final static Log logger = LogFactory.getLog(WorkflowFormProcessor.class);
public static final String TRANSIENT_PACKAGE_ITEMS = "packageItems"; /** WorkflowService */
private WorkflowService workflowService;
/** workflow service */ /** Unprotected Node Service */
protected WorkflowService workflowService; private NodeService unprotectedNodeService;
protected NodeService unprotectedNodeService; /* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#getAssociationValues(java.lang.Object)
/**
* Sets the workflow service
*
* @param workflowService The WorkflowService instance
*/ */
public void setWorkflowService(WorkflowService workflowService) @Override
protected Map<QName, Serializable> getAssociationValues(WorkflowDefinition item)
{ {
this.workflowService = workflowService; return null;
} }
public void setSmallNodeService(NodeService nodeService) /* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#getBaseType(java.lang.Object)
*/
@Override
protected TypeDefinition getBaseType(WorkflowDefinition item)
{ {
this.unprotectedNodeService = nodeService; //TODO I'm not sure this is safe as getStartTaskDefinition() is 'optional'.
WorkflowTaskDefinition startTask = item.getStartTaskDefinition();
return startTask.getMetadata();
} }
/* /* (non-Javadoc)
* @see * @see org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#getPropertyValues(java.lang.Object)
* org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#getLogger */
* () @Override
protected Map<QName, Serializable> getPropertyValues(WorkflowDefinition item)
{
return null;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.node.ContentModelFormProcessor#getTransientValues(java.lang.Object)
*/
@Override
protected Map<String, Object> getTransientValues(WorkflowDefinition item)
{
return Collections.<String, Object>singletonMap(
PackageItemsFieldProcessor.KEY, Collections.EMPTY_LIST);
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemType(java.lang.Object)
*/
@Override
protected String getItemType(WorkflowDefinition item)
{
return item.name;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemURI(java.lang.Object)
*/
@Override
protected String getItemURI(WorkflowDefinition item)
{
return "api/workflow-definitions/"+item.id;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#getLogger()
*/ */
@Override @Override
protected Log getLogger() protected Log getLogger()
@@ -109,6 +130,11 @@ public class WorkflowFormProcessor extends ContentModelFormProcessor<WorkflowDef
return logger; return logger;
} }
public void setSmallNodeService(NodeService nodeService)
{
this.unprotectedNodeService = nodeService;
}
/* /*
* @see * @see
* org.alfresco.repo.forms.processor.node.NodeFormProcessor#getTypedItem * org.alfresco.repo.forms.processor.node.NodeFormProcessor#getTypedItem
@@ -117,151 +143,47 @@ public class WorkflowFormProcessor extends ContentModelFormProcessor<WorkflowDef
@Override @Override
protected WorkflowDefinition getTypedItem(Item item) protected WorkflowDefinition getTypedItem(Item item)
{ {
WorkflowDefinition workflowDef = null;
try try
{ {
// item id could be the raw workflow definition name or it could be String itemId = item.getId();
// in a URL friendly format return getWorkflowDefinitionForName(itemId);
String workflowDefName = item.getId(); }
if (workflowDefName.indexOf("$") == -1) catch (Exception e)
{ {
// decode the itemId throw new FormNotFoundException(item, e);
workflowDefName = workflowDefName.replace("jbpm_", "jbpm$"); }
workflowDefName = workflowDefName.replace('_', ':');
} }
// Extract the workflow definition private WorkflowDefinition getWorkflowDefinitionForName(String itemId)
workflowDef = this.workflowService.getDefinitionByName(workflowDefName); {
String workflowDefName = decodeWorkflowDefinitionName(itemId);
WorkflowDefinition workflowDef = workflowService.getDefinitionByName(workflowDefName);
if (workflowDef == null) if (workflowDef == null)
{ {
throw new FormNotFoundException(item, String msg = "Workflow definition does not exist: " + itemId;
new IllegalArgumentException("Workflow definition does not exist: " + item.getId())); throw new IllegalArgumentException(msg);
} }
}
catch (WorkflowException we)
{
throw new FormNotFoundException(item, we);
}
// return the type definition object for the requested type
return workflowDef; return workflowDef;
} }
/*
* @see
* org.alfresco.repo.forms.processor.FilteredFormProcessor#internalGenerate
* (java.lang.Object, java.util.List, java.util.List,
* org.alfresco.repo.forms.Form, java.util.Map)
*/
@Override
protected void internalGenerate(WorkflowDefinition workflowDef, List<String> fields,
List<String> forcedFields, Form form, Map<String, Object> context)
{
if (logger.isDebugEnabled()) logger.debug("Generating form for item: " + workflowDef);
// generate the form for the workflow definition
form.getItem().setType(workflowDef.name);
form.getItem().setUrl("/api/workflow-definition/" + workflowDef.id);
// get the type of the start task for the workflow definition
TypeDefinition typeDef = workflowDef.getStartTaskDefinition().metadata;
if (fields != null && fields.size() > 0)
{
generateSelectedFields(null, typeDef, fields, forcedFields, form);
}
else
{
// setup field definitions and data
generateAllPropertyFields(typeDef, form);
generateAllAssociationFields(typeDef, form);
}
// add the "packageItems" transient field
generatePackageItemsTransientField(form);
if (logger.isDebugEnabled()) logger.debug("Generating form: " + form);
}
/** /**
* Generates the 'packageItems' field * The itemId may be in a URL/Webscript-friendly format. If so it must be converted
* back to the proper workflow definition name.
* *
* @param form The Form instance to populate * @param itemId
*/ */
protected void generatePackageItemsTransientField(Form form) private String decodeWorkflowDefinitionName(String itemId)
{ {
// setup basic field info String defName = itemId;
AssociationFieldDefinition fieldDef = new AssociationFieldDefinition(TRANSIENT_PACKAGE_ITEMS, if (itemId.contains("$")==false)
"cm:content", Direction.TARGET); {
fieldDef.setLabel("Items"); defName = itemId.replaceFirst("_", "$");
fieldDef.setDescription("Items that are part of the workflow");
fieldDef.setProtectedField(false);
fieldDef.setEndpointMandatory(false);
fieldDef.setEndpointMany(true);
// define the data key name and set
fieldDef.setDataKeyName(ASSOC_DATA_PREFIX + TRANSIENT_PACKAGE_ITEMS);
// add definition to the form
form.addFieldDefinition(fieldDef);
} }
if (itemId.contains(":")==false)
/**
* Sets up the field definitions for all the type's properties.
*
* @param typeDef The type being setup
* @param form The Form instance to populate
*/
protected void generateAllPropertyFields(TypeDefinition typeDef, Form form)
{ {
// iterate round the property defintions and setup field definition defName = defName.replaceFirst("_", ":");
Map<QName, PropertyDefinition> propDefs = typeDef.getProperties();
for (PropertyDefinition propDef : propDefs.values())
{
generatePropertyField(propDef, form, this.namespaceService);
}
// get all default aspects for the type and iterate round their
// property definitions too
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
for (AspectDefinition aspect : aspects)
{
propDefs = aspect.getProperties();
for (PropertyDefinition propDef : propDefs.values())
{
generatePropertyField(propDef, form, this.namespaceService);
}
}
}
/**
* Sets up the field definitions for all the type's associations.
*
* @param typeDef The type being setup
* @param form The Form instance to populate
*/
protected void generateAllAssociationFields(TypeDefinition typeDef, Form form)
{
// iterate round the association defintions and setup field definition
Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations();
for (AssociationDefinition assocDef : assocDefs.values())
{
generateAssociationField(assocDef, form, this.namespaceService);
}
// get all default aspects for the type and iterate round their
// association definitions too
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
for (AspectDefinition aspect : aspects)
{
assocDefs = aspect.getAssociations();
for (AssociationDefinition assocDef : assocDefs.values())
{
generateAssociationField(assocDef, form, this.namespaceService);
}
} }
return defName;
} }
/* /*
@@ -341,595 +263,10 @@ public class WorkflowFormProcessor extends ContentModelFormProcessor<WorkflowDef
} }
/** /**
* Sets up a field definition for the given property. * @param workflowService the workflowService to set
* <p>
* NOTE: This method is static so that it can serve as a helper method for
* FormFilter implementations as adding additional property fields is likely
* to be a common extension.
* </p>
*
* @param propDef The PropertyDefinition of the field to generate
* @param form The Form instance to populate
* @param namespaceService NamespaceService instance
*/ */
protected void generatePropertyField(PropertyDefinition propDef, Form form, NamespaceService namespaceService) public void setWorkflowService(WorkflowService workflowService)
{ {
generatePropertyField(propDef, form, null, null, namespaceService); this.workflowService = workflowService;
}
/**
* Sets up a field definition for the given property.
* <p>
* NOTE: This method is static so that it can serve as a helper method for
* FormFilter implementations as adding additional property fields is likely
* to be a common extension.
* </p>
*
* @param propDef The PropertyDefinition of the field to generate
* @param form The Form instance to populate
* @param propValue The value of the property field
* @param namespaceService NamespaceService instance
*/
protected void generatePropertyField(PropertyDefinition propDef, Form form, Serializable propValue,
NamespaceService namespaceService)
{
generatePropertyField(propDef, form, propValue, null, namespaceService);
}
/**
* Sets up a field definition for the given property.
* <p>
* NOTE: This method is static so that it can serve as a helper method for
* FormFilter implementations as adding additional property fields is likely
* to be a common extension.
* </p>
*
* @param propDef The PropertyDefinition of the field to generate
* @param form The Form instance to populate
* @param propValue The value of the property field
* @param group The FieldGroup the property field belongs to, can be null
* @param namespaceService NamespaceService instance
*/
@SuppressWarnings("unchecked")
protected void generatePropertyField(PropertyDefinition propDef, Form form, Serializable propValue,
FieldGroup group, NamespaceService namespaceService)
{
String propName = propDef.getName().toPrefixString(namespaceService);
String[] nameParts = QName.splitPrefixedQName(propName);
PropertyFieldDefinition fieldDef = new PropertyFieldDefinition(propName, propDef.getDataType().getName()
.getLocalName());
String title = propDef.getTitle();
if (title == null)
{
title = propName;
}
fieldDef.setLabel(title);
fieldDef.setDefaultValue(propDef.getDefaultValue());
fieldDef.setDescription(propDef.getDescription());
fieldDef.setMandatory(propDef.isMandatory());
fieldDef.setProtectedField(propDef.isProtected());
fieldDef.setRepeating(propDef.isMultiValued());
fieldDef.setGroup(group);
// any property from the system model (sys prefix) should be protected
// the model doesn't currently enforce this so make sure they are not
// editable
if (NamespaceService.SYSTEM_MODEL_1_0_URI.equals(propDef.getName().getNamespaceURI()))
{
fieldDef.setProtectedField(true);
}
// define the data key name and set
String dataKeyName = PROP_DATA_PREFIX + nameParts[0] + DATA_KEY_SEPARATOR + nameParts[1];
fieldDef.setDataKeyName(dataKeyName);
// setup any parameters requried for the data type
if (propDef.getDataType().getName().equals(DataTypeDefinition.PERIOD))
{
// if the property data type is d:period we need to setup a data
// type parameters object to represent the options and rules
PeriodDataTypeParameters periodOptions = new PeriodDataTypeParameters();
Set<String> providers = Period.getProviderNames();
for (String provider : providers)
{
periodOptions.addPeriodProvider(Period.getProvider(provider));
}
fieldDef.setDataTypeParameters(periodOptions);
}
// setup constraints for the property
List<ConstraintDefinition> constraints = propDef.getConstraints();
if (constraints != null && constraints.size() > 0)
{
List<FieldConstraint> fieldConstraints = new ArrayList<FieldConstraint>(constraints.size());
for (ConstraintDefinition constraintDef : constraints)
{
Constraint constraint = constraintDef.getConstraint();
FieldConstraint fieldConstraint = new FieldConstraint(constraint.getType(), constraint.getParameters());
fieldConstraints.add(fieldConstraint);
}
fieldDef.setConstraints(fieldConstraints);
}
form.addFieldDefinition(fieldDef);
// add the property value to the form
if (propValue != null)
{
if (propValue instanceof List)
{
// temporarily add repeating field data as a comma
// separated list, this will be changed to using
// a separate field for each value once we have full
// UI support in place.
propValue = StringUtils.collectionToCommaDelimitedString((List) propValue);
}
else if (propValue instanceof ContentData)
{
// for content properties retrieve the info URL rather than the
// the object value itself
propValue = ((ContentData)propValue).getInfoUrl();
}
form.addData(dataKeyName, propValue);
}
}
/**
* Sets up a field definition for the given association.
* <p>
* NOTE: This method is static so that it can serve as a helper method for
* FormFilter implementations as adding additional association fields is
* likely to be a common extension.
* </p>
*
* @param assocDef The AssociationDefinition of the field to generate
* @param form The Form instance to populate
* @param namespaceService NamespaceService instance
*/
protected void generateAssociationField(AssociationDefinition assocDef, Form form,
NamespaceService namespaceService)
{
generateAssociationField(assocDef, form, null, null, namespaceService);
}
/**
* Sets up a field definition for the given association.
* <p>
* NOTE: This method is static so that it can serve as a helper method for
* FormFilter implementations as adding additional association fields is
* likely to be a common extension.
* </p>
*
* @param assocDef The AssociationDefinition of the field to generate
* @param form The Form instance to populate
* @param assocValues The values of the association field, can be null
* @param namespaceService NamespaceService instance
*/
@SuppressWarnings("unchecked")
protected void generateAssociationField(AssociationDefinition assocDef, Form form, List assocValues,
NamespaceService namespaceService)
{
generateAssociationField(assocDef, form, assocValues, null, namespaceService);
}
/**
* Sets up a field definition for the given association.
* <p>
* NOTE: This method is static so that it can serve as a helper method for
* FormFilter implementations as adding additional association fields is
* likely to be a common extension.
* </p>
*
* @param assocDef The AssociationDefinition of the field to generate
* @param form The Form instance to populate
* @param assocValues The values of the association field, can be null
* @param group The FieldGroup the association field belongs to, can be null
* @param namespaceService NamespaceService instance
*/
@SuppressWarnings("unchecked")
protected static void generateAssociationField(AssociationDefinition assocDef, Form form, List assocValues,
FieldGroup group, NamespaceService namespaceService)
{
String assocName = assocDef.getName().toPrefixString(namespaceService);
String[] nameParts = QName.splitPrefixedQName(assocName);
AssociationFieldDefinition fieldDef = new AssociationFieldDefinition(assocName, assocDef.getTargetClass()
.getName().toPrefixString(namespaceService), Direction.TARGET);
String title = assocDef.getTitle();
if (title == null)
{
title = assocName;
}
fieldDef.setLabel(title);
fieldDef.setDescription(assocDef.getDescription());
fieldDef.setProtectedField(assocDef.isProtected());
fieldDef.setEndpointMandatory(assocDef.isTargetMandatory());
fieldDef.setEndpointMany(assocDef.isTargetMany());
fieldDef.setGroup(group);
// define the data key name and set
String dataKeyName = ASSOC_DATA_PREFIX + nameParts[0] + DATA_KEY_SEPARATOR + nameParts[1];
fieldDef.setDataKeyName(dataKeyName);
// add definition to the form
form.addFieldDefinition(fieldDef);
if (assocValues != null)
{
// add the association value to the form
// determine the type of association values data and extract
// accordingly
List<String> values = new ArrayList<String>(4);
for (Object value : assocValues)
{
if (value instanceof ChildAssociationRef)
{
values.add(((ChildAssociationRef) value).getChildRef().toString());
}
else if (value instanceof AssociationRef)
{
values.add(((AssociationRef) value).getTargetRef().toString());
}
else
{
values.add(value.toString());
}
}
// Add the list as the value for the association.
form.addData(dataKeyName, values);
}
}
/**
* Sets up the field definitions for all the requested fields.
* <p>
* A NodeRef or TypeDefinition can be provided, however, if a NodeRef is
* provided all type information will be derived from the NodeRef and the
* TypeDefinition will be ignored.
* </p>
* <p>
* If any of the requested fields are not present on the type and they
* appear in the forcedFields list an attempt to find a model definition for
* those fields is made so they can be included.
* </p>
*
* @param nodeRef The NodeRef of the item being generated
* @param typeDef The TypeDefiniton of the item being generated
* @param fields Restricted list of fields to include
* @param forcedFields List of field names that should be included even if
* the field is not currently present
* @param form The Form instance to populate
*/
protected void generateSelectedFields(NodeRef nodeRef, TypeDefinition typeDef, List<String> fields,
List<String> forcedFields, Form form)
{
// ensure a NodeRef or TypeDefinition is provided
if (nodeRef == null && typeDef == null) { throw new IllegalArgumentException(
"A NodeRef or TypeDefinition must be provided"); }
if (getLogger().isDebugEnabled())
getLogger().debug("Generating selected fields: " + fields + " and forcing: " + forcedFields);
// get data dictionary definition for node if it is provided
QName type = null;
Map<QName, Serializable> propValues = Collections.emptyMap();
Map<QName, PropertyDefinition> propDefs = null;
Map<QName, AssociationDefinition> assocDefs = null;
if (nodeRef != null)
{
type = this.nodeService.getType(nodeRef);
typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
// NOTE: the anonymous type returns all property and association
// defs
// for all aspects applied as well as the type
propDefs = typeDef.getProperties();
assocDefs = typeDef.getAssociations();
propValues = this.nodeService.getProperties(nodeRef);
}
else
{
type = typeDef.getName();
// we only get the properties and associations of the actual type so
// we also need to manually get properties and associations from any
// mandatory aspects
propDefs = new HashMap<QName, PropertyDefinition>(16);
assocDefs = new HashMap<QName, AssociationDefinition>(16);
propDefs.putAll(typeDef.getProperties());
assocDefs.putAll(typeDef.getAssociations());
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
for (AspectDefinition aspect : aspects)
{
propDefs.putAll(aspect.getProperties());
assocDefs.putAll(aspect.getAssociations());
}
}
for (String fieldName : fields)
{
// try and split the field name
String[] parts = fieldName.split(":");
if (parts.length == 2 || parts.length == 3)
{
boolean foundField = false;
boolean tryProperty = true;
boolean tryAssociation = true;
String qNamePrefix = null;
String localName = null;
if (parts.length == 2)
{
qNamePrefix = parts[0];
localName = parts[1];
}
else
{
// if there are 3 parts to the field name the first one
// represents
// whether the field is a property or association i.e.
// prop:prefix:local
// or assoc:prefix:local, determine the prefix and ensure
// it's valid
if (PROP.equals(parts[0]))
{
tryAssociation = false;
}
else if (ASSOC.equals(parts[0]))
{
tryProperty = false;
}
else
{
if (getLogger().isWarnEnabled())
getLogger()
.warn(
"\""
+ parts[0]
+ "\" is an invalid prefix for requesting a property or association");
continue;
}
qNamePrefix = parts[1];
localName = parts[2];
}
// create qname of field name
QName fullQName = QName.createQName(qNamePrefix, localName, namespaceService);
// try the field as a property
if (tryProperty)
{
// lookup property def on node
PropertyDefinition propDef = propDefs.get(fullQName);
if (propDef != null)
{
// generate the property field
generatePropertyField(propDef, form, propValues.get(fullQName), this.namespaceService);
// no need to try and find an association
tryAssociation = false;
foundField = true;
}
}
// try the field as an association
if (tryAssociation)
{
AssociationDefinition assocDef = assocDefs.get(fullQName);
if (assocDef != null)
{
// generate the association field
generateAssociationField(assocDef, form, (nodeRef != null) ? retrieveAssociationValues(nodeRef,
assocDef) : null, this.namespaceService);
foundField = true;
}
}
// still not found the field, is it a force'd field?
if (!foundField)
{
if (forcedFields != null && forcedFields.size() > 0 && forcedFields.contains(fieldName))
{
generateForcedField(fieldName, form);
}
else if (getLogger().isDebugEnabled())
{
getLogger().debug(
"Ignoring field \"" + fieldName + "\" as it is not defined for the current "
+ ((nodeRef != null) ? "node" : "type")
+ " and it does not appear in the 'force' list");
}
}
}
else
{
// see if the fieldName is a well known transient property
if (TRANSIENT_MIMETYPE.equals(fieldName) || TRANSIENT_ENCODING.equals(fieldName)
|| TRANSIENT_SIZE.equals(fieldName))
{
// if the node type is content or sublcass thereof generate appropriate field
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
{
ContentData content = null;
if (nodeRef != null)
{
content = (ContentData) this.nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
}
if (TRANSIENT_MIMETYPE.equals(fieldName))
{
generateMimetypePropertyField(content, form);
}
else if (TRANSIENT_ENCODING.equals(fieldName))
{
generateEncodingPropertyField(content, form);
}
else if (TRANSIENT_SIZE.equals(fieldName))
{
generateSizePropertyField(content, form);
}
}
}
else if (getLogger().isWarnEnabled())
{
getLogger().warn("Ignoring unrecognised field \"" + fieldName + "\"");
}
}
}
}
/**
* Generates a field definition for the given field that is being forced to
* show.
*
* @param fieldName Name of the field to force
* @param form The Form instance to populated
*/
protected void generateForcedField(String fieldName, Form form)
{
if (getLogger().isDebugEnabled())
getLogger().debug("Attempting to force the inclusion of field \"" + fieldName + "\"");
String[] parts = fieldName.split(":");
if (parts.length == 2 || parts.length == 3)
{
boolean foundField = false;
boolean tryProperty = true;
boolean tryAssociation = true;
String qNamePrefix = null;
String localName = null;
if (parts.length == 2)
{
qNamePrefix = parts[0];
localName = parts[1];
}
else
{
// if there are 3 parts to the field name the first one
// represents
// whether the field is a property or association i.e.
// prop:prefix:local
// or assoc:prefix:local, determine the prefix and ensure it's
// valid
if (PROP.equals(parts[0]))
{
tryAssociation = false;
}
else if (ASSOC.equals(parts[0]))
{
tryProperty = false;
}
else
{
if (getLogger().isWarnEnabled())
getLogger().warn(
"\"" + parts[0]
+ "\" is an invalid prefix for requesting a property or association");
return;
}
qNamePrefix = parts[1];
localName = parts[2];
}
// create qname of field name
QName fullQName = QName.createQName(qNamePrefix, localName, namespaceService);
if (tryProperty)
{
// lookup the field as a property in the whole model
PropertyDefinition propDef = this.dictionaryService.getProperty(fullQName);
if (propDef != null)
{
// generate the property field
generatePropertyField(propDef, form, this.namespaceService);
// no need to try and find an association
tryAssociation = false;
foundField = true;
}
}
if (tryAssociation)
{
// lookup the field as an association in the whole model
AssociationDefinition assocDef = this.dictionaryService.getAssociation(fullQName);
if (assocDef != null)
{
// generate the association field
generateAssociationField(assocDef, form, this.namespaceService);
foundField = true;
}
}
if (!foundField && getLogger().isDebugEnabled())
{
getLogger()
.debug(
"Ignoring field \""
+ fieldName
+ "\" as it is not defined for the current node and can not be found in any model");
}
}
else if (getLogger().isWarnEnabled())
{
getLogger().warn("Ignoring unrecognised field \"" + fieldName + "\"");
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemType(java.lang.Object)
*/
@Override
protected String getItemType(WorkflowDefinition item)
{
return item.name;
}
/* (non-Javadoc)
* @see org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemURI(java.lang.Object)
*/
@Override
protected String getItemURI(WorkflowDefinition item)
{
return "/api/workflow-definitions/" + item.id;
}
@Override
protected Map<QName, Serializable> getAssociationValues(WorkflowDefinition item)
{
return null;
}
@Override
protected Map<QName, Serializable> getPropertyValues(WorkflowDefinition item)
{
return null;
}
@Override
protected Map<String, Object> getTransientValues(WorkflowDefinition item)
{
return null;
}
@Override
protected TypeDefinition getBaseType(WorkflowDefinition item)
{
return item.getStartTaskDefinition().metadata;
} }
} }

View File

@@ -40,10 +40,34 @@ public class WorkflowTaskDefinition
/** Task Metadata */ /** Task Metadata */
public TypeDefinition metadata; public TypeDefinition metadata;
/**
* @return the id
*/
public String getId()
{
return id;
}
/**
* @return the metadata
*/
public TypeDefinition getMetadata()
{
return metadata;
}
/**
* @return the node
*/
public WorkflowNode getNode()
{
return node;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see java.lang.Object#toString() * @see java.lang.Object#toString()
*/ */
@Override
public String toString() public String toString()
{ {
return "WorkflowTaskDefinition[id=" + id + ",metadata=" + metadata + "]"; return "WorkflowTaskDefinition[id=" + id + ",metadata=" + metadata + "]";