mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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()
|
||||
{
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
Reference in New Issue
Block a user