mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
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:
@@ -11,10 +11,18 @@
|
|||||||
<property name="contentService" ref="ContentService"/>
|
<property name="contentService" ref="ContentService"/>
|
||||||
<property name="namespaceService" ref="namespaceService"/>
|
<property name="namespaceService" ref="namespaceService"/>
|
||||||
<property name="messageService" ref="messageService"/>
|
<property name="messageService" ref="messageService"/>
|
||||||
|
<property name="workflowService" ref="WorkflowService"/>
|
||||||
|
|
||||||
<property name="repositoryModelsLocation" ref="customModelsRepositoryLocation"/>
|
<property name="repositoryModelsLocation" ref="customModelsRepositoryLocation"/>
|
||||||
<property name="repositoryMessagesLocation" ref="customMessagesRepositoryLocation"/>
|
<property name="repositoryMessagesLocation" ref="customMessagesRepositoryLocation"/>
|
||||||
|
|
||||||
|
<property name="storeUrls">
|
||||||
|
<list>
|
||||||
|
<value>${spaces.store}</value>
|
||||||
|
<value>${spaces.archive.store}</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="repoAdminInterpreter" class="org.alfresco.repo.admin.RepoAdminInterpreter">
|
<bean id="repoAdminInterpreter" class="org.alfresco.repo.admin.RepoAdminInterpreter">
|
||||||
|
@@ -43,7 +43,12 @@ import org.alfresco.repo.dictionary.DictionaryDAO;
|
|||||||
import org.alfresco.repo.dictionary.M2Model;
|
import org.alfresco.repo.dictionary.M2Model;
|
||||||
import org.alfresco.repo.dictionary.RepositoryLocation;
|
import org.alfresco.repo.dictionary.RepositoryLocation;
|
||||||
import org.alfresco.repo.i18n.MessageService;
|
import org.alfresco.repo.i18n.MessageService;
|
||||||
|
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||||
import org.alfresco.service.cmr.admin.RepoAdminService;
|
import org.alfresco.service.cmr.admin.RepoAdminService;
|
||||||
|
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
@@ -51,7 +56,11 @@ import org.alfresco.service.cmr.repository.ContentWriter;
|
|||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.search.ResultSet;
|
||||||
import org.alfresco.service.cmr.search.SearchService;
|
import org.alfresco.service.cmr.search.SearchService;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
@@ -79,10 +88,13 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
private ContentService contentService;
|
private ContentService contentService;
|
||||||
private NamespaceService namespaceService;
|
private NamespaceService namespaceService;
|
||||||
private MessageService messageService;
|
private MessageService messageService;
|
||||||
|
private WorkflowService workflowService;
|
||||||
|
|
||||||
private RepositoryLocation repoModelsLocation;
|
private RepositoryLocation repoModelsLocation;
|
||||||
private RepositoryLocation repoMessagesLocation;
|
private RepositoryLocation repoMessagesLocation;
|
||||||
|
|
||||||
|
private List<String> storeUrls; // stores against which model changes (updates/deletes) should be validated
|
||||||
|
|
||||||
public final static String CRITERIA_ALL = "/*"; // immediate children only
|
public final static String CRITERIA_ALL = "/*"; // immediate children only
|
||||||
|
|
||||||
public final static String defaultSubtypeOfDictionaryModel = "subtypeOf('cm:dictionaryModel')";
|
public final static String defaultSubtypeOfDictionaryModel = "subtypeOf('cm:dictionaryModel')";
|
||||||
@@ -114,11 +126,16 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
this.namespaceService = namespaceService;
|
this.namespaceService = namespaceService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setmessageService(MessageService messageService)
|
public void setMessageService(MessageService messageService)
|
||||||
{
|
{
|
||||||
this.messageService = messageService;
|
this.messageService = messageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setWorkflowService(WorkflowService workflowService)
|
||||||
|
{
|
||||||
|
this.workflowService = workflowService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setRepositoryModelsLocation(RepositoryLocation repoModelsLocation)
|
public void setRepositoryModelsLocation(RepositoryLocation repoModelsLocation)
|
||||||
{
|
{
|
||||||
@@ -130,6 +147,11 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
this.repoMessagesLocation = repoMessagesLocation;
|
this.repoMessagesLocation = repoMessagesLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setStoreUrls(List<String> storeUrls)
|
||||||
|
{
|
||||||
|
this.storeUrls = storeUrls;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
@@ -202,7 +224,7 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
ParameterCheck.mandatory("ModelStream", modelStream);
|
ParameterCheck.mandatory("ModelStream", modelStream);
|
||||||
ParameterCheck.mandatoryString("ModelFileName", modelFileName);
|
ParameterCheck.mandatoryString("ModelFileName", modelFileName);
|
||||||
|
|
||||||
QName modelName = null;
|
QName modelQName = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -262,10 +284,13 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
writer.putContent(out.toString("UTF-8"));
|
writer.putContent(out.toString("UTF-8"));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// parse and update model in the dictionary
|
// validate model against dictionary - could be new, unchanged or updated
|
||||||
modelName = dictionaryDAO.putModel(model);
|
dictionaryDAO.validateModel(model);
|
||||||
|
|
||||||
logger.info("Model re-deployed: " + modelName);
|
// parse and update model in the dictionary
|
||||||
|
modelQName = dictionaryDAO.putModel(model);
|
||||||
|
|
||||||
|
logger.info("Model re-deployed: " + modelQName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -306,10 +331,13 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
writer.putContent(out.toString("UTF-8"));
|
writer.putContent(out.toString("UTF-8"));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// parse and add model to dictionary
|
// validate model against dictionary - could be new, unchanged or updated
|
||||||
modelName = dictionaryDAO.putModel(model);
|
dictionaryDAO.validateModel(model);
|
||||||
|
|
||||||
logger.info("Model deployed: " + modelName);
|
// parse and add model to dictionary
|
||||||
|
modelQName = dictionaryDAO.putModel(model);
|
||||||
|
|
||||||
|
logger.info("Model deployed: " + modelQName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
@@ -317,7 +345,7 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
throw new AlfrescoRuntimeException("Model deployment failed", e);
|
throw new AlfrescoRuntimeException("Model deployment failed", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return modelName;
|
return modelQName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -359,12 +387,13 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
|
|
||||||
if (model != null)
|
if (model != null)
|
||||||
{
|
{
|
||||||
String modelName = model.getName();
|
// validate model against dictionary - could be new, unchanged or updated
|
||||||
|
dictionaryDAO.validateModel(model);
|
||||||
|
|
||||||
// parse and update model in the dictionary
|
// parse and update model in the dictionary
|
||||||
modelQName = dictionaryDAO.putModel(model);
|
modelQName = dictionaryDAO.putModel(model);
|
||||||
|
|
||||||
logger.info("Model loaded: " + modelName);
|
logger.info("Model loaded: " + modelQName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
@@ -430,9 +459,12 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
|
|
||||||
modelQName = QName.createQName(modelName, namespaceService);
|
modelQName = QName.createQName(modelName, namespaceService);
|
||||||
|
|
||||||
|
// simple check for usages
|
||||||
|
validateModelDelete(modelQName);
|
||||||
|
|
||||||
dictionaryDAO.removeModel(modelQName);
|
dictionaryDAO.removeModel(modelQName);
|
||||||
|
|
||||||
logger.info("Model undeployed: " + modelFileName);
|
logger.info("Model undeployed: " + modelQName);
|
||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
{
|
{
|
||||||
@@ -738,4 +770,74 @@ public class RepoAdminServiceImpl implements RepoAdminService
|
|||||||
throw new AlfrescoRuntimeException("Message resource re-load failed", e);
|
throw new AlfrescoRuntimeException("Message resource re-load failed", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* validate against repository contents / workflows (e.g. when deleting an existing model)
|
||||||
|
*
|
||||||
|
* @param modelName
|
||||||
|
*/
|
||||||
|
private void validateModelDelete(QName modelName)
|
||||||
|
{
|
||||||
|
// TODO add model locking during delete (would need to be tenant-aware & cluster-aware) to avoid potential
|
||||||
|
// for concurrent addition of new content/workflow as model is being deleted
|
||||||
|
|
||||||
|
for (WorkflowDefinition workflowDef : workflowService.getDefinitions())
|
||||||
|
{
|
||||||
|
String workflowDefName = workflowDef.getName();
|
||||||
|
String workflowNamespaceURI = QName.createQName(BPMEngineRegistry.getLocalId(workflowDefName), namespaceService).getNamespaceURI();
|
||||||
|
for (NamespaceDefinition namespace : dictionaryDAO.getNamespaces(modelName))
|
||||||
|
{
|
||||||
|
if (workflowNamespaceURI.equals(namespace.getUri()))
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Failed to validate model delete - found workflow process definition " + workflowDefName + " using model namespace '" + namespace.getUri() + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TypeDefinition type : dictionaryDAO.getTypes(modelName))
|
||||||
|
{
|
||||||
|
validateClass(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AspectDefinition aspect : dictionaryDAO.getAspects(modelName))
|
||||||
|
{
|
||||||
|
validateClass(aspect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateClass(ClassDefinition classDef)
|
||||||
|
{
|
||||||
|
QName className = classDef.getName();
|
||||||
|
|
||||||
|
String classType = "TYPE";
|
||||||
|
if (classDef instanceof AspectDefinition)
|
||||||
|
{
|
||||||
|
classType = "ASPECT";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String storeUrl : this.storeUrls)
|
||||||
|
{
|
||||||
|
StoreRef store = new StoreRef(storeUrl);
|
||||||
|
|
||||||
|
// search for TYPE or ASPECT - TODO - alternative would be to extract QName and search by namespace ...
|
||||||
|
ResultSet rs = searchService.query(store, SearchService.LANGUAGE_LUCENE, classType+":\""+className+"\"");
|
||||||
|
if (rs.length() > 0)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Failed to validate model delete - found " + rs.length() + " nodes in store " + store + " with " + classType + " '" + className + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check against workflow usage
|
||||||
|
for (WorkflowDefinition workflowDef : workflowService.getDefinitions())
|
||||||
|
{
|
||||||
|
for (WorkflowTaskDefinition workflowTaskDef : workflowService.getTaskDefinitions(workflowDef.getId()))
|
||||||
|
{
|
||||||
|
TypeDefinition workflowTypeDef = workflowTaskDef.metadata;
|
||||||
|
if (workflowTypeDef.getName().toString().equals(className))
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Failed to validate model delete - found task definition in workflow " + workflowDef.getName() + " with " + classType + " '" + className + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,7 @@ import java.util.Collection;
|
|||||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
||||||
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.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
@@ -71,11 +72,9 @@ public interface DictionaryDAO extends ModelQuery
|
|||||||
*/
|
*/
|
||||||
public Collection<AspectDefinition> getAspects(QName model);
|
public Collection<AspectDefinition> getAspects(QName model);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param model the model for which to get properties for
|
||||||
* @param model the model for which to get properties
|
* @return the properties of the model
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public Collection<PropertyDefinition> getProperties(QName model);
|
public Collection<PropertyDefinition> getProperties(QName model);
|
||||||
|
|
||||||
@@ -115,6 +114,28 @@ public interface DictionaryDAO extends ModelQuery
|
|||||||
*/
|
*/
|
||||||
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
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Register with the Dictionary
|
* Register with the Dictionary
|
||||||
|
@@ -47,9 +47,11 @@ import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
|||||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.ParameterCheck;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
@@ -449,6 +451,7 @@ public class DictionaryDAOImpl implements DictionaryDAO
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.alfresco.repo.dictionary.ModelQuery#getDataType(java.lang.Class)
|
* @see org.alfresco.repo.dictionary.ModelQuery#getDataType(java.lang.Class)
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public DataTypeDefinition getDataType(Class javaClass)
|
public DataTypeDefinition getDataType(Class javaClass)
|
||||||
{
|
{
|
||||||
if (tenantService.isTenantUser() == true)
|
if (tenantService.isTenantUser() == true)
|
||||||
@@ -758,6 +761,24 @@ public class DictionaryDAOImpl implements DictionaryDAO
|
|||||||
return properties;
|
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)
|
* 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 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() + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
1111
source/java/org/alfresco/repo/dictionary/DiffModelTest.java
Executable file
1111
source/java/org/alfresco/repo/dictionary/DiffModelTest.java
Executable file
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.dictionary;
|
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.AssociationDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||||
@@ -70,6 +74,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
// note: currently used for model 'diffs'
|
||||||
StringBuilder sb = new StringBuilder(56);
|
StringBuilder sb = new StringBuilder(56);
|
||||||
sb.append("Association")
|
sb.append("Association")
|
||||||
.append("[ class=").append(classDef)
|
.append("[ class=").append(classDef)
|
||||||
@@ -246,4 +251,56 @@ import org.alfresco.service.namespace.QName;
|
|||||||
return assoc.isTargetMany();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,7 @@ package org.alfresco.repo.dictionary;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -460,4 +461,206 @@ import org.alfresco.service.namespace.QName;
|
|||||||
return name.equals(((M2ClassDefinition)obj).name);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
104
source/java/org/alfresco/repo/dictionary/M2ModelDiff.java
Executable file
104
source/java/org/alfresco/repo/dictionary/M2ModelDiff.java
Executable 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);
|
||||||
|
}
|
||||||
|
}
|
64
source/java/org/alfresco/repo/dictionary/M2NamespaceDefinition.java
Executable file
64
source/java/org/alfresco/repo/dictionary/M2NamespaceDefinition.java
Executable 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;
|
||||||
|
}
|
||||||
|
}
|
@@ -25,6 +25,7 @@
|
|||||||
package org.alfresco.repo.dictionary;
|
package org.alfresco.repo.dictionary;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -224,7 +225,24 @@ import org.alfresco.service.namespace.QName;
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
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)
|
/* (non-Javadoc)
|
||||||
@@ -365,8 +383,64 @@ import org.alfresco.service.namespace.QName;
|
|||||||
return m2Property.isTokenisedInIndex();
|
return m2Property.isTokenisedInIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.service.cmr.dictionary.PropertyDefinition#getConstraints()
|
||||||
|
*/
|
||||||
public List<ConstraintDefinition> getConstraints()
|
public List<ConstraintDefinition> getConstraints()
|
||||||
{
|
{
|
||||||
return constraintDefs;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
48
source/java/org/alfresco/service/cmr/dictionary/NamespaceDefinition.java
Executable file
48
source/java/org/alfresco/service/cmr/dictionary/NamespaceDefinition.java
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.service.cmr.dictionary;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read-only definition of a Namespace.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface NamespaceDefinition
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return defining model
|
||||||
|
*/
|
||||||
|
public ModelDefinition getModel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the namespace URI
|
||||||
|
*/
|
||||||
|
public String getUri();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the namespace Prefix
|
||||||
|
*/
|
||||||
|
public String getPrefix();
|
||||||
|
}
|
Reference in New Issue
Block a user