Creating a TaskFormProcessor to allow properties on tasks to be edited through Forms.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@16038 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
N Smith
2009-09-02 10:04:06 +00:00
parent bd9fe31142
commit 4f1cf347a1
14 changed files with 1606 additions and 174 deletions

View File

@@ -22,18 +22,20 @@
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.forms.processor; package org.alfresco.repo.forms.processor;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.repo.forms.Form;
import org.alfresco.repo.forms.Item; import org.alfresco.repo.forms.Item;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* Abstract base class for all FormProcessor implementations provides * Abstract base class for all FormProcessor implementations provides a regex
* a regex pattern match to test for processor applicability * pattern match to test for processor applicability
* *
* @author Gavin Cornwell * @author Gavin Cornwell
*/ */
@@ -42,8 +44,11 @@ public abstract class AbstractFormProcessor implements FormProcessor
private static final Log logger = LogFactory.getLog(AbstractFormProcessor.class); private static final Log logger = LogFactory.getLog(AbstractFormProcessor.class);
protected FormProcessorRegistry processorRegistry; protected FormProcessorRegistry processorRegistry;
protected String matchPattern; protected String matchPattern;
protected boolean active = true; protected boolean active = true;
protected Pattern patternMatcher; protected Pattern patternMatcher;
/** /**
@@ -59,7 +64,8 @@ public abstract class AbstractFormProcessor implements FormProcessor
/** /**
* Sets the match pattern * Sets the match pattern
* *
* @param pattern The regex pattern to use to determine if this processor is applicable * @param pattern The regex pattern to use to determine if this processor is
* applicable
*/ */
public void setMatchPattern(String pattern) public void setMatchPattern(String pattern)
{ {
@@ -84,7 +90,8 @@ public abstract class AbstractFormProcessor implements FormProcessor
if (this.processorRegistry == null) if (this.processorRegistry == null)
{ {
if (logger.isWarnEnabled()) if (logger.isWarnEnabled())
logger.warn("Property 'processorRegistry' has not been set. Ignoring auto-registration of processor: " + this); logger.warn("Property 'processorRegistry' has not been set. Ignoring auto-registration of processor: "
+ this);
return; return;
} }
@@ -92,7 +99,8 @@ public abstract class AbstractFormProcessor implements FormProcessor
if (this.matchPattern == null) if (this.matchPattern == null)
{ {
if (logger.isWarnEnabled()) if (logger.isWarnEnabled())
logger.warn("Property 'matchPattern' has not been set. Ignoring auto-registration of processor: " + this); logger.warn("Property 'matchPattern' has not been set. Ignoring auto-registration of processor: "
+ this);
return; return;
} }
@@ -115,7 +123,9 @@ public abstract class AbstractFormProcessor implements FormProcessor
} }
/* /*
* @see org.alfresco.repo.forms.processor.FormProcessor#isApplicable(org.alfresco.repo.forms.Item) * @see
* org.alfresco.repo.forms.processor.FormProcessor#isApplicable(org.alfresco
* .repo.forms.Item)
*/ */
public boolean isApplicable(Item item) public boolean isApplicable(Item item)
{ {
@@ -126,7 +136,8 @@ public abstract class AbstractFormProcessor implements FormProcessor
boolean matches = matcher.matches(); boolean matches = matcher.matches();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Checking processor " + this + " for applicability for item '" + item + "', result = " + matches); logger.debug("Checking processor " + this + " for applicability for item '" + item + "', result = "
+ matches);
return matches; return matches;
} }
@@ -143,4 +154,29 @@ public abstract class AbstractFormProcessor implements FormProcessor
buffer.append(")"); buffer.append(")");
return buffer.toString(); return buffer.toString();
} }
/**
* Gets the Item from the <code>form</code> parameter and sets its type
* field to <code>type</code>.
*
* @param form
* @param type
*/
protected void setFormItemType(Form form, String type)
{
form.getItem().setType(type);
}
/**
* Gets the Item from the <code>form</code> parameter and sets its URL field
* to <code>url</code>.
*
* @param form
* @param url
*/
protected void setFormItemUrl(Form form, String url)
{
form.getItem().setUrl(url);
}
} }

View File

@@ -75,7 +75,7 @@ public abstract class FilteredFormProcessor<ItemType, PersistType> extends Abstr
// inform all regsitered filters the form is about to be generated // inform all regsitered filters the form is about to be generated
if (this.filterRegistry != null) if (this.filterRegistry != null)
{ {
for (Filter filter : this.filterRegistry.getFilters()) for (Filter<ItemType, PersistType> filter : this.filterRegistry.getFilters())
{ {
filter.beforeGenerate(typedItem, fields, forcedFields, form, context); filter.beforeGenerate(typedItem, fields, forcedFields, form, context);
} }
@@ -87,7 +87,7 @@ public abstract class FilteredFormProcessor<ItemType, PersistType> extends Abstr
// inform all regsitered filters the form has been generated // inform all regsitered filters the form has been generated
if (this.filterRegistry != null) if (this.filterRegistry != null)
{ {
for (Filter filter : this.filterRegistry.getFilters()) for (Filter<ItemType, PersistType> filter : this.filterRegistry.getFilters())
{ {
filter.afterGenerate(typedItem, fields, forcedFields, form, context); filter.afterGenerate(typedItem, fields, forcedFields, form, context);
} }
@@ -114,19 +114,19 @@ public abstract class FilteredFormProcessor<ItemType, PersistType> extends Abstr
// inform all regsitered filters the form is about to be persisted // inform all regsitered filters the form is about to be persisted
if (this.filterRegistry != null) if (this.filterRegistry != null)
{ {
for (Filter filter : this.filterRegistry.getFilters()) for (Filter<ItemType, PersistType> filter : this.filterRegistry.getFilters())
{ {
filter.beforePersist(typedItem, data); filter.beforePersist(typedItem, data);
} }
} }
// perform the actual persistence of the form // perform the actual persistence of the form
Object persistedObject = internalPersist(typedItem, data); PersistType persistedObject = internalPersist(typedItem, data);
// inform all regsitered filters the form has been persisted // inform all regsitered filters the form has been persisted
if (this.filterRegistry != null) if (this.filterRegistry != null)
{ {
for (Filter filter : this.filterRegistry.getFilters()) for (Filter<ItemType, PersistType> filter : this.filterRegistry.getFilters())
{ {
filter.afterPersist(typedItem, data, persistedObject); filter.afterPersist(typedItem, data, persistedObject);
} }
@@ -135,16 +135,6 @@ public abstract class FilteredFormProcessor<ItemType, PersistType> extends Abstr
return persistedObject; return persistedObject;
} }
protected void setItemType(Form form, String type)
{
form.getItem().setType(type);
}
protected void setItemUrl(Form form, String url)
{
form.getItem().setUrl(url);
}
/** /**
* Returns a typed Object representing the given item. * Returns a typed Object representing the given item.
* <p> * <p>

View File

@@ -125,8 +125,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* pattern can also be used to extract the "cm", the "name" and the suffix * pattern can also be used to extract the "cm", the "name" and the suffix
* parts. * parts.
*/ */
protected Pattern associationNamePattern = Pattern.compile(ASSOC_DATA_PREFIX protected Pattern associationNamePattern = Pattern.compile(ASSOC_DATA_PREFIX + "(.*){1}?_(.*){1}?(_[a-zA-Z]+)");
+ "(.*){1}?_(.*){1}?(_[a-zA-Z]+)");
/** /**
* Sets the node service * Sets the node service
@@ -180,8 +179,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param form The Form instance to populate * @param form The Form instance to populate
* @param namespaceService NamespaceService instance * @param namespaceService NamespaceService instance
*/ */
public static void generatePropertyField(PropertyDefinition propDef, Form form, public static void generatePropertyField(PropertyDefinition propDef, Form form, NamespaceService namespaceService)
NamespaceService namespaceService)
{ {
generatePropertyField(propDef, form, null, null, namespaceService); generatePropertyField(propDef, form, null, null, namespaceService);
} }
@@ -199,8 +197,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param propValue The value of the property field * @param propValue The value of the property field
* @param namespaceService NamespaceService instance * @param namespaceService NamespaceService instance
*/ */
public static void generatePropertyField(PropertyDefinition propDef, Form form, public static void generatePropertyField(PropertyDefinition propDef, Form form, Serializable propValue,
Serializable propValue, NamespaceService namespaceService) NamespaceService namespaceService)
{ {
generatePropertyField(propDef, form, propValue, null, namespaceService); generatePropertyField(propDef, form, propValue, null, namespaceService);
} }
@@ -220,13 +218,13 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param namespaceService NamespaceService instance * @param namespaceService NamespaceService instance
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void generatePropertyField(PropertyDefinition propDef, Form form, public static void generatePropertyField(PropertyDefinition propDef, Form form, Serializable propValue,
Serializable propValue, FieldGroup group, NamespaceService namespaceService) FieldGroup group, NamespaceService namespaceService)
{ {
String propName = propDef.getName().toPrefixString(namespaceService); String propName = propDef.getName().toPrefixString(namespaceService);
String[] nameParts = QName.splitPrefixedQName(propName); String[] nameParts = QName.splitPrefixedQName(propName);
PropertyFieldDefinition fieldDef = new PropertyFieldDefinition(propName, propDef PropertyFieldDefinition fieldDef = new PropertyFieldDefinition(propName, propDef.getDataType().getName()
.getDataType().getName().getLocalName()); .getLocalName());
String title = propDef.getTitle(); String title = propDef.getTitle();
if (title == null) if (title == null)
@@ -272,14 +270,12 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
List<ConstraintDefinition> constraints = propDef.getConstraints(); List<ConstraintDefinition> constraints = propDef.getConstraints();
if (constraints != null && constraints.size() > 0) if (constraints != null && constraints.size() > 0)
{ {
List<FieldConstraint> fieldConstraints = new ArrayList<FieldConstraint>(constraints List<FieldConstraint> fieldConstraints = new ArrayList<FieldConstraint>(constraints.size());
.size());
for (ConstraintDefinition constraintDef : constraints) for (ConstraintDefinition constraintDef : constraints)
{ {
Constraint constraint = constraintDef.getConstraint(); Constraint constraint = constraintDef.getConstraint();
FieldConstraint fieldConstraint = new FieldConstraint(constraint.getType(), FieldConstraint fieldConstraint = new FieldConstraint(constraint.getType(), constraint.getParameters());
constraint.getParameters());
fieldConstraints.add(fieldConstraint); fieldConstraints.add(fieldConstraint);
} }
@@ -336,8 +332,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param namespaceService NamespaceService instance * @param namespaceService NamespaceService instance
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void generateAssociationField(AssociationDefinition assocDef, Form form, public static void generateAssociationField(AssociationDefinition assocDef, Form form, List assocValues,
List assocValues, NamespaceService namespaceService) NamespaceService namespaceService)
{ {
generateAssociationField(assocDef, form, assocValues, null, namespaceService); generateAssociationField(assocDef, form, assocValues, null, namespaceService);
} }
@@ -357,13 +353,13 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param namespaceService NamespaceService instance * @param namespaceService NamespaceService instance
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void generateAssociationField(AssociationDefinition assocDef, Form form, public static void generateAssociationField(AssociationDefinition assocDef, Form form, List assocValues,
List assocValues, FieldGroup group, NamespaceService namespaceService) FieldGroup group, NamespaceService namespaceService)
{ {
String assocName = assocDef.getName().toPrefixString(namespaceService); String assocName = assocDef.getName().toPrefixString(namespaceService);
String[] nameParts = QName.splitPrefixedQName(assocName); String[] nameParts = QName.splitPrefixedQName(assocName);
AssociationFieldDefinition fieldDef = new AssociationFieldDefinition(assocName, assocDef AssociationFieldDefinition fieldDef = new AssociationFieldDefinition(assocName, assocDef.getTargetClass()
.getTargetClass().getName().toPrefixString(namespaceService), Direction.TARGET); .getName().toPrefixString(namespaceService), Direction.TARGET);
String title = assocDef.getTitle(); String title = assocDef.getTitle();
if (title == null) if (title == null)
{ {
@@ -437,16 +433,15 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* the field is not currently present * the field is not currently present
* @param form The Form instance to populate * @param form The Form instance to populate
*/ */
protected void generateSelectedFields(NodeRef nodeRef, TypeDefinition typeDef, protected void generateSelectedFields(NodeRef nodeRef, TypeDefinition typeDef, List<String> fields,
List<String> fields, List<String> forcedFields, Form form) List<String> forcedFields, Form form)
{ {
// ensure a NodeRef or TypeDefinition is provided // ensure a NodeRef or TypeDefinition is provided
if (nodeRef == null && typeDef == null) { throw new IllegalArgumentException( if (nodeRef == null && typeDef == null) { throw new IllegalArgumentException(
"A NodeRef or TypeDefinition must be provided"); } "A NodeRef or TypeDefinition must be provided"); }
if (getLogger().isDebugEnabled()) if (getLogger().isDebugEnabled())
getLogger().debug( getLogger().debug("Generating selected fields: " + fields + " and forcing: " + forcedFields);
"Generating selected fields: " + fields + " and forcing: " + forcedFields);
// get data dictionary definition for node if it is provided // get data dictionary definition for node if it is provided
QName type = null; QName type = null;
@@ -457,8 +452,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (nodeRef != null) if (nodeRef != null)
{ {
type = this.nodeService.getType(nodeRef); type = this.nodeService.getType(nodeRef);
typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
.getAspects(nodeRef));
// NOTE: the anonymous type returns all property and association // NOTE: the anonymous type returns all property and association
// defs // defs
@@ -547,8 +541,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (propDef != null) if (propDef != null)
{ {
// generate the property field // generate the property field
generatePropertyField(propDef, form, propValues.get(fullQName), generatePropertyField(propDef, form, propValues.get(fullQName), this.namespaceService);
this.namespaceService);
// no need to try and find an association // no need to try and find an association
tryAssociation = false; tryAssociation = false;
@@ -563,11 +556,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (assocDef != null) if (assocDef != null)
{ {
// generate the association field // generate the association field
generateAssociationField( generateAssociationField(assocDef, form, (nodeRef != null) ? retrieveAssociationValues(nodeRef,
assocDef, assocDef) : null, this.namespaceService);
form,
(nodeRef != null) ? retrieveAssociationValues(nodeRef, assocDef)
: null, this.namespaceService);
foundField = true; foundField = true;
} }
@@ -576,16 +566,14 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
// still not found the field, is it a force'd field? // still not found the field, is it a force'd field?
if (!foundField) if (!foundField)
{ {
if (forcedFields != null && forcedFields.size() > 0 if (forcedFields != null && forcedFields.size() > 0 && forcedFields.contains(fieldName))
&& forcedFields.contains(fieldName))
{ {
generateForcedField(fieldName, form); generateForcedField(fieldName, form);
} }
else if (getLogger().isDebugEnabled()) else if (getLogger().isDebugEnabled())
{ {
getLogger().debug( getLogger().debug(
"Ignoring field \"" + fieldName "Ignoring field \"" + fieldName + "\" as it is not defined for the current "
+ "\" as it is not defined for the current "
+ ((nodeRef != null) ? "node" : "type") + ((nodeRef != null) ? "node" : "type")
+ " and it does not appear in the 'force' list"); + " and it does not appear in the 'force' list");
} }
@@ -599,9 +587,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
{ {
// if the node type is content or sublcass thereof generate // if the node type is content or sublcass thereof generate
// appropriate field // appropriate field
if (nodeRef != null if (nodeRef != null && this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
&& this.dictionaryService.isSubClass(type,
ContentModel.TYPE_CONTENT))
{ {
ContentData content = (ContentData) this.nodeService.getProperty(nodeRef, ContentData content = (ContentData) this.nodeService.getProperty(nodeRef,
ContentModel.PROP_CONTENT); ContentModel.PROP_CONTENT);
@@ -675,10 +661,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
else else
{ {
if (getLogger().isWarnEnabled()) if (getLogger().isWarnEnabled())
getLogger() getLogger().warn(
.warn( "\"" + parts[0]
"\""
+ parts[0]
+ "\" is an invalid prefix for requesting a property or association"); + "\" is an invalid prefix for requesting a property or association");
return; return;
@@ -743,8 +727,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
protected void generateMimetypePropertyField(ContentData content, Form form) protected void generateMimetypePropertyField(ContentData content, Form form)
{ {
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_MIMETYPE; String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_MIMETYPE;
PropertyFieldDefinition mimetypeField = new PropertyFieldDefinition(TRANSIENT_MIMETYPE, PropertyFieldDefinition mimetypeField = new PropertyFieldDefinition(TRANSIENT_MIMETYPE, DataTypeDefinition.TEXT
DataTypeDefinition.TEXT.getLocalName()); .getLocalName());
mimetypeField.setLabel(I18NUtil.getMessage(MSG_MIMETYPE_LABEL)); mimetypeField.setLabel(I18NUtil.getMessage(MSG_MIMETYPE_LABEL));
mimetypeField.setDescription(I18NUtil.getMessage(MSG_MIMETYPE_DESC)); mimetypeField.setDescription(I18NUtil.getMessage(MSG_MIMETYPE_DESC));
mimetypeField.setDataKeyName(dataKeyName); mimetypeField.setDataKeyName(dataKeyName);
@@ -765,8 +749,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
protected void generateEncodingPropertyField(ContentData content, Form form) protected void generateEncodingPropertyField(ContentData content, Form form)
{ {
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, DataTypeDefinition.TEXT
DataTypeDefinition.TEXT.getLocalName()); .getLocalName());
encodingField.setLabel(I18NUtil.getMessage(MSG_ENCODING_LABEL)); encodingField.setLabel(I18NUtil.getMessage(MSG_ENCODING_LABEL));
encodingField.setDescription(I18NUtil.getMessage(MSG_ENCODING_DESC)); encodingField.setDescription(I18NUtil.getMessage(MSG_ENCODING_DESC));
encodingField.setDataKeyName(dataKeyName); encodingField.setDataKeyName(dataKeyName);
@@ -787,8 +771,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
protected void generateSizePropertyField(ContentData content, Form form) protected void generateSizePropertyField(ContentData content, Form form)
{ {
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, DataTypeDefinition.LONG
DataTypeDefinition.LONG.getLocalName()); .getLocalName());
sizeField.setLabel(I18NUtil.getMessage(MSG_SIZE_LABEL)); sizeField.setLabel(I18NUtil.getMessage(MSG_SIZE_LABEL));
sizeField.setDescription(I18NUtil.getMessage(MSG_SIZE_DESC)); sizeField.setDescription(I18NUtil.getMessage(MSG_SIZE_DESC));
sizeField.setDataKeyName(dataKeyName); sizeField.setDataKeyName(dataKeyName);
@@ -818,8 +802,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
// get the list of values (if any) for the association // get the list of values (if any) for the association
if (assocDef instanceof ChildAssociationDefinition) if (assocDef instanceof ChildAssociationDefinition)
{ {
assocValues = this.nodeService.getChildAssocs(nodeRef, assocDef.getName(), assocValues = this.nodeService.getChildAssocs(nodeRef, assocDef.getName(), RegexQNamePattern.MATCH_ALL);
RegexQNamePattern.MATCH_ALL);
} }
else else
{ {
@@ -839,14 +822,12 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
{ {
// get the property definitions for the type of node being persisted // get the property definitions for the type of node being persisted
QName type = this.nodeService.getType(nodeRef); QName type = this.nodeService.getType(nodeRef);
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
.getAspects(nodeRef));
Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations(); Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations();
Map<QName, ChildAssociationDefinition> childAssocDefs = typeDef.getChildAssociations(); Map<QName, ChildAssociationDefinition> childAssocDefs = typeDef.getChildAssociations();
Map<QName, PropertyDefinition> propDefs = typeDef.getProperties(); Map<QName, PropertyDefinition> propDefs = typeDef.getProperties();
Map<QName, Serializable> propsToPersist = new HashMap<QName, Serializable>(data Map<QName, Serializable> propsToPersist = new HashMap<QName, Serializable>(data.getNumberOfFields());
.getNumberOfFields());
List<AbstractAssocCommand> assocsToPersist = new ArrayList<AbstractAssocCommand>(); List<AbstractAssocCommand> assocsToPersist = new ArrayList<AbstractAssocCommand>();
for (FieldData fieldData : data) for (FieldData fieldData : data)
@@ -862,8 +843,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
} }
else if (fieldName.startsWith(ASSOC_DATA_PREFIX)) else if (fieldName.startsWith(ASSOC_DATA_PREFIX))
{ {
processAssociationPersist(nodeRef, assocDefs, childAssocDefs, fieldData, processAssociationPersist(nodeRef, assocDefs, childAssocDefs, fieldData, assocsToPersist);
assocsToPersist);
} }
else if (getLogger().isWarnEnabled()) else if (getLogger().isWarnEnabled())
{ {
@@ -1004,8 +984,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
// everything else // everything else
// should be represented as null // should be represented as null
if (!propDef.getDataType().getName().equals(DataTypeDefinition.TEXT) if (!propDef.getDataType().getName().equals(DataTypeDefinition.TEXT)
&& !propDef.getDataType().getName().equals( && !propDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT))
DataTypeDefinition.MLTEXT))
{ {
value = null; value = null;
} }
@@ -1018,8 +997,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
else if (getLogger().isWarnEnabled()) else if (getLogger().isWarnEnabled())
{ {
getLogger().warn( getLogger().warn(
"Ignoring field '" + fieldData.getName() "Ignoring field '" + fieldData.getName() + "' as a property definition can not be found");
+ "' as a property definition can not be found");
} }
} }
else else
@@ -1064,8 +1042,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param fieldData Data to persist for the associations * @param fieldData Data to persist for the associations
* @param assocCommands List of associations to be persisted * @param assocCommands List of associations to be persisted
*/ */
protected void processAssociationPersist(NodeRef nodeRef, protected void processAssociationPersist(NodeRef nodeRef, Map<QName, AssociationDefinition> assocDefs,
Map<QName, AssociationDefinition> assocDefs,
Map<QName, ChildAssociationDefinition> childAssocDefs, FieldData fieldData, Map<QName, ChildAssociationDefinition> childAssocDefs, FieldData fieldData,
List<AbstractAssocCommand> assocCommands) List<AbstractAssocCommand> assocCommands)
{ {
@@ -1102,9 +1079,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
{ {
if (getLogger().isWarnEnabled()) if (getLogger().isWarnEnabled())
{ {
getLogger().warn( getLogger().warn("Definition for association " + fullQName + " not recognised and not persisted.");
"Definition for association " + fullQName
+ " not recognised and not persisted.");
} }
return; return;
} }
@@ -1125,26 +1100,25 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
{ {
if (assocDef.isChild()) if (assocDef.isChild())
{ {
assocCommands.add(new AddChildAssocCommand(nodeRef, new NodeRef( assocCommands.add(new AddChildAssocCommand(nodeRef, new NodeRef(nextTargetNode),
nextTargetNode), fullQName)); fullQName));
} }
else else
{ {
assocCommands.add(new AddAssocCommand(nodeRef, new NodeRef( assocCommands.add(new AddAssocCommand(nodeRef, new NodeRef(nextTargetNode), fullQName));
nextTargetNode), fullQName));
} }
} }
else if (assocSuffix.equals(ASSOC_DATA_REMOVED_SUFFIX)) else if (assocSuffix.equals(ASSOC_DATA_REMOVED_SUFFIX))
{ {
if (assocDef.isChild()) if (assocDef.isChild())
{ {
assocCommands.add(new RemoveChildAssocCommand(nodeRef, new NodeRef( assocCommands.add(new RemoveChildAssocCommand(nodeRef, new NodeRef(nextTargetNode),
nextTargetNode), fullQName)); fullQName));
} }
else else
{ {
assocCommands.add(new RemoveAssocCommand(nodeRef, new NodeRef( assocCommands.add(new RemoveAssocCommand(nodeRef, new NodeRef(nextTargetNode),
nextTargetNode), fullQName)); fullQName));
} }
} }
else else
@@ -1153,10 +1127,9 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
{ {
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();
msg.append("fieldName ").append(fieldName).append( msg.append("fieldName ").append(fieldName).append(
" does not have one of the expected suffixes [") " does not have one of the expected suffixes [").append(
.append(ASSOC_DATA_ADDED_SUFFIX).append(", ").append( ASSOC_DATA_ADDED_SUFFIX).append(", ").append(ASSOC_DATA_REMOVED_SUFFIX)
ASSOC_DATA_REMOVED_SUFFIX).append( .append("] and has been ignored.");
"] and has been ignored.");
getLogger().warn(msg.toString()); getLogger().warn(msg.toString());
} }
} }
@@ -1215,8 +1188,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (contentData == null) if (contentData == null)
{ {
// content data has not been persisted yet so get it from the node // content data has not been persisted yet so get it from the node
contentData = (ContentData) this.nodeService.getProperty(nodeRef, contentData = (ContentData) this.nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
ContentModel.PROP_CONTENT);
} }
if (contentData != null) if (contentData != null)
@@ -1241,8 +1213,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (contentData == null) if (contentData == null)
{ {
// content data has not been persisted yet so get it from the node // content data has not been persisted yet so get it from the node
contentData = (ContentData) this.nodeService.getProperty(nodeRef, contentData = (ContentData) this.nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
ContentModel.PROP_CONTENT);
} }
if (contentData != null) if (contentData != null)
@@ -1300,8 +1271,7 @@ class AddAssocCommand extends AbstractAssocCommand
@Override @Override
protected void updateAssociations(NodeService nodeService) protected void updateAssociations(NodeService nodeService)
{ {
List<AssociationRef> existingAssocs = nodeService List<AssociationRef> existingAssocs = nodeService.getTargetAssocs(sourceNodeRef, assocQName);
.getTargetAssocs(sourceNodeRef, assocQName);
for (AssociationRef assoc : existingAssocs) for (AssociationRef assoc : existingAssocs)
{ {
if (assoc.getTargetRef().equals(targetNodeRef)) if (assoc.getTargetRef().equals(targetNodeRef))
@@ -1334,8 +1304,7 @@ class RemoveAssocCommand extends AbstractAssocCommand
@Override @Override
protected void updateAssociations(NodeService nodeService) protected void updateAssociations(NodeService nodeService)
{ {
List<AssociationRef> existingAssocs = nodeService List<AssociationRef> existingAssocs = nodeService.getTargetAssocs(sourceNodeRef, assocQName);
.getTargetAssocs(sourceNodeRef, assocQName);
boolean assocDoesNotExist = true; boolean assocDoesNotExist = true;
for (AssociationRef assoc : existingAssocs) for (AssociationRef assoc : existingAssocs)
{ {
@@ -1350,8 +1319,8 @@ class RemoveAssocCommand extends AbstractAssocCommand
if (logger.isWarnEnabled()) if (logger.isWarnEnabled())
{ {
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();
msg.append("Attempt to remove non-existent association prevented. ").append( msg.append("Attempt to remove non-existent association prevented. ").append(sourceNodeRef).append("|")
sourceNodeRef).append("|").append(targetNodeRef).append(assocQName); .append(targetNodeRef).append(assocQName);
logger.warn(msg.toString()); logger.warn(msg.toString());
} }
return; return;
@@ -1432,8 +1401,8 @@ class RemoveChildAssocCommand extends AbstractAssocCommand
if (logger.isWarnEnabled()) if (logger.isWarnEnabled())
{ {
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();
msg.append("Attempt to remove non-existent child association prevented. ").append( msg.append("Attempt to remove non-existent child association prevented. ").append(sourceNodeRef)
sourceNodeRef).append("|").append(targetNodeRef).append(assocQName); .append("|").append(targetNodeRef).append(assocQName);
logger.warn(msg.toString()); logger.warn(msg.toString());
} }
return; return;

View File

@@ -95,21 +95,19 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
{ {
// ignored for now, dealt with below // ignored for now, dealt with below
if (logger.isDebugEnabled()) if (logger.isDebugEnabled()) logger.debug("NodeRef creation failed for: " + item.getId(), iae);
logger.debug("NodeRef creation failed for: " + item.getId(), iae);
} }
} }
} }
// check we have a valid node ref // check we have a valid node ref
if (nodeRef == null) { throw new FormNotFoundException(item, new IllegalArgumentException( if (nodeRef == null) { throw new FormNotFoundException(item, new IllegalArgumentException(item.getId())); }
item.getId())); }
// check the node itself exists // check the node itself exists
if (this.nodeService.exists(nodeRef) == false) if (this.nodeService.exists(nodeRef) == false)
{ {
throw new FormNotFoundException(item, new InvalidNodeRefException( throw new FormNotFoundException(item, new InvalidNodeRefException("Node does not exist: " + nodeRef,
"Node does not exist: " + nodeRef, nodeRef)); nodeRef));
} }
else else
{ {
@@ -125,8 +123,8 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
* org.alfresco.repo.forms.Form, java.util.Map) * org.alfresco.repo.forms.Form, java.util.Map)
*/ */
@Override @Override
protected void internalGenerate(NodeRef item, List<String> fields, List<String> forcedFields, protected void internalGenerate(NodeRef item, List<String> fields, List<String> forcedFields, Form form,
Form form, Map<String, Object> context) Map<String, Object> context)
{ {
if (logger.isDebugEnabled()) logger.debug("Generating form for: " + item); if (logger.isDebugEnabled()) logger.debug("Generating form for: " + item);
@@ -144,17 +142,17 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
* @param forcedFields List of fields to forcibly include * @param forcedFields List of fields to forcibly include
* @param form The Form instance to populate * @param form The Form instance to populate
*/ */
protected void generateNode(NodeRef nodeRef, List<String> fields, List<String> forcedFields, protected void generateNode(NodeRef nodeRef, List<String> fields, List<String> forcedFields, Form form)
Form form)
{ {
// set the type and URL of the item // set the type and URL of the item
QName type = this.nodeService.getType(nodeRef); QName type = this.nodeService.getType(nodeRef);
form.getItem().setType(type.toPrefixString(this.namespaceService)); setFormItemType(form, type.toPrefixString(this.namespaceService));
StringBuilder builder = new StringBuilder("/api/node/"); StringBuilder builder = new StringBuilder("/api/node/");
builder.append(nodeRef.getStoreRef().getProtocol()).append("/"); builder.append(nodeRef.getStoreRef().getProtocol()).append("/");
builder.append(nodeRef.getStoreRef().getIdentifier()).append("/"); builder.append(nodeRef.getStoreRef().getIdentifier()).append("/");
builder.append(nodeRef.getId()); builder.append(nodeRef.getId());
form.getItem().setUrl(builder.toString()); setFormItemUrl(form, builder.toString());
if (fields != null && fields.size() > 0) if (fields != null && fields.size() > 0)
{ {
@@ -179,8 +177,7 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
{ {
// get data dictionary definition for node // get data dictionary definition for node
QName type = this.nodeService.getType(nodeRef); QName type = this.nodeService.getType(nodeRef);
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
.getAspects(nodeRef));
// iterate round the property definitions for the node and create // iterate round the property definitions for the node and create
// the equivalent field definition and setup the data for the property // the equivalent field definition and setup the data for the property
@@ -188,8 +185,7 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
Map<QName, Serializable> propValues = this.nodeService.getProperties(nodeRef); Map<QName, Serializable> propValues = this.nodeService.getProperties(nodeRef);
for (PropertyDefinition propDef : propDefs.values()) for (PropertyDefinition propDef : propDefs.values())
{ {
generatePropertyField(propDef, form, propValues.get(propDef.getName()), generatePropertyField(propDef, form, propValues.get(propDef.getName()), this.namespaceService);
this.namespaceService);
} }
} }
@@ -203,8 +199,7 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
{ {
// get data dictionary definition for the node // get data dictionary definition for the node
QName type = this.nodeService.getType(nodeRef); QName type = this.nodeService.getType(nodeRef);
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
.getAspects(nodeRef));
// iterate round the association defintions and setup field definition // iterate round the association defintions and setup field definition
Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations(); Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations();
@@ -229,8 +224,7 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
QName type = this.nodeService.getType(nodeRef); QName type = this.nodeService.getType(nodeRef);
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT)) if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
{ {
ContentData content = (ContentData) this.nodeService.getProperty(nodeRef, ContentData content = (ContentData) this.nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
ContentModel.PROP_CONTENT);
if (content != null) if (content != null)
{ {
// setup mimetype field // setup mimetype field

View File

@@ -0,0 +1,402 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.forms.processor.task;
/**
* @author Nick Smith
*/
public abstract class AbstractFormHelper
{
// /** Protected constants */
// protected static final String MSG_MIMETYPE_LABEL =
// "form_service.mimetype.label";
//
// protected static final String MSG_MIMETYPE_DESC =
// "form_service.mimetype.description";
//
// protected static final String MSG_ENCODING_LABEL =
// "form_service.encoding.label";
//
// protected static final String MSG_ENCODING_DESC =
// "form_service.encoding.description";
//
// protected static final String MSG_SIZE_LABEL = "form_service.size.label";
//
// protected static final String MSG_SIZE_DESC =
// "form_service.size.description";
//
// /**
// * A regular expression which can be used to match property names. These
// * names will look like <code>"prop_cm_name"</code>. The pattern can also
// be
// * used to extract the "cm" and the "name" parts.
// */
// protected Pattern propertyNamePattern = Pattern.compile(PROP_DATA_PREFIX
// + "(.*){1}?_(.*){1}?");
//
// /**
// * A regular expression which can be used to match tranisent property
// names.
// * These names will look like <code>"prop_name"</code>. The pattern can
// also
// * be used to extract the "name" part.
// */
// protected Pattern transientPropertyPattern =
// Pattern.compile(PROP_DATA_PREFIX + "(.*){1}?");
//
// /**
// * A regular expression which can be used to match association names.
// These
// * names will look like <code>"assoc_cm_references_added"</code>. The
// * pattern can also be used to extract the "cm", the "name" and the suffix
// * parts.
// */
// protected Pattern associationNamePattern =
// Pattern.compile(ASSOC_DATA_PREFIX + "(.*){1}?_(.*){1}?(_[a-zA-Z]+)");
//
// private NamespaceService namespaceService;
//
// private FieldDefinitionFactory factory;
//
// /**
// * 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
// */
// public void generateSelectedField(String fieldName, FieldCreationData
// data)
// {
// FieldInfo fieldInfo = new FieldInfo(fieldName, data);
// if (fieldInfo.isValid()) fieldInfo.addToForm(form);
//
// // try the field as a property
// if (fieldInfo.tryProperty)
// {
// // lookup property def on node
// PropertyDefinition propDef = propDefs.get(fullQName);
// if (propDef != null)
// {
// // generate the property field
// generatePropertyField(propDef, propValues.get(fullQName), null);
//
// // no need to try and find an association
// tryAssociation = false;
// foundField = true;
// }
// }
//
// // try the field as an association
// if (fieldInfo.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 forced 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");
// }
// }
// }
//
// /**
// * 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
// */
// public void generateAssociationField(AssociationDefinition assocDef,
// List<?> assocValues, FieldGroup group)
// {
// AssociationFieldDefinition fieldDef =
// makeAssociationFieldDefinition(assocDef, group);
//
// // 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(fieldDef.getDataKeyName(), values);
// }
// }
//
// /**
// * 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")
// public void generatePropertyField(PropertyDefinition propDef,
// Serializable propValue, FieldGroup group)
// {
// PropertyFieldDefinition fieldDef =
// factory.makePropertyFieldDefinition(propDef, group);
// form.addFieldDefinition(fieldDef);
//
// // add the property value to the form
// if (propValue != null)
// {
// if (propValue instanceof List)
// {
// // TODO Currently this adds repeating field data as a comma
// // separated list, this needs to be replaced with a separate
// // field for each value once we have full UI support in place.
// propValue = StringUtils.collectionToCommaDelimitedString((List)
// propValue);
// }
// form.addData(fieldDef.getDataKeyName(), propValue);
// }
// }
//
// private class FieldInfo
// {
// private final QName name;
//
// private final FieldDefinition fieldDefinition;
//
// private FieldType fieldType;
//
// private FieldInfo(String fieldName, FieldCreationData data)
// {
// this.name = makeNameAndFieldType(fieldName);
// this.fieldDefinition = createDefinition(data);
// }
//
// /**
// * @return
// */
// public boolean isValid()
// {
// return fieldDefinition != null;
// }
//
// private QName makeNameAndFieldType(String fieldName)
// {
// String[] parts = fieldName.split(":");
// if (parts.length < 2 || parts.length > 3)
// {
// this.fieldType = FieldType.INVALID;
// return QName.createQName(null, fieldName);
// }
// int indexer = 0;
// if (parts.length == 3)
// {
// indexer = 1;
// this.fieldType = FieldType.getType(parts[0]);
// }
// else
// this.fieldType = FieldType.UNKNOWN;
// String prefix = parts[0 + indexer];
// String localName = parts[1 + indexer];
// return QName.createQName(prefix, localName, namespaceService);
// }
//
// /**
// * @param data
// */
// private FieldDefinition createDefinition(FieldCreationData data)
// {
// FieldDefinition fieldDef = null;
// switch (fieldType)
// {
// case INVALID:// So fieldDef will stay null.
// break;
// case PROPERTY:
// fieldDef = generatePropertyDefinition(data);
// break;
// case ASSOCIATION:
// fieldDef = generateAssociationDefinition(data);
// break;
// case UNKNOWN:
// fieldDef = generatePropertyDefinition(data);
// if (fieldDef != null)
// fieldType = FieldType.PROPERTY;
// else
// {
// fieldDef = generateAssociationDefinition(data);
// if (fieldDef != null) fieldType = FieldType.ASSOCIATION;
// }
// }
// if (fieldDef == null)
// {
// this.fieldType = FieldType.INVALID;
// }
// return fieldDef;
// }
//
// /**
// * @param data
// * @return
// */
// private AssociationFieldDefinition
// generateAssociationDefinition(FieldCreationData data)
// {
// AssociationDefinition assocDef = data.getAssocDefs().get(name);
// if (assocDef != null)
// return factory.makeAssociationFieldDefinition(assocDef, data.getGroup());
// else
// return null;
// }
//
// /**
// * @param data
// */
// private PropertyFieldDefinition
// generatePropertyDefinition(FieldCreationData data)
// {
// PropertyDefinition propDef = data.getPropDefs().get(name);
// if (propDef != null) //
// return factory.makePropertyFieldDefinition(propDef, data.getGroup());
// else
// return null;
// }
//
// public void addToForm(Form form, FieldCreationData data)
// {
// if (isValid())
// {
// form.addFieldDefinition(fieldDefinition);
// Object value = null;
// if (fieldType == FieldType.PROPERTY)
// {
// value = buildPropertyData(data, (PropertyFieldDefinition)
// fieldDefinition);
// }
// else if (fieldType == FieldType.ASSOCIATION)
// {
// value = buildAssociationData(data, (AssociationFieldDefinition)
// fieldDefinition);
// }
// if (value != null)
// {
// form.addData(fieldDefinition.getDataKeyName(), value);
// }
// }
// else
// {
// throw new IllegalStateException("Cannot add invalid field:" +
// name.getLocalName() + " to a form!");
// }
// }
// }
//
// private enum FieldType
// {
// ASSOCIATION, INVALID, PROPERTY, UNKNOWN;
//
// public static FieldType getType(String type)
// {
// if (PROP.equals(type))
// {
// return PROPERTY;
// }
// else if (ASSOC.equals(type)) return ASSOCIATION;
// return UNKNOWN;
// }
// }
//
// protected abstract Object buildPropertyData(FieldCreationData data,
// PropertyFieldDefinition fieldDef);
//
// protected abstract Object buildAssociationData(FieldCreationData data,
// AssociationFieldDefinition fieldDef);
}

View File

@@ -0,0 +1,181 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.forms.processor.task;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.forms.FieldGroup;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.namespace.QName;
/**
* @author Nick Smith
*/
public class FieldCreationData
{
private final QName type;
private final TypeDefinition typeDef;
private final Map<QName, Serializable> propValues;
private final Map<QName, PropertyDefinition> propDefs;
private final Map<QName, AssociationDefinition> assocDefs;
private final FieldGroup group;
private final List<String> forcedFields;
public FieldCreationData(NodeRef nodeRef, List<String> forcedFields, FieldGroup group, NodeService nodeService,
DictionaryService dictionaryService)
{
this.forcedFields = forcedFields;
this.group = group;
this.type = nodeService.getType(nodeRef);
Set<QName> aspects = nodeService.getAspects(nodeRef);
this.typeDef = dictionaryService.getAnonymousType(type, aspects);
// NOTE: the anonymous type returns all property and association
// defs for all aspects applied as well as the type
this.propDefs = typeDef.getProperties();
this.assocDefs = typeDef.getAssociations();
this.propValues = nodeService.getProperties(nodeRef);
}
public FieldCreationData(TypeDefinition typeDef, List<String> forcedFields, FieldGroup group)
{
this.propValues = null;
this.forcedFields = forcedFields;
this.group = group;
this.typeDef = typeDef;
this.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
this.propDefs = new HashMap<QName, PropertyDefinition>(16);
this.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());
}
}
public FieldCreationData(WorkflowTask task, List<String> forcedFields, FieldGroup group)
{
this.forcedFields = forcedFields;
this.group = group;
this.typeDef = task.definition.metadata;
this.type = typeDef.getName();
this.propDefs = populateProperties(typeDef);
this.assocDefs = populateAssociations(typeDef);
this.propValues = task.properties;
}
private Map<QName, AssociationDefinition> populateAssociations(TypeDefinition typeDef2)
{
HashMap<QName, AssociationDefinition> allProps = new HashMap<QName, AssociationDefinition>();
allProps.putAll(typeDef.getAssociations());
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
for (AspectDefinition aspect : aspects)
{
allProps.putAll(aspect.getAssociations());
}
return Collections.unmodifiableMap(allProps);
}
private Map<QName, PropertyDefinition> populateProperties(TypeDefinition typeDef)
{
HashMap<QName, PropertyDefinition> allProps = new HashMap<QName, PropertyDefinition>();
allProps.putAll(typeDef.getProperties());
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
for (AspectDefinition aspect : aspects)
{
allProps.putAll(aspect.getProperties());
}
return Collections.unmodifiableMap(allProps);
}
/**
* @return the propValues
*/
public Map<QName, Serializable> getPropValues()
{
return this.propValues;
}
/**
* @return the propDefs
*/
public Map<QName, PropertyDefinition> getPropDefs()
{
return this.propDefs;
}
/**
* @return the assocDefs
*/
public Map<QName, AssociationDefinition> getAssocDefs()
{
return this.assocDefs;
}
/**
* @return the group
*/
public FieldGroup getGroup()
{
return this.group;
}
/**
* @return the forcedFields
*/
public List<String> getForcedFields()
{
return this.forcedFields;
}
}

View File

@@ -0,0 +1,199 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.forms.processor.task;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.*;
import org.alfresco.repo.forms.AssociationFieldDefinition;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.FieldGroup;
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.PeriodDataTypeParameters;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassAttributeDefinition;
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.repository.Period;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* @author Nick Smith
*/
public class FieldDefinitionFactory
{
private final NamespaceService namespaceService;
public FieldDefinitionFactory(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
public AssociationFieldDefinition makeAssociationFieldDefinition(
final AssociationDefinition assocDef, FieldGroup group)
{
// Callback used to construct the AssociationFieldDefinition.
FieldDefinitionCreator<AssociationFieldDefinition> factory = new FieldDefinitionCreator<AssociationFieldDefinition>()
{
public AssociationFieldDefinition create(String name)
{
String endpointType = assocDef.getTargetClass().getName().toPrefixString(
namespaceService);
return new AssociationFieldDefinition(name, endpointType, Direction.TARGET);
}
};
AssociationFieldDefinition fieldDef = makeFieldDefinition(assocDef, group,
ASSOC_DATA_PREFIX, factory);
fieldDef.setEndpointMandatory(assocDef.isTargetMandatory());
fieldDef.setEndpointMany(assocDef.isTargetMany());
return fieldDef;
}
public PropertyFieldDefinition makePropertyFieldDefinition(final PropertyDefinition propDef,
FieldGroup group)
{
// Callback used to construct the PropertyFieldDefinition.
FieldDefinitionCreator<PropertyFieldDefinition> factory = new FieldDefinitionCreator<PropertyFieldDefinition>()
{
public PropertyFieldDefinition create(String name)
{
QName dataType = propDef.getDataType().getName();
return new PropertyFieldDefinition(name, dataType.getLocalName());
}
};
PropertyFieldDefinition fieldDef = makeFieldDefinition(propDef, group, PROP_DATA_PREFIX,
factory);
fieldDef.setDefaultValue(propDef.getDefaultValue());
fieldDef.setMandatory(propDef.isMandatory());
fieldDef.setRepeating(propDef.isMultiValued());
// any property from the system model (sys prefix) should be protected
// the model doesn't
// cu rrently enforce this so make sure they are not editable
if (NamespaceService.SYSTEM_MODEL_1_0_URI.equals(propDef.getName().getNamespaceURI()))
{
fieldDef.setProtectedField(true);
}
// If the property data type is d:period we need to setup a data
// type parameters object to represent the options and rules
if (fieldDef.getDataType().equals(DataTypeDefinition.PERIOD))
{
PeriodDataTypeParameters periodOptions = getPeriodOptions();
fieldDef.setDataTypeParameters(periodOptions);
}
// setup constraints for the property
List<FieldConstraint> fieldConstraints = makeFieldConstraints(propDef);
fieldDef.setConstraints(fieldConstraints);
return fieldDef;
}
/**
* Creates either a PropertyFieldDefinition or an
* AssociationFieldDefinition, as defined by the factory class being passed
* in. Sets several properties on this FieldDefinition, including name,
* label, description, dataKeyName and whether the field is protected. These
* values are derived from the <code>attribDef</code> parameter.
*
* @param attribDef Used to set the values of name, description, label,
* dataKeyName and isProtected properties on the returned object.
* @param group Used to set the group on the returned FieldDefinition.
* @param factory A factory object used to create the FieldDefinition to be
* returned.
* @return An object of type <code>T</code> which extends
* <code>FieldDefinition</code>.
*/
private <T extends FieldDefinition> T makeFieldDefinition(ClassAttributeDefinition attribDef,
FieldGroup group, String dataKeyPrefix, FieldDefinitionCreator<T> factory)
{
String attribName = attribDef.getName().toPrefixString(namespaceService);
T fieldDef = factory.create(attribName);
fieldDef.setGroup(group);
String title = attribDef.getTitle();
title = title == null ? attribName : title;
fieldDef.setLabel(title);
fieldDef.setDescription(attribDef.getDescription());
fieldDef.setProtectedField(attribDef.isProtected());
// define the data key name and set
String dataKeyName = makeDataKeyForName(attribName, dataKeyPrefix);
fieldDef.setDataKeyName(dataKeyName);
return fieldDef;
}
private static List<FieldConstraint> makeFieldConstraints(PropertyDefinition propDef)
{
List<FieldConstraint> fieldConstraints = null;
List<ConstraintDefinition> constraints = propDef.getConstraints();
if (constraints != null && constraints.size() > 0)
{
fieldConstraints = new ArrayList<FieldConstraint>(constraints.size());
for (ConstraintDefinition constraintDef : constraints)
{
Constraint constraint = constraintDef.getConstraint();
String type = constraint.getType();
Map<String, Object> params = constraint.getParameters();
FieldConstraint fieldConstraint = new FieldConstraint(type, params);
fieldConstraints.add(fieldConstraint);
}
}
return fieldConstraints;
}
private PeriodDataTypeParameters getPeriodOptions()
{
PeriodDataTypeParameters periodOptions = new PeriodDataTypeParameters();
Set<String> providers = Period.getProviderNames();
for (String provider : providers)
{
periodOptions.addPeriodProvider(Period.getProvider(provider));
}
return periodOptions;
}
private static String makeDataKeyForName(String propName, String prefix)
{
String[] nameParts = QName.splitPrefixedQName(propName);
return prefix + nameParts[0] + DATA_KEY_SEPARATOR + nameParts[1];
}
private interface FieldDefinitionCreator<T extends FieldDefinition>
{
T create(String fieldDefinitionName);
}
}

View File

@@ -0,0 +1,235 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.forms.processor.task;
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.*;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* @author Nick Smith
*/
public class FieldInfo
{
private final QName fullName;
private final FieldDefinition fieldDefinition;
private final String fieldName;
private final DictionaryService dictionaryService;
private final FieldDefinitionFactory factory;
private FieldType fieldType;
public FieldInfo(String fieldName, FieldCreationData data, FieldDefinitionFactory factory,
DictionaryService dictionaryService, NamespaceService namespaceService)
{
this.factory = factory;
this.dictionaryService = dictionaryService;
this.fieldName = fieldName;
this.fullName = makeNameAndFieldType(fieldName, namespaceService);
this.fieldDefinition = createDefinition(data);
}
private FieldDefinition createDefinition(final FieldCreationData data)
{
// Callback used to find the PropertyDefinition associated with this
// field (if any).
Getter<PropertyDefinition> propDefGetter = new Getter<PropertyDefinition>()
{
public PropertyDefinition get()
{
return data.getPropDefs().get(fullName);
}
};
// Callback used to find the PropertyDefinition associated with this
// field (if any).
Getter<AssociationDefinition> assocDefGetter = new Getter<AssociationDefinition>()
{
public AssociationDefinition get()
{
return data.getAssocDefs().get(fullName);
}
};
FieldDefinition fieldDef = createDefinition(data, propDefGetter, assocDefGetter);
if (fieldDef == null)
{
// If field is a forced field try to get it from dictionary
// service.
if (data.getForcedFields().contains(fieldName))
{
propDefGetter = new Getter<PropertyDefinition>()
{
public PropertyDefinition get()
{
return dictionaryService.getProperty(fullName);
}
};
new Getter<AssociationDefinition>()
{
public AssociationDefinition get()
{
return dictionaryService.getAssociation(fullName);
}
};
fieldDef = createDefinition(data);
}
}
// If no field definition found then set fieldType to Invalid.
if (fieldDef == null)
{
this.fieldType = FieldType.INVALID;
}
return fieldDef;
}
/**
* @return
*/
public boolean isValid()
{
return fieldDefinition != null;
}
private QName makeNameAndFieldType(String fieldName, NamespaceService namespaceService)
{
String[] parts = fieldName.split(":");
if (parts.length < 2 || parts.length > 3)
{
this.fieldType = FieldType.INVALID;
return QName.createQName(null, fieldName);
}
int indexer = 0;
if (parts.length == 3)
{
indexer = 1;
this.fieldType = FieldType.getType(parts[0]);
}
else
this.fieldType = FieldType.UNKNOWN;
String prefix = parts[0 + indexer];
String localName = parts[1 + indexer];
return QName.createQName(prefix, localName, namespaceService);
}
/**
* @param data
*/
private FieldDefinition createDefinition(FieldCreationData data, Getter<PropertyDefinition> propDefGetter,
Getter<AssociationDefinition> assocDefGetter)
{
FieldDefinition fieldDef = null;
switch (fieldType)
{
case INVALID:// So fieldDef will stay null.
break;
case PROPERTY:
fieldDef = generatePropertyDefinition(data, propDefGetter);
break;
case ASSOCIATION:
fieldDef = generateAssociationDefinition(data, assocDefGetter);
break;
case UNKNOWN:
fieldDef = generatePropertyDefinition(data, propDefGetter);
if (fieldDef != null)
fieldType = FieldType.PROPERTY;
else
{
fieldDef = generateAssociationDefinition(data, assocDefGetter);
if (fieldDef != null) fieldType = FieldType.ASSOCIATION;
}
}
return fieldDef;
}
private FieldDefinition generateAssociationDefinition(FieldCreationData data,
Getter<AssociationDefinition> assocDefGetter)
{
AssociationDefinition assocDef = assocDefGetter.get();
if (assocDef != null)
return factory.makeAssociationFieldDefinition(assocDef, data.getGroup());
else
return null;
}
private FieldDefinition generatePropertyDefinition(FieldCreationData data, Getter<PropertyDefinition> propDefGetter)
{
PropertyDefinition propDef = propDefGetter.get();
if (propDef != null) //
return factory.makePropertyFieldDefinition(propDef, data.getGroup());
else
return null;
}
/**
* @return the fieldDefinition
*/
public FieldDefinition getFieldDefinition()
{
return this.fieldDefinition;
}
/**
* @return the fullName
*/
public QName getFullName()
{
return this.fullName;
}
/**
* @return the fieldName
*/
public String getFieldName()
{
return this.fieldName;
}
private enum FieldType
{
ASSOCIATION, INVALID, PROPERTY, UNKNOWN;
public static FieldType getType(String type)
{
if (PROP.equals(type))
{
return PROPERTY;
}
else if (ASSOC.equals(type)) return ASSOCIATION;
return UNKNOWN;
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.forms.processor.task;
/**
* This interface may be used as a parameter in a method instead of passing in
* an object of type T. This can be useful if you wish to lazy-create a
* parameter, cache a parameter or otherwise control how the parameter is used.
*
* @author Nick Smith
*/
public interface Getter<T>
{
/**
* Returns an object of type T.
*
* @return
*/
T get();
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.forms.processor.task;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.forms.FieldDefinition;
import org.alfresco.repo.forms.Form;
import org.alfresco.repo.forms.FormData;
import org.alfresco.repo.forms.Item;
import org.alfresco.repo.forms.FormData.FieldData;
import org.alfresco.repo.forms.processor.FilteredFormProcessor;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
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;
import org.alfresco.util.ParameterCheck;
/**
* @author Nick Smith
*/
public class TaskFormProcessor extends FilteredFormProcessor<WorkflowTask, WorkflowTask>
{
/** Logger */
// private static final Log logger =
// LogFactory.getLog(TaskFormProcessor.class);
private final WorkflowService workflowService;
private final NamespaceService namespaceService;
private final DictionaryService dictionaryService;
private final FieldDefinitionFactory factory;
public TaskFormProcessor(WorkflowService workflowService, NamespaceService namespaceService,
DictionaryService dictionaryService)
{
this.workflowService = workflowService;
this.namespaceService = namespaceService;
this.dictionaryService = dictionaryService;
this.factory = new FieldDefinitionFactory(namespaceService);
}
/*
* @see
* org.alfresco.repo.forms.processor.FilteredFormProcessor#getTypedItem(
* org.alfresco.repo.forms.Item)
*/
@Override
protected WorkflowTask getTypedItem(Item item)
{
ParameterCheck.mandatory("item", item);
String id = item.getId();
WorkflowTask task = workflowService.getTaskById(id);
return task;
}
/*
* @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(WorkflowTask item, List<String> fields, List<String> forcedFields, Form form,
Map<String, Object> context)
{
TypeDefinition typeDef = item.definition.metadata;
String type = typeDef.getName().toPrefixString(namespaceService);
setFormItemType(form, type);
// TODO Check this URL is OK.
setFormItemUrl(form, "/api/task/" + item.id);
FieldCreationData data = new FieldCreationData(item, forcedFields, null);
List<FieldInfo> fieldsToAdd = generateFields(data, fields);
for (FieldInfo fieldToAdd : fieldsToAdd)
{
if (fieldToAdd.isValid())
{
FieldDefinition fieldDef = fieldToAdd.getFieldDefinition();
form.addFieldDefinition(fieldDef);
Object value = data.getPropValues().get(fieldToAdd.getFullName());
if (value != null)
{
form.addData(fieldDef.getDataKeyName(), value);
}
}
}
}
private List<FieldInfo> generateFields(FieldCreationData data, List<String> fields)
{
ArrayList<FieldInfo> fieldData = new ArrayList<FieldInfo>(fields.size());
for (String fieldName : fields)
{
fieldData.add(makeFieldInfo(data, fieldName));
}
return fieldData;
}
private FieldInfo makeFieldInfo(FieldCreationData data, String fieldName)
{
return new FieldInfo(fieldName, data, factory, dictionaryService, namespaceService);
}
/*
* @see
* org.alfresco.repo.forms.processor.FilteredFormProcessor#internalPersist
* (java.lang.Object, org.alfresco.repo.forms.FormData)
*/
@Override
protected WorkflowTask internalPersist(WorkflowTask item, FormData data)
{
//TODO Implement this method properly.
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
for (FieldData fieldData : data)
{
fieldData.getName();
}
workflowService.updateTask(item.id, props, null, null);
return null;
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.forms.processor.task;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
import java.io.Serializable;
import java.util.HashMap;
import junit.framework.TestCase;
import org.alfresco.repo.forms.Item;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.workflow.WorkflowException;
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.NamespaceServiceMemoryImpl;
import org.alfresco.service.namespace.QName;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
* @author Nick Smith
*/
public class TaskFormProcessorTest extends TestCase
{
/**
*
*/
private static final String TASK_ID = "Real Id";
private WorkflowService workflowService;
TaskFormProcessor processor;
private WorkflowTask task;
public void testGetTypedItem() throws Exception
{
try
{
processor.getTypedItem(null);
fail("Should have thrown an Exception here!");
}
catch (IllegalArgumentException e)
{
// Do nothing!
}
try
{
processor.getTypedItem(new Item("task", "bad id"));
fail("Should have thrown an Exception here!");
}
catch (WorkflowException e)
{
// Do nothing!
}
Item item = new Item("task", TASK_ID);
WorkflowTask task = processor.getTypedItem(item);
assertNotNull(task);
assertEquals(TASK_ID, task.id);
}
// public void testGenerateSimple()
// {
// Item item = new Item("task", TASK_ID);
// Form form = new Form(item);
// List<String> fields = Arrays.asList("description");
// processor.internalGenerate(task, fields, null, form, null);
// }
// public void testPersist() throws Exception
// {
// FormData data = new FormData();
// processor.internalPersist(task, data);
// }
/*
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception
{
super.setUp();
task = makeTask();
workflowService = makeWorkflowService();
DictionaryService dictionaryService = makeDictionaryService();
NamespaceService namespaceService = makeNamespaceService();
processor = new TaskFormProcessor(workflowService, namespaceService, dictionaryService);
}
/**
*
*/
private WorkflowTask makeTask()
{
WorkflowTask task = new WorkflowTask();
task.id = TASK_ID;
task.description = "Description";
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
QName descName = WorkflowModel.PROP_DESCRIPTION;
properties.put(descName, "Description");
return task;
}
private NamespaceService makeNamespaceService()
{
return new NamespaceServiceMemoryImpl();
}
private DictionaryService makeDictionaryService()
{
return mock(DictionaryService.class);
}
private WorkflowService makeWorkflowService()
{
WorkflowService service = mock(WorkflowService.class);
when(service.getTaskById(anyString())).thenAnswer(new Answer<WorkflowTask>()
{
public WorkflowTask answer(InvocationOnMock invocation) throws Throwable
{
String id = (String) invocation.getArguments()[0];
if (TASK_ID.equals(id))
return task;
else
throw new WorkflowException("Task Id not found!");
}
});
return service;
}
}

View File

@@ -33,7 +33,7 @@ import org.alfresco.service.namespace.QName;
* @author David Caruana * @author David Caruana
* *
*/ */
public interface AssociationDefinition public interface AssociationDefinition extends ClassAttributeDefinition
{ {
/** /**

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.service.cmr.dictionary;
import org.alfresco.service.namespace.QName;
/**
*
* @author Nick Smith
*/
public interface ClassAttributeDefinition
{
/**
* @return defining model
*/
public ModelDefinition getModel();
/**
* @return the qualified name
*/
public QName getName();
/**
* @return the human-readable title
*/
public String getTitle();
/**
* @return the human-readable description
*/
public String getDescription();
/**
* Is this association or property maintained by the Repository?
*
* @return true => system maintained, false => client may maintain
*/
public boolean isProtected();
}

View File

@@ -22,6 +22,7 @@
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.service.cmr.dictionary; package org.alfresco.service.cmr.dictionary;
import java.util.List; import java.util.List;
@@ -34,7 +35,7 @@ import org.alfresco.service.namespace.QName;
* *
* @author David Caruana * @author David Caruana
*/ */
public interface PropertyDefinition public interface PropertyDefinition extends ClassAttributeDefinition
{ {
/** /**
* @return defining model * @return defining model
@@ -85,8 +86,9 @@ public interface PropertyDefinition
/** /**
* @return Returns true if the system enforces the presence of * @return Returns true if the system enforces the presence of
* {@link #isMandatory() mandatory} properties, or false if the system * {@link #isMandatory() mandatory} properties, or false if the
* just marks objects that don't have all mandatory properties present. * system just marks objects that don't have all mandatory
* properties present.
*/ */
public boolean isMandatoryEnforced(); public boolean isMandatoryEnforced();
@@ -106,15 +108,17 @@ public interface PropertyDefinition
public boolean isStoredInIndex(); public boolean isStoredInIndex();
/** /**
* @return IndexTokenisationMode.TREU => tokenised when it is indexed (the stored value will not be tokenised) * @return IndexTokenisationMode.TREU => tokenised when it is indexed (the
* stored value will not be tokenised)
*/ */
public IndexTokenisationMode getIndexTokenisationMode(); public IndexTokenisationMode getIndexTokenisationMode();
/** /**
* All non atomic properties will be indexed at the same time. * All non atomic properties will be indexed at the same time.
* *
* @return true => The attribute must be indexed in the commit of the transaction. * @return true => The attribute must be indexed in the commit of the
* false => the indexing will be done in the background and may be out of date. * transaction. false => the indexing will be done in the background
* and may be out of date.
*/ */
public boolean isIndexedAtomically(); public boolean isIndexedAtomically();