Updates to data dictionary constraints

- Added getType and getParameters methods to Constraint interface
  - Updated existing constraint implementations
Updates to FormService
  - Implemented regex pattern match for selecting appropriate form processor
  - Added constraints to Form object constructed in NodeHandler

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@12396 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gavin Cornwell
2008-12-15 21:18:51 +00:00
parent 6bda204c4d
commit e04da90fac
14 changed files with 257 additions and 30 deletions

View File

@@ -41,6 +41,14 @@ public abstract class AbstractConstraint implements Constraint
public static final String ERR_PROP_NOT_SET = "d_dictionary.constraint.err.property_not_set";
public static final String ERR_EVALUATE_EXCEPTION = "d_dictionary.constraint.err.evaluate_exception";
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getType()
*/
public String getType()
{
return this.getClass().getName();
}
/**
* Check that the given value is not <tt>null</tt>.
*

View File

@@ -24,6 +24,8 @@
*/
package org.alfresco.repo.dictionary.constraint;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
@@ -56,9 +58,19 @@ public class AuthorityNameConstraint extends AbstractConstraint
}
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#initialize()
*/
public void initialize()
{
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getParameters()
*/
public Map<String, Object> getParameters()
{
return null;
}
}

View File

@@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase;
@@ -63,7 +64,12 @@ public class ConstraintsTest extends TestCase
{
DummyConstraint constraint = new DummyConstraint();
constraint.initialize();
assertEquals("DummyConstraint type should be 'org.alfresco.repo.dictionary.constraint.ConstraintsTest$DummyConstraint'",
"org.alfresco.repo.dictionary.constraint.ConstraintsTest$DummyConstraint",
constraint.getType());
assertNull("DummyConstraint should not have parameters", constraint.getParameters());
List<Object> dummyObjects = new ArrayList<Object>(3);
dummyObjects.add("ABC"); // correct
dummyObjects.add("DEF"); // correct
@@ -150,6 +156,15 @@ public class ConstraintsTest extends TestCase
constraint.setMinLength(3);
constraint.setMaxLength(6);
assertEquals("StringLengthConstraint type should be 'LENGTH'",
"LENGTH", constraint.getType());
assertNotNull("StringLengthConstraint should have parameters", constraint.getParameters());
assertEquals("StringLengthConstraint should have 2 parameters", 2, constraint.getParameters().size());
assertEquals("minLength should be 3", 3,
constraint.getParameters().get("minLength"));
assertEquals("maxLength should be 6", 6,
constraint.getParameters().get("maxLength"));
evaluate(constraint, "abc", false);
evaluate(constraint, "abcdef", false);
evaluate(constraint, Arrays.asList("abc", "abcdef"), false);
@@ -158,6 +173,7 @@ public class ConstraintsTest extends TestCase
evaluate(constraint, Arrays.asList("abc", "abcdefg"), true);
}
@SuppressWarnings("unchecked")
public void testListOfValuesConstraint() throws Exception
{
ListOfValuesConstraint constraint = new ListOfValuesConstraint();
@@ -173,6 +189,18 @@ public class ConstraintsTest extends TestCase
List<String> allowedValues = Arrays.asList(new String[] {"abc", "def", "ghi"});
constraint.setAllowedValues(allowedValues);
assertEquals("ListOfValuesConstraint type should be 'LIST'",
"LIST", constraint.getType());
assertNotNull("ListOfValuesConstraint should have parameters", constraint.getParameters());
assertEquals("ListOfValuesConstraint should have 2 parameters", 2, constraint.getParameters().size());
assertEquals("caseSensitive should be true", Boolean.TRUE,
constraint.getParameters().get("caseSensitive"));
List<String> allowedValuesParam = (List<String>)constraint.getParameters().get("allowedValues");
assertEquals("Should be 3 allowable values", 3, allowedValuesParam.size());
assertEquals("First allowable value should be 'abc'", "abc", allowedValuesParam.get(0));
assertEquals("First allowable value should be 'def'", "def", allowedValuesParam.get(1));
assertEquals("First allowable value should be 'ghi'", "ghi", allowedValuesParam.get(2));
evaluate(constraint, "def", false);
evaluate(constraint, "DEF", true);
evaluate(constraint, Arrays.asList("abc", "def"), false);
@@ -180,6 +208,8 @@ public class ConstraintsTest extends TestCase
// now make it case-insensitive
constraint.setCaseSensitive(false);
assertEquals("caseSensitive should be false", Boolean.FALSE,
constraint.getParameters().get("caseSensitive"));
evaluate(constraint, "DEF", false);
evaluate(constraint, Arrays.asList("abc", "DEF"), false);
}
@@ -189,6 +219,11 @@ public class ConstraintsTest extends TestCase
NumericRangeConstraint constraint = new NumericRangeConstraint();
constraint.initialize();
assertEquals("NumericRangeConstraint type should be 'MINMAX'",
"MINMAX", constraint.getType());
assertNotNull("NumericRangeConstraint should have parameters", constraint.getParameters());
assertEquals("NumericRangeConstraint should have 2 parameters", 2, constraint.getParameters().size());
// check that Double.MIN_VALUE and Double.MAX_VALUE are allowed by default
constraint.evaluate(Double.MIN_VALUE);
constraint.evaluate(Double.MAX_VALUE);
@@ -201,6 +236,9 @@ public class ConstraintsTest extends TestCase
constraint.setMaxValue(+5.0D);
constraint.initialize();
assertEquals("minValue should be -5", -5.0D, constraint.getParameters().get("minValue"));
assertEquals("maxValue should be 5", 5.0D, constraint.getParameters().get("maxValue"));
evaluate(constraint, "-1.0", false);
evaluate(constraint, "+1.0", false);
evaluate(constraint, Arrays.asList(-1, 0, 1), false);
@@ -216,6 +254,15 @@ public class ConstraintsTest extends TestCase
constraint.setRequiresMatch(true);
constraint.initialize();
assertEquals("RegexConstraint type should be 'REGEX'",
"REGEX", constraint.getType());
assertNotNull("RegexConstraint should have parameters", constraint.getParameters());
assertEquals("RegexConstraint should have 2 parameters", 2, constraint.getParameters().size());
assertEquals("requiresMatch should be true", Boolean.TRUE,
constraint.getParameters().get("requiresMatch"));
assertEquals("expression should be [A-Z]*", "[A-Z]*",
constraint.getParameters().get("expression"));
// do some successful stuff
evaluate(constraint, "ABC", false);
evaluate(constraint, "DEF", false);
@@ -231,6 +278,8 @@ public class ConstraintsTest extends TestCase
// now switch the requiresMatch around
constraint.setRequiresMatch(false);
constraint.initialize();
assertEquals("requiresMatch should be false", Boolean.FALSE,
constraint.getParameters().get("requiresMatch"));
evaluate(constraint, DummyEnum.abc, false);
}
@@ -269,7 +318,10 @@ public class ConstraintsTest extends TestCase
private class DummyConstraint extends AbstractConstraint
{
private List<Object> tested;
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#initialize()
*/
public void initialize()
{
tested = new ArrayList<Object>(4);
@@ -296,5 +348,13 @@ public class ConstraintsTest extends TestCase
throw new ConstraintException("Non-String value");
}
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getParameters()
*/
public Map<String, Object> getParameters()
{
return null;
}
}
}

View File

@@ -26,7 +26,9 @@ package org.alfresco.repo.dictionary.constraint;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.dictionary.DictionaryException;
@@ -57,6 +59,15 @@ public class ListOfValuesConstraint extends AbstractConstraint
caseSensitive = true;
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getType()
*/
@Override
public String getType()
{
return "LIST";
}
@Override
public String toString()
{
@@ -157,4 +168,17 @@ public class ListOfValuesConstraint extends AbstractConstraint
}
}
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getParameters()
*/
public Map<String, Object> getParameters()
{
Map<String, Object> params = new HashMap<String, Object>(2);
params.put("caseSensitive", this.caseSensitive);
params.put("allowedValues", this.allowedValues);
return params;
}
}

View File

@@ -24,6 +24,9 @@
*/
package org.alfresco.repo.dictionary.constraint;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
@@ -49,6 +52,15 @@ public class NumericRangeConstraint extends AbstractConstraint
private double minValue = Double.MIN_VALUE;
private double maxValue = Double.MAX_VALUE;
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getType()
*/
@Override
public String getType()
{
return "MINMAX";
}
@Override
public String toString()
@@ -107,10 +119,16 @@ public class NumericRangeConstraint extends AbstractConstraint
this.maxValue = maxValue;
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#initialize()
*/
public void initialize()
{
}
/*
* @see org.alfresco.repo.dictionary.constraint.AbstractConstraint#evaluateSingleValue(java.lang.Object)
*/
protected void evaluateSingleValue(Object value)
{
// ensure that the value can be converted to a double
@@ -136,4 +154,17 @@ public class NumericRangeConstraint extends AbstractConstraint
throw new ConstraintException(ERR_OUT_OF_RANGE, checkValue, minValue, maxValue);
}
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getParameters()
*/
public Map<String, Object> getParameters()
{
Map<String, Object> params = new HashMap<String, Object>(2);
params.put("minValue", this.minValue);
params.put("maxValue", this.maxValue);
return params;
}
}

View File

@@ -24,6 +24,8 @@
*/
package org.alfresco.repo.dictionary.constraint;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -54,6 +56,14 @@ public class RegexConstraint extends AbstractConstraint
private Pattern patternMatcher;
private boolean requiresMatch = true;
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getType()
*/
public String getType()
{
return "REGEX";
}
@Override
public String toString()
{
@@ -127,4 +137,14 @@ public class RegexConstraint extends AbstractConstraint
}
}
}
public Map<String, Object> getParameters()
{
Map<String, Object> params = new HashMap<String, Object>(2);
params.put("expression", this.expression);
params.put("requiresMatch", this.requiresMatch);
return params;
}
}

View File

@@ -24,6 +24,9 @@
*/
package org.alfresco.repo.dictionary.constraint;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
@@ -47,6 +50,15 @@ public class StringLengthConstraint extends AbstractConstraint
private int minLength = 0;
private int maxLength = Integer.MAX_VALUE;
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getType()
*/
@Override
public String getType()
{
return "LENGTH";
}
@Override
public String toString()
{
@@ -132,4 +144,17 @@ public class StringLengthConstraint extends AbstractConstraint
throw new ConstraintException(ERR_INVALID_LENGTH, checkValue, minLength, maxLength);
}
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getParameters()
*/
public Map<String, Object> getParameters()
{
Map<String, Object> params = new HashMap<String, Object>(2);
params.put("minLength", this.minLength);
params.put("maxLength", this.maxLength);
return params;
}
}

View File

@@ -24,6 +24,8 @@
*/
package org.alfresco.repo.dictionary.constraint;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
@@ -61,9 +63,19 @@ public class UserNameConstraint extends AbstractConstraint
}
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#initialize()
*/
public void initialize()
{
}
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getParameters()
*/
public Map<String, Object> getParameters()
{
return null;
}
}

View File

@@ -32,9 +32,12 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.forms.AssociationFieldDefinition.Direction;
import org.alfresco.repo.forms.PropertyFieldDefinition.FieldConstraint;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
@@ -149,7 +152,7 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
setComplete();
endTransaction();
}
public void testGetForm() throws Exception
{
Form form = this.formService.getForm(this.document.toString());
@@ -228,18 +231,16 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
assertTrue("Expecting cm:name to be mandatory", nameField.isMandatory());
assertFalse("Expecting cm:name to be single valued", nameField.isRepeating());
// TODO: get the constraint for the name field and check
/*
// get the constraint for the name field and check
List<FieldConstraint> constraints = nameField.getConstraints();
assertEquals("Expecting 1 constraint for cm:name", constraints.size());
assertEquals("Expecting 1 constraint for cm:name", 1, constraints.size());
FieldConstraint constraint = constraints.get(0);
assertEquals("Expecting name of constraint to be 'REGEX'", "REGEX", constraint.getName());
assertEquals("Expecting name of constraint to be 'REGEX'", "REGEX", constraint.getType());
Map<String, String> params = constraint.getParams();
assertNotNull("Expecting constraint parameters", params);
assertEquals("Expecting 2 constraint parameters", 2, params.size());
assertNotNull("Expecting an 'expression' constraint parameter", params.get("expression"));
assertNotNull("Expecting an 'requiresMatch' constraint parameter", params.get("requiresMatch"));
*/
// check details of the addressees field
assertEquals("Expecting cm:addressees type to be d:text", "d:text", addresseesField.getDataType());

View File

@@ -151,30 +151,30 @@ public class PropertyFieldDefinition extends FieldDefinition
*/
public class FieldConstraint
{
protected String name;
protected String type;
protected Map<String, String> params;
/**
* Constructs a FieldConstraint
*
* @param name The name of the constraint
* @param type The type of the constraint
* @param params Map of parameters for the constraint
*/
public FieldConstraint(String name, Map<String, String> params)
public FieldConstraint(String type, Map<String, String> params)
{
super();
this.name = name;
this.type = type;
this.params = params;
}
/**
* Returns the name of the constraint
* Returns the type of the constraint
*
* @return The constraint name
* @return The constraint type
*/
public String getName()
public String getType()
{
return this.name;
return this.type;
}
/**

View File

@@ -24,6 +24,9 @@
*/
package org.alfresco.repo.forms.processor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -40,6 +43,7 @@ public abstract class AbstractFormProcessor implements FormProcessor
protected FormProcessorRegistry processorRegistry;
protected String matchPattern;
protected boolean active = true;
protected Pattern patternMatcher;
/**
* Sets the form process registry
@@ -91,6 +95,11 @@ public abstract class AbstractFormProcessor implements FormProcessor
return;
}
else
{
// setup pattern matcher
this.patternMatcher = Pattern.compile(this.matchPattern);
}
// register this instance
this.processorRegistry.addProcessor(this);
@@ -109,12 +118,16 @@ public abstract class AbstractFormProcessor implements FormProcessor
*/
public boolean isApplicable(String item)
{
// TODO: do a regular expression match on the pattern supplied to
// determine if the processor matches
// this form processor matches if the match pattern provided matches
// the item provided
// NOTE: For now just return true as there is only going to be one
// form processor instance
return true;
Matcher matcher = patternMatcher.matcher(item);
boolean matches = matcher.matches();
if (logger.isDebugEnabled())
logger.debug("Checking processor " + this + " for applicability for item '" + item + "', result = " + matches);
return matches;
}
/*

View File

@@ -178,16 +178,20 @@ public class NodeHandler extends AbstractHandler
for (ConstraintDefinition constraintDef : constraints)
{
// TODO: We need to define a common interface for all constraints
// so that we can determine the name and parameters without
// having to know all the implementations
/*
Constraint constraint = constraintDef.getConstraint();
FieldConstraint fieldConstraint = fieldDef.new FieldConstraint(constraint.toString(),
new HashMap<String,String>());
Map<String, String> fieldConstraintParams = null;
Map<String, Object> constraintParams = constraint.getParameters();
if (constraintParams != null)
{
fieldConstraintParams = new HashMap<String, String>(constraintParams.size());
for (String name : constraintParams.keySet())
{
fieldConstraintParams.put(name, constraintParams.get(name).toString());
}
}
FieldConstraint fieldConstraint = fieldDef.new FieldConstraint(
constraint.getType(), fieldConstraintParams);
fieldConstraints.add(fieldConstraint);
*/
}
fieldDef.setConstraints(fieldConstraints);

View File

@@ -24,6 +24,8 @@
*/
package org.alfresco.service.cmr.dictionary;
import java.util.Map;
/**
* The interface for classes that implement constraints on property values.
@@ -43,6 +45,21 @@ package org.alfresco.service.cmr.dictionary;
*/
public interface Constraint
{
/**
* Returns the 'type' of the constraint, this is the identifier given to
* constraint in the configuration.
*
* @return The type
*/
public String getType();
/**
* Returns the parameters passed to the instance of the constraint.
*
* @return Map of parameters, null if there are no parameters
*/
public Map<String, Object> getParameters();
/**
* Initializes the constraint with appropriate values, which will depend
* on the implementation itself. This method can be implemented as a