Fix AR-521: Constraints are inherited (added test to ensure) and overridable (new)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2970 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2006-05-24 15:22:34 +00:00
parent 0cc08b2518
commit b9a95c2b31
8 changed files with 126 additions and 22 deletions

View File

@@ -90,7 +90,14 @@ import org.apache.commons.logging.LogFactory;
resolveDependencies(query, namespaceDAO);
// Phase 3: Resolve inheritance of values within class hierachy
resolveInheritance(query);
NamespacePrefixResolver localPrefixes = createLocalPrefixResolver(model, namespaceDAO);
resolveInheritance(query, localPrefixes, constraints);
// Phase 4: Resolve constraint dependencies
for (ConstraintDefinition def : constraints.values())
{
((M2ConstraintDefinition)def).resolveDependencies(query);
}
}
catch(Exception e)
{
@@ -220,10 +227,6 @@ import org.apache.commons.logging.LogFactory;
{
((M2ClassDefinition)def).resolveDependencies(query, prefixResolver, constraints);
}
for (ConstraintDefinition def : constraints.values())
{
((M2ConstraintDefinition)def).resolveDependencies(query);
}
}
@@ -232,7 +235,10 @@ import org.apache.commons.logging.LogFactory;
*
* @param query support for querying other items in model
*/
private void resolveInheritance(ModelQuery query)
private void resolveInheritance(
ModelQuery query,
NamespacePrefixResolver prefixResolver,
Map<QName, ConstraintDefinition> modelConstraints)
{
// Calculate order of class processing (root to leaf)
Map<Integer,List<ClassDefinition>> order = new TreeMap<Integer,List<ClassDefinition>>();
@@ -270,7 +276,7 @@ import org.apache.commons.logging.LogFactory;
{
for (ClassDefinition def : order.get(depth))
{
((M2ClassDefinition)def).resolveInheritance(query);
((M2ClassDefinition)def).resolveInheritance(query, prefixResolver, modelConstraints);
}
}
}

View File

@@ -24,6 +24,7 @@ import junit.framework.TestCase;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.dictionary.constraint.RegexConstraint;
import org.alfresco.repo.dictionary.constraint.StringLengthConstraint;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.Constraint;
@@ -35,6 +36,7 @@ import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
public class DictionaryDAOTest extends TestCase
@@ -145,6 +147,38 @@ public class DictionaryDAOTest extends TestCase
// make sure it is the correct type of constraint
assertTrue("Expected type REGEX constraint", constraint instanceof RegexConstraint);
}
public void testConstraintsOverrideInheritance()
{
QName baseQName = QName.createQName(TEST_URL, "base");
QName fileQName = QName.createQName(TEST_URL, "file");
QName folderQName = QName.createQName(TEST_URL, "folder");
QName prop1QName = QName.createQName(TEST_URL, "prop1");
// get the base property
PropertyDefinition prop1Def = service.getProperty(baseQName, prop1QName);
assertNotNull(prop1Def);
List<ConstraintDefinition> prop1Constraints = prop1Def.getConstraints();
assertEquals("Incorrect number of constraints", 2, prop1Constraints.size());
assertTrue("Constraint instance incorrect", prop1Constraints.get(0).getConstraint() instanceof RegexConstraint);
assertTrue("Constraint instance incorrect", prop1Constraints.get(1).getConstraint() instanceof StringLengthConstraint);
// check the inherited property on folder (must be same as above)
prop1Def = service.getProperty(folderQName, prop1QName);
assertNotNull(prop1Def);
prop1Constraints = prop1Def.getConstraints();
assertEquals("Incorrect number of constraints", 2, prop1Constraints.size());
assertTrue("Constraint instance incorrect", prop1Constraints.get(0).getConstraint() instanceof RegexConstraint);
assertTrue("Constraint instance incorrect", prop1Constraints.get(1).getConstraint() instanceof StringLengthConstraint);
// check the overridden property on file (must be reverse of above)
prop1Def = service.getProperty(fileQName, prop1QName);
assertNotNull(prop1Def);
prop1Constraints = prop1Def.getConstraints();
assertEquals("Incorrect number of constraints", 2, prop1Constraints.size());
assertTrue("Constraint instance incorrect", prop1Constraints.get(0).getConstraint() instanceof StringLengthConstraint);
assertTrue("Constraint instance incorrect", prop1Constraints.get(1).getConstraint() instanceof RegexConstraint);
}
public void testArchive()
{

View File

@@ -204,7 +204,10 @@ import org.alfresco.service.namespace.QName;
}
/*package*/ void resolveInheritance(ModelQuery query)
/*package*/ void resolveInheritance(
ModelQuery query,
NamespacePrefixResolver prefixResolver,
Map<QName, ConstraintDefinition> modelConstraints)
{
// Retrieve parent class
ClassDefinition parentClass = (parentName == null) ? null : query.getClass(parentName);
@@ -221,7 +224,9 @@ import org.alfresco.service.namespace.QName;
}
else
{
inheritedProperties.put(def.getName(), new M2PropertyDefinition(this, def, override));
inheritedProperties.put(
def.getName(),
new M2PropertyDefinition(this, def, override, prefixResolver, modelConstraints));
}
}
}

View File

@@ -19,6 +19,8 @@ package org.alfresco.repo.dictionary;
import java.util.Collections;
import java.util.List;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
/**
* Property Definition

View File

@@ -44,8 +44,7 @@ import org.alfresco.service.namespace.QName;
private QName name;
private QName propertyTypeName;
private DataTypeDefinition dataType;
private List<ConstraintDefinition> constraints = new ArrayList<ConstraintDefinition>(5);
private Map<QName, ConstraintDefinition> constraintsByQName = new HashMap<QName, ConstraintDefinition>(7);
private List<ConstraintDefinition> constraintDefs = Collections.emptyList();
/*package*/ M2PropertyDefinition(
ClassDefinition classDef,
@@ -64,10 +63,12 @@ import org.alfresco.service.namespace.QName;
/*package*/ M2PropertyDefinition(
ClassDefinition classDef,
PropertyDefinition propertyDef,
M2PropertyOverride override)
M2PropertyOverride override,
NamespacePrefixResolver prefixResolver,
Map<QName, ConstraintDefinition> modelConstraints)
{
this.classDef = classDef;
this.m2Property = createOverriddenProperty(propertyDef, override);
this.m2Property = createOverriddenProperty(propertyDef, override, prefixResolver, modelConstraints);
this.name = propertyDef.getName();
this.dataType = propertyDef.getDataType();
this.propertyTypeName = this.dataType.getName();
@@ -100,15 +101,30 @@ import org.alfresco.service.namespace.QName;
}
// Construct constraints
for (M2Constraint constraint : m2Property.getConstraints())
constraintDefs = buildConstraints(
m2Property.getConstraints(),
this,
prefixResolver,
modelConstraints);
}
private static List<ConstraintDefinition> buildConstraints(
List<M2Constraint> m2constraints,
M2PropertyDefinition m2PropertyDef,
NamespacePrefixResolver prefixResolver,
Map<QName, ConstraintDefinition> modelConstraints)
{
List<ConstraintDefinition> constraints = new ArrayList<ConstraintDefinition>(5);
Map<QName, ConstraintDefinition> constraintsByQName = new HashMap<QName, ConstraintDefinition>(7);
for (M2Constraint constraint : m2constraints)
{
ConstraintDefinition def = new M2ConstraintDefinition(this, constraint, prefixResolver);
ConstraintDefinition def = new M2ConstraintDefinition(m2PropertyDef, constraint, prefixResolver);
QName qname = def.getName();
if (constraintsByQName.containsKey(qname))
{
throw new DictionaryException(
"d_dictionary.property.err.duplicate_constraint_on_property",
def.getName().toPrefixString(), name.toPrefixString());
def.getName().toPrefixString(), m2PropertyDef.name.toPrefixString());
}
else if (modelConstraints.containsKey(qname))
{
@@ -120,9 +136,10 @@ import org.alfresco.service.namespace.QName;
constraints.add(def);
modelConstraints.put(qname, def);
}
// done
return constraints;
}
/**
* Create a property definition whose values are overridden
*
@@ -130,7 +147,11 @@ import org.alfresco.service.namespace.QName;
* @param override the overridden values
* @return the property definition
*/
private M2Property createOverriddenProperty(PropertyDefinition propertyDef, M2PropertyOverride override)
private M2Property createOverriddenProperty(
PropertyDefinition propertyDef,
M2PropertyOverride override,
NamespacePrefixResolver prefixResolver,
Map<QName, ConstraintDefinition> modelConstraints)
{
M2Property property = new M2Property();
@@ -161,6 +182,21 @@ import org.alfresco.service.namespace.QName;
property.setMandatory(isOverrideMandatory == null ? propertyDef.isMandatory() : isOverrideMandatory);
property.setMandatoryEnforced(isOverrideMandatoryEnforced);
// inherit or override constraints
List<M2Constraint> overrideConstraints = override.getConstraints();
if (overrideConstraints != null)
{
constraintDefs = buildConstraints(
overrideConstraints,
(M2PropertyDefinition) propertyDef,
prefixResolver,
modelConstraints);
}
else
{
this.constraintDefs = propertyDef.getConstraints();
}
// Copy all other properties as they are
property.setDescription(propertyDef.getDescription());
property.setIndexed(propertyDef.isIndexed());
@@ -323,6 +359,6 @@ import org.alfresco.service.namespace.QName;
public List<ConstraintDefinition> getConstraints()
{
return Collections.unmodifiableList(constraints);
return constraintDefs;
}
}

View File

@@ -16,6 +16,8 @@
*/
package org.alfresco.repo.dictionary;
import java.util.List;
/**
* Property override definition
@@ -29,7 +31,7 @@ public class M2PropertyOverride
private Boolean isMandatory;
private boolean isMandatoryEnforced = false;
private String defaultValue;
private List<M2Constraint> constraints;
/*package*/ M2PropertyOverride()
{
@@ -74,5 +76,9 @@ public class M2PropertyOverride
{
this.defaultValue = defaultValue;
}
public List<M2Constraint> getConstraints()
{
return constraints;
}
}

View File

@@ -27,10 +27,18 @@
<parameter name="expression"><value>[A-Z]*</value></parameter>
<parameter name="requiresMatch"><value>false</value></parameter>
</constraint>
<constraint name="test:regex2" type="REGEX">
<parameter name="expression"><value>[a-z]*</value></parameter>
<parameter name="requiresMatch"><value>false</value></parameter>
</constraint>
<constraint name="test:stringLength1" type="LENGTH">
<parameter name="minLength"><value>0</value></parameter>
<parameter name="maxLength"><value>256</value></parameter>
</constraint>
<constraint name="test:stringLength2" type="LENGTH">
<parameter name="minLength"><value>0</value></parameter>
<parameter name="maxLength"><value>128</value></parameter>
</constraint>
<constraint name="test:minMax1" type="MINMAX">
<parameter name="minValue"><value>0</value></parameter>
<parameter name="maxValue"><value>256</value></parameter>
@@ -132,8 +140,12 @@
</associations>
<overrides>
<property name="test:prop">
<property name="test:prop1">
<default>an overriden default value</default>
<constraints>
<constraint ref="test:stringLength2"/>
<constraint ref="test:regex2"/>
</constraints>
</property>
</overrides>
</type>

View File

@@ -77,6 +77,9 @@
<value style="text" field="isMandatory" />
</structure>
<value name="default" field="defaultValue" usage="optional"/>
<structure name="constraints" usage="optional">
<collection field="constraints" item-type="org.alfresco.repo.dictionary.M2Constraint" factory="org.alfresco.repo.dictionary.M2Model.createList"/>
</structure>
</structure>
</collection>
</structure>