mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Property constraint dictionary support
Constraint implementation support Regular expression constraint git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2547 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -71,6 +71,7 @@
|
|||||||
<value>alfresco.messages.template-service</value>
|
<value>alfresco.messages.template-service</value>
|
||||||
<value>alfresco.messages.lock-service</value>
|
<value>alfresco.messages.lock-service</value>
|
||||||
<value>alfresco.messages.patch-service</value>
|
<value>alfresco.messages.patch-service</value>
|
||||||
|
<value>alfresco.messages.dictionary-messages</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
22
config/alfresco/messages/dictionary-messages.properties
Normal file
22
config/alfresco/messages/dictionary-messages.properties
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Dictionary-related messages
|
||||||
|
|
||||||
|
d_dictionary.model.err.no_model=Model ''{0}'' does not exist
|
||||||
|
d_dictionary.model.err.type_not_found=Failed to create anonymous type as specified type {0} not found
|
||||||
|
d_dictionary.model.err.aspect_not_found=Failed to create anonymous type as specified aspect {0} not found
|
||||||
|
|
||||||
|
d_dictionary.model.err.cyclic_ref=Constraint ''{0}'' is part of a cyclic reference of constraints
|
||||||
|
d_dictionary.model.err.type_and_ref=Constraint ''{0}'' cannot have a ''type'' and be a ''reference'' attribute
|
||||||
|
d_dictionary.model.err.type_or_ref=Constraint ''{0}'' cannot have a ''type'' and be a ''reference'' attribute
|
||||||
|
d_dictionary.model.err.ref_not_found=Constraint reference ''{0}'' not found on constraint ''{1}''
|
||||||
|
d_dictionary.model.err.anon_needs_property=Anonymous constraints can only be declared within the context of a property
|
||||||
|
d_dictionary.model.err.invalid_type=Constraint type ''{0}'' on constraint ''{1}'' is not a well-known type or a valid Constraint implementation
|
||||||
|
d_dictionary.model.err.construct_failure=Failed to construct an instance of type ''{0}'' for constraint ''{1}''
|
||||||
|
d_dictionary.model.err.property_not_set=Property ''{0}'' has not been set on constraint ''{1}''
|
||||||
|
d_dictionary.model.err.evaluate_exception=Exception during evaluation of constraint ''{0}'': {1}
|
||||||
|
|
||||||
|
d_dictionary.property.err.property_type_not_specified=Property type of property ''{0}'' must be specified
|
||||||
|
d_dictionary.property.err.property_type_not_found=Property type ''{0}'' of property ''{1}'' is not found
|
||||||
|
d_dictionary.property.err.single_valued_content=Content properties must be single-valued
|
||||||
|
d_dictionary.property.err.duplicate_constraint_on_property=Found duplicate constraint definition ''{0}'' within property ''{1}''
|
||||||
|
|
||||||
|
d_dictionary.constraint.regex.no_match=Value ''{0}'' does not match regular expression: {1}
|
@@ -26,6 +26,7 @@ import java.util.TreeMap;
|
|||||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
@@ -66,7 +67,7 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
private Map<QName, AspectDefinition> aspects = new HashMap<QName, AspectDefinition>();
|
private Map<QName, AspectDefinition> aspects = new HashMap<QName, AspectDefinition>();
|
||||||
private Map<QName, PropertyDefinition> properties = new HashMap<QName, PropertyDefinition>();
|
private Map<QName, PropertyDefinition> properties = new HashMap<QName, PropertyDefinition>();
|
||||||
private Map<QName, AssociationDefinition> associations = new HashMap<QName, AssociationDefinition>();
|
private Map<QName, AssociationDefinition> associations = new HashMap<QName, AssociationDefinition>();
|
||||||
|
private Map<QName, ConstraintDefinition> constraints = new HashMap<QName, ConstraintDefinition>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct
|
* Construct
|
||||||
@@ -82,11 +83,11 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
// Phase 1: Construct model definitions from model entries
|
// Phase 1: Construct model definitions from model entries
|
||||||
// resolving qualified names
|
// resolving qualified names
|
||||||
this.model = model;
|
this.model = model;
|
||||||
constructDefinitions(model, dictionaryDAO, namespaceDAO);
|
constructDefinitions(model, namespaceDAO);
|
||||||
|
|
||||||
// Phase 2: Resolve dependencies between model definitions
|
// Phase 2: Resolve dependencies between model definitions
|
||||||
ModelQuery query = new DelegateModelQuery(this, dictionaryDAO);
|
ModelQuery query = new DelegateModelQuery(this, dictionaryDAO);
|
||||||
resolveDependencies(query);
|
resolveDependencies(query, namespaceDAO);
|
||||||
|
|
||||||
// Phase 3: Resolve inheritance of values within class hierachy
|
// Phase 3: Resolve inheritance of values within class hierachy
|
||||||
resolveInheritance(query);
|
resolveInheritance(query);
|
||||||
@@ -111,10 +112,9 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
* Construct compiled definitions
|
* Construct compiled definitions
|
||||||
*
|
*
|
||||||
* @param model model definition
|
* @param model model definition
|
||||||
* @param dictionaryDAO dictionary DAO
|
|
||||||
* @param namespaceDAO namespace DAO
|
* @param namespaceDAO namespace DAO
|
||||||
*/
|
*/
|
||||||
private void constructDefinitions(M2Model model, DictionaryDAO dictionaryDAO, NamespaceDAO namespaceDAO)
|
private void constructDefinitions(M2Model model, NamespaceDAO namespaceDAO)
|
||||||
{
|
{
|
||||||
NamespacePrefixResolver localPrefixes = createLocalPrefixResolver(model, namespaceDAO);
|
NamespacePrefixResolver localPrefixes = createLocalPrefixResolver(model, namespaceDAO);
|
||||||
|
|
||||||
@@ -155,6 +155,18 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
classes.put(def.getName(), def);
|
classes.put(def.getName(), def);
|
||||||
aspects.put(def.getName(), def);
|
aspects.put(def.getName(), def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct Constraint Definitions
|
||||||
|
for (M2Constraint constraint : model.getConstraints())
|
||||||
|
{
|
||||||
|
M2ConstraintDefinition def = new M2ConstraintDefinition(modelDefinition, null, constraint, localPrefixes);
|
||||||
|
QName qname = def.getName();
|
||||||
|
if (constraints.containsKey(qname))
|
||||||
|
{
|
||||||
|
throw new DictionaryException("Found duplicate constraint definition " + constraint.getName() + " (an aspect)");
|
||||||
|
}
|
||||||
|
constraints.put(qname, def);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -196,15 +208,21 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
*
|
*
|
||||||
* @param query support for querying other items in model
|
* @param query support for querying other items in model
|
||||||
*/
|
*/
|
||||||
private void resolveDependencies(ModelQuery query)
|
private void resolveDependencies(ModelQuery query, NamespaceDAO namespaceDAO)
|
||||||
{
|
{
|
||||||
|
NamespacePrefixResolver prefixResolver = createLocalPrefixResolver(model, namespaceDAO);
|
||||||
|
|
||||||
for (DataTypeDefinition def : dataTypes.values())
|
for (DataTypeDefinition def : dataTypes.values())
|
||||||
{
|
{
|
||||||
((M2DataTypeDefinition)def).resolveDependencies(query);
|
((M2DataTypeDefinition)def).resolveDependencies(query);
|
||||||
}
|
}
|
||||||
for (ClassDefinition def : classes.values())
|
for (ClassDefinition def : classes.values())
|
||||||
{
|
{
|
||||||
((M2ClassDefinition)def).resolveDependencies(query);
|
((M2ClassDefinition)def).resolveDependencies(query, prefixResolver, constraints);
|
||||||
|
}
|
||||||
|
for (ConstraintDefinition def : constraints.values())
|
||||||
|
{
|
||||||
|
((M2ConstraintDefinition)def).resolveDependencies(query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,4 +381,11 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
return associations.get(name);
|
return associations.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getConstraint(QName)
|
||||||
|
*/
|
||||||
|
public ConstraintDefinition getConstraint(QName name)
|
||||||
|
{
|
||||||
|
return constraints.get(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@ package org.alfresco.repo.dictionary;
|
|||||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||||
@@ -148,4 +149,16 @@ import org.alfresco.service.namespace.QName;
|
|||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see ModelQuery#getConstraint(QName)
|
||||||
|
*/
|
||||||
|
public ConstraintDefinition getConstraint(QName name)
|
||||||
|
{
|
||||||
|
ConstraintDefinition def = query.getConstraint(name);
|
||||||
|
if (def == null)
|
||||||
|
{
|
||||||
|
def = delegate.getConstraint(name);
|
||||||
|
}
|
||||||
|
return def;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ import java.util.Map;
|
|||||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
||||||
@@ -144,7 +145,7 @@ public class DictionaryDAOImpl implements DictionaryDAO
|
|||||||
if (model == null)
|
if (model == null)
|
||||||
{
|
{
|
||||||
// TODO: Load model from persistent store
|
// TODO: Load model from persistent store
|
||||||
throw new DictionaryException("Model " + modelName + " does not exist");
|
throw new DictionaryException("d_dictionary.model.err.no_model", modelName);
|
||||||
}
|
}
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
@@ -226,6 +227,11 @@ public class DictionaryDAOImpl implements DictionaryDAO
|
|||||||
return (model == null) ? null : model.getProperty(propertyName);
|
return (model == null) ? null : model.getProperty(propertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConstraintDefinition getConstraint(QName constraintQName)
|
||||||
|
{
|
||||||
|
CompiledModel model = getCompiledModelForNamespace(constraintQName.getNamespaceURI());
|
||||||
|
return (model == null) ? null : model.getConstraint(constraintQName);
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getAssociation(org.alfresco.repo.ref.QName)
|
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getAssociation(org.alfresco.repo.ref.QName)
|
||||||
@@ -288,7 +294,7 @@ public class DictionaryDAOImpl implements DictionaryDAO
|
|||||||
TypeDefinition typeDef = getType(type);
|
TypeDefinition typeDef = getType(type);
|
||||||
if (typeDef == null)
|
if (typeDef == null)
|
||||||
{
|
{
|
||||||
throw new DictionaryException("Failed to create anonymous type as specified type " + type + " not found");
|
throw new DictionaryException("d_dictionary.model.err.type_not_found", type);
|
||||||
}
|
}
|
||||||
Collection<AspectDefinition> aspectDefs = new ArrayList<AspectDefinition>();
|
Collection<AspectDefinition> aspectDefs = new ArrayList<AspectDefinition>();
|
||||||
if (aspects != null)
|
if (aspects != null)
|
||||||
@@ -298,7 +304,7 @@ public class DictionaryDAOImpl implements DictionaryDAO
|
|||||||
AspectDefinition aspectDef = getAspect(aspect);
|
AspectDefinition aspectDef = getAspect(aspect);
|
||||||
if (typeDef == null)
|
if (typeDef == null)
|
||||||
{
|
{
|
||||||
throw new DictionaryException("Failed to create anonymous type as specified aspect " + aspect + " not found");
|
throw new DictionaryException("d_dictionary.model.err.aspect_not_found", aspect);
|
||||||
}
|
}
|
||||||
aspectDefs.add(aspectDef);
|
aspectDefs.add(aspectDef);
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,11 @@ import java.util.List;
|
|||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.alfresco.i18n.I18NUtil;
|
||||||
|
import org.alfresco.repo.dictionary.constraint.RegexConstraint;
|
||||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.Constraint;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
|
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
|
||||||
@@ -33,7 +37,9 @@ import org.alfresco.service.namespace.QName;
|
|||||||
|
|
||||||
public class DictionaryDAOTest extends TestCase
|
public class DictionaryDAOTest extends TestCase
|
||||||
{
|
{
|
||||||
|
public static final String TEST_RESOURCE_MESSAGES = "alfresco/messages/dictionary-messages";
|
||||||
|
|
||||||
|
private static final String TEST_URL = "http://www.alfresco.org/test/dictionarydaotest/1.0";
|
||||||
private static final String TEST_MODEL = "org/alfresco/repo/dictionary/dictionarydaotest_model.xml";
|
private static final String TEST_MODEL = "org/alfresco/repo/dictionary/dictionarydaotest_model.xml";
|
||||||
private static final String TEST_BUNDLE = "org/alfresco/repo/dictionary/dictionarydaotest_model";
|
private static final String TEST_BUNDLE = "org/alfresco/repo/dictionary/dictionarydaotest_model";
|
||||||
private DictionaryService service;
|
private DictionaryService service;
|
||||||
@@ -42,6 +48,9 @@ public class DictionaryDAOTest extends TestCase
|
|||||||
@Override
|
@Override
|
||||||
public void setUp()
|
public void setUp()
|
||||||
{
|
{
|
||||||
|
// register resource bundles for messages
|
||||||
|
I18NUtil.registerResourceBundle(TEST_RESOURCE_MESSAGES);
|
||||||
|
|
||||||
// Instantiate Dictionary Service
|
// Instantiate Dictionary Service
|
||||||
NamespaceDAO namespaceDAO = new NamespaceDAOImpl();
|
NamespaceDAO namespaceDAO = new NamespaceDAOImpl();
|
||||||
DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(namespaceDAO);
|
DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(namespaceDAO);
|
||||||
@@ -90,34 +99,59 @@ public class DictionaryDAOTest extends TestCase
|
|||||||
|
|
||||||
public void testLabels()
|
public void testLabels()
|
||||||
{
|
{
|
||||||
QName model = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "dictionarydaotest");
|
QName model = QName.createQName(TEST_URL, "dictionarydaotest");
|
||||||
ModelDefinition modelDef = service.getModel(model);
|
ModelDefinition modelDef = service.getModel(model);
|
||||||
assertEquals("Model Description", modelDef.getDescription());
|
assertEquals("Model Description", modelDef.getDescription());
|
||||||
QName type = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "base");
|
QName type = QName.createQName(TEST_URL, "base");
|
||||||
TypeDefinition typeDef = service.getType(type);
|
TypeDefinition typeDef = service.getType(type);
|
||||||
assertEquals("Base Title", typeDef.getTitle());
|
assertEquals("Base Title", typeDef.getTitle());
|
||||||
assertEquals("Base Description", typeDef.getDescription());
|
assertEquals("Base Description", typeDef.getDescription());
|
||||||
QName prop = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "prop1");
|
QName prop = QName.createQName(TEST_URL, "prop1");
|
||||||
PropertyDefinition propDef = service.getProperty(prop);
|
PropertyDefinition propDef = service.getProperty(prop);
|
||||||
assertEquals("Prop1 Title", propDef.getTitle());
|
assertEquals("Prop1 Title", propDef.getTitle());
|
||||||
assertEquals("Prop1 Description", propDef.getDescription());
|
assertEquals("Prop1 Description", propDef.getDescription());
|
||||||
QName assoc = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "assoc1");
|
QName assoc = QName.createQName(TEST_URL, "assoc1");
|
||||||
AssociationDefinition assocDef = service.getAssociation(assoc);
|
AssociationDefinition assocDef = service.getAssociation(assoc);
|
||||||
assertEquals("Assoc1 Title", assocDef.getTitle());
|
assertEquals("Assoc1 Title", assocDef.getTitle());
|
||||||
assertEquals("Assoc1 Description", assocDef.getDescription());
|
assertEquals("Assoc1 Description", assocDef.getDescription());
|
||||||
QName datatype = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "datatype");
|
QName datatype = QName.createQName(TEST_URL, "datatype");
|
||||||
DataTypeDefinition datatypeDef = service.getDataType(datatype);
|
DataTypeDefinition datatypeDef = service.getDataType(datatype);
|
||||||
assertEquals("Datatype Analyser", datatypeDef.getAnalyserClassName());
|
assertEquals("Datatype Analyser", datatypeDef.getAnalyserClassName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testConstraints()
|
||||||
|
{
|
||||||
|
// get the constraints for a property without constraints
|
||||||
|
QName propNoConstraintsQName = QName.createQName(TEST_URL, "fileprop");
|
||||||
|
PropertyDefinition propNoConstraintsDef = service.getProperty(propNoConstraintsQName);
|
||||||
|
assertNotNull("Property without constraints returned empty list", propNoConstraintsDef.getConstraints());
|
||||||
|
|
||||||
|
// get the constraints defined for the property
|
||||||
|
QName prop1QName = QName.createQName(TEST_URL, "prop1");
|
||||||
|
PropertyDefinition propDef = service.getProperty(prop1QName);
|
||||||
|
List<ConstraintDefinition> constraints = propDef.getConstraints();
|
||||||
|
assertNotNull("Null constraints list", constraints);
|
||||||
|
assertEquals("Incorrect number of constraints", 1, constraints.size());
|
||||||
|
|
||||||
|
// check the individual constraints
|
||||||
|
ConstraintDefinition constraintDef = constraints.get(0);
|
||||||
|
assertTrue("Constraint anonymous name incorrect", constraintDef.getName().getLocalName().startsWith("prop1_anon"));
|
||||||
|
// check that the constraint implementation is valid (it used a reference)
|
||||||
|
Constraint constraint = constraintDef.getConstraint();
|
||||||
|
assertNotNull("Reference constraint has no implementation", constraint);
|
||||||
|
|
||||||
|
// make sure it is the correct type of constraint
|
||||||
|
assertTrue("Expected type REGEX constraint", constraint instanceof RegexConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testSubClassOf()
|
public void testSubClassOf()
|
||||||
{
|
{
|
||||||
QName invalid = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "invalid");
|
QName invalid = QName.createQName(TEST_URL, "invalid");
|
||||||
QName base = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "base");
|
QName base = QName.createQName(TEST_URL, "base");
|
||||||
QName file = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "file");
|
QName file = QName.createQName(TEST_URL, "file");
|
||||||
QName folder = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "folder");
|
QName folder = QName.createQName(TEST_URL, "folder");
|
||||||
QName referenceable = QName.createQName("http://www.alfresco.org/test/dictionarydaotest/1.0", "referenceable");
|
QName referenceable = QName.createQName(TEST_URL, "referenceable");
|
||||||
|
|
||||||
// Test invalid args
|
// Test invalid args
|
||||||
try
|
try
|
||||||
|
@@ -27,6 +27,7 @@ import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
|||||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
@@ -166,7 +167,10 @@ import org.alfresco.service.namespace.QName;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*package*/ void resolveDependencies(ModelQuery query)
|
/*package*/ void resolveDependencies(
|
||||||
|
ModelQuery query,
|
||||||
|
NamespacePrefixResolver prefixResolver,
|
||||||
|
Map<QName, ConstraintDefinition> modelConstraints)
|
||||||
{
|
{
|
||||||
if (parentName != null)
|
if (parentName != null)
|
||||||
{
|
{
|
||||||
@@ -179,7 +183,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
|
|
||||||
for (PropertyDefinition def : properties.values())
|
for (PropertyDefinition def : properties.values())
|
||||||
{
|
{
|
||||||
((M2PropertyDefinition)def).resolveDependencies(query);
|
((M2PropertyDefinition)def).resolveDependencies(query, prefixResolver, modelConstraints);
|
||||||
}
|
}
|
||||||
for (AssociationDefinition def : associations.values())
|
for (AssociationDefinition def : associations.values())
|
||||||
{
|
{
|
||||||
|
74
source/java/org/alfresco/repo/dictionary/M2Constraint.java
Normal file
74
source/java/org/alfresco/repo/dictionary/M2Constraint.java
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract Property Constraint.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class M2Constraint
|
||||||
|
{
|
||||||
|
private String name;
|
||||||
|
private String ref;
|
||||||
|
private String type;
|
||||||
|
private String description;
|
||||||
|
private List<M2NamedValue> parameters = new ArrayList<M2NamedValue>(2);
|
||||||
|
|
||||||
|
/*package*/ M2Constraint()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRef()
|
||||||
|
{
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType()
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<M2NamedValue> getParameters()
|
||||||
|
{
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.repo.dictionary.constraint.RegexConstraint;
|
||||||
|
import org.alfresco.service.cmr.dictionary.Constraint;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
||||||
|
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.springframework.beans.BeanWrapper;
|
||||||
|
import org.springframework.beans.BeanWrapperImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiled Property Constraint
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
/*package*/ class M2ConstraintDefinition implements ConstraintDefinition
|
||||||
|
{
|
||||||
|
public static final String ERR_CYCLIC_REF = "d_dictionary.model.err.cyclic_ref";
|
||||||
|
public static final String ERR_TYPE_AND_REF = "d_dictionary.constraint.err.type_and_ref";
|
||||||
|
public static final String ERR_TYPE_OR_REF = "d_dictionary.constraint.err.type_or_ref";
|
||||||
|
public static final String ERR_REF_NOT_FOUND = "d_dictionary.constraint.err.ref_not_found";
|
||||||
|
public static final String ERR_ANON_NEEDS_PROPERTY = "d_dictionary.constraint.err.anon_needs_property";
|
||||||
|
public static final String ERR_INVALID_TYPE = "d_dictionary.constraint.err.invalid_type";
|
||||||
|
public static final String ERR_CONSTRUCT_FAILURE = "d_dictionary.constraint.err.construct_failure";
|
||||||
|
|
||||||
|
private static int anonPropCount = 0;
|
||||||
|
|
||||||
|
private ModelDefinition model;
|
||||||
|
private NamespacePrefixResolver prefixResolver;
|
||||||
|
private M2Constraint m2Constraint;
|
||||||
|
private QName name;
|
||||||
|
private Constraint constraint;
|
||||||
|
private boolean resolving;
|
||||||
|
|
||||||
|
/*package*/ M2ConstraintDefinition(
|
||||||
|
M2PropertyDefinition m2PropertyDef,
|
||||||
|
M2Constraint m2Constraint,
|
||||||
|
NamespacePrefixResolver prefixResolver)
|
||||||
|
{
|
||||||
|
this(m2PropertyDef.getModel(), m2PropertyDef, m2Constraint, prefixResolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ M2ConstraintDefinition(
|
||||||
|
ModelDefinition modelDefinition,
|
||||||
|
M2PropertyDefinition m2PropertyDef,
|
||||||
|
M2Constraint m2Constraint,
|
||||||
|
NamespacePrefixResolver prefixResolver)
|
||||||
|
{
|
||||||
|
this.model = modelDefinition;
|
||||||
|
this.m2Constraint = m2Constraint;
|
||||||
|
this.prefixResolver = prefixResolver;
|
||||||
|
|
||||||
|
String constraintName = m2Constraint.getName();
|
||||||
|
if (constraintName == null)
|
||||||
|
{
|
||||||
|
// the constraint is anonymous, so it has to be defined within the context of a property
|
||||||
|
if (m2PropertyDef == null)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_ANON_NEEDS_PROPERTY);
|
||||||
|
}
|
||||||
|
// pick the name up from the property and some anonymous value
|
||||||
|
String localName = m2PropertyDef.getName().getLocalName() + "_anon_" + (++anonPropCount);
|
||||||
|
this.name = QName.createQName(m2PropertyDef.getName().getNamespaceURI(), localName);
|
||||||
|
m2Constraint.setName(localName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.name = QName.createQName(m2Constraint.getName(), prefixResolver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ synchronized void resolveDependencies(ModelQuery query)
|
||||||
|
{
|
||||||
|
if (resolving)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_CYCLIC_REF, name.toPrefixString());
|
||||||
|
}
|
||||||
|
// prevent circular references
|
||||||
|
try
|
||||||
|
{
|
||||||
|
resolving = true;
|
||||||
|
resolveInternal(query);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
resolving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void resolveInternal(ModelQuery query)
|
||||||
|
{
|
||||||
|
if (constraint != null)
|
||||||
|
{
|
||||||
|
// already been resolved
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String shortName = name.toPrefixString();
|
||||||
|
String ref = m2Constraint.getRef();
|
||||||
|
String type = m2Constraint.getType();
|
||||||
|
if (ref != null && type != null)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_TYPE_AND_REF, shortName);
|
||||||
|
}
|
||||||
|
else if (ref == null && type == null)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_TYPE_OR_REF, shortName);
|
||||||
|
}
|
||||||
|
else if (ref != null)
|
||||||
|
{
|
||||||
|
// resolve the reference name
|
||||||
|
QName qnameRef = QName.createQName(ref, prefixResolver);
|
||||||
|
// ensure that the reference exists in the model
|
||||||
|
M2ConstraintDefinition constraintDef = (M2ConstraintDefinition) query.getConstraint(qnameRef);
|
||||||
|
if (constraintDef == null)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_REF_NOT_FOUND, ref, shortName);
|
||||||
|
}
|
||||||
|
// make sure that the constraint definition has itself been resolved
|
||||||
|
constraintDef.resolveDependencies(query);
|
||||||
|
// just use the constraint provided by the referenced definition
|
||||||
|
this.constraint = constraintDef.getConstraint();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we have to build the constraint from the type
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ConstraintType constraintType = ConstraintType.valueOf(type);
|
||||||
|
constraint = constraintType.newInstance();
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
// try to establish it as a class
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Class clazz = Class.forName(type);
|
||||||
|
constraint = (Constraint) clazz.newInstance();
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException ee)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_INVALID_TYPE, type, shortName);
|
||||||
|
}
|
||||||
|
catch (ClassCastException ee)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_INVALID_TYPE, type, shortName);
|
||||||
|
}
|
||||||
|
catch (Exception ee)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(ERR_CONSTRUCT_FAILURE, type, shortName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// property setters
|
||||||
|
BeanWrapper beanWrapper = new BeanWrapperImpl(constraint);
|
||||||
|
List<M2NamedValue> constraintNamedValues = m2Constraint.getParameters();
|
||||||
|
for (M2NamedValue namedValue : constraintNamedValues)
|
||||||
|
{
|
||||||
|
beanWrapper.setPropertyValue(namedValue.getName(), namedValue.getValue());
|
||||||
|
}
|
||||||
|
// now initialize
|
||||||
|
constraint.initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #getName()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getName().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelDefinition getModel()
|
||||||
|
{
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QName getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Constraint getConstraint()
|
||||||
|
{
|
||||||
|
return constraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Well-known constraint types
|
||||||
|
*/
|
||||||
|
public static enum ConstraintType
|
||||||
|
{
|
||||||
|
REGEX
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected Constraint newInstance()
|
||||||
|
{
|
||||||
|
return new RegexConstraint();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the constraint implementation
|
||||||
|
*/
|
||||||
|
protected abstract Constraint newInstance();
|
||||||
|
}
|
||||||
|
}
|
@@ -50,7 +50,7 @@ public class M2Model
|
|||||||
private List<M2DataType> dataTypes = new ArrayList<M2DataType>();
|
private List<M2DataType> dataTypes = new ArrayList<M2DataType>();
|
||||||
private List<M2Type> types = new ArrayList<M2Type>();
|
private List<M2Type> types = new ArrayList<M2Type>();
|
||||||
private List<M2Aspect> aspects = new ArrayList<M2Aspect>();
|
private List<M2Aspect> aspects = new ArrayList<M2Aspect>();
|
||||||
|
private List<M2Constraint> constraints = new ArrayList<M2Constraint>();
|
||||||
|
|
||||||
private M2Model()
|
private M2Model()
|
||||||
{
|
{
|
||||||
@@ -379,8 +379,13 @@ public class M2Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<M2Constraint> getConstraints()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableList(constraints);
|
||||||
|
}
|
||||||
|
|
||||||
// Do not delete: referenced by m2binding.xml
|
// Do not delete: referenced by m2binding.xml
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private static List createList()
|
private static List createList()
|
||||||
{
|
{
|
||||||
return new ArrayList();
|
return new ArrayList();
|
||||||
|
53
source/java/org/alfresco/repo/dictionary/M2NamedValue.java
Normal file
53
source/java/org/alfresco/repo/dictionary/M2NamedValue.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Definition of a named value that can be used for property injection.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class M2NamedValue
|
||||||
|
{
|
||||||
|
private String name;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
|
||||||
|
/*package*/ M2NamedValue()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return (name + "=" + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the raw, unconverted value
|
||||||
|
*/
|
||||||
|
public String getValue()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@@ -16,6 +16,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.dictionary;
|
package org.alfresco.repo.dictionary;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property Definition
|
* Property Definition
|
||||||
@@ -37,7 +40,7 @@ public class M2Property
|
|||||||
private boolean isIndexedAtomically = true;
|
private boolean isIndexedAtomically = true;
|
||||||
private boolean isStoredInIndex = false;
|
private boolean isStoredInIndex = false;
|
||||||
private boolean isTokenisedInIndex = true;
|
private boolean isTokenisedInIndex = true;
|
||||||
|
private List<M2Constraint> constraints;
|
||||||
|
|
||||||
/*package*/ M2Property()
|
/*package*/ M2Property()
|
||||||
{
|
{
|
||||||
@@ -193,4 +196,16 @@ public class M2Property
|
|||||||
this.isTokenisedInIndex = isTokenisedInIndex;
|
this.isTokenisedInIndex = isTokenisedInIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<M2Constraint> getConstraints()
|
||||||
|
{
|
||||||
|
if (constraints == null)
|
||||||
|
{
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return constraints;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,11 +16,18 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.dictionary;
|
package org.alfresco.repo.dictionary;
|
||||||
|
|
||||||
|
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.ClassDefinition;
|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
|
||||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
@@ -33,49 +40,85 @@ import org.alfresco.service.namespace.QName;
|
|||||||
/*package*/ class M2PropertyDefinition implements PropertyDefinition
|
/*package*/ class M2PropertyDefinition implements PropertyDefinition
|
||||||
{
|
{
|
||||||
private ClassDefinition classDef;
|
private ClassDefinition classDef;
|
||||||
private M2Property property;
|
private M2Property m2Property;
|
||||||
private QName name;
|
private QName name;
|
||||||
private QName propertyTypeName;
|
private QName propertyTypeName;
|
||||||
private DataTypeDefinition dataType;
|
private DataTypeDefinition dataType;
|
||||||
|
private List<ConstraintDefinition> constraints = new ArrayList<ConstraintDefinition>(5);
|
||||||
|
private Map<QName, ConstraintDefinition> constraintsByQName = new HashMap<QName, ConstraintDefinition>(7);
|
||||||
|
|
||||||
|
/*package*/ M2PropertyDefinition(
|
||||||
/*package*/ M2PropertyDefinition(ClassDefinition classDef, M2Property m2Property, NamespacePrefixResolver resolver)
|
ClassDefinition classDef,
|
||||||
|
M2Property m2Property,
|
||||||
|
NamespacePrefixResolver prefixResolver)
|
||||||
{
|
{
|
||||||
this.classDef = classDef;
|
this.classDef = classDef;
|
||||||
this.property = m2Property;
|
this.m2Property = m2Property;
|
||||||
|
|
||||||
// Resolve Names
|
// Resolve Names
|
||||||
this.name = QName.createQName(property.getName(), resolver);
|
this.name = QName.createQName(m2Property.getName(), prefixResolver);
|
||||||
this.propertyTypeName = QName.createQName(property.getType(), resolver);
|
this.propertyTypeName = QName.createQName(m2Property.getType(), prefixResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*package*/ M2PropertyDefinition(ClassDefinition classDef, PropertyDefinition propertyDef, M2PropertyOverride override)
|
/*package*/ M2PropertyDefinition(
|
||||||
|
ClassDefinition classDef,
|
||||||
|
PropertyDefinition propertyDef,
|
||||||
|
M2PropertyOverride override)
|
||||||
{
|
{
|
||||||
this.classDef = classDef;
|
this.classDef = classDef;
|
||||||
this.property = createOverriddenProperty(propertyDef, override);
|
this.m2Property = createOverriddenProperty(propertyDef, override);
|
||||||
this.name = propertyDef.getName();
|
this.name = propertyDef.getName();
|
||||||
this.dataType = propertyDef.getDataType();
|
this.dataType = propertyDef.getDataType();
|
||||||
this.propertyTypeName = this.dataType.getName();
|
this.propertyTypeName = this.dataType.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*package*/ void resolveDependencies(ModelQuery query)
|
/*package*/ void resolveDependencies(
|
||||||
|
ModelQuery query,
|
||||||
|
NamespacePrefixResolver prefixResolver,
|
||||||
|
Map<QName, ConstraintDefinition> modelConstraints)
|
||||||
{
|
{
|
||||||
if (propertyTypeName == null)
|
if (propertyTypeName == null)
|
||||||
{
|
{
|
||||||
throw new DictionaryException("Property type of property " + name.toPrefixString() + " must be specified");
|
throw new DictionaryException(
|
||||||
|
"d_dictionary.property.err.property_type_not_specified",
|
||||||
|
name.toPrefixString());
|
||||||
}
|
}
|
||||||
dataType = query.getDataType(propertyTypeName);
|
dataType = query.getDataType(propertyTypeName);
|
||||||
if (dataType == null)
|
if (dataType == null)
|
||||||
{
|
{
|
||||||
throw new DictionaryException("Property type " + propertyTypeName.toPrefixString() + " of property " + name.toPrefixString() + " is not found");
|
throw new DictionaryException(
|
||||||
|
"d_dictionary.property.err.property_type_not_found",
|
||||||
|
propertyTypeName.toPrefixString(), name.toPrefixString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure content properties are not multi-valued
|
// ensure content properties are not multi-valued
|
||||||
if (propertyTypeName.equals(DataTypeDefinition.CONTENT) && isMultiValued())
|
if (propertyTypeName.equals(DataTypeDefinition.CONTENT) && isMultiValued())
|
||||||
{
|
{
|
||||||
throw new DictionaryException("Content properties must be single-valued");
|
throw new DictionaryException("d_dictionary.property.err.single_valued_content");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct constraints
|
||||||
|
for (M2Constraint constraint : m2Property.getConstraints())
|
||||||
|
{
|
||||||
|
ConstraintDefinition def = new M2ConstraintDefinition(this, 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());
|
||||||
|
}
|
||||||
|
else if (modelConstraints.containsKey(qname))
|
||||||
|
{
|
||||||
|
throw new DictionaryException(
|
||||||
|
"d_dictionary.model.err.duplicate_constraint_on_model",
|
||||||
|
def.getName().toPrefixString());
|
||||||
|
}
|
||||||
|
constraintsByQName.put(qname, def);
|
||||||
|
constraints.add(def);
|
||||||
|
modelConstraints.put(qname, def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +196,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
String value = M2Label.getLabel(classDef.getModel(), "property", name, "title");
|
String value = M2Label.getLabel(classDef.getModel(), "property", name, "title");
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
value = property.getTitle();
|
value = m2Property.getTitle();
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@@ -167,7 +210,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
String value = M2Label.getLabel(classDef.getModel(), "property", name, "description");
|
String value = M2Label.getLabel(classDef.getModel(), "property", name, "description");
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
value = property.getDescription();
|
value = m2Property.getDescription();
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@@ -178,7 +221,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public String getDefaultValue()
|
public String getDefaultValue()
|
||||||
{
|
{
|
||||||
return property.getDefaultValue();
|
return m2Property.getDefaultValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -205,7 +248,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public boolean isMultiValued()
|
public boolean isMultiValued()
|
||||||
{
|
{
|
||||||
return property.isMultiValued();
|
return m2Property.isMultiValued();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -214,7 +257,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public boolean isMandatory()
|
public boolean isMandatory()
|
||||||
{
|
{
|
||||||
return property.isMandatory();
|
return m2Property.isMandatory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -223,7 +266,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public boolean isProtected()
|
public boolean isProtected()
|
||||||
{
|
{
|
||||||
return property.isProtected();
|
return m2Property.isProtected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -232,7 +275,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public boolean isIndexed()
|
public boolean isIndexed()
|
||||||
{
|
{
|
||||||
return property.isIndexed();
|
return m2Property.isIndexed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -241,7 +284,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public boolean isStoredInIndex()
|
public boolean isStoredInIndex()
|
||||||
{
|
{
|
||||||
return property.isStoredInIndex();
|
return m2Property.isStoredInIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -250,7 +293,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public boolean isIndexedAtomically()
|
public boolean isIndexedAtomically()
|
||||||
{
|
{
|
||||||
return property.isIndexedAtomically();
|
return m2Property.isIndexedAtomically();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -259,7 +302,11 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public boolean isTokenisedInIndex()
|
public boolean isTokenisedInIndex()
|
||||||
{
|
{
|
||||||
return property.isTokenisedInIndex();
|
return m2Property.isTokenisedInIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ConstraintDefinition> getConstraints()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableList(constraints);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
|||||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
@@ -81,6 +82,14 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public PropertyDefinition getProperty(QName name);
|
public PropertyDefinition getProperty(QName name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the specified property constraint
|
||||||
|
*
|
||||||
|
* @param name the qualified name of the property constraint
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ConstraintDefinition getConstraint(QName name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the specified association
|
* Gets the specified association
|
||||||
*
|
*
|
||||||
|
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.dictionary.Constraint;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base services for constraints.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public abstract class AbstractConstraint implements Constraint
|
||||||
|
{
|
||||||
|
public static final String ERR_PROP_NOT_SET = "d_dictionary.model.err.property_not_set";
|
||||||
|
public static final String ERR_EVALUATE_EXCEPTION = "d_dictionary.model.err.evaluate_exception";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #evaluateSingleValue(Object)
|
||||||
|
* @see #evaluateCollection(Collection)
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public final void evaluate(Object value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// check for collection
|
||||||
|
if (value instanceof Collection)
|
||||||
|
{
|
||||||
|
Collection collection = (Collection) value;
|
||||||
|
evaluateCollection(collection);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
evaluateSingleValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (DictionaryException e)
|
||||||
|
{
|
||||||
|
// this can go
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(AbstractConstraint.ERR_EVALUATE_EXCEPTION, this, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only override if there is some specific evaluation that needs to be performed on the
|
||||||
|
* collection as a whole.
|
||||||
|
*
|
||||||
|
* @param collection the collection of values to evaluate
|
||||||
|
*
|
||||||
|
* @see #evaluateSingleValue(Object)
|
||||||
|
*/
|
||||||
|
protected void evaluateCollection(Collection<Object> collection)
|
||||||
|
{
|
||||||
|
for (Object value : collection)
|
||||||
|
{
|
||||||
|
evaluateSingleValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for evaluation of properties. The value passed in will never be a
|
||||||
|
* collection.
|
||||||
|
*
|
||||||
|
* @throws DictionaryException throw this when the evaluation fails
|
||||||
|
*/
|
||||||
|
protected abstract void evaluateSingleValue(Object value);
|
||||||
|
}
|
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* 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 java.util.ArrayList;
|
||||||
|
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.DictionaryException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.service.cmr.dictionary.Constraint
|
||||||
|
* @see org.alfresco.repo.dictionary.constraint.AbstractConstraint
|
||||||
|
* @see org.alfresco.repo.dictionary.constraint.RegexConstraint
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class ConstraintsTest extends TestCase
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
// register resource bundles for messages
|
||||||
|
I18NUtil.registerResourceBundle(DictionaryDAOTest.TEST_RESOURCE_MESSAGES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ensure that the default handling of checks on collections will work
|
||||||
|
*/
|
||||||
|
public void testCollections() throws Exception
|
||||||
|
{
|
||||||
|
DummyConstraint constraint = new DummyConstraint();
|
||||||
|
constraint.initialize();
|
||||||
|
|
||||||
|
List<Object> dummyObjects = new ArrayList<Object>(3);
|
||||||
|
dummyObjects.add("ABC"); // correct
|
||||||
|
dummyObjects.add("DEF"); // correct
|
||||||
|
dummyObjects.add(this); // NO
|
||||||
|
try
|
||||||
|
{
|
||||||
|
constraint.evaluate(dummyObjects);
|
||||||
|
fail("Failed to detected constraint violation in collection");
|
||||||
|
}
|
||||||
|
catch (DictionaryException e)
|
||||||
|
{
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
// check that the two strings were properly dealt with
|
||||||
|
assertEquals("String values not checked", 2, constraint.tested.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRegexConstraint() throws Exception
|
||||||
|
{
|
||||||
|
RegexConstraint constraint = new RegexConstraint();
|
||||||
|
constraint.setExpression("[A-Z]*");
|
||||||
|
constraint.initialize();
|
||||||
|
|
||||||
|
// do some successful stuff
|
||||||
|
constraint.evaluate("ABC");
|
||||||
|
constraint.evaluate("DEF");
|
||||||
|
|
||||||
|
// now some failures
|
||||||
|
try
|
||||||
|
{
|
||||||
|
constraint.evaluate("abc");
|
||||||
|
fail("Regular expression evaluation should have failed: abc");
|
||||||
|
}
|
||||||
|
catch (DictionaryException 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
|
||||||
|
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 (DictionaryException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum DummyEnum
|
||||||
|
{
|
||||||
|
ABC,
|
||||||
|
DEF,
|
||||||
|
abc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DummyConstraint extends AbstractConstraint
|
||||||
|
{
|
||||||
|
private List<Object> tested;
|
||||||
|
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
tested = new ArrayList<Object>(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fails on everything but String values, which pass.
|
||||||
|
* Null values cause runtime exceptions and all other failures are by
|
||||||
|
* DictionaryException.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void evaluateSingleValue(Object value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
throw new NullPointerException("Null value in dummy test");
|
||||||
|
}
|
||||||
|
else if (value instanceof String)
|
||||||
|
{
|
||||||
|
tested.add(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new DictionaryException("Non-String value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.DictionaryException;
|
||||||
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constraint implementation that performs regular expression comparisons.
|
||||||
|
* Where possible, the {@link org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter type converter}
|
||||||
|
* will be used to first convert the value to a <code>String</code>, so the evaluation
|
||||||
|
* will be against the value's <code>String</code> equivalent.
|
||||||
|
*
|
||||||
|
* @see java.lang.String#matches(java.lang.String)
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class RegexConstraint extends AbstractConstraint
|
||||||
|
{
|
||||||
|
public static final String CONSTRAINT_REGEX_NO_MATCH = "d_dictionary.constraint.regex.no_match";
|
||||||
|
|
||||||
|
private String expression;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the regular expression used to evaluate string values
|
||||||
|
* @param expression similar to the {@link String#matches(java.lang.String) argument
|
||||||
|
*/
|
||||||
|
public void setExpression(String expression)
|
||||||
|
{
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize()
|
||||||
|
{
|
||||||
|
if (expression == null)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(AbstractConstraint.ERR_PROP_NOT_SET, "expression");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void evaluateSingleValue(Object value)
|
||||||
|
{
|
||||||
|
// convert the value to a String
|
||||||
|
String valueStr = DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||||
|
boolean matches = valueStr.matches(expression);
|
||||||
|
if (!matches)
|
||||||
|
{
|
||||||
|
throw new DictionaryException(RegexConstraint.CONSTRAINT_REGEX_NO_MATCH, value, expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -22,6 +22,12 @@
|
|||||||
|
|
||||||
</data-types>
|
</data-types>
|
||||||
|
|
||||||
|
<constraints>
|
||||||
|
<constraint name="test:regex1" type="REGEX">
|
||||||
|
<parameter name="expression">[A-Z]*</parameter>
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
|
|
||||||
<types>
|
<types>
|
||||||
|
|
||||||
<type name="test:base">
|
<type name="test:base">
|
||||||
@@ -34,6 +40,9 @@
|
|||||||
<type>d:text</type>
|
<type>d:text</type>
|
||||||
<protected>true</protected>
|
<protected>true</protected>
|
||||||
<default></default>
|
<default></default>
|
||||||
|
<constraints>
|
||||||
|
<constraint ref="test:regex1"/>
|
||||||
|
</constraints>
|
||||||
</property>
|
</property>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
@@ -41,6 +41,10 @@
|
|||||||
</collection>
|
</collection>
|
||||||
</structure>
|
</structure>
|
||||||
|
|
||||||
|
<structure name="constraints" usage="optional">
|
||||||
|
<collection field="constraints" item-type="org.alfresco.repo.dictionary.M2Constraint" factory="org.alfresco.repo.dictionary.M2Model.createList"/>
|
||||||
|
</structure>
|
||||||
|
|
||||||
<structure name="types" usage="optional">
|
<structure name="types" usage="optional">
|
||||||
<collection field="types" item-type="org.alfresco.repo.dictionary.M2Type" factory="org.alfresco.repo.dictionary.M2Model.createList"/>
|
<collection field="types" item-type="org.alfresco.repo.dictionary.M2Type" factory="org.alfresco.repo.dictionary.M2Model.createList"/>
|
||||||
</structure>
|
</structure>
|
||||||
@@ -102,6 +106,24 @@
|
|||||||
<value name="stored" field="isStoredInIndex" usage="optional"/>
|
<value name="stored" field="isStoredInIndex" usage="optional"/>
|
||||||
<value name="tokenised" field="isTokenisedInIndex" usage="optional"/>
|
<value name="tokenised" field="isTokenisedInIndex" usage="optional"/>
|
||||||
</structure>
|
</structure>
|
||||||
|
<structure name="constraints" usage="optional">
|
||||||
|
<collection field="constraints" item-type="org.alfresco.repo.dictionary.M2Constraint" factory="org.alfresco.repo.dictionary.M2Model.createList"/>
|
||||||
|
</structure>
|
||||||
|
</mapping>
|
||||||
|
|
||||||
|
<mapping abstract="true" class="org.alfresco.repo.dictionary.M2NamedValue">
|
||||||
|
<value style="attribute" name="name" field="name" />
|
||||||
|
<value style="text" field="value"/>
|
||||||
|
</mapping>
|
||||||
|
|
||||||
|
<mapping name="constraint" class="org.alfresco.repo.dictionary.M2Constraint">
|
||||||
|
<value style="attribute" name="name" field="name" usage="optional"/>
|
||||||
|
<value style="attribute" name="type" field="type" usage="optional"/>
|
||||||
|
<value style="attribute" name="ref" field="ref" usage="optional"/>
|
||||||
|
<value name="description" field="description" usage="optional"/>
|
||||||
|
<collection field="parameters" factory="org.alfresco.repo.dictionary.M2Model.createList" usage="optional">
|
||||||
|
<structure name="parameter" type="org.alfresco.repo.dictionary.M2NamedValue" />
|
||||||
|
</collection>
|
||||||
</mapping>
|
</mapping>
|
||||||
|
|
||||||
<mapping class="org.alfresco.repo.dictionary.M2ClassAssociation" abstract="true">
|
<mapping class="org.alfresco.repo.dictionary.M2ClassAssociation" abstract="true">
|
||||||
|
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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.service.cmr.dictionary;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface for classes that implement constraints on property values.
|
||||||
|
* <p>
|
||||||
|
* Implementations of the actual constraint code should must not synchronize
|
||||||
|
* or in any other way block threads. Concurrent access of the evaluation
|
||||||
|
* method is expected, but will always occur after initialization has completed.
|
||||||
|
* <p>
|
||||||
|
* Attention to performance is <u>crucial</u> for all implementations as
|
||||||
|
* instances of this class are heavily used.
|
||||||
|
* <p>
|
||||||
|
* The constraint implementations can provide standard setter methods that will
|
||||||
|
* be populated by bean setter injection. Once all the available properties have
|
||||||
|
* been set, the contraint will be initialized.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public interface Constraint
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes the constraint with appropriate values, which will depend
|
||||||
|
* on the implementation itself. This method can be implemented as a
|
||||||
|
* once-off, i.e. reinitialization does not have to be supported.
|
||||||
|
*
|
||||||
|
* @param parameters constraint parameters
|
||||||
|
*/
|
||||||
|
public void initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates a property value according to the implementation and initialization
|
||||||
|
* parameters provided.
|
||||||
|
*
|
||||||
|
* @param value the property value to check
|
||||||
|
*
|
||||||
|
* @throws ConstraintException if the value doesn't pass all constraints
|
||||||
|
*/
|
||||||
|
public void evaluate(Object value);
|
||||||
|
}
|
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.service.cmr.dictionary;
|
||||||
|
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property constraint definition
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public interface ConstraintDefinition
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return defining model
|
||||||
|
*/
|
||||||
|
public ModelDefinition getModel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the qualified name of the constraint
|
||||||
|
*/
|
||||||
|
public QName getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the constraint implementation
|
||||||
|
*/
|
||||||
|
public Constraint getConstraint();
|
||||||
|
}
|
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.service.cmr.dictionary;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when property value fails to meet a property constraint.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class ConstraintException extends AlfrescoRuntimeException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -3925105163386197586L;
|
||||||
|
|
||||||
|
public ConstraintException(String msgId, Object ... args)
|
||||||
|
{
|
||||||
|
super(msgId, args);
|
||||||
|
}
|
||||||
|
}
|
@@ -16,13 +16,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.service.cmr.dictionary;
|
package org.alfresco.service.cmr.dictionary;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Exception of Data Dictionary Exceptions.
|
* Base Exception of Data Dictionary Exceptions.
|
||||||
*
|
*
|
||||||
* @author David Caruana
|
* @author David Caruana
|
||||||
*/
|
*/
|
||||||
public class DictionaryException extends RuntimeException
|
public class DictionaryException extends AlfrescoRuntimeException
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 3257008761007847733L;
|
private static final long serialVersionUID = 3257008761007847733L;
|
||||||
|
|
||||||
@@ -36,4 +37,13 @@ public class DictionaryException extends RuntimeException
|
|||||||
super(msg, cause);
|
super(msg, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DictionaryException(String msgId, Object ... args)
|
||||||
|
{
|
||||||
|
super(msgId, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DictionaryException(String msgId, Throwable cause, Object ... args)
|
||||||
|
{
|
||||||
|
super(msgId, args, cause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.service.cmr.dictionary;
|
package org.alfresco.service.cmr.dictionary;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,4 +100,10 @@ public interface PropertyDefinition
|
|||||||
*/
|
*/
|
||||||
public boolean isIndexedAtomically();
|
public boolean isIndexedAtomically();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all constraints that apply to the property value
|
||||||
|
*
|
||||||
|
* @return Returns a list of property constraint definitions
|
||||||
|
*/
|
||||||
|
public List<ConstraintDefinition> getConstraints();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user