mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Further constraints
- MINMAX (NumericRangeConstraint) - LENGTH (StringLengthConstraint) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2622 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -23,4 +23,14 @@ d_dictionary.property.err.cannot_relax_mandatory=Cannot relax mandatory attribut
|
|||||||
d_dictionary.property.err.cannot_relax_mandatory_enforcement=Cannot relax mandatory attribute enforcement of property ''{0}
|
d_dictionary.property.err.cannot_relax_mandatory_enforcement=Cannot relax mandatory attribute enforcement of property ''{0}
|
||||||
|
|
||||||
d_dictionary.constraint.regex.no_match=Value ''{0}'' does not match regular expression: {1}
|
d_dictionary.constraint.regex.no_match=Value ''{0}'' does not match regular expression: {1}
|
||||||
d_dictionary.constraint.regex.match=Value ''{0}'' matches regular expression: {1}
|
d_dictionary.constraint.regex.match=Value ''{0}'' matches regular expression: {1}
|
||||||
|
|
||||||
|
d_dictionary.constraint.numeric_range.invalid_min_value=Invalid ''minValue'' property: {0}
|
||||||
|
d_dictionary.constraint.numeric_range.invalid_max_value=Invalid ''maxValue'' property: {0}
|
||||||
|
d_dictionary.constraint.numeric_range.non_numeric=Property value could not be converted to a double: {0}
|
||||||
|
d_dictionary.constraint.numeric_range.out_of_range=Numeric value ''{0}'' is not in range [{1}; {2}]
|
||||||
|
|
||||||
|
d_dictionary.constraint.string_length.invalid_min_length=Invalid ''minLength'' property: {0}
|
||||||
|
d_dictionary.constraint.string_length.invalid_max_length=Invalid ''maxLength'' property: {0}
|
||||||
|
d_dictionary.constraint.string_length.non_string=Property value could not be converted to a String: {0}
|
||||||
|
d_dictionary.constraint.string_length.invalid_length=String length of ''{0}'' is not in range [{1}; {2}]
|
||||||
|
@@ -133,7 +133,7 @@ public class DictionaryDAOTest extends TestCase
|
|||||||
PropertyDefinition propDef = service.getProperty(prop1QName);
|
PropertyDefinition propDef = service.getProperty(prop1QName);
|
||||||
List<ConstraintDefinition> constraints = propDef.getConstraints();
|
List<ConstraintDefinition> constraints = propDef.getConstraints();
|
||||||
assertNotNull("Null constraints list", constraints);
|
assertNotNull("Null constraints list", constraints);
|
||||||
assertEquals("Incorrect number of constraints", 1, constraints.size());
|
assertEquals("Incorrect number of constraints", 2, constraints.size());
|
||||||
|
|
||||||
// check the individual constraints
|
// check the individual constraints
|
||||||
ConstraintDefinition constraintDef = constraints.get(0);
|
ConstraintDefinition constraintDef = constraints.get(0);
|
||||||
|
@@ -18,7 +18,9 @@ package org.alfresco.repo.dictionary;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.repo.dictionary.constraint.NumericRangeConstraint;
|
||||||
import org.alfresco.repo.dictionary.constraint.RegexConstraint;
|
import org.alfresco.repo.dictionary.constraint.RegexConstraint;
|
||||||
|
import org.alfresco.repo.dictionary.constraint.StringLengthConstraint;
|
||||||
import org.alfresco.service.cmr.dictionary.Constraint;
|
import org.alfresco.service.cmr.dictionary.Constraint;
|
||||||
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
@@ -226,6 +228,22 @@ import org.springframework.beans.TypeMismatchException;
|
|||||||
{
|
{
|
||||||
return new RegexConstraint();
|
return new RegexConstraint();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
MINMAX
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected Constraint newInstance()
|
||||||
|
{
|
||||||
|
return new NumericRangeConstraint();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
LENGTH
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected Constraint newInstance()
|
||||||
|
{
|
||||||
|
return new StringLengthConstraint();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -21,6 +21,7 @@ import java.util.Collection;
|
|||||||
import org.alfresco.service.cmr.dictionary.Constraint;
|
import org.alfresco.service.cmr.dictionary.Constraint;
|
||||||
import org.alfresco.service.cmr.dictionary.ConstraintException;
|
import org.alfresco.service.cmr.dictionary.ConstraintException;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base services for constraints.
|
* Base services for constraints.
|
||||||
@@ -39,12 +40,17 @@ public abstract class AbstractConstraint implements Constraint
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final void evaluate(Object value)
|
public final void evaluate(Object value)
|
||||||
{
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
// null values are never evaluated
|
||||||
|
return;
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// check for collection
|
// ensure that we can handle collections
|
||||||
if (value instanceof Collection)
|
if (DefaultTypeConverter.INSTANCE.isMultiValued(value))
|
||||||
{
|
{
|
||||||
Collection collection = (Collection) value;
|
Collection collection = DefaultTypeConverter.INSTANCE.getCollection(Object.class, value);
|
||||||
evaluateCollection(collection);
|
evaluateCollection(collection);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -75,13 +81,18 @@ public abstract class AbstractConstraint implements Constraint
|
|||||||
{
|
{
|
||||||
for (Object value : collection)
|
for (Object value : collection)
|
||||||
{
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
// contract states that it will always pass
|
||||||
|
continue;
|
||||||
|
}
|
||||||
evaluateSingleValue(value);
|
evaluateSingleValue(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for evaluation of properties. The value passed in will never be a
|
* Support for evaluation of properties. The value passed in will never be a
|
||||||
* collection.
|
* <tt>Collection</tt> and will never be <tt>null</tt>.
|
||||||
*
|
*
|
||||||
* @throws ConstraintException throw this when the evaluation fails
|
* @throws ConstraintException throw this when the evaluation fails
|
||||||
*/
|
*/
|
||||||
|
@@ -17,13 +17,16 @@
|
|||||||
package org.alfresco.repo.dictionary.constraint;
|
package org.alfresco.repo.dictionary.constraint;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.alfresco.i18n.I18NUtil;
|
import org.alfresco.i18n.I18NUtil;
|
||||||
import org.alfresco.repo.dictionary.DictionaryDAOTest;
|
import org.alfresco.repo.dictionary.DictionaryDAOTest;
|
||||||
|
import org.alfresco.service.cmr.dictionary.Constraint;
|
||||||
import org.alfresco.service.cmr.dictionary.ConstraintException;
|
import org.alfresco.service.cmr.dictionary.ConstraintException;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>This file must be saved using UTF-8.</b>
|
* <b>This file must be saved using UTF-8.</b>
|
||||||
@@ -63,11 +66,113 @@ public class ConstraintsTest extends TestCase
|
|||||||
catch (ConstraintException e)
|
catch (ConstraintException e)
|
||||||
{
|
{
|
||||||
// expected
|
// expected
|
||||||
|
checkI18NofExceptionMessage(e);
|
||||||
}
|
}
|
||||||
// check that the two strings were properly dealt with
|
// check that the two strings were properly dealt with
|
||||||
assertEquals("String values not checked", 2, constraint.tested.size());
|
assertEquals("String values not checked", 2, constraint.tested.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testNull() throws Exception
|
||||||
|
{
|
||||||
|
DummyConstraint constraint = new DummyConstraint();
|
||||||
|
constraint.initialize();
|
||||||
|
|
||||||
|
// a null always passes
|
||||||
|
constraint.evaluate(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkI18NofExceptionMessage(Throwable e)
|
||||||
|
{
|
||||||
|
String msg = e.getMessage();
|
||||||
|
assertFalse("I18N of constraint message failed", msg.startsWith("d_dictionary.constraint"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void evaluate(Constraint constraint, Object value, boolean expectFailure) throws Exception
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
constraint.evaluate(value);
|
||||||
|
if (expectFailure)
|
||||||
|
{
|
||||||
|
// it should have failed
|
||||||
|
fail("Failure did not occur: \n" +
|
||||||
|
" constraint: " + constraint + "\n" +
|
||||||
|
" value: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ConstraintException e)
|
||||||
|
{
|
||||||
|
// check if we expect an error
|
||||||
|
if (expectFailure)
|
||||||
|
{
|
||||||
|
// expected - check message I18N
|
||||||
|
checkI18NofExceptionMessage(e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// didn't expect it
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStringLengthConstraint() throws Exception
|
||||||
|
{
|
||||||
|
StringLengthConstraint constraint = new StringLengthConstraint();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
constraint.setMinLength(-1);
|
||||||
|
}
|
||||||
|
catch (DictionaryException e)
|
||||||
|
{
|
||||||
|
// expected
|
||||||
|
checkI18NofExceptionMessage(e);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
constraint.setMaxLength(-1);
|
||||||
|
}
|
||||||
|
catch (DictionaryException e)
|
||||||
|
{
|
||||||
|
// expected
|
||||||
|
checkI18NofExceptionMessage(e);
|
||||||
|
}
|
||||||
|
constraint.setMinLength(3);
|
||||||
|
constraint.setMaxLength(6);
|
||||||
|
|
||||||
|
evaluate(constraint, "abc", false);
|
||||||
|
evaluate(constraint, "abcdef", false);
|
||||||
|
evaluate(constraint, Arrays.asList("abc", "abcdef"), false);
|
||||||
|
evaluate(constraint, "ab", true);
|
||||||
|
evaluate(constraint, "abcdefg", true);
|
||||||
|
evaluate(constraint, Arrays.asList("abc", "abcdefg"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNumericRangeConstraint() throws Exception
|
||||||
|
{
|
||||||
|
NumericRangeConstraint constraint = new NumericRangeConstraint();
|
||||||
|
constraint.initialize();
|
||||||
|
|
||||||
|
// check that Double.MIN_VALUE and Double.MAX_VALUE are allowed by default
|
||||||
|
constraint.evaluate(Double.MIN_VALUE);
|
||||||
|
constraint.evaluate(Double.MAX_VALUE);
|
||||||
|
|
||||||
|
// check that Double.NaN is not allowed by default
|
||||||
|
evaluate(constraint, Double.NaN, true);
|
||||||
|
|
||||||
|
// set some limits and check
|
||||||
|
constraint.setMinValue(-5.0D);
|
||||||
|
constraint.setMaxValue(+5.0D);
|
||||||
|
constraint.initialize();
|
||||||
|
|
||||||
|
evaluate(constraint, "-1.0", false);
|
||||||
|
evaluate(constraint, "+1.0", false);
|
||||||
|
evaluate(constraint, Arrays.asList(-1, 0, 1), false);
|
||||||
|
evaluate(constraint, "abc", true);
|
||||||
|
evaluate(constraint, 56.453E4, true);
|
||||||
|
evaluate(constraint, Arrays.asList(-1, 6), true);
|
||||||
|
}
|
||||||
|
|
||||||
public void testRegexConstraint() throws Exception
|
public void testRegexConstraint() throws Exception
|
||||||
{
|
{
|
||||||
RegexConstraint constraint = new RegexConstraint();
|
RegexConstraint constraint = new RegexConstraint();
|
||||||
@@ -76,38 +181,22 @@ public class ConstraintsTest extends TestCase
|
|||||||
constraint.initialize();
|
constraint.initialize();
|
||||||
|
|
||||||
// do some successful stuff
|
// do some successful stuff
|
||||||
constraint.evaluate("ABC");
|
evaluate(constraint, "ABC", false);
|
||||||
constraint.evaluate("DEF");
|
evaluate(constraint, "DEF", false);
|
||||||
|
|
||||||
// now some failures
|
// now some failures
|
||||||
try
|
evaluate(constraint, "abc", true);
|
||||||
{
|
|
||||||
constraint.evaluate("abc");
|
|
||||||
fail("Regular expression evaluation should have failed: abc");
|
|
||||||
}
|
|
||||||
catch (ConstraintException e)
|
|
||||||
{
|
|
||||||
String msg = e.getMessage();
|
|
||||||
assertFalse("I18N of constraint message failed", msg.startsWith("d_dictionary.constraint"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// now a case of passing in an object that could be a string
|
// now a case of passing in an object that could be a string
|
||||||
constraint.evaluate(DummyEnum.ABC);
|
evaluate(constraint, DummyEnum.ABC, false);
|
||||||
constraint.evaluate(DummyEnum.DEF);
|
evaluate(constraint, DummyEnum.DEF, false);
|
||||||
try
|
evaluate(constraint, DummyEnum.abc, true);
|
||||||
{
|
|
||||||
constraint.evaluate(DummyEnum.abc);
|
|
||||||
fail("Regular expression evaluation should have failed for enum: " + DummyEnum.abc);
|
|
||||||
}
|
|
||||||
catch (ConstraintException e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// now switch the requiresMatch around
|
// now switch the requiresMatch around
|
||||||
constraint.setRequiresMatch(false);
|
constraint.setRequiresMatch(false);
|
||||||
constraint.initialize();
|
constraint.initialize();
|
||||||
|
|
||||||
constraint.evaluate(DummyEnum.abc);
|
evaluate(constraint, DummyEnum.abc, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRegexConstraintFilename() throws Exception
|
public void testRegexConstraintFilename() throws Exception
|
||||||
@@ -125,30 +214,12 @@ public class ConstraintsTest extends TestCase
|
|||||||
for (int i = 0; i < invalidChars.length(); i++)
|
for (int i = 0; i < invalidChars.length(); i++)
|
||||||
{
|
{
|
||||||
String invalidStr = invalidChars.substring(i, i+1);
|
String invalidStr = invalidChars.substring(i, i+1);
|
||||||
try
|
evaluate(constraint, invalidStr, true);
|
||||||
{
|
|
||||||
constraint.evaluate(invalidStr);
|
|
||||||
fail("Regex constraint failed to detect illegal characters: \n" +
|
|
||||||
" constraint: " + constraint + "\n" +
|
|
||||||
" invalid string: " + invalidStr);
|
|
||||||
}
|
|
||||||
catch (ConstraintException e)
|
|
||||||
{
|
|
||||||
// expected
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// check a bogus filename
|
// check a bogus filename
|
||||||
try
|
evaluate(constraint, "Bogus<>.txt", true);
|
||||||
{
|
|
||||||
constraint.evaluate("Bogus<>.txt");
|
|
||||||
fail("Failed to detect invalid filename");
|
|
||||||
}
|
|
||||||
catch (ConstraintException e)
|
|
||||||
{
|
|
||||||
// expected
|
|
||||||
}
|
|
||||||
// ... and a valid one
|
// ... and a valid one
|
||||||
constraint.evaluate("Company Home");
|
evaluate(constraint, "Company Home", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum DummyEnum
|
private enum DummyEnum
|
||||||
|
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Alfresco, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Mozilla Public License version 1.1
|
||||||
|
* with a permitted attribution clause. You may obtain a
|
||||||
|
* copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.alfresco.org/legal/license.txt
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||||
|
* either express or implied. See the License for the specific
|
||||||
|
* language governing permissions and limitations under the
|
||||||
|
* License.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.dictionary.constraint;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintException;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constraint implementation that ensures that the value is a numeric value bewteen a given
|
||||||
|
* minimum and maximum value. If a minimum or maximum value are not provided, then the JAVA
|
||||||
|
* Double's {@link Double#MIN_VALUE minimum value} or {@link Double#MAX_VALUE maximum value}
|
||||||
|
* are assumed.
|
||||||
|
*
|
||||||
|
* @see #setMinValue(double)
|
||||||
|
* @see #setMaxValue(double)
|
||||||
|
* @see java.lang.Double#parseDouble(java.lang.String)
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class NumericRangeConstraint extends AbstractConstraint
|
||||||
|
{
|
||||||
|
private static final String ERR_INVALID_MIN_VALUE = "d_dictionary.constraint.numeric_range.invalid_min_value";
|
||||||
|
private static final String ERR_INVALID_MAX_VALUE = "d_dictionary.constraint.numeric_range.invalid_max_value";
|
||||||
|
private static final String ERR_NON_NUMERIC = "d_dictionary.constraint.numeric_range.non_numeric";
|
||||||
|
private static final String ERR_OUT_OF_RANGE = "d_dictionary.constraint.numeric_range.out_of_range";
|
||||||
|
|
||||||
|
private double minValue = Double.MIN_VALUE;
|
||||||
|
private double maxValue = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder(80);
|
||||||
|
sb.append("NumericRangeConstraint")
|
||||||
|
.append("[ minValue=").append(minValue)
|
||||||
|
.append(", maxValue=").append(maxValue)
|
||||||
|
.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the minimum value allowed by the constraint
|
||||||
|
*/
|
||||||
|
public double getMinValue()
|
||||||
|
{
|
||||||
|
return minValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the minimum value allowed, which can be any value between
|
||||||
|
* {@link Double#MIN_VALUE} and {@link Double#MAX_VALUE}.
|
||||||
|
*
|
||||||
|
* @param minValue the minimum value allowed by the constraint
|
||||||
|
*/
|
||||||
|
public void setMinValue(double minValue)
|
||||||
|
{
|
||||||
|
if (minValue > this.maxValue)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_INVALID_MIN_VALUE, minValue);
|
||||||
|
}
|
||||||
|
this.minValue = minValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the minimum value allowed by the constraint
|
||||||
|
*/
|
||||||
|
public double getMaxValue()
|
||||||
|
{
|
||||||
|
return maxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum value allowed, which can be any value between
|
||||||
|
* {@link Double#MIN_VALUE} and {@link Double#MAX_VALUE}.
|
||||||
|
*
|
||||||
|
* @param maxValue the minimum value allowed by the constraint
|
||||||
|
*/
|
||||||
|
public void setMaxValue(double maxValue)
|
||||||
|
{
|
||||||
|
if (maxValue < this.minValue)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_INVALID_MAX_VALUE, minValue);
|
||||||
|
}
|
||||||
|
this.maxValue = maxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void evaluateSingleValue(Object value)
|
||||||
|
{
|
||||||
|
// ensure that the value can be converted to a double
|
||||||
|
double checkValue = Double.NaN;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
checkValue = DefaultTypeConverter.INSTANCE.doubleValue(value);
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e)
|
||||||
|
{
|
||||||
|
throw new ConstraintException(ERR_NON_NUMERIC, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infinity and NaN cannot match
|
||||||
|
if (Double.isInfinite(checkValue) || Double.isNaN(checkValue))
|
||||||
|
{
|
||||||
|
throw new ConstraintException(ERR_OUT_OF_RANGE, checkValue, minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the value is in range
|
||||||
|
if (checkValue > maxValue || checkValue < minValue)
|
||||||
|
{
|
||||||
|
throw new ConstraintException(ERR_OUT_OF_RANGE, checkValue, minValue, maxValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -59,14 +59,37 @@ public class RegexConstraint extends AbstractConstraint
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the regular expression used to evaluate string values
|
* @return Returns the regular expression similar to the {@link String#matches(java.lang.String)}
|
||||||
* @param expression similar to the {@link String#matches(java.lang.String) argument
|
*/
|
||||||
|
public String getExpression()
|
||||||
|
{
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the regular expression used to evaluate String values
|
||||||
|
* @param regular expression similar to the {@link String#matches(java.lang.String)} argument
|
||||||
*/
|
*/
|
||||||
public void setExpression(String expression)
|
public void setExpression(String expression)
|
||||||
{
|
{
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns <tt>true</tt> if the value must match the regular expression
|
||||||
|
* or <tt>false</tt> if the value must not match the regular expression
|
||||||
|
*/
|
||||||
|
public boolean getRequiresMatch()
|
||||||
|
{
|
||||||
|
return requiresMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether the regular expression must be matched or not
|
||||||
|
*
|
||||||
|
* @param requiresMatch Set to <tt>true</tt> if the value must match the regular expression
|
||||||
|
* or <tt>false</tt> if the value must not match the regular expression
|
||||||
|
*/
|
||||||
public void setRequiresMatch(boolean requiresMatch)
|
public void setRequiresMatch(boolean requiresMatch)
|
||||||
{
|
{
|
||||||
this.requiresMatch = requiresMatch;
|
this.requiresMatch = requiresMatch;
|
||||||
|
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Alfresco, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Mozilla Public License version 1.1
|
||||||
|
* with a permitted attribution clause. You may obtain a
|
||||||
|
* copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.alfresco.org/legal/license.txt
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||||
|
* either express or implied. See the License for the specific
|
||||||
|
* language governing permissions and limitations under the
|
||||||
|
* License.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.dictionary.constraint;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintException;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
|
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constraint implementation that ensures that the length of the String value.
|
||||||
|
*
|
||||||
|
* @see #setMinLength(int)
|
||||||
|
* @see #setMaxLength(int)
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class StringLengthConstraint extends AbstractConstraint
|
||||||
|
{
|
||||||
|
private static final String ERR_INVALID_MIN_LENGTH = "d_dictionary.constraint.string_length.invalid_min_length";
|
||||||
|
private static final String ERR_INVALID_MAX_LENGTH = "d_dictionary.constraint.string_length.invalid_max_length";
|
||||||
|
private static final String ERR_NON_STRING = "d_dictionary.constraint.string_length.non_string";
|
||||||
|
private static final String ERR_INVALID_LENGTH = "d_dictionary.constraint.string_length.invalid_length";
|
||||||
|
|
||||||
|
private int minLength = 0;
|
||||||
|
private int maxLength = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder(80);
|
||||||
|
sb.append("StringLengthConstraint")
|
||||||
|
.append("[ minLength=").append(minLength)
|
||||||
|
.append(", maxLength=").append(maxLength)
|
||||||
|
.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the minimum number of characters allowed
|
||||||
|
*/
|
||||||
|
public int getMinLength()
|
||||||
|
{
|
||||||
|
return minLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the minimum number of characters allowed. Valid values are in
|
||||||
|
* the range [0, {@link Integer#MAX_VALUE}].
|
||||||
|
*
|
||||||
|
* @param minLength the minimum numbers of characters allowed
|
||||||
|
*/
|
||||||
|
public void setMinLength(int minLength)
|
||||||
|
{
|
||||||
|
if (minLength > this.maxLength || minLength < 0)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_INVALID_MIN_LENGTH, minLength);
|
||||||
|
}
|
||||||
|
this.minLength = minLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the maximum number of characters allowed
|
||||||
|
*/
|
||||||
|
public int getMaxLength()
|
||||||
|
{
|
||||||
|
return maxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum number of characters allowed. Valid values are in
|
||||||
|
* the range [0, {@link Integer#MAX_VALUE}].
|
||||||
|
*
|
||||||
|
* @param maxLength the minimum numbers of characters allowed
|
||||||
|
*/
|
||||||
|
public void setMaxLength(int maxLength)
|
||||||
|
{
|
||||||
|
if (maxLength < this.minLength)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_INVALID_MAX_LENGTH, maxLength);
|
||||||
|
}
|
||||||
|
this.maxLength = maxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void evaluateSingleValue(Object value)
|
||||||
|
{
|
||||||
|
// ensure that the value can be converted to a String
|
||||||
|
String checkValue = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
checkValue = DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||||
|
}
|
||||||
|
catch (TypeConversionException e)
|
||||||
|
{
|
||||||
|
throw new ConstraintException(ERR_NON_STRING, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the value length
|
||||||
|
int length = checkValue.length();
|
||||||
|
if (length > maxLength || length < minLength)
|
||||||
|
{
|
||||||
|
if (length > 20)
|
||||||
|
{
|
||||||
|
checkValue = checkValue.substring(0, 17) + "...";
|
||||||
|
}
|
||||||
|
throw new ConstraintException(ERR_INVALID_LENGTH, checkValue, minLength, maxLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -27,6 +27,14 @@
|
|||||||
<parameter name="expression">[A-Z]*</parameter>
|
<parameter name="expression">[A-Z]*</parameter>
|
||||||
<parameter name="requiresMatch">false</parameter>
|
<parameter name="requiresMatch">false</parameter>
|
||||||
</constraint>
|
</constraint>
|
||||||
|
<constraint name="test:stringLength1" type="LENGTH">
|
||||||
|
<parameter name="minLength">0</parameter>
|
||||||
|
<parameter name="maxLength">256</parameter>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="test:minMax1" type="MINMAX">
|
||||||
|
<parameter name="minValue">0</parameter>
|
||||||
|
<parameter name="maxValue">256</parameter>
|
||||||
|
</constraint>
|
||||||
</constraints>
|
</constraints>
|
||||||
|
|
||||||
<types>
|
<types>
|
||||||
@@ -43,6 +51,7 @@
|
|||||||
<default></default>
|
<default></default>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint ref="test:regex1"/>
|
<constraint ref="test:regex1"/>
|
||||||
|
<constraint ref="test:stringLength1"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</property>
|
</property>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -165,6 +174,9 @@
|
|||||||
<atomic>true</atomic>
|
<atomic>true</atomic>
|
||||||
<stored>false</stored>
|
<stored>false</stored>
|
||||||
</index>
|
</index>
|
||||||
|
<constraints>
|
||||||
|
<constraint ref="test:minMax1"/>
|
||||||
|
</constraints>
|
||||||
</property>
|
</property>
|
||||||
</properties>
|
</properties>
|
||||||
</aspect>
|
</aspect>
|
||||||
|
Reference in New Issue
Block a user