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:
@@ -133,7 +133,7 @@ public class DictionaryDAOTest extends TestCase
|
||||
PropertyDefinition propDef = service.getProperty(prop1QName);
|
||||
List<ConstraintDefinition> constraints = propDef.getConstraints();
|
||||
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
|
||||
ConstraintDefinition constraintDef = constraints.get(0);
|
||||
|
@@ -18,7 +18,9 @@ package org.alfresco.repo.dictionary;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.dictionary.constraint.NumericRangeConstraint;
|
||||
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.ConstraintDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||
@@ -226,6 +228,22 @@ import org.springframework.beans.TypeMismatchException;
|
||||
{
|
||||
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.ConstraintException;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
|
||||
/**
|
||||
* Base services for constraints.
|
||||
@@ -39,12 +40,17 @@ public abstract class AbstractConstraint implements Constraint
|
||||
@SuppressWarnings("unchecked")
|
||||
public final void evaluate(Object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
// null values are never evaluated
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
// check for collection
|
||||
if (value instanceof Collection)
|
||||
// ensure that we can handle collections
|
||||
if (DefaultTypeConverter.INSTANCE.isMultiValued(value))
|
||||
{
|
||||
Collection collection = (Collection) value;
|
||||
Collection collection = DefaultTypeConverter.INSTANCE.getCollection(Object.class, value);
|
||||
evaluateCollection(collection);
|
||||
}
|
||||
else
|
||||
@@ -75,13 +81,18 @@ public abstract class AbstractConstraint implements Constraint
|
||||
{
|
||||
for (Object value : collection)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
// contract states that it will always pass
|
||||
continue;
|
||||
}
|
||||
evaluateSingleValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@@ -17,13 +17,16 @@
|
||||
package org.alfresco.repo.dictionary.constraint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
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.DictionaryException;
|
||||
|
||||
/**
|
||||
* <b>This file must be saved using UTF-8.</b>
|
||||
@@ -63,11 +66,113 @@ public class ConstraintsTest extends TestCase
|
||||
catch (ConstraintException e)
|
||||
{
|
||||
// expected
|
||||
checkI18NofExceptionMessage(e);
|
||||
}
|
||||
// check that the two strings were properly dealt with
|
||||
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
|
||||
{
|
||||
RegexConstraint constraint = new RegexConstraint();
|
||||
@@ -76,38 +181,22 @@ public class ConstraintsTest extends TestCase
|
||||
constraint.initialize();
|
||||
|
||||
// do some successful stuff
|
||||
constraint.evaluate("ABC");
|
||||
constraint.evaluate("DEF");
|
||||
evaluate(constraint, "ABC", false);
|
||||
evaluate(constraint, "DEF", false);
|
||||
|
||||
// now some failures
|
||||
try
|
||||
{
|
||||
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"));
|
||||
}
|
||||
evaluate(constraint, "abc", true);
|
||||
|
||||
// now a case of passing in an object that could be a string
|
||||
constraint.evaluate(DummyEnum.ABC);
|
||||
constraint.evaluate(DummyEnum.DEF);
|
||||
try
|
||||
{
|
||||
constraint.evaluate(DummyEnum.abc);
|
||||
fail("Regular expression evaluation should have failed for enum: " + DummyEnum.abc);
|
||||
}
|
||||
catch (ConstraintException e)
|
||||
{
|
||||
}
|
||||
evaluate(constraint, DummyEnum.ABC, false);
|
||||
evaluate(constraint, DummyEnum.DEF, false);
|
||||
evaluate(constraint, DummyEnum.abc, true);
|
||||
|
||||
// now switch the requiresMatch around
|
||||
constraint.setRequiresMatch(false);
|
||||
constraint.initialize();
|
||||
|
||||
constraint.evaluate(DummyEnum.abc);
|
||||
evaluate(constraint, DummyEnum.abc, false);
|
||||
}
|
||||
|
||||
public void testRegexConstraintFilename() throws Exception
|
||||
@@ -125,30 +214,12 @@ public class ConstraintsTest extends TestCase
|
||||
for (int i = 0; i < invalidChars.length(); i++)
|
||||
{
|
||||
String invalidStr = invalidChars.substring(i, i+1);
|
||||
try
|
||||
{
|
||||
constraint.evaluate(invalidStr);
|
||||
fail("Regex constraint failed to detect illegal characters: \n" +
|
||||
" constraint: " + constraint + "\n" +
|
||||
" invalid string: " + invalidStr);
|
||||
}
|
||||
catch (ConstraintException e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
evaluate(constraint, invalidStr, true);
|
||||
}
|
||||
// check a bogus filename
|
||||
try
|
||||
{
|
||||
constraint.evaluate("Bogus<>.txt");
|
||||
fail("Failed to detect invalid filename");
|
||||
}
|
||||
catch (ConstraintException e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
evaluate(constraint, "Bogus<>.txt", true);
|
||||
// ... and a valid one
|
||||
constraint.evaluate("Company Home");
|
||||
evaluate(constraint, "Company Home", false);
|
||||
}
|
||||
|
||||
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
|
||||
* @param expression similar to the {@link String#matches(java.lang.String) argument
|
||||
* @return Returns the regular expression similar to the {@link String#matches(java.lang.String)}
|
||||
*/
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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="requiresMatch">false</parameter>
|
||||
</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>
|
||||
|
||||
<types>
|
||||
@@ -43,6 +51,7 @@
|
||||
<default></default>
|
||||
<constraints>
|
||||
<constraint ref="test:regex1"/>
|
||||
<constraint ref="test:stringLength1"/>
|
||||
</constraints>
|
||||
</property>
|
||||
</properties>
|
||||
@@ -165,6 +174,9 @@
|
||||
<atomic>true</atomic>
|
||||
<stored>false</stored>
|
||||
</index>
|
||||
<constraints>
|
||||
<constraint ref="test:minMax1"/>
|
||||
</constraints>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
|
Reference in New Issue
Block a user