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:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.forms.processor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.alfresco.repo.forms.Form;
import org.alfresco.repo.forms.Item;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Abstract base class for all FormProcessor implementations provides
* a regex pattern match to test for processor applicability
* Abstract base class for all FormProcessor implementations provides a regex
* pattern match to test for processor applicability
*
* @author Gavin Cornwell
*/
@@ -42,8 +44,11 @@ public abstract class AbstractFormProcessor implements FormProcessor
private static final Log logger = LogFactory.getLog(AbstractFormProcessor.class);
protected FormProcessorRegistry processorRegistry;
protected String matchPattern;
protected boolean active = true;
protected Pattern patternMatcher;
/**
@@ -59,7 +64,8 @@ public abstract class AbstractFormProcessor implements FormProcessor
/**
* 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)
{
@@ -84,7 +90,8 @@ public abstract class AbstractFormProcessor implements FormProcessor
if (this.processorRegistry == null)
{
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;
}
@@ -92,7 +99,8 @@ public abstract class AbstractFormProcessor implements FormProcessor
if (this.matchPattern == null)
{
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;
}
@@ -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)
{
@@ -126,7 +136,8 @@ public abstract class AbstractFormProcessor implements FormProcessor
boolean matches = matcher.matches();
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;
}
@@ -143,4 +154,29 @@ public abstract class AbstractFormProcessor implements FormProcessor
buffer.append(")");
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
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);
}
@@ -87,7 +87,7 @@ public abstract class FilteredFormProcessor<ItemType, PersistType> extends Abstr
// inform all regsitered filters the form has been generated
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);
}
@@ -114,19 +114,19 @@ public abstract class FilteredFormProcessor<ItemType, PersistType> extends Abstr
// inform all regsitered filters the form is about to be persisted
if (this.filterRegistry != null)
{
for (Filter filter : this.filterRegistry.getFilters())
for (Filter<ItemType, PersistType> filter : this.filterRegistry.getFilters())
{
filter.beforePersist(typedItem, data);
}
}
// 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
if (this.filterRegistry != null)
{
for (Filter filter : this.filterRegistry.getFilters())
for (Filter<ItemType, PersistType> filter : this.filterRegistry.getFilters())
{
filter.afterPersist(typedItem, data, persistedObject);
}
@@ -135,16 +135,6 @@ public abstract class FilteredFormProcessor<ItemType, PersistType> extends Abstr
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.
* <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
* parts.
*/
protected Pattern associationNamePattern = Pattern.compile(ASSOC_DATA_PREFIX
+ "(.*){1}?_(.*){1}?(_[a-zA-Z]+)");
protected Pattern associationNamePattern = Pattern.compile(ASSOC_DATA_PREFIX + "(.*){1}?_(.*){1}?(_[a-zA-Z]+)");
/**
* Sets the node service
@@ -180,8 +179,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param form The Form instance to populate
* @param namespaceService NamespaceService instance
*/
public static void generatePropertyField(PropertyDefinition propDef, Form form,
NamespaceService namespaceService)
public static void generatePropertyField(PropertyDefinition propDef, Form form, NamespaceService 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 namespaceService NamespaceService instance
*/
public static void generatePropertyField(PropertyDefinition propDef, Form form,
Serializable propValue, NamespaceService namespaceService)
public static void generatePropertyField(PropertyDefinition propDef, Form form, Serializable propValue,
NamespaceService namespaceService)
{
generatePropertyField(propDef, form, propValue, null, namespaceService);
}
@@ -220,13 +218,13 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param namespaceService NamespaceService instance
*/
@SuppressWarnings("unchecked")
public static void generatePropertyField(PropertyDefinition propDef, Form form,
Serializable propValue, FieldGroup group, NamespaceService namespaceService)
public static 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());
PropertyFieldDefinition fieldDef = new PropertyFieldDefinition(propName, propDef.getDataType().getName()
.getLocalName());
String title = propDef.getTitle();
if (title == null)
@@ -272,14 +270,12 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
List<ConstraintDefinition> constraints = propDef.getConstraints();
if (constraints != null && constraints.size() > 0)
{
List<FieldConstraint> fieldConstraints = new ArrayList<FieldConstraint>(constraints
.size());
List<FieldConstraint> fieldConstraints = new ArrayList<FieldConstraint>(constraints.size());
for (ConstraintDefinition constraintDef : constraints)
{
Constraint constraint = constraintDef.getConstraint();
FieldConstraint fieldConstraint = new FieldConstraint(constraint.getType(),
constraint.getParameters());
FieldConstraint fieldConstraint = new FieldConstraint(constraint.getType(), constraint.getParameters());
fieldConstraints.add(fieldConstraint);
}
@@ -336,8 +332,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param namespaceService NamespaceService instance
*/
@SuppressWarnings("unchecked")
public static void generateAssociationField(AssociationDefinition assocDef, Form form,
List assocValues, NamespaceService namespaceService)
public static void generateAssociationField(AssociationDefinition assocDef, Form form, List assocValues,
NamespaceService namespaceService)
{
generateAssociationField(assocDef, form, assocValues, null, namespaceService);
}
@@ -357,13 +353,13 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param namespaceService NamespaceService instance
*/
@SuppressWarnings("unchecked")
public static void generateAssociationField(AssociationDefinition assocDef, Form form,
List assocValues, FieldGroup group, NamespaceService namespaceService)
public 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);
AssociationFieldDefinition fieldDef = new AssociationFieldDefinition(assocName, assocDef.getTargetClass()
.getName().toPrefixString(namespaceService), Direction.TARGET);
String title = assocDef.getTitle();
if (title == null)
{
@@ -437,16 +433,15 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* 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)
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);
getLogger().debug("Generating selected fields: " + fields + " and forcing: " + forcedFields);
// get data dictionary definition for node if it is provided
QName type = null;
@@ -457,8 +452,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (nodeRef != null)
{
type = this.nodeService.getType(nodeRef);
typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService
.getAspects(nodeRef));
typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
// NOTE: the anonymous type returns all property and association
// defs
@@ -547,8 +541,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (propDef != null)
{
// generate the property field
generatePropertyField(propDef, form, propValues.get(fullQName),
this.namespaceService);
generatePropertyField(propDef, form, propValues.get(fullQName), this.namespaceService);
// no need to try and find an association
tryAssociation = false;
@@ -563,11 +556,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (assocDef != null)
{
// generate the association field
generateAssociationField(
assocDef,
form,
(nodeRef != null) ? retrieveAssociationValues(nodeRef, assocDef)
: null, this.namespaceService);
generateAssociationField(assocDef, form, (nodeRef != null) ? retrieveAssociationValues(nodeRef,
assocDef) : null, this.namespaceService);
foundField = true;
}
@@ -576,16 +566,14 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
// still not found the field, is it a force'd field?
if (!foundField)
{
if (forcedFields != null && forcedFields.size() > 0
&& forcedFields.contains(fieldName))
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 "
"Ignoring field \"" + fieldName + "\" as it is not defined for the current "
+ ((nodeRef != null) ? "node" : "type")
+ " 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
// appropriate field
if (nodeRef != null
&& this.dictionaryService.isSubClass(type,
ContentModel.TYPE_CONTENT))
if (nodeRef != null && this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
{
ContentData content = (ContentData) this.nodeService.getProperty(nodeRef,
ContentModel.PROP_CONTENT);
@@ -675,11 +661,9 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
else
{
if (getLogger().isWarnEnabled())
getLogger()
.warn(
"\""
+ parts[0]
+ "\" is an invalid prefix for requesting a property or association");
getLogger().warn(
"\"" + parts[0]
+ "\" is an invalid prefix for requesting a property or association");
return;
}
@@ -743,8 +727,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
protected void generateMimetypePropertyField(ContentData content, Form form)
{
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_MIMETYPE;
PropertyFieldDefinition mimetypeField = new PropertyFieldDefinition(TRANSIENT_MIMETYPE,
DataTypeDefinition.TEXT.getLocalName());
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);
@@ -765,8 +749,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
protected void generateEncodingPropertyField(ContentData content, Form form)
{
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_ENCODING;
PropertyFieldDefinition encodingField = new PropertyFieldDefinition(TRANSIENT_ENCODING,
DataTypeDefinition.TEXT.getLocalName());
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);
@@ -787,8 +771,8 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
protected void generateSizePropertyField(ContentData content, Form form)
{
String dataKeyName = PROP_DATA_PREFIX + TRANSIENT_SIZE;
PropertyFieldDefinition sizeField = new PropertyFieldDefinition(TRANSIENT_SIZE,
DataTypeDefinition.LONG.getLocalName());
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);
@@ -818,8 +802,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
// get the list of values (if any) for the association
if (assocDef instanceof ChildAssociationDefinition)
{
assocValues = this.nodeService.getChildAssocs(nodeRef, assocDef.getName(),
RegexQNamePattern.MATCH_ALL);
assocValues = this.nodeService.getChildAssocs(nodeRef, assocDef.getName(), RegexQNamePattern.MATCH_ALL);
}
else
{
@@ -839,14 +822,12 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
{
// get the property definitions for the type of node being persisted
QName type = this.nodeService.getType(nodeRef);
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService
.getAspects(nodeRef));
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations();
Map<QName, ChildAssociationDefinition> childAssocDefs = typeDef.getChildAssociations();
Map<QName, PropertyDefinition> propDefs = typeDef.getProperties();
Map<QName, Serializable> propsToPersist = new HashMap<QName, Serializable>(data
.getNumberOfFields());
Map<QName, Serializable> propsToPersist = new HashMap<QName, Serializable>(data.getNumberOfFields());
List<AbstractAssocCommand> assocsToPersist = new ArrayList<AbstractAssocCommand>();
for (FieldData fieldData : data)
@@ -862,8 +843,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
}
else if (fieldName.startsWith(ASSOC_DATA_PREFIX))
{
processAssociationPersist(nodeRef, assocDefs, childAssocDefs, fieldData,
assocsToPersist);
processAssociationPersist(nodeRef, assocDefs, childAssocDefs, fieldData, assocsToPersist);
}
else if (getLogger().isWarnEnabled())
{
@@ -1004,8 +984,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
// everything else
// should be represented as null
if (!propDef.getDataType().getName().equals(DataTypeDefinition.TEXT)
&& !propDef.getDataType().getName().equals(
DataTypeDefinition.MLTEXT))
&& !propDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT))
{
value = null;
}
@@ -1018,8 +997,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
else if (getLogger().isWarnEnabled())
{
getLogger().warn(
"Ignoring field '" + fieldData.getName()
+ "' as a property definition can not be found");
"Ignoring field '" + fieldData.getName() + "' as a property definition can not be found");
}
}
else
@@ -1064,8 +1042,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
* @param fieldData Data to persist for the associations
* @param assocCommands List of associations to be persisted
*/
protected void processAssociationPersist(NodeRef nodeRef,
Map<QName, AssociationDefinition> assocDefs,
protected void processAssociationPersist(NodeRef nodeRef, Map<QName, AssociationDefinition> assocDefs,
Map<QName, ChildAssociationDefinition> childAssocDefs, FieldData fieldData,
List<AbstractAssocCommand> assocCommands)
{
@@ -1102,9 +1079,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
{
if (getLogger().isWarnEnabled())
{
getLogger().warn(
"Definition for association " + fullQName
+ " not recognised and not persisted.");
getLogger().warn("Definition for association " + fullQName + " not recognised and not persisted.");
}
return;
}
@@ -1125,26 +1100,25 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
{
if (assocDef.isChild())
{
assocCommands.add(new AddChildAssocCommand(nodeRef, new NodeRef(
nextTargetNode), fullQName));
assocCommands.add(new AddChildAssocCommand(nodeRef, new NodeRef(nextTargetNode),
fullQName));
}
else
{
assocCommands.add(new AddAssocCommand(nodeRef, new NodeRef(
nextTargetNode), fullQName));
assocCommands.add(new AddAssocCommand(nodeRef, new NodeRef(nextTargetNode), fullQName));
}
}
else if (assocSuffix.equals(ASSOC_DATA_REMOVED_SUFFIX))
{
if (assocDef.isChild())
{
assocCommands.add(new RemoveChildAssocCommand(nodeRef, new NodeRef(
nextTargetNode), fullQName));
assocCommands.add(new RemoveChildAssocCommand(nodeRef, new NodeRef(nextTargetNode),
fullQName));
}
else
{
assocCommands.add(new RemoveAssocCommand(nodeRef, new NodeRef(
nextTargetNode), fullQName));
assocCommands.add(new RemoveAssocCommand(nodeRef, new NodeRef(nextTargetNode),
fullQName));
}
}
else
@@ -1153,10 +1127,9 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
{
StringBuilder msg = new StringBuilder();
msg.append("fieldName ").append(fieldName).append(
" does not have one of the expected suffixes [")
.append(ASSOC_DATA_ADDED_SUFFIX).append(", ").append(
ASSOC_DATA_REMOVED_SUFFIX).append(
"] and has been ignored.");
" does not have one of the expected suffixes [").append(
ASSOC_DATA_ADDED_SUFFIX).append(", ").append(ASSOC_DATA_REMOVED_SUFFIX)
.append("] and has been ignored.");
getLogger().warn(msg.toString());
}
}
@@ -1215,8 +1188,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (contentData == null)
{
// content data has not been persisted yet so get it from the node
contentData = (ContentData) this.nodeService.getProperty(nodeRef,
ContentModel.PROP_CONTENT);
contentData = (ContentData) this.nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
}
if (contentData != null)
@@ -1241,8 +1213,7 @@ public abstract class ContentModelFormProcessor<ItemType, PersistType> extends
if (contentData == null)
{
// content data has not been persisted yet so get it from the node
contentData = (ContentData) this.nodeService.getProperty(nodeRef,
ContentModel.PROP_CONTENT);
contentData = (ContentData) this.nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
}
if (contentData != null)
@@ -1300,8 +1271,7 @@ class AddAssocCommand extends AbstractAssocCommand
@Override
protected void updateAssociations(NodeService nodeService)
{
List<AssociationRef> existingAssocs = nodeService
.getTargetAssocs(sourceNodeRef, assocQName);
List<AssociationRef> existingAssocs = nodeService.getTargetAssocs(sourceNodeRef, assocQName);
for (AssociationRef assoc : existingAssocs)
{
if (assoc.getTargetRef().equals(targetNodeRef))
@@ -1334,8 +1304,7 @@ class RemoveAssocCommand extends AbstractAssocCommand
@Override
protected void updateAssociations(NodeService nodeService)
{
List<AssociationRef> existingAssocs = nodeService
.getTargetAssocs(sourceNodeRef, assocQName);
List<AssociationRef> existingAssocs = nodeService.getTargetAssocs(sourceNodeRef, assocQName);
boolean assocDoesNotExist = true;
for (AssociationRef assoc : existingAssocs)
{
@@ -1350,8 +1319,8 @@ class RemoveAssocCommand extends AbstractAssocCommand
if (logger.isWarnEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Attempt to remove non-existent association prevented. ").append(
sourceNodeRef).append("|").append(targetNodeRef).append(assocQName);
msg.append("Attempt to remove non-existent association prevented. ").append(sourceNodeRef).append("|")
.append(targetNodeRef).append(assocQName);
logger.warn(msg.toString());
}
return;
@@ -1432,8 +1401,8 @@ class RemoveChildAssocCommand extends AbstractAssocCommand
if (logger.isWarnEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Attempt to remove non-existent child association prevented. ").append(
sourceNodeRef).append("|").append(targetNodeRef).append(assocQName);
msg.append("Attempt to remove non-existent child association prevented. ").append(sourceNodeRef)
.append("|").append(targetNodeRef).append(assocQName);
logger.warn(msg.toString());
}
return;

View File

@@ -95,21 +95,19 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
{
// ignored for now, dealt with below
if (logger.isDebugEnabled())
logger.debug("NodeRef creation failed for: " + item.getId(), iae);
if (logger.isDebugEnabled()) logger.debug("NodeRef creation failed for: " + item.getId(), iae);
}
}
}
// check we have a valid node ref
if (nodeRef == null) { throw new FormNotFoundException(item, new IllegalArgumentException(
item.getId())); }
if (nodeRef == null) { throw new FormNotFoundException(item, new IllegalArgumentException(item.getId())); }
// check the node itself exists
if (this.nodeService.exists(nodeRef) == false)
{
throw new FormNotFoundException(item, new InvalidNodeRefException(
"Node does not exist: " + nodeRef, nodeRef));
throw new FormNotFoundException(item, new InvalidNodeRefException("Node does not exist: " + nodeRef,
nodeRef));
}
else
{
@@ -125,8 +123,8 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
* 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)
protected void internalGenerate(NodeRef item, List<String> fields, List<String> forcedFields, Form form,
Map<String, Object> context)
{
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 form The Form instance to populate
*/
protected void generateNode(NodeRef nodeRef, List<String> fields, List<String> forcedFields,
Form form)
protected void generateNode(NodeRef nodeRef, List<String> fields, List<String> forcedFields, Form form)
{
// set the type and URL of the item
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/");
builder.append(nodeRef.getStoreRef().getProtocol()).append("/");
builder.append(nodeRef.getStoreRef().getIdentifier()).append("/");
builder.append(nodeRef.getId());
form.getItem().setUrl(builder.toString());
setFormItemUrl(form, builder.toString());
if (fields != null && fields.size() > 0)
{
@@ -179,8 +177,7 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
{
// get data dictionary definition for node
QName type = this.nodeService.getType(nodeRef);
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService
.getAspects(nodeRef));
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
// iterate round the property definitions for the node and create
// 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);
for (PropertyDefinition propDef : propDefs.values())
{
generatePropertyField(propDef, form, propValues.get(propDef.getName()),
this.namespaceService);
generatePropertyField(propDef, form, propValues.get(propDef.getName()), this.namespaceService);
}
}
@@ -203,8 +199,7 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
{
// get data dictionary definition for the node
QName type = this.nodeService.getType(nodeRef);
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService
.getAspects(nodeRef));
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
// iterate round the association defintions and setup field definition
Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations();
@@ -229,8 +224,7 @@ public class NodeFormProcessor extends ContentModelFormProcessor<NodeRef, NodeRe
QName type = this.nodeService.getType(nodeRef);
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
{
ContentData content = (ContentData) this.nodeService.getProperty(nodeRef,
ContentModel.PROP_CONTENT);
ContentData content = (ContentData) this.nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
if (content != null)
{
// 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
*
*/
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:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.service.cmr.dictionary;
import java.util.List;
@@ -34,7 +35,7 @@ import org.alfresco.service.namespace.QName;
*
* @author David Caruana
*/
public interface PropertyDefinition
public interface PropertyDefinition extends ClassAttributeDefinition
{
/**
* @return defining model
@@ -74,47 +75,50 @@ public interface PropertyDefinition
public boolean isOverride();
/**
* @return true => multi-valued, false => single-valued
* @return true => multi-valued, false => single-valued
*/
public boolean isMultiValued();
/**
* @return true => mandatory, false => optional
* @return true => mandatory, false => optional
*/
public boolean isMandatory();
/**
* @return Returns true if the system enforces the presence of
* {@link #isMandatory() mandatory} properties, or false if the system
* just marks objects that don't have all mandatory properties present.
* {@link #isMandatory() mandatory} properties, or false if the
* system just marks objects that don't have all mandatory
* properties present.
*/
public boolean isMandatoryEnforced();
/**
* @return true => system maintained, false => client may maintain
* @return true => system maintained, false => client may maintain
*/
public boolean isProtected();
/**
* @return true => indexed, false => not indexed
* @return true => indexed, false => not indexed
*/
public boolean isIndexed();
/**
* @return true => stored in index
* @return true => stored in index
*/
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();
/**
* All non atomic properties will be indexed at the same time.
*
* @return true => The attribute must be indexed in the commit of the transaction.
* false => the indexing will be done in the background and may be out of date.
* @return true => The attribute must be indexed in the commit of the
* transaction. false => the indexing will be done in the background
* and may be out of date.
*/
public boolean isIndexedAtomically();