First-cut validation of dynamic model changes

- in case of re-deploy (dynamic update) check for incremental updates only
- in case of undeploy (dynamic delete) check for type/aspect usages (in content and workflows)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6698 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jan Vonka
2007-09-07 11:32:51 +00:00
parent 6e002e6de8
commit a03df08f5e
11 changed files with 1980 additions and 20 deletions

View File

@@ -29,6 +29,7 @@ import java.util.Collection;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
@@ -70,12 +71,10 @@ public interface DictionaryDAO extends ModelQuery
* @return the aspects of the model
*/
public Collection<AspectDefinition> getAspects(QName model);
/**
*
* @param model the model for which to get properties
* @return
* @param model the model for which to get properties for
* @return the properties of the model
*/
public Collection<PropertyDefinition> getProperties(QName model);
@@ -114,6 +113,28 @@ public interface DictionaryDAO extends ModelQuery
* @return
*/
public Collection<PropertyDefinition> getProperties(QName modelName, QName dataType);
/**
* @param model the model to retrieve namespaces for
* @return the namespaces of the model
*/
public Collection<NamespaceDefinition> getNamespaces(QName modelName);
/**
* validate against dictionary
*
* if new model
* then nothing to validate
*
* 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
* - no deletion of types, aspects or properties or associations
* - no addition, update or deletion of default/mandatory aspects
*
* @param newOrUpdatedModel
*/
public void validateModel(M2Model newOrUpdatedModel);
/**
*

View File

@@ -47,9 +47,11 @@ 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.ModelDefinition;
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -449,6 +451,7 @@ public class DictionaryDAOImpl implements DictionaryDAO
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ModelQuery#getDataType(java.lang.Class)
*/
@SuppressWarnings("unchecked")
public DataTypeDefinition getDataType(Class javaClass)
{
if (tenantService.isTenantUser() == true)
@@ -758,6 +761,24 @@ public class DictionaryDAOImpl implements DictionaryDAO
return properties;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryDAO#getNamespaces(org.alfresco.service.namespace.QName)
*/
public Collection<NamespaceDefinition> getNamespaces(QName modelName)
{
CompiledModel model = getCompiledModel(modelName);
ModelDefinition modelDef = model.getModelDefinition();
List<NamespaceDefinition> namespaces = new ArrayList<NamespaceDefinition>();
for (M2Namespace namespace : model.getM2Model().getNamespaces())
{
namespaces.add(new M2NamespaceDefinition(modelDef, namespace.getUri(), namespace.getPrefix()));
}
return namespaces;
}
/**
* Get compiledModels from the cache (in the context of the current user's tenant domain)
*
@@ -950,4 +971,151 @@ public class DictionaryDAOImpl implements DictionaryDAO
{
return tenantService.getCurrentUserDomain();
}
/**
* Return diffs between input model and model in the Dictionary.
*
* If the input model does not exist in the Dictionary or is equivalent to the one in the Dictionary
* then no diffs will be returned.
*
* @param model
* @return model diffs (if any)
*/
private List<M2ModelDiff> diffModel(M2Model model)
{
// Compile model definition
CompiledModel compiledModel = model.compile(this, namespaceDAO);
QName modelName = compiledModel.getModelDefinition().getName();
CompiledModel previousVersion = getCompiledModels().get(modelName);
if (previousVersion == null)
{
return new ArrayList<M2ModelDiff>(0);
}
else
{
return diffModel(previousVersion, compiledModel);
}
}
/**
* Return diffs between two compiled models.
*
*
* @param model
* @return model diffs (if any)
*/
/* package */ List<M2ModelDiff> diffModel(CompiledModel previousVersion, CompiledModel model)
{
List<M2ModelDiff> M2ModelDiffs = new ArrayList<M2ModelDiff>();
if (previousVersion != null)
{
Collection<TypeDefinition> previousTypes = previousVersion.getTypes();
Collection<AspectDefinition> previousAspects = previousVersion.getAspects();
if (model == null)
{
// delete model
for (TypeDefinition previousType : previousTypes)
{
M2ModelDiffs.add(new M2ModelDiff(previousType.getName(), M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_DELETED));
}
for (AspectDefinition previousAspect : previousAspects)
{
M2ModelDiffs.add(new M2ModelDiff(previousAspect.getName(), M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_DELETED));
}
}
else
{
// update model
Collection<TypeDefinition> types = model.getTypes();
Collection<AspectDefinition> aspects = model.getAspects();
if (previousTypes.size() != 0)
{
M2ModelDiffs.addAll(M2ClassDefinition.diffClassLists(new ArrayList<ClassDefinition>(previousTypes), new ArrayList<ClassDefinition>(types), M2ModelDiff.TYPE_TYPE));
}
else
{
for (TypeDefinition type : types)
{
M2ModelDiffs.add(new M2ModelDiff(type.getName(), M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_CREATED));
}
}
if (previousAspects.size() != 0)
{
M2ModelDiffs.addAll(M2ClassDefinition.diffClassLists(new ArrayList<ClassDefinition>(previousAspects), new ArrayList<ClassDefinition>(aspects), M2ModelDiff.TYPE_ASPECT));
}
else
{
for (AspectDefinition aspect : aspects)
{
M2ModelDiffs.add(new M2ModelDiff(aspect.getName(), M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_CREATED));
}
}
}
}
else
{
if (model != null)
{
// new model
Collection<TypeDefinition> types = model.getTypes();
Collection<AspectDefinition> aspects = model.getAspects();
for (TypeDefinition type : types)
{
M2ModelDiffs.add(new M2ModelDiff(type.getName(), M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_CREATED));
}
for (AspectDefinition aspect : aspects)
{
M2ModelDiffs.add(new M2ModelDiff(aspect.getName(), M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_CREATED));
}
}
else
{
// nothing to diff
}
}
return M2ModelDiffs;
}
/**
* validate against dictionary
*
* if new model
* then nothing to validate
*
* 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
* - no deletion of types, aspects or properties or associations
* - no addition, update or deletion of default/mandatory aspects
*
* @param newOrUpdatedModel
*/
public void validateModel(M2Model newOrUpdatedModel)
{
// Check that all the passed values are not null
ParameterCheck.mandatory("newOrUpdatedModel", newOrUpdatedModel);
List<M2ModelDiff> modelDiffs = diffModel(newOrUpdatedModel);
for (M2ModelDiff modelDiff : modelDiffs)
{
if (modelDiff.getDiffType().equals(M2ModelDiff.DIFF_DELETED))
{
throw new AlfrescoRuntimeException("Failed to validate model update - found deleted " + modelDiff.getElementType() + " '" + modelDiff.getElementName() + "'");
}
if (modelDiff.getDiffType().equals(M2ModelDiff.DIFF_UPDATED))
{
throw new AlfrescoRuntimeException("Failed to validate model update - found non-incrementally updated " + modelDiff.getElementType() + " '" + modelDiff.getElementName() + "'");
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -24,6 +24,10 @@
*/
package org.alfresco.repo.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
@@ -70,6 +74,7 @@ import org.alfresco.service.namespace.QName;
@Override
public String toString()
{
// note: currently used for model 'diffs'
StringBuilder sb = new StringBuilder(56);
sb.append("Association")
.append("[ class=").append(classDef)
@@ -245,5 +250,57 @@ import org.alfresco.service.namespace.QName;
{
return assoc.isTargetMany();
}
/*package*/ static Collection<M2ModelDiff> diffAssocLists(Collection<AssociationDefinition> previousAssocs, Collection<AssociationDefinition> newAssocs)
{
List<M2ModelDiff> M2ModelDiffs = new ArrayList<M2ModelDiff>();
for (AssociationDefinition previousAssoc : previousAssocs)
{
boolean found = false;
for (AssociationDefinition newAssoc : newAssocs)
{
if (newAssoc.getName().equals(previousAssoc.getName()))
{
// TODO currently uses toString() to check whether changed - could override equals()
if ((((M2AssociationDefinition)previousAssoc).toString()).equals(((M2AssociationDefinition)newAssoc).toString()))
{
M2ModelDiffs.add(new M2ModelDiff(newAssoc.getName(), M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UNCHANGED));
}
else
{
M2ModelDiffs.add(new M2ModelDiff(newAssoc.getName(), M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UPDATED));
}
found = true;
break;
}
}
if (! found)
{
M2ModelDiffs.add(new M2ModelDiff(previousAssoc.getName(), M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_DELETED));
}
}
for (AssociationDefinition newAssoc : newAssocs)
{
boolean found = false;
for (AssociationDefinition previousAssoc : previousAssocs)
{
if (newAssoc.getName().equals(previousAssoc.getName()))
{
found = true;
break;
}
}
if (! found)
{
M2ModelDiffs.add(new M2ModelDiff(newAssoc.getName(), M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_CREATED));
}
}
return M2ModelDiffs;
}
}

View File

@@ -26,6 +26,7 @@ package org.alfresco.repo.dictionary;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -460,4 +461,206 @@ import org.alfresco.service.namespace.QName;
return name.equals(((M2ClassDefinition)obj).name);
}
/**
* return differences in class definition
*
* note:
* - ignores changes in model title, description, author, published date, version
* - ignores changes in default values
* - checks properties for incremental updates, but does not include the diffs
* - checks assocs &<26>child assocs for incremental updates, but does not include the diffs
* - does not check default values
*/
/* package */ List<M2ModelDiff> diffClass(ClassDefinition classDef)
{
List<M2ModelDiff> modelDiffs = new ArrayList<M2ModelDiff>();
boolean isUpdated = false;
boolean isUpdatedIncrementally = false;
if (this == classDef)
{
return modelDiffs;
}
// check name - cannot be null
if (! name.equals(classDef.getName()))
{
isUpdatedIncrementally = true;
}
// check parent name
if (parentName != null)
{
if (! parentName.equals(classDef.getParentName()))
{
isUpdated = true;
}
}
else if (classDef.getParentName() != null)
{
isUpdated = true;
}
// check if aspect (or type)
if (isAspect() != classDef.isAspect())
{
isUpdated = true;
}
// check if container
if (isContainer() != classDef.isContainer())
{
if (isContainer())
{
// updated (non-incrementally) if class was a container and now is not a container - ie. all child associations removed
isUpdated = true;
}
if (classDef.isContainer())
{
// updated incrementally if class was not a container and now is a container - ie. some child associations added
isUpdatedIncrementally = true;
}
}
// check all properties (including inherited properties)
Collection<M2ModelDiff> propertyDiffs = M2PropertyDefinition.diffPropertyLists(getProperties().values(), classDef.getProperties().values());
for (M2ModelDiff propertyDiff : propertyDiffs)
{
// note: incremental property updates not supported yet, added for completeness
if (propertyDiff.getDiffType().equals(M2ModelDiff.DIFF_CREATED) || propertyDiff.getDiffType().equals(M2ModelDiff.DIFF_UPDATED_INC))
{
isUpdatedIncrementally = true;
}
if (propertyDiff.getDiffType().equals(M2ModelDiff.DIFF_UPDATED) || propertyDiff.getDiffType().equals(M2ModelDiff.DIFF_DELETED))
{
isUpdated = true;
break;
}
}
// check all associations (including inherited associations, child associations and inherited child associations)
Collection<M2ModelDiff> assocDiffs = M2AssociationDefinition.diffAssocLists(getAssociations().values(), classDef.getAssociations().values());
for (M2ModelDiff assocDiff : assocDiffs)
{
// note: incremental association updates not supported yet, added for completeness
if (assocDiff.getDiffType().equals(M2ModelDiff.DIFF_CREATED) || assocDiff.getDiffType().equals(M2ModelDiff.DIFF_UPDATED_INC))
{
isUpdatedIncrementally = true;
}
if (assocDiff.getDiffType().equals(M2ModelDiff.DIFF_UPDATED) || assocDiff.getDiffType().equals(M2ModelDiff.DIFF_DELETED))
{
isUpdated = true;
break;
}
}
// check default/mandatory aspects (including inherited default aspects)
Collection<M2ModelDiff> defaultAspectsDiffs = M2ClassDefinition.diffClassLists(new ArrayList<ClassDefinition>(getDefaultAspects()), new ArrayList<ClassDefinition>(classDef.getDefaultAspects()), M2ModelDiff.TYPE_DEFAULT_ASPECT);
for (M2ModelDiff defaultAspectDiff : defaultAspectsDiffs)
{
// note: incremental default/mandatory aspect updates not supported yet, added for completeness
if (defaultAspectDiff.getDiffType().equals(M2ModelDiff.DIFF_UPDATED_INC))
{
isUpdatedIncrementally = true;
}
if (defaultAspectDiff.getDiffType().equals(M2ModelDiff.DIFF_CREATED) || defaultAspectDiff.getDiffType().equals(M2ModelDiff.DIFF_UPDATED) || defaultAspectDiff.getDiffType().equals(M2ModelDiff.DIFF_DELETED))
{
isUpdated = true;
break;
}
}
// check archive/inheritedArchive
if (isArchive() != classDef.isArchive())
{
isUpdatedIncrementally = true;
}
String modelDiffType;
if (isAspect())
{
modelDiffType = M2ModelDiff.TYPE_ASPECT;
}
else
{
modelDiffType = M2ModelDiff.TYPE_TYPE;
}
if (isUpdated)
{
modelDiffs.add(new M2ModelDiff(name, modelDiffType, M2ModelDiff.DIFF_UPDATED));
}
else if (isUpdatedIncrementally)
{
modelDiffs.add(new M2ModelDiff(name, modelDiffType, M2ModelDiff.DIFF_UPDATED_INC));
}
else
{
for (M2ModelDiff modelDiff : modelDiffs)
{
if (! modelDiff.getDiffType().equals(M2ModelDiff.DIFF_UNCHANGED))
{
throw new DictionaryException("Unexpected: diff found although '" + name + "' not marked as updated");
}
}
modelDiffs.add(new M2ModelDiff(name, modelDiffType, M2ModelDiff.DIFF_UNCHANGED));
}
return modelDiffs;
}
/**
* return differences in class definition lists
*
*/
/*package*/ static List<M2ModelDiff> diffClassLists(Collection<ClassDefinition> previousClasses, Collection<ClassDefinition> newClasses, String M2ModelDiffType)
{
List<M2ModelDiff> modelDiffs = new ArrayList<M2ModelDiff>();
for (ClassDefinition previousClass : previousClasses)
{
boolean found = false;
for (ClassDefinition newClass : newClasses)
{
if (newClass.getName().equals(previousClass.getName()))
{
modelDiffs.addAll(((M2ClassDefinition)previousClass).diffClass(newClass));
found = true;
break;
}
}
if (! found)
{
modelDiffs.add(new M2ModelDiff(previousClass.getName(), M2ModelDiffType, M2ModelDiff.DIFF_DELETED));
}
}
for (ClassDefinition newClass : newClasses)
{
boolean found = false;
for (ClassDefinition previousClass : previousClasses)
{
if (newClass.getName().equals(previousClass.getName()))
{
found = true;
break;
}
}
if (! found)
{
modelDiffs.add(new M2ModelDiff(newClass.getName(), M2ModelDiffType, M2ModelDiff.DIFF_CREATED));
}
}
return modelDiffs;
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* 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
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.dictionary;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
/**
* Compiled Model Difference
*
* @author JanV
*
*/
public class M2ModelDiff
{
public static final String DIFF_CREATED = "created";
public static final String DIFF_UPDATED = "updated";
public static final String DIFF_UPDATED_INC = "updated_inc"; // incremental update
public static final String DIFF_DELETED = "deleted";
public static final String DIFF_UNCHANGED = "unchanged";
public static final String TYPE_TYPE = "TYPE";
public static final String TYPE_ASPECT = "ASPECT";
public static final String TYPE_DEFAULT_ASPECT = "DEFAULT_ASPECT";
public static final String TYPE_PROPERTY = "PROPERTY";
public static final String TYPE_ASSOCIATION = "ASSOCIATION";
private QName elementName;
private String elementType;
private String diffType;
public M2ModelDiff(QName elementName, String elementType, String diffType)
{
// Check that all the passed values are not null
ParameterCheck.mandatory("elementName", elementName);
ParameterCheck.mandatoryString("elementType", elementType);
ParameterCheck.mandatoryString("diffType", diffType);
if ((!elementType.equals(TYPE_TYPE)) &&
(!elementType.equals(TYPE_ASPECT)) &&
(!elementType.equals(TYPE_DEFAULT_ASPECT)) &&
(!elementType.equals(TYPE_PROPERTY)) &&
(!elementType.equals(TYPE_ASSOCIATION)))
{
throw new AlfrescoRuntimeException("Unknown element type = " + elementType);
}
if ((! diffType.equals(DIFF_CREATED)) &&
(! diffType.equals(DIFF_UPDATED)) &&
(! diffType.equals(DIFF_UPDATED_INC)) &&
(! diffType.equals(DIFF_DELETED)) &&
(! diffType.equals(DIFF_UNCHANGED)))
{
throw new AlfrescoRuntimeException("Unknown diff type = " + diffType);
}
this.elementName = elementName;
this.elementType = elementType;
this.diffType = diffType;
}
public QName getElementName()
{
return elementName;
}
public String getElementType()
{
return elementType;
}
public String getDiffType()
{
return diffType;
}
public String toString()
{
return new String(elementType + " " + elementName + " " + diffType);
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* 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
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.dictionary;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
/**
* Namespace Definition.
*
*
*/
public class M2NamespaceDefinition implements NamespaceDefinition
{
ModelDefinition model = null;
private String uri = null;
private String prefix = null;
/*package*/ M2NamespaceDefinition(ModelDefinition model, String uri, String prefix)
{
this.model = model;
this.uri = uri;
this.prefix = prefix;
}
public ModelDefinition getModel()
{
return model;
}
public String getUri()
{
return uri;
}
public String getPrefix()
{
return prefix;
}
}

View File

@@ -25,6 +25,7 @@
package org.alfresco.repo.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -224,7 +225,24 @@ import org.alfresco.service.namespace.QName;
@Override
public String toString()
{
return getName().toString();
// note: currently used for model 'diffs'
StringBuffer sb = new StringBuffer();
sb.append("Name: " + getName() + "\n");
sb.append("Title: " + getTitle() + "\n");
sb.append("Description: " + getDescription() + "\n");
sb.append("Default Value: " + getDefaultValue() + "\n");
sb.append("DataType Name: " + getDataType().getName() + "\n");
sb.append("ContainerClass Name: " + getContainerClass().getName() + "\n");
sb.append("isMultiValued: " + isMultiValued() + "\n");
sb.append("isMandatory: " + isMandatory() + "\n");
sb.append("isMandatoryEnforced: " + isMandatoryEnforced() + "\n");
sb.append("isProtected: " + isProtected() + "\n");
sb.append("isIndexed: " + isIndexed() + "\n");
sb.append("isStoredInIndex: " + isStoredInIndex() + "\n");
sb.append("isIndexedAtomically: " + isIndexedAtomically() + "\n");
sb.append("isTokenisedInIndex: " + isTokenisedInIndex() + "\n");
return sb.toString();
}
/* (non-Javadoc)
@@ -365,8 +383,64 @@ import org.alfresco.service.namespace.QName;
return m2Property.isTokenisedInIndex();
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.PropertyDefinition#getConstraints()
*/
public List<ConstraintDefinition> getConstraints()
{
return constraintDefs;
}
/*package*/ static Collection<M2ModelDiff> diffPropertyLists(Collection<PropertyDefinition> previousProperties, Collection<PropertyDefinition> newProperties)
{
List<M2ModelDiff> M2ModelDiffs = new ArrayList<M2ModelDiff>();
for (PropertyDefinition previousProperty : previousProperties)
{
boolean found = false;
for (PropertyDefinition newProperty : newProperties)
{
if (newProperty.getName().equals(previousProperty.getName()))
{
// TODO currently uses toString() to check whether changed - could override equals()
if ((((M2PropertyDefinition)previousProperty).toString()).equals(((M2PropertyDefinition)newProperty).toString()))
{
M2ModelDiffs.add(new M2ModelDiff(newProperty.getName(), M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED));
}
else
{
M2ModelDiffs.add(new M2ModelDiff(newProperty.getName(), M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UPDATED));
}
found = true;
break;
}
}
if (! found)
{
M2ModelDiffs.add(new M2ModelDiff(previousProperty.getName(), M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_DELETED));
}
}
for (PropertyDefinition newProperty : newProperties)
{
boolean found = false;
for (PropertyDefinition previousProperty : previousProperties)
{
if (newProperty.getName().equals(previousProperty.getName()))
{
found = true;
break;
}
}
if (! found)
{
M2ModelDiffs.add(new M2ModelDiff(newProperty.getName(), M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_CREATED));
}
}
return M2ModelDiffs;
}
}