Dictionary/Constraint improvements (required by MOB-1276)

- get constraints (for model)
- add optional title and/or description

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@15913 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jan Vonka
2009-08-25 21:29:27 +00:00
parent 9fff828051
commit 1bba527f56
16 changed files with 1680 additions and 1404 deletions

View File

@@ -35,10 +35,10 @@ 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.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.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.DynamicNamespacePrefixResolver; import org.alfresco.service.namespace.DynamicNamespacePrefixResolver;
import org.alfresco.service.namespace.NamespaceException; import org.alfresco.service.namespace.NamespaceException;
@@ -414,6 +414,14 @@ import org.apache.commons.logging.LogFactory;
return associations.values(); return associations.values();
} }
/**
* @return the compiled constraints
*/
public Collection<ConstraintDefinition> getConstraints()
{
return constraints.values();
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getConstraint(QName) * @see org.alfresco.repo.dictionary.impl.ModelQuery#getConstraint(QName)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -33,6 +33,7 @@ import org.alfresco.repo.tenant.TenantDeployer;
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.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.ModelDefinition; import org.alfresco.service.cmr.dictionary.ModelDefinition;
@@ -396,6 +397,11 @@ public class DictionaryComponent implements DictionaryService, TenantDeployer
} }
return props; return props;
} }
public Collection<ConstraintDefinition> getConstraints(QName model)
{
return dictionaryDAO.getConstraints(model);
}
public void init() public void init()
{ {

View File

@@ -1,186 +1,193 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.dictionary; package org.alfresco.repo.dictionary;
import java.util.Collection; import java.util.Collection;
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.ModelDefinition; 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.NamespaceDefinition; import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.namespace.QName; import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
/**
* Dictionary Data Access /**
* * Dictionary Data Access
* @author David Caruana *
*/ * @author David Caruana
public interface DictionaryDAO extends ModelQuery */
{ public interface DictionaryDAO extends ModelQuery
{
/**
* @return the models known by the dictionary /**
*/ * @return the models known by the dictionary
public Collection<QName> getModels(); */
public Collection<QName> getModels();
/**
* @param name the model to retrieve /**
* @return the named model definition * @param name the model to retrieve
*/ * @return the named model definition
public ModelDefinition getModel(QName name); */
public ModelDefinition getModel(QName name);
/**
* @param model the model to retrieve property types for /**
* @return the property types of the model * @param model the model to retrieve property types for
*/ * @return the property types of the model
public Collection<DataTypeDefinition> getDataTypes(QName model); */
public Collection<DataTypeDefinition> getDataTypes(QName model);
/**
* @param model the model to retrieve types for /**
* @return the types of the model * @param model the model to retrieve types for
*/ * @return the types of the model
public Collection<TypeDefinition> getTypes(QName model); */
public Collection<TypeDefinition> getTypes(QName model);
/**
* @param superType /**
* @param follow true => follow up the super-class hierarchy, false => immediate sub types only * @param superType
* @return * @param follow true => follow up the super-class hierarchy, false => immediate sub types only
*/ * @return
public Collection<QName> getSubTypes(QName superType, boolean follow); */
public Collection<QName> getSubTypes(QName superType, boolean follow);
/**
* @param model the model to retrieve aspects for /**
* @return the aspects of the model * @param model the model to retrieve aspects for
*/ * @return the aspects of the model
public Collection<AspectDefinition> getAspects(QName model); */
public Collection<AspectDefinition> getAspects(QName model);
/**
* @param model the model to retrieve associations for /**
* @return the associations of the model * @param model the model to retrieve associations for
*/ * @return the associations of the model
public Collection<AssociationDefinition> getAssociations(QName model); */
public Collection<AssociationDefinition> getAssociations(QName model);
/**
* @param superAspect /**
* @param follow true => follow up the super-class hierarchy, false => immediate sub aspects only * @param superAspect
* @return * @param follow true => follow up the super-class hierarchy, false => immediate sub aspects only
*/ * @return
public Collection<QName> getSubAspects(QName superAspect, boolean follow); */
public Collection<QName> getSubAspects(QName superAspect, boolean follow);
/**
* @param model the model for which to get properties for /**
* @return the properties of the model * @param model the model for which to get properties for
*/ * @return the properties of the model
public Collection<PropertyDefinition> getProperties(QName model); */
public Collection<PropertyDefinition> getProperties(QName model);
/**
* Construct an anonymous type that combines a primary type definition and /**
* and one or more aspects * Construct an anonymous type that combines a primary type definition and
* * and one or more aspects
* @param type the primary type *
* @param aspects the aspects to combine * @param type the primary type
* @return the anonymous type definition * @param aspects the aspects to combine
*/ * @return the anonymous type definition
public TypeDefinition getAnonymousType(QName type, Collection<QName> aspects); */
public TypeDefinition getAnonymousType(QName type, Collection<QName> aspects);
/**
* Adds a model to the dictionary. The model is compiled and validated. /**
* * Adds a model to the dictionary. The model is compiled and validated.
* @param model the model to add *
* @return QName name of model * @param model the model to add
*/ * @return QName name of model
public QName putModel(M2Model model); */
public QName putModel(M2Model model);
/**
* Removes a model from the dictionary. The types and aspect in the model will no longer be /**
* available. * Removes a model from the dictionary. The types and aspect in the model will no longer be
* * available.
* @param model the qname of the model to remove *
*/ * @param model the qname of the model to remove
public void removeModel(QName model); */
public void removeModel(QName model);
/**
* Get all properties for the model and that are of the given data type. /**
* If dataType is null then the all properties will be returned. * Get all properties for the model and that are of the given data type.
* * If dataType is null then the all properties will be returned.
* @param modelName *
* @param dataType * @param modelName
* @return * @param dataType
*/ * @return
public Collection<PropertyDefinition> getProperties(QName modelName, QName dataType); */
public Collection<PropertyDefinition> getProperties(QName modelName, QName dataType);
/**
* @param model the model to retrieve namespaces for /**
* @return the namespaces of the model * @param model the model to retrieve namespaces for
*/ * @return the namespaces of the model
public Collection<NamespaceDefinition> getNamespaces(QName modelName); */
public Collection<NamespaceDefinition> getNamespaces(QName modelName);
/**
* validate against dictionary /**
* * @param model the model to retrieve constraints for
* if new model * @return the constraints of the model
* then nothing to validate */
* public Collection<ConstraintDefinition> getConstraints(QName model);
* else if an existing model
* then could be updated (or unchanged) so validate to currently only allow incremental updates /**
* - addition of new types, aspects (except default aspects), properties, associations * validate against dictionary
* - no deletion of types, aspects or properties or associations *
* - no addition, update or deletion of default/mandatory aspects * if new model
* * then nothing to validate
* @param newOrUpdatedModel *
*/ * else if an existing model
public void validateModel(M2Model newOrUpdatedModel); * then could be updated (or unchanged) so validate to currently only allow incremental updates
* - addition of new types, aspects (except default aspects), properties, associations
/** * - no deletion of types, aspects or properties or associations
* * - no addition, update or deletion of default/mandatory aspects
* Register listener with the Dictionary *
* * @param newOrUpdatedModel
* @param dictionaryListener */
*/ public void validateModel(M2Model newOrUpdatedModel);
public void register(DictionaryListener dictionaryListener);
/**
/** *
* Reset the Dictionary - destroy & re-initialise * Register listener with the Dictionary
*/ *
public void reset(); * @param dictionaryListener
*/
/** public void register(DictionaryListener dictionaryListener);
* Initialise the Dictionary
*/ /**
public void init(); * Reset the Dictionary - destroy & re-initialise
*/
/** public void reset();
* Destroy the Dictionary
*/ /**
public void destroy(); * Initialise the Dictionary
*/
// MT-specific public void init();
public boolean isModelInherited(QName name);
} /**
* Destroy the Dictionary
*/
public void destroy();
// MT-specific
public boolean isModelInherited(QName name);
}

View File

@@ -932,6 +932,15 @@ public class DictionaryDAOImpl implements DictionaryDAO
return namespaces; return namespaces;
} }
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryDAO#getConstraints(org.alfresco.service.namespace.QName)
*/
public Collection<ConstraintDefinition> getConstraints(QName modelName)
{
CompiledModel model = getCompiledModel(modelName);
return model.getConstraints();
}
// re-entrant (eg. via reset) // re-entrant (eg. via reset)
private DictionaryRegistry getDictionaryRegistry(String tenantDomain) private DictionaryRegistry getDictionaryRegistry(String tenantDomain)
{ {

View File

@@ -29,6 +29,7 @@ import java.io.ByteArrayOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -172,7 +173,7 @@ public class DictionaryDAOTest extends TestCase
bootstrap.setModels(bootstrapModels); bootstrap.setModels(bootstrapModels);
bootstrap.setDictionaryDAO(dictionaryDAO); bootstrap.setDictionaryDAO(dictionaryDAO);
bootstrap.setTenantService(tenantService); bootstrap.setTenantService(tenantService);
bootstrap.bootstrap(); bootstrap.bootstrap();
} }
@@ -203,7 +204,36 @@ public class DictionaryDAOTest extends TestCase
// Check that the registered constraints are correct // Check that the registered constraints are correct
assertNotNull("Constraint reg1 not registered", ConstraintRegistry.getInstance().getConstraint("cm:reg1")); assertNotNull("Constraint reg1 not registered", ConstraintRegistry.getInstance().getConstraint("cm:reg1"));
assertNotNull("Constraint reg2 not registered", ConstraintRegistry.getInstance().getConstraint("cm:reg2")); assertNotNull("Constraint reg2 not registered", ConstraintRegistry.getInstance().getConstraint("cm:reg2"));
QName model = QName.createQName(TEST_URL, "dictionarydaotest");
Collection<ConstraintDefinition> modelConstraints = service.getConstraints(model);
assertEquals(15, modelConstraints.size()); // 8 + 7
QName conRegExp1QName = QName.createQName(TEST_URL, "regex1");
boolean found1 = false;
QName conStrLen1QName = QName.createQName(TEST_URL, "stringLength1");
boolean found2 = false;
for (ConstraintDefinition constraintDef : modelConstraints)
{
if (constraintDef.getName().equals(conRegExp1QName))
{
assertEquals("Regex1 title", constraintDef.getTitle());
assertEquals("Regex1 description", constraintDef.getDescription());
found1 = true;
}
if (constraintDef.getName().equals(conStrLen1QName))
{
assertNull(constraintDef.getTitle());
assertNull(constraintDef.getDescription());
found2 = true;
}
}
assertTrue(found1);
assertTrue(found2);
// get the constraints for a property without constraints // get the constraints for a property without constraints
QName propNoConstraintsQName = QName.createQName(TEST_URL, "fileprop"); QName propNoConstraintsQName = QName.createQName(TEST_URL, "fileprop");
PropertyDefinition propNoConstraintsDef = service.getProperty(propNoConstraintsQName); PropertyDefinition propNoConstraintsDef = service.getProperty(propNoConstraintsQName);
@@ -222,6 +252,17 @@ public class DictionaryDAOTest extends TestCase
// check the individual constraints // check the individual constraints
ConstraintDefinition constraintDef = constraints.get(0); ConstraintDefinition constraintDef = constraints.get(0);
assertTrue("Constraint anonymous name incorrect", constraintDef.getName().getLocalName().startsWith("prop1_anon")); assertTrue("Constraint anonymous name incorrect", constraintDef.getName().getLocalName().startsWith("prop1_anon"));
// inherit title / description for reference constraint
assertTrue("Constraint title incorrect", constraintDef.getTitle().equals("Regex1 title"));
assertTrue("Constraint description incorrect", constraintDef.getDescription().equals("Regex1 description"));
constraintDef = constraints.get(1);
assertTrue("Constraint anonymous name incorrect", constraintDef.getName().getLocalName().startsWith("prop1_anon"));
assertTrue("Constraint title incorrect", constraintDef.getTitle().equals("Prop1 Strlen1 title"));
assertTrue("Constraint description incorrect", constraintDef.getDescription().equals("Prop1 Strlen1 description"));
// check that the constraint implementation is valid (it used a reference) // check that the constraint implementation is valid (it used a reference)
Constraint constraint = constraintDef.getConstraint(); Constraint constraint = constraintDef.getConstraint();
assertNotNull("Reference constraint has no implementation", constraint); assertNotNull("Reference constraint has no implementation", constraint);

View File

@@ -1,82 +1,133 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.dictionary; package org.alfresco.repo.dictionary;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Abstract Property Constraint. * Abstract Property Constraint.
* *
* @author Derek Hulley * @author Derek Hulley
*/ */
public class M2Constraint public class M2Constraint
{ {
private String name; private String name;
private String ref; private String ref;
private String type; private String type;
private String description; private String title;
private List<M2NamedValue> parameters = new ArrayList<M2NamedValue>(2); private String description;
private List<M2NamedValue> parameters = new ArrayList<M2NamedValue>(2);
/*package*/ M2Constraint()
{ /*package*/ M2Constraint()
} {
}
@Override
public String toString() @Override
{ public String toString()
return this.name; {
} return this.name;
}
public String getName()
{ public String getName()
return name; {
} return name;
}
public void setName(String name)
{ public void setName(String name)
this.name = name; {
} this.name = name;
}
public String getRef()
{ public String getRef()
return ref; {
} return ref;
}
public String getType()
{ public String getType()
return type; {
} return type;
}
public String getDescription()
{ public void setType(String type)
return description; {
} this.type = type;
}
public List<M2NamedValue> getParameters()
{ public String getTitle()
return parameters; {
} return title;
} }
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public List<M2NamedValue> getParameters()
{
return parameters;
}
public M2NamedValue createParameter(String name, String simpleValue)
{
M2NamedValue param = new M2NamedValue();
param.setName(name);
param.setSimpleValue(simpleValue);
parameters.add(param);
return param;
}
public M2NamedValue createParameter(String name, List<String> listValue)
{
M2NamedValue param = new M2NamedValue();
param.setName(name);
param.setListValue(listValue);
parameters.add(param);
return param;
}
public void removeParameter(String name)
{
List<M2NamedValue> params = getParameters();
for (M2NamedValue param : params)
{
if (param.getName().equals(name))
{
parameters.remove(param);
}
}
}
}

View File

@@ -1,327 +1,375 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.dictionary; package org.alfresco.repo.dictionary;
import java.util.List; import java.util.List;
import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint; import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint;
import org.alfresco.repo.dictionary.constraint.NumericRangeConstraint; import org.alfresco.repo.dictionary.constraint.NumericRangeConstraint;
import org.alfresco.repo.dictionary.constraint.RegexConstraint; import org.alfresco.repo.dictionary.constraint.RegexConstraint;
import org.alfresco.repo.dictionary.constraint.RegisteredConstraint; import org.alfresco.repo.dictionary.constraint.RegisteredConstraint;
import org.alfresco.repo.dictionary.constraint.StringLengthConstraint; import org.alfresco.repo.dictionary.constraint.StringLengthConstraint;
import org.alfresco.service.cmr.dictionary.Constraint; import org.alfresco.service.cmr.dictionary.Constraint;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition; import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException; import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.ModelDefinition; import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.namespace.NamespacePrefixResolver; import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.InvalidPropertyException; import org.springframework.beans.InvalidPropertyException;
import org.springframework.beans.PropertyAccessException; import org.springframework.beans.PropertyAccessException;
/** /**
* Compiled Property Constraint * Compiled Property Constraint
* *
* @author Derek Hulley * @author Derek Hulley
*/ */
/* package */class M2ConstraintDefinition implements ConstraintDefinition /* package */class M2ConstraintDefinition implements ConstraintDefinition
{ {
private static final String PROP_SHORT_NAME = "shortName"; private static final String PROP_SHORT_NAME = "shortName";
private static final String PROP_TITLE = "title";
public static final String ERR_CYCLIC_REF = "d_dictionary.constraint.err.cyclic_ref"; private static final String PROP_DESCRIPTION = "description";
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_CYCLIC_REF = "d_dictionary.constraint.err.cyclic_ref";
public static final String ERR_REF_NOT_FOUND = "d_dictionary.constraint.err.ref_not_found"; public static final String ERR_TYPE_AND_REF = "d_dictionary.constraint.err.type_and_ref";
public static final String ERR_ANON_NEEDS_PROPERTY = "d_dictionary.constraint.err.anon_needs_property"; public static final String ERR_TYPE_OR_REF = "d_dictionary.constraint.err.type_or_ref";
public static final String ERR_INVALID_TYPE = "d_dictionary.constraint.err.invalid_type"; public static final String ERR_REF_NOT_FOUND = "d_dictionary.constraint.err.ref_not_found";
public static final String ERR_SIMPLE_AND_LIST = "d_dictionary.constraint.err.property_simple_and_list"; public static final String ERR_ANON_NEEDS_PROPERTY = "d_dictionary.constraint.err.anon_needs_property";
public static final String ERR_CONSTRUCT_FAILURE = "d_dictionary.constraint.err.construct_failure"; public static final String ERR_INVALID_TYPE = "d_dictionary.constraint.err.invalid_type";
public static final String ERR_PROPERTY_MISMATCH = "d_dictionary.constraint.err.property_mismatch"; public static final String ERR_SIMPLE_AND_LIST = "d_dictionary.constraint.err.property_simple_and_list";
public static final String ERR_RESERVED_PROPERTY = "d_dictionary.constraint.err.reserved_property"; public static final String ERR_CONSTRUCT_FAILURE = "d_dictionary.constraint.err.construct_failure";
public static final String ERR_PROPERTY_MISMATCH = "d_dictionary.constraint.err.property_mismatch";
private static int anonPropCount = 0; public static final String ERR_RESERVED_PROPERTY = "d_dictionary.constraint.err.reserved_property";
private ModelDefinition model; private static int anonPropCount = 0;
private NamespacePrefixResolver prefixResolver;
private M2Constraint m2Constraint; private ModelDefinition model;
private QName name; private NamespacePrefixResolver prefixResolver;
private Constraint constraint; private M2Constraint m2Constraint;
private boolean resolving; private QName name;
private Constraint constraint;
/* package */M2ConstraintDefinition(M2PropertyDefinition m2PropertyDef, M2Constraint m2Constraint, private boolean resolving;
NamespacePrefixResolver prefixResolver)
{ /* package */M2ConstraintDefinition(M2PropertyDefinition m2PropertyDef, M2Constraint m2Constraint,
this(m2PropertyDef.getModel(), m2PropertyDef, m2Constraint, prefixResolver); NamespacePrefixResolver prefixResolver)
} {
this(m2PropertyDef.getModel(), m2PropertyDef, m2Constraint, prefixResolver);
/* package */M2ConstraintDefinition(ModelDefinition modelDefinition, M2PropertyDefinition m2PropertyDef, }
M2Constraint m2Constraint, NamespacePrefixResolver prefixResolver)
{ /* package */M2ConstraintDefinition(ModelDefinition modelDefinition, M2PropertyDefinition m2PropertyDef,
this.model = modelDefinition; M2Constraint m2Constraint, NamespacePrefixResolver prefixResolver)
this.m2Constraint = m2Constraint; {
this.prefixResolver = prefixResolver; this.model = modelDefinition;
this.m2Constraint = m2Constraint;
String constraintName = m2Constraint.getName(); this.prefixResolver = prefixResolver;
if (constraintName == null)
{ String constraintName = m2Constraint.getName();
// the constraint is anonymous, so it has to be defined within the context of a property if (constraintName == null)
if (m2PropertyDef == null) {
{ // the constraint is anonymous, so it has to be defined within the context of a property
throw new DictionaryException(ERR_ANON_NEEDS_PROPERTY); if (m2PropertyDef == null)
} {
// pick the name up from the property and some anonymous value throw new DictionaryException(ERR_ANON_NEEDS_PROPERTY);
String localName = m2PropertyDef.getName().getLocalName() + "_anon_" + (++anonPropCount); }
this.name = QName.createQName(m2PropertyDef.getName().getNamespaceURI(), localName); // pick the name up from the property and some anonymous value
m2Constraint.setName(this.name.getPrefixedQName(prefixResolver).toPrefixString()); String localName = m2PropertyDef.getName().getLocalName() + "_anon_" + (++anonPropCount);
} this.name = QName.createQName(m2PropertyDef.getName().getNamespaceURI(), localName);
else m2Constraint.setName(this.name.getPrefixedQName(prefixResolver).toPrefixString());
{ }
this.name = QName.createQName(m2Constraint.getName(), prefixResolver); else
} {
} this.name = QName.createQName(m2Constraint.getName(), prefixResolver);
}
/* package */synchronized void resolveDependencies(ModelQuery query) }
{
if (resolving) /* package */synchronized void resolveDependencies(ModelQuery query)
{ {
throw new DictionaryException(ERR_CYCLIC_REF, name.toPrefixString()); if (resolving)
} {
// prevent circular references throw new DictionaryException(ERR_CYCLIC_REF, name.toPrefixString());
try }
{ // prevent circular references
resolving = true; try
resolveInternal(query); {
} resolving = true;
finally resolveInternal(query);
{ }
resolving = false; finally
} {
} resolving = false;
}
private synchronized void resolveInternal(ModelQuery query) }
{
if (constraint != null) private synchronized void resolveInternal(ModelQuery query)
{ {
// already been resolved if (constraint != null)
return; {
} // already been resolved
String shortName = name.toPrefixString(); return;
String ref = m2Constraint.getRef(); }
String type = m2Constraint.getType();
if (ref != null && type != null) String shortName = name.toPrefixString();
{ String ref = m2Constraint.getRef();
throw new DictionaryException(ERR_TYPE_AND_REF, shortName); String type = m2Constraint.getType();
}
else if (ref == null && type == null) String title = m2Constraint.getTitle();
{ String description = m2Constraint.getDescription();
throw new DictionaryException(ERR_TYPE_OR_REF, shortName);
} if (ref != null && type != null)
else if (ref != null) {
{ throw new DictionaryException(ERR_TYPE_AND_REF, shortName);
// resolve the reference name }
QName qnameRef = QName.createQName(ref, prefixResolver); else if (ref == null && type == null)
// ensure that the reference exists in the model {
M2ConstraintDefinition constraintDef = (M2ConstraintDefinition) query.getConstraint(qnameRef); throw new DictionaryException(ERR_TYPE_OR_REF, shortName);
if (constraintDef == null) }
{ else if (ref != null)
throw new DictionaryException(ERR_REF_NOT_FOUND, ref, shortName); {
} // resolve the reference name
// make sure that the constraint definition has itself been resolved QName qnameRef = QName.createQName(ref, prefixResolver);
constraintDef.resolveDependencies(query); // ensure that the reference exists in the model
// just use the constraint provided by the referenced definition M2ConstraintDefinition constraintDef = (M2ConstraintDefinition) query.getConstraint(qnameRef);
this.constraint = constraintDef.getConstraint(); if (constraintDef == null)
} {
else throw new DictionaryException(ERR_REF_NOT_FOUND, ref, shortName);
{ }
// we have to build the constraint from the type // make sure that the constraint definition has itself been resolved
try constraintDef.resolveDependencies(query);
{ // just use the constraint provided by the referenced definition
ConstraintType constraintType = ConstraintType.valueOf(type); this.constraint = constraintDef.getConstraint();
constraint = constraintType.newInstance();
} if (m2Constraint.getTitle() == null)
catch (IllegalArgumentException e) {
{ m2Constraint.setTitle(constraintDef.getTitle());
// try to establish it as a class }
try
{ if (m2Constraint.getDescription() == null)
@SuppressWarnings("unchecked") {
Class clazz = Class.forName(type); m2Constraint.setDescription(constraintDef.getDescription());
constraint = (Constraint) clazz.newInstance(); }
} }
catch (ClassNotFoundException ee) else
{ {
throw new DictionaryException(ERR_INVALID_TYPE, type, shortName); // we have to build the constraint from the type
} try
catch (ClassCastException ee) {
{ ConstraintType constraintType = ConstraintType.valueOf(type);
throw new DictionaryException(ERR_INVALID_TYPE, type, shortName); constraint = constraintType.newInstance();
} }
catch (Exception ee) catch (IllegalArgumentException e)
{ {
throw new DictionaryException(ERR_CONSTRUCT_FAILURE, type, shortName); // try to establish it as a class
} try
} {
// property setters @SuppressWarnings("unchecked")
BeanWrapper beanWrapper = new BeanWrapperImpl(constraint); Class clazz = Class.forName(type);
List<M2NamedValue> constraintNamedValues = m2Constraint.getParameters(); constraint = (Constraint) clazz.newInstance();
}
if (constraintNamedValues != null) catch (ClassNotFoundException ee)
{ {
for (M2NamedValue namedValue : constraintNamedValues) throw new DictionaryException(ERR_INVALID_TYPE, type, shortName);
{ }
String namedValueName = namedValue.getName(); catch (ClassCastException ee)
// Check for reserved properties {
if (namedValueName.equals(PROP_SHORT_NAME)) throw new DictionaryException(ERR_INVALID_TYPE, type, shortName);
{ }
throw new DictionaryException(ERR_RESERVED_PROPERTY, PROP_SHORT_NAME, namedValueName); catch (Exception ee)
} {
throw new DictionaryException(ERR_CONSTRUCT_FAILURE, type, shortName);
Object value = null; }
if (namedValue.getSimpleValue() != null && namedValue.getListValue() != null) }
{
throw new DictionaryException(ERR_SIMPLE_AND_LIST, shortName, namedValue.getName()); // property setters
} BeanWrapper beanWrapper = new BeanWrapperImpl(constraint);
else if (namedValue.getSimpleValue() != null) List<M2NamedValue> constraintNamedValues = m2Constraint.getParameters();
{
value = namedValue.getSimpleValue(); if (constraintNamedValues != null)
} {
else if (namedValue.getListValue() != null) for (M2NamedValue namedValue : constraintNamedValues)
{ {
value = namedValue.getListValue(); String namedValueName = namedValue.getName();
} // Check for reserved properties
try if (namedValueName.equals(PROP_SHORT_NAME))
{ {
beanWrapper.setPropertyValue(namedValueName, value); throw new DictionaryException(ERR_RESERVED_PROPERTY, PROP_SHORT_NAME, namedValueName);
} }
catch (PropertyAccessException e)
{ Object value = null;
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValueName, shortName); if (namedValue.getSimpleValue() != null && namedValue.getListValue() != null)
} {
catch (InvalidPropertyException e) throw new DictionaryException(ERR_SIMPLE_AND_LIST, shortName, namedValue.getName());
{ }
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValueName, shortName); else if (namedValue.getSimpleValue() != null)
} {
} value = namedValue.getSimpleValue();
}
// Pass in the short name as a special property, if it is available else if (namedValue.getListValue() != null)
if (beanWrapper.isWritableProperty(PROP_SHORT_NAME)) {
{ value = namedValue.getListValue();
try }
{ try
beanWrapper.setPropertyValue(PROP_SHORT_NAME, shortName); {
} beanWrapper.setPropertyValue(namedValueName, value);
catch (PropertyAccessException e) }
{ catch (PropertyAccessException e)
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName); {
} throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValueName, shortName);
catch (InvalidPropertyException e) }
{ catch (InvalidPropertyException e)
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName); {
} throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValueName, shortName);
}
} }
}
// now initialize // Pass in the short name as a special property, if it is available
constraint.initialize(); if (beanWrapper.isWritableProperty(PROP_SHORT_NAME))
} {
} try
{
/** beanWrapper.setPropertyValue(PROP_SHORT_NAME, shortName);
* @see #getName() }
*/ catch (PropertyAccessException e)
@Override {
public String toString() throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName);
{ }
return getName().toString(); catch (InvalidPropertyException e)
} {
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName);
public ModelDefinition getModel() }
{ }
return model;
} if ((title != null) && (beanWrapper.isWritableProperty(PROP_TITLE)))
{
public QName getName() beanWrapper.setPropertyValue(PROP_TITLE, title);
{ }
return name;
} if ((title != null) && (beanWrapper.isWritableProperty(PROP_DESCRIPTION)))
{
public Constraint getConstraint() beanWrapper.setPropertyValue(PROP_DESCRIPTION, description);
{ }
return constraint; }
}
// now initialize
/** constraint.initialize();
* Well-known constraint types }
*/ }
public static enum ConstraintType
{ /**
REGISTERED * @see #getName()
{ */
@Override @Override
protected Constraint newInstance() public String toString()
{ {
return new RegisteredConstraint(); return getName().toString();
} }
},
REGEX public ModelDefinition getModel()
{ {
@Override return model;
protected Constraint newInstance() }
{
return new RegexConstraint(); public QName getName()
} {
}, return name;
MINMAX }
{
@Override public String getTitle()
protected Constraint newInstance() {
{ String value = M2Label.getLabel(model, "constraint", name, "title");
return new NumericRangeConstraint(); if (value == null)
} {
}, value = m2Constraint.getTitle();
LENGTH }
{ return value;
@Override }
protected Constraint newInstance()
{ public String getDescription()
return new StringLengthConstraint(); {
} String value = M2Label.getLabel(model, "constraint", name, "description");
}, if (value == null)
LIST {
{ value = m2Constraint.getDescription();
@Override }
protected Constraint newInstance() return value;
{ }
return new ListOfValuesConstraint();
} public Constraint getConstraint()
}; {
return constraint;
/** }
* @return Returns the constraint implementation
*/ /**
protected abstract Constraint newInstance(); * Well-known constraint types
} */
} public static enum ConstraintType
{
REGISTERED
{
@Override
protected Constraint newInstance()
{
return new RegisteredConstraint();
}
},
REGEX
{
@Override
protected Constraint newInstance()
{
return new RegexConstraint();
}
},
MINMAX
{
@Override
protected Constraint newInstance()
{
return new NumericRangeConstraint();
}
},
LENGTH
{
@Override
protected Constraint newInstance()
{
return new StringLengthConstraint();
}
},
LIST
{
@Override
protected Constraint newInstance()
{
return new ListOfValuesConstraint();
}
};
/**
* @return Returns the constraint implementation
*/
protected abstract Constraint newInstance();
}
}

View File

@@ -1,402 +1,432 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.dictionary; package org.alfresco.repo.dictionary;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.alfresco.service.cmr.dictionary.DictionaryException; import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.jibx.runtime.BindingDirectory; import org.jibx.runtime.BindingDirectory;
import org.jibx.runtime.IBindingFactory; import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.IMarshallingContext; import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IUnmarshallingContext; import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException; import org.jibx.runtime.JiBXException;
/** /**
* Model Definition. * Model Definition.
* *
* @author David Caruana * @author David Caruana
* *
*/ */
public class M2Model public class M2Model
{ {
private String name = null; private String name = null;
private String description = null; private String description = null;
private String author = null; private String author = null;
private Date published = null; private Date published = null;
private String version; private String version;
private List<M2Namespace> namespaces = new ArrayList<M2Namespace>(); private List<M2Namespace> namespaces = new ArrayList<M2Namespace>();
private List<M2Namespace> imports = new ArrayList<M2Namespace>(); private List<M2Namespace> imports = new ArrayList<M2Namespace>();
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 List<M2Constraint> constraints = new ArrayList<M2Constraint>();
private M2Model() private M2Model()
{ {
} }
/** /**
* Construct an empty model * Construct an empty model
* *
* @param name the name of the model * @param name the name of the model
* @return the model * @return the model
*/ */
public static M2Model createModel(String name) public static M2Model createModel(String name)
{ {
M2Model model = new M2Model(); M2Model model = new M2Model();
model.name = name; model.name = name;
return model; return model;
} }
/** /**
* Construct a model from a dictionary xml specification * Construct a model from a dictionary xml specification
* *
* @param xml the dictionary xml * @param xml the dictionary xml
* @return the model representation of the xml * @return the model representation of the xml
*/ */
public static M2Model createModel(InputStream xml) public static M2Model createModel(InputStream xml)
{ {
try try
{ {
IBindingFactory factory = BindingDirectory.getFactory(M2Model.class); IBindingFactory factory = BindingDirectory.getFactory(M2Model.class);
IUnmarshallingContext context = factory.createUnmarshallingContext(); IUnmarshallingContext context = factory.createUnmarshallingContext();
Object obj = context.unmarshalDocument(xml, null); Object obj = context.unmarshalDocument(xml, null);
return (M2Model)obj; return (M2Model)obj;
} }
catch(JiBXException e) catch(JiBXException e)
{ {
throw new DictionaryException("Failed to parse model", e); throw new DictionaryException("Failed to parse model", e);
} }
} }
/** /**
* Render the model to dictionary XML * Render the model to dictionary XML
* *
* @param xml the dictionary xml representation of the model * @param xml the dictionary xml representation of the model
*/ */
public void toXML(OutputStream xml) public void toXML(OutputStream xml)
{ {
try try
{ {
IBindingFactory factory = BindingDirectory.getFactory(M2Model.class); IBindingFactory factory = BindingDirectory.getFactory(M2Model.class);
IMarshallingContext context = factory.createMarshallingContext(); IMarshallingContext context = factory.createMarshallingContext();
context.setIndent(4); context.setIndent(4);
context.marshalDocument(this, "UTF-8", null, xml); context.marshalDocument(this, "UTF-8", null, xml);
} }
catch(JiBXException e) catch(JiBXException e)
{ {
throw new DictionaryException("Failed to create M2 Model", e); throw new DictionaryException("Failed to create M2 Model", e);
} }
} }
/** /**
* Create a compiled form of this model * Create a compiled form of this model
* *
* @param dictionaryDAO dictionary DAO * @param dictionaryDAO dictionary DAO
* @param namespaceDAO namespace DAO * @param namespaceDAO namespace DAO
* @return the compiled form of the model * @return the compiled form of the model
*/ */
/*package*/ CompiledModel compile(DictionaryDAO dictionaryDAO, NamespaceDAO namespaceDAO) /*package*/ CompiledModel compile(DictionaryDAO dictionaryDAO, NamespaceDAO namespaceDAO)
{ {
CompiledModel compiledModel = new CompiledModel(this, dictionaryDAO, namespaceDAO); CompiledModel compiledModel = new CompiledModel(this, dictionaryDAO, namespaceDAO);
return compiledModel; return compiledModel;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public void setName(String name) public void setName(String name)
{ {
this.name = name; this.name = name;
} }
public String getDescription() public String getDescription()
{ {
return description; return description;
} }
public void setDescription(String description) public void setDescription(String description)
{ {
this.description = description; this.description = description;
} }
public String getAuthor() public String getAuthor()
{ {
return author; return author;
} }
public void setAuthor(String author) public void setAuthor(String author)
{ {
this.author = author; this.author = author;
} }
public Date getPublishedDate() public Date getPublishedDate()
{ {
return published; return published;
} }
public void setPublishedDate(Date published) public void setPublishedDate(Date published)
{ {
this.published = published; this.published = published;
} }
public String getVersion() public String getVersion()
{ {
return version; return version;
} }
public void setVersion(String version) public void setVersion(String version)
{ {
this.version = version; this.version = version;
} }
public M2Type createType(String name) public M2Type createType(String name)
{ {
M2Type type = new M2Type(); M2Type type = new M2Type();
type.setName(name); type.setName(name);
types.add(type); types.add(type);
return type; return type;
} }
public void removeType(String name) public void removeType(String name)
{ {
M2Type type = getType(name); M2Type type = getType(name);
if (type != null) if (type != null)
{ {
types.remove(type); types.remove(type);
} }
} }
public List<M2Type> getTypes() public List<M2Type> getTypes()
{ {
return Collections.unmodifiableList(types); return Collections.unmodifiableList(types);
} }
public M2Type getType(String name) public M2Type getType(String name)
{ {
for (M2Type candidate : types) for (M2Type candidate : types)
{ {
if (candidate.getName().equals(name)) if (candidate.getName().equals(name))
{ {
return candidate; return candidate;
} }
} }
return null; return null;
} }
public M2Aspect createAspect(String name) public M2Aspect createAspect(String name)
{ {
M2Aspect aspect = new M2Aspect(); M2Aspect aspect = new M2Aspect();
aspect.setName(name); aspect.setName(name);
aspects.add(aspect); aspects.add(aspect);
return aspect; return aspect;
} }
public void removeAspect(String name) public void removeAspect(String name)
{ {
M2Aspect aspect = getAspect(name); M2Aspect aspect = getAspect(name);
if (aspect != null) if (aspect != null)
{ {
aspects.remove(name); aspects.remove(name);
} }
} }
public List<M2Aspect> getAspects() public List<M2Aspect> getAspects()
{ {
return Collections.unmodifiableList(aspects); return Collections.unmodifiableList(aspects);
} }
public M2Aspect getAspect(String name) public M2Aspect getAspect(String name)
{ {
for (M2Aspect candidate : aspects) for (M2Aspect candidate : aspects)
{ {
if (candidate.getName().equals(name)) if (candidate.getName().equals(name))
{ {
return candidate; return candidate;
} }
} }
return null; return null;
} }
public M2DataType createPropertyType(String name) public M2DataType createPropertyType(String name)
{ {
M2DataType type = new M2DataType(); M2DataType type = new M2DataType();
type .setName(name); type.setName(name);
dataTypes.add(type); dataTypes.add(type);
return type; return type;
} }
public void removePropertyType(String name) public void removePropertyType(String name)
{ {
M2DataType type = getPropertyType(name); M2DataType type = getPropertyType(name);
if (type != null) if (type != null)
{ {
dataTypes.remove(name); dataTypes.remove(name);
} }
} }
public List<M2DataType> getPropertyTypes() public List<M2DataType> getPropertyTypes()
{ {
return Collections.unmodifiableList(dataTypes); return Collections.unmodifiableList(dataTypes);
} }
public M2DataType getPropertyType(String name) public M2DataType getPropertyType(String name)
{ {
for (M2DataType candidate : dataTypes) for (M2DataType candidate : dataTypes)
{ {
if (candidate.getName().equals(name)) if (candidate.getName().equals(name))
{ {
return candidate; return candidate;
} }
} }
return null; return null;
} }
public M2Namespace createNamespace(String uri, String prefix) public M2Namespace createNamespace(String uri, String prefix)
{ {
M2Namespace namespace = new M2Namespace(); M2Namespace namespace = new M2Namespace();
namespace.setUri(uri); namespace.setUri(uri);
namespace.setPrefix(prefix); namespace.setPrefix(prefix);
namespaces.add(namespace); namespaces.add(namespace);
return namespace; return namespace;
} }
public void removeNamespace(String uri) public void removeNamespace(String uri)
{ {
M2Namespace namespace = getNamespace(uri); M2Namespace namespace = getNamespace(uri);
if (namespace != null) if (namespace != null)
{ {
namespaces.remove(namespace); namespaces.remove(namespace);
} }
} }
public List<M2Namespace> getNamespaces() public List<M2Namespace> getNamespaces()
{ {
return Collections.unmodifiableList(namespaces); return Collections.unmodifiableList(namespaces);
} }
public M2Namespace getNamespace(String uri) public M2Namespace getNamespace(String uri)
{ {
for (M2Namespace candidate : namespaces) for (M2Namespace candidate : namespaces)
{ {
if (candidate.getUri().equals(uri)) if (candidate.getUri().equals(uri))
{ {
return candidate; return candidate;
} }
} }
return null; return null;
} }
public M2Namespace createImport(String uri, String prefix) public M2Namespace createImport(String uri, String prefix)
{ {
M2Namespace namespace = new M2Namespace(); M2Namespace namespace = new M2Namespace();
namespace.setUri(uri); namespace.setUri(uri);
namespace.setPrefix(prefix); namespace.setPrefix(prefix);
imports.add(namespace); imports.add(namespace);
return namespace; return namespace;
} }
public void removeImport(String uri) public void removeImport(String uri)
{ {
M2Namespace namespace = getImport(uri); M2Namespace namespace = getImport(uri);
if (namespace != null) if (namespace != null)
{ {
imports.remove(namespace); imports.remove(namespace);
} }
} }
public List<M2Namespace> getImports() public List<M2Namespace> getImports()
{ {
return Collections.unmodifiableList(imports); return Collections.unmodifiableList(imports);
} }
public M2Namespace getImport(String uri) public M2Namespace getImport(String uri)
{ {
for (M2Namespace candidate : imports) for (M2Namespace candidate : imports)
{ {
if (candidate.getUri().equals(uri)) if (candidate.getUri().equals(uri))
{ {
return candidate; return candidate;
} }
} }
return null; return null;
} }
public List<M2Constraint> getConstraints() public List<M2Constraint> getConstraints()
{ {
return Collections.unmodifiableList(constraints); return Collections.unmodifiableList(constraints);
} }
// Do not delete: referenced by m2binding.xml public M2Constraint getConstraint(String name)
@SuppressWarnings("unused") {
private static List createList() for (M2Constraint candidate : constraints)
{ {
return new ArrayList(); if (candidate.getName().equals(name))
} {
return candidate;
} }
}
return null;
}
public M2Constraint createConstraint(String name, String type)
{
M2Constraint constraint = new M2Constraint();
constraint.setName(name);
constraint.setType(type);
constraints.add(constraint);
return constraint;
}
public void removeConstraint(String name)
{
M2Constraint constraint = getConstraint(name);
if (constraint != null)
{
constraints.remove(name);
}
}
// Do not delete: referenced by m2binding.xml
@SuppressWarnings("unused")
private static List createList()
{
return new ArrayList();
}
}

View File

@@ -1,71 +1,97 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.dictionary; package org.alfresco.repo.dictionary;
import java.util.List; import java.util.List;
/** /**
* Definition of a named value that can be used for property injection. * Definition of a named value that can be used for property injection.
* *
* @author Derek Hulley * @author Derek Hulley
*/ */
public class M2NamedValue public class M2NamedValue
{ {
private String name; private String name;
private String simpleValue = null; private String simpleValue = null;
private List<String> listValue = null; private List<String> listValue = null;
/*package*/ M2NamedValue() /*package*/ M2NamedValue()
{ {
} }
@Override @Override
public String toString() public String toString()
{ {
return (name + "=" + (simpleValue == null ? listValue : simpleValue)); return (name + "=" + (simpleValue == null ? listValue : simpleValue));
} }
public String getName() public String getName()
{ {
return name; return name;
} }
/** /**
* @return Returns the raw, unconverted value * @return Returns the raw, unconverted value
*/ */
public String getSimpleValue() public String getSimpleValue()
{ {
return simpleValue; return simpleValue;
} }
/** /**
* @return Returns the list of raw, unconverted values * @return Returns the list of raw, unconverted values
*/ */
public List<String> getListValue() public List<String> getListValue()
{ {
return listValue; return listValue;
} }
}
public void setName(String name)
{
this.name = name;
}
public void setSimpleValue(String simpleValue)
{
this.simpleValue = simpleValue;
}
public void setListValue(List<String> listValue)
{
this.listValue = listValue;
}
public boolean hasSimpleValue()
{
return (this.simpleValue != null);
}
public boolean hasListValue()
{
return (this.listValue != null);
}
}

View File

@@ -1,197 +1,209 @@
/* /*
* Copyright (C) 2005-2009 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have received a copy of the text describing * FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.dictionary.constraint; package org.alfresco.repo.dictionary.constraint;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.alfresco.service.cmr.dictionary.Constraint; import org.alfresco.service.cmr.dictionary.Constraint;
import org.alfresco.service.cmr.dictionary.ConstraintException; import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.dictionary.DictionaryException; import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
/** /**
* Base services for constraints. * Base services for constraints.
* *
* @author Derek Hulley * @author Derek Hulley
*/ */
public abstract class AbstractConstraint implements Constraint public abstract class AbstractConstraint implements Constraint
{ {
public static final String ERR_PROP_NOT_SET = "d_dictionary.constraint.err.property_not_set"; public static final String ERR_PROP_NOT_SET = "d_dictionary.constraint.err.property_not_set";
public static final String ERR_EVALUATE_EXCEPTION = "d_dictionary.constraint.err.evaluate_exception"; public static final String ERR_EVALUATE_EXCEPTION = "d_dictionary.constraint.err.evaluate_exception";
/** The constraint name. May be useful in error messages */ /** The constraint name. May be useful in error messages */
private String shortName; private String shortName;
private ConstraintRegistry registry; private String title;
/** private ConstraintRegistry registry;
* Sets the constraint name. Automatically called after construction. Please excuse the strange method name as we
* want the property name to begin with an underscore to avoid property name clashes. /**
* * Sets the constraint name. Automatically called after construction. Please excuse the strange method name as we
* @param shortName * want the property name to begin with an underscore to avoid property name clashes.
* @deprecated *
*/ * @param shortName
public void set_shortName(String shortName) * @deprecated
{ */
setShortName(shortName); public void set_shortName(String shortName)
} {
setShortName(shortName);
/** }
* Sets the constraint name
* @param name /**
*/ * Sets the constraint name
public void setShortName(String name) * @param name
{ */
this.shortName = name; public void setShortName(String name)
} {
this.shortName = name;
/** }
* Gets the constraint name.
* /**
* @return the constraint name. * Gets the constraint name.
*/ *
public String getShortName() * @return the constraint name.
{ */
return this.shortName; public String getShortName()
} {
return this.shortName;
/** }
* Optionally specify the registry that will be used to register the constraint.
* This is used when instantiating constraints outside the dictionary. /**
* * Optionally specify the registry that will be used to register the constraint.
* @param registry the constraint registry * This is used when instantiating constraints outside the dictionary.
*/ *
public void setRegistry(ConstraintRegistry registry) * @param registry the constraint registry
{ */
this.registry = registry; public void setRegistry(ConstraintRegistry registry)
} {
this.registry = registry;
public String getType() }
{
return this.getClass().getName(); public String getType()
} {
return this.getClass().getName();
public Map<String, Object> getParameters() }
{
return new HashMap<String, Object>(3); public void setTitle(String title)
} {
this.title = title;
/** }
* {@inheritDoc}
* <p> public String getTitle()
* Registers the constraint with the registry, if present. Call this method if {
* you want the constraint to be auto-registered. return title;
*/ }
public void initialize()
{ public Map<String, Object> getParameters()
if (registry != null) {
{ return new HashMap<String, Object>(3);
registry.register(shortName, this); }
}
} /**
* {@inheritDoc}
/** * <p>
* Check that the given value is not <tt>null</tt>. * Registers the constraint with the registry, if present. Call this method if
* * you want the constraint to be auto-registered.
* @param name the name of the property */
* @param value the value to check for <tt>null</tt> public void initialize()
* {
* @throws DictionaryException if the the property is null if (registry != null)
*/ {
protected void checkPropertyNotNull(String name, Object value) registry.register(shortName, this);
{ }
if (value == null) }
{
throw new DictionaryException(AbstractConstraint.ERR_PROP_NOT_SET, name, getShortName()); /**
} * Check that the given value is not <tt>null</tt>.
} *
* @param name the name of the property
/** * @param value the value to check for <tt>null</tt>
* @see #evaluateSingleValue(Object) *
* @see #evaluateCollection(Collection) * @throws DictionaryException if the the property is null
*/ */
@SuppressWarnings("unchecked") protected void checkPropertyNotNull(String name, Object value)
public final void evaluate(Object value) {
{ if (value == null)
if (value == null) {
{ throw new DictionaryException(AbstractConstraint.ERR_PROP_NOT_SET, name, getShortName());
// null values are never evaluated }
return; }
}
try /**
{ * @see #evaluateSingleValue(Object)
// ensure that we can handle collections * @see #evaluateCollection(Collection)
if (DefaultTypeConverter.INSTANCE.isMultiValued(value)) */
{ @SuppressWarnings("unchecked")
Collection collection = DefaultTypeConverter.INSTANCE.getCollection(Object.class, value); public final void evaluate(Object value)
evaluateCollection(collection); {
} if (value == null)
else {
{ // null values are never evaluated
evaluateSingleValue(value); return;
} }
} try
catch (ConstraintException e) {
{ // ensure that we can handle collections
// this can go if (DefaultTypeConverter.INSTANCE.isMultiValued(value))
throw e; {
} Collection collection = DefaultTypeConverter.INSTANCE.getCollection(Object.class, value);
catch (Throwable e) evaluateCollection(collection);
{ }
throw new DictionaryException(AbstractConstraint.ERR_EVALUATE_EXCEPTION, this, e.getMessage()); else
} {
} evaluateSingleValue(value);
}
/** }
* Only override if there is some specific evaluation that needs to be performed on the catch (ConstraintException e)
* collection as a whole. {
* // this can go
* @param collection the collection of values to evaluate throw e;
* }
* @see #evaluateSingleValue(Object) catch (Throwable e)
*/ {
protected void evaluateCollection(Collection<Object> collection) throw new DictionaryException(AbstractConstraint.ERR_EVALUATE_EXCEPTION, this, e.getMessage());
{ }
for (Object value : collection) }
{
if (value == null) /**
{ * Only override if there is some specific evaluation that needs to be performed on the
// contract states that it will always pass * collection as a whole.
continue; *
} * @param collection the collection of values to evaluate
evaluateSingleValue(value); *
} * @see #evaluateSingleValue(Object)
} */
protected void evaluateCollection(Collection<Object> collection)
/** {
* Support for evaluation of properties. The value passed in will never be a for (Object value : collection)
* <tt>Collection</tt> and will never be <tt>null</tt>. {
* if (value == null)
* @throws ConstraintException throw this when the evaluation fails {
*/ // contract states that it will always pass
protected abstract void evaluateSingleValue(Object value); continue;
} }
evaluateSingleValue(value);
}
}
/**
* Support for evaluation of properties. The value passed in will never be a
* <tt>Collection</tt> and will never be <tt>null</tt>.
*
* @throws ConstraintException throw this when the evaluation fails
*/
protected abstract void evaluateSingleValue(Object value);
}

View File

@@ -109,6 +109,14 @@ public final class RegisteredConstraint implements Constraint
return getConstraint().getType(); return getConstraint().getType();
} }
/**
* Defers to the registered constraint
*/
public String getTitle()
{
return getConstraint().getTitle();
}
/** /**
* Defers to the registered constraint * Defers to the registered constraint
*/ */

View File

@@ -30,6 +30,8 @@
<parameter name="registeredName"><value>cm:reg2</value></parameter> <parameter name="registeredName"><value>cm:reg2</value></parameter>
</constraint> </constraint>
<constraint name="test:regex1" type="REGEX"> <constraint name="test:regex1" type="REGEX">
<title>Regex1 title</title>
<description>Regex1 description</description>
<parameter name="expression"><value>[A-Z]*</value></parameter> <parameter name="expression"><value>[A-Z]*</value></parameter>
<parameter name="requiresMatch"><value>false</value></parameter> <parameter name="requiresMatch"><value>false</value></parameter>
</constraint> </constraint>
@@ -74,7 +76,10 @@
<default></default> <default></default>
<constraints> <constraints>
<constraint ref="test:regex1"/> <constraint ref="test:regex1"/>
<constraint ref="test:stringLength1"/> <constraint ref="test:stringLength1">
<title>Prop1 Strlen1 title</title>
<description>Prop1 Strlen1 description</description>
</constraint>
<constraint ref="test:registered1"/> <constraint ref="test:registered1"/>
</constraints> </constraints>
</property> </property>

View File

@@ -122,8 +122,8 @@
<mapping abstract="true" class="org.alfresco.repo.dictionary.M2NamedValue"> <mapping abstract="true" class="org.alfresco.repo.dictionary.M2NamedValue">
<value style="attribute" name="name" field="name" /> <value style="attribute" name="name" field="name" />
<value name="value" field="simpleValue" usage="optional" /> <value name="value" field="simpleValue" test-method="hasSimpleValue" usage="optional"/>
<structure name="list" usage="optional"> <structure name="list" test-method="hasListValue" usage="optional">
<collection field="listValue" factory="org.alfresco.repo.dictionary.M2Model.createList" usage="optional"> <collection field="listValue" factory="org.alfresco.repo.dictionary.M2Model.createList" usage="optional">
<value name="value" style="element" usage="optional" type="java.lang.String"/> <value name="value" style="element" usage="optional" type="java.lang.String"/>
</collection> </collection>
@@ -134,6 +134,7 @@
<value style="attribute" name="name" field="name" usage="optional"/> <value style="attribute" name="name" field="name" usage="optional"/>
<value style="attribute" name="type" field="type" usage="optional"/> <value style="attribute" name="type" field="type" usage="optional"/>
<value style="attribute" name="ref" field="ref" usage="optional"/> <value style="attribute" name="ref" field="ref" usage="optional"/>
<value name="title" field="title" usage="optional"/>
<value name="description" field="description" usage="optional"/> <value name="description" field="description" usage="optional"/>
<collection field="parameters" factory="org.alfresco.repo.dictionary.M2Model.createList" usage="optional"> <collection field="parameters" factory="org.alfresco.repo.dictionary.M2Model.createList" usage="optional">
<structure name="parameter" type="org.alfresco.repo.dictionary.M2NamedValue" /> <structure name="parameter" type="org.alfresco.repo.dictionary.M2NamedValue" />

View File

@@ -1,81 +1,86 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.service.cmr.dictionary; package org.alfresco.service.cmr.dictionary;
import java.util.Map; import java.util.Map;
/** /**
* The interface for classes that implement constraints on property values. * The interface for classes that implement constraints on property values.
* <p> * <p>
* Implementations of the actual constraint code should must not synchronize * Implementations of the actual constraint code should must not synchronize
* or in any other way block threads. Concurrent access of the evaluation * or in any other way block threads. Concurrent access of the evaluation
* method is expected, but will always occur after initialization has completed. * method is expected, but will always occur after initialization has completed.
* <p> * <p>
* Attention to performance is <u>crucial</u> for all implementations as * Attention to performance is <u>crucial</u> for all implementations as
* instances of this class are heavily used. * instances of this class are heavily used.
* <p> * <p>
* The constraint implementations can provide standard setter methods that will * The constraint implementations can provide standard setter methods that will
* be populated by bean setter injection. Once all the available properties have * be populated by bean setter injection. Once all the available properties have
* been set, the contraint will be initialized. * been set, the contraint will be initialized.
* *
* @author Derek Hulley * @author Derek Hulley
*/ */
public interface Constraint public interface Constraint
{ {
/** /**
* Returns the 'type' of the constraint, this is the identifier given to * Returns the 'type' of the constraint, this is the identifier given to
* constraint in the configuration. * constraint in the configuration.
* *
* @return The type * @return The type
*/ */
public String getType(); public String getType();
/** /**
* Returns the parameters passed to the instance of the constraint. * @return the human-readable constraint title (optional)
* */
* @return Map of parameters or an empty <tt>Map</tt> if none exist public String getTitle();
*/
public Map<String, Object> getParameters(); /**
* Returns the parameters passed to the instance of the constraint.
/** *
* Initializes the constraint with appropriate values, which will depend * @return Map of parameters or an empty <tt>Map</tt> if none exist
* on the implementation itself. This method can be implemented as a */
* once-off, i.e. reinitialization does not have to be supported. public Map<String, Object> getParameters();
*
* @param parameters constraint parameters /**
*/ * Initializes the constraint with appropriate values, which will depend
public void initialize(); * on the implementation itself. This method can be implemented as a
* once-off, i.e. reinitialization does not have to be supported.
/** *
* Evaluates a property value according to the implementation and initialization * @param parameters constraint parameters
* parameters provided. */
* public void initialize();
* @param value the property value to check
* /**
* @throws ConstraintException if the value doesn't pass all constraints * Evaluates a property value according to the implementation and initialization
*/ * parameters provided.
public void evaluate(Object value); *
} * @param value the property value to check
*
* @throws ConstraintException if the value doesn't pass all constraints
*/
public void evaluate(Object value);
}

View File

@@ -1,50 +1,60 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.service.cmr.dictionary; package org.alfresco.service.cmr.dictionary;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
/** /**
* Property constraint definition * Property constraint definition
* *
* @author Derek Hulley * @author Derek Hulley
*/ */
public interface ConstraintDefinition public interface ConstraintDefinition
{ {
/** /**
* @return defining model * @return defining model
*/ */
public ModelDefinition getModel(); public ModelDefinition getModel();
/** /**
* @return Returns the qualified name of the constraint * @return Returns the qualified name of the constraint
*/ */
public QName getName(); public QName getName();
/** /**
* @return Returns the constraint implementation * @return the human-readable class title
*/ */
public Constraint getConstraint(); public String getTitle();
}
/**
* @return the human-readable class description
*/
public String getDescription();
/**
* @return Returns the constraint implementation
*/
public Constraint getConstraint();
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2007 Alfresco Software Limited. * Copyright (C) 2005-2009 Alfresco Software Limited.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -25,6 +25,7 @@
package org.alfresco.service.cmr.dictionary; package org.alfresco.service.cmr.dictionary;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.service.NotAuditable; import org.alfresco.service.NotAuditable;
@@ -262,6 +263,14 @@ public interface DictionaryService
@NotAuditable @NotAuditable
Collection<QName> getAllAssociations(); Collection<QName> getAllAssociations();
/**
* Get constraints for the specified model
*
* @param model
* @return
*/
public Collection<ConstraintDefinition> getConstraints(QName model);
// TODO: Behaviour definitions // TODO: Behaviour definitions
} }