mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
- Action web service implementation
- Simple Ruby web service examples - Outstanding work around persiatancy of models in the repository git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2094 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -79,4 +79,12 @@ public interface DictionaryDAO extends ModelQuery
|
|||||||
*/
|
*/
|
||||||
public void putModel(M2Model model);
|
public void putModel(M2Model model);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public void removeModel(QName model);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -99,6 +99,28 @@ public class DictionaryDAOImpl implements DictionaryDAO
|
|||||||
// Publish new Model Definition
|
// Publish new Model Definition
|
||||||
compiledModels.put(modelName, compiledModel);
|
compiledModels.put(modelName, compiledModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.repo.dictionary.DictionaryDAO#removeModel(org.alfresco.service.namespace.QName)
|
||||||
|
*/
|
||||||
|
public void removeModel(QName modelName)
|
||||||
|
{
|
||||||
|
CompiledModel compiledModel = this.compiledModels.get(modelName);
|
||||||
|
if (compiledModel != null)
|
||||||
|
{
|
||||||
|
// Remove the namespaces from the namespace service
|
||||||
|
M2Model model = compiledModel.getM2Model();
|
||||||
|
for (M2Namespace namespace : model.getNamespaces())
|
||||||
|
{
|
||||||
|
namespaceDAO.removePrefix(namespace.getPrefix());
|
||||||
|
namespaceDAO.removeURI(namespace.getUri());
|
||||||
|
namespaceToModel.remove(namespace.getUri());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the model from the list
|
||||||
|
this.compiledModels.remove(modelName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -44,7 +44,7 @@ public class DictionaryModelType
|
|||||||
{
|
{
|
||||||
/** Key to the pending models */
|
/** Key to the pending models */
|
||||||
private static final String KEY_PENDING_MODELS = "dictionaryModelType.pendingModels";
|
private static final String KEY_PENDING_MODELS = "dictionaryModelType.pendingModels";
|
||||||
|
|
||||||
/** The dictionary DAO */
|
/** The dictionary DAO */
|
||||||
private DictionaryDAO dictionaryDAO;
|
private DictionaryDAO dictionaryDAO;
|
||||||
|
|
||||||
@@ -124,6 +124,18 @@ public class DictionaryModelType
|
|||||||
ContentModel.TYPE_DICTIONARY_MODEL,
|
ContentModel.TYPE_DICTIONARY_MODEL,
|
||||||
new JavaBehaviour(this, "onContentUpdate"));
|
new JavaBehaviour(this, "onContentUpdate"));
|
||||||
|
|
||||||
|
// Register interest in the onPropertyUpdate policy for the dictionary model type
|
||||||
|
policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
||||||
|
ContentModel.TYPE_DICTIONARY_MODEL,
|
||||||
|
new JavaBehaviour(this, "onUpdateProperties"));
|
||||||
|
|
||||||
|
// Register interest in the node delete policy
|
||||||
|
policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||||
|
ContentModel.TYPE_DICTIONARY_MODEL,
|
||||||
|
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||||
|
|
||||||
// Create the transaction listener
|
// Create the transaction listener
|
||||||
this.transactionListener = new DictionaryModelTypeTransactionListener(this.nodeService, this.contentService);
|
this.transactionListener = new DictionaryModelTypeTransactionListener(this.nodeService, this.contentService);
|
||||||
}
|
}
|
||||||
@@ -133,8 +145,13 @@ public class DictionaryModelType
|
|||||||
*
|
*
|
||||||
* @param nodeRef the node reference whose content has been updated
|
* @param nodeRef the node reference whose content has been updated
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void onContentUpdate(NodeRef nodeRef)
|
public void onContentUpdate(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
queueModel(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void queueModel(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
Set<NodeRef> pendingModelUpdates = (Set<NodeRef>)AlfrescoTransactionSupport.getResource(KEY_PENDING_MODELS);
|
Set<NodeRef> pendingModelUpdates = (Set<NodeRef>)AlfrescoTransactionSupport.getResource(KEY_PENDING_MODELS);
|
||||||
if (pendingModelUpdates == null)
|
if (pendingModelUpdates == null)
|
||||||
@@ -147,9 +164,52 @@ public class DictionaryModelType
|
|||||||
AlfrescoTransactionSupport.bindListener(this.transactionListener);
|
AlfrescoTransactionSupport.bindListener(this.transactionListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO need to listen for a change in the modelActive attribute and update appropriatly
|
/**
|
||||||
|
* On update properties behaviour implementation
|
||||||
|
*
|
||||||
|
* @param nodeRef the node reference
|
||||||
|
* @param before the values of the properties before update
|
||||||
|
* @param after the values of the properties after the update
|
||||||
|
*/
|
||||||
|
public void onUpdateProperties(
|
||||||
|
NodeRef nodeRef,
|
||||||
|
Map<QName, Serializable> before,
|
||||||
|
Map<QName, Serializable> after)
|
||||||
|
{
|
||||||
|
Boolean beforeValue = (Boolean)before.get(ContentModel.PROP_MODEL_ACTIVE);
|
||||||
|
Boolean afterValue = (Boolean)after.get(ContentModel.PROP_MODEL_ACTIVE);
|
||||||
|
|
||||||
|
if (beforeValue == null && afterValue != null)
|
||||||
|
{
|
||||||
|
queueModel(nodeRef);
|
||||||
|
}
|
||||||
|
else if (afterValue == null && beforeValue != null)
|
||||||
|
{
|
||||||
|
// Remove the model since the value has been cleared
|
||||||
|
queueModel(nodeRef);
|
||||||
|
}
|
||||||
|
else if (beforeValue != null && afterValue != null && beforeValue.equals(afterValue) == false)
|
||||||
|
{
|
||||||
|
queueModel(nodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO need to listen for node deletion and act accordingly
|
@SuppressWarnings("unchecked")
|
||||||
|
public void beforeDeleteNode(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
// Ignore if the node is a working copy
|
||||||
|
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY) == false)
|
||||||
|
{
|
||||||
|
QName modelName = (QName)this.nodeService.getProperty(nodeRef, ContentModel.PROP_MODEL_NAME);
|
||||||
|
if (modelName != null)
|
||||||
|
{
|
||||||
|
// Remove the model from the dictionary
|
||||||
|
dictionaryDAO.removeModel(modelName);
|
||||||
|
|
||||||
|
// TODO how can we make this transactional ??
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dictionary model type transaction listener class.
|
* Dictionary model type transaction listener class.
|
||||||
@@ -190,7 +250,7 @@ public class DictionaryModelType
|
|||||||
for (NodeRef nodeRef : pendingModels)
|
for (NodeRef nodeRef : pendingModels)
|
||||||
{
|
{
|
||||||
// Find out whether the model is active (by default it is)
|
// Find out whether the model is active (by default it is)
|
||||||
boolean isActive = true;
|
boolean isActive = false;
|
||||||
Boolean value = (Boolean)nodeService.getProperty(nodeRef, ContentModel.PROP_MODEL_ACTIVE);
|
Boolean value = (Boolean)nodeService.getProperty(nodeRef, ContentModel.PROP_MODEL_ACTIVE);
|
||||||
if (value != null)
|
if (value != null)
|
||||||
{
|
{
|
||||||
@@ -198,36 +258,47 @@ public class DictionaryModelType
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ignore if the node is a working copy or if its inactive
|
// Ignore if the node is a working copy or if its inactive
|
||||||
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY) == false &&
|
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY) == false)
|
||||||
isActive == true)
|
|
||||||
{
|
{
|
||||||
// 1. Compile the model and update the details on the node
|
if (isActive == true)
|
||||||
// 2. Re-put the model
|
|
||||||
|
|
||||||
ContentReader contentReader = this.contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
|
||||||
if (contentReader != null)
|
|
||||||
{
|
{
|
||||||
// Create a model from the current content
|
// 1. Compile the model and update the details on the node
|
||||||
M2Model m2Model = M2Model.createModel(contentReader.getContentInputStream());
|
// 2. Re-put the model
|
||||||
// TODO what do we do if we don't have a model??
|
|
||||||
|
|
||||||
// Try and compile the model
|
ContentReader contentReader = this.contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
||||||
ModelDefinition modelDefintion = m2Model.compile(dictionaryDAO, namespaceDAO).getModelDefinition();
|
if (contentReader != null)
|
||||||
// TODO what do we do if the model does not compile
|
{
|
||||||
|
// Create a model from the current content
|
||||||
// Update the meta data for the model
|
M2Model m2Model = M2Model.createModel(contentReader.getContentInputStream());
|
||||||
Map<QName, Serializable> props = this.nodeService.getProperties(nodeRef);
|
// TODO what do we do if we don't have a model??
|
||||||
props.put(ContentModel.PROP_MODEL_NAME, modelDefintion.getName());
|
|
||||||
props.put(ContentModel.PROP_MODEL_DESCRIPTION, modelDefintion.getDescription());
|
// Try and compile the model
|
||||||
props.put(ContentModel.PROP_MODEL_AUTHOR, modelDefintion.getAuthor());
|
ModelDefinition modelDefintion = m2Model.compile(dictionaryDAO, namespaceDAO).getModelDefinition();
|
||||||
props.put(ContentModel.PROP_MODEL_PUBLISHED_DATE, modelDefintion.getPublishedDate());
|
// TODO what do we do if the model does not compile
|
||||||
props.put(ContentModel.PROP_MODEL_VERSION, modelDefintion.getVersion());
|
|
||||||
this.nodeService.setProperties(nodeRef, props);
|
// Update the meta data for the model
|
||||||
|
Map<QName, Serializable> props = this.nodeService.getProperties(nodeRef);
|
||||||
// TODO how do we get the dependancies for this model ??
|
props.put(ContentModel.PROP_MODEL_NAME, modelDefintion.getName());
|
||||||
|
props.put(ContentModel.PROP_MODEL_DESCRIPTION, modelDefintion.getDescription());
|
||||||
// Put the model
|
props.put(ContentModel.PROP_MODEL_AUTHOR, modelDefintion.getAuthor());
|
||||||
dictionaryDAO.putModel(m2Model);
|
props.put(ContentModel.PROP_MODEL_PUBLISHED_DATE, modelDefintion.getPublishedDate());
|
||||||
|
props.put(ContentModel.PROP_MODEL_VERSION, modelDefintion.getVersion());
|
||||||
|
this.nodeService.setProperties(nodeRef, props);
|
||||||
|
|
||||||
|
// TODO how do we get the dependancies for this model ??
|
||||||
|
|
||||||
|
// Put the model
|
||||||
|
dictionaryDAO.putModel(m2Model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QName modelName = (QName)this.nodeService.getProperty(nodeRef, ContentModel.PROP_MODEL_NAME);
|
||||||
|
if (modelName != null)
|
||||||
|
{
|
||||||
|
// Remove the model from the dictionary
|
||||||
|
dictionaryDAO.removeModel(modelName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,6 +322,7 @@ public class DictionaryModelType
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.repo.transaction.TransactionListener#afterRollback()
|
* @see org.alfresco.repo.transaction.TransactionListener#afterRollback()
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void afterRollback()
|
public void afterRollback()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@@ -112,6 +112,7 @@ public class DictionaryModelTypeTest extends BaseAlfrescoSpringTest
|
|||||||
private DictionaryService dictionaryService;
|
private DictionaryService dictionaryService;
|
||||||
private NamespaceService namespaceService;
|
private NamespaceService namespaceService;
|
||||||
private CheckOutCheckInService cociService;
|
private CheckOutCheckInService cociService;
|
||||||
|
private DictionaryDAO dictionaryDAO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On setup in transaction override
|
* On setup in transaction override
|
||||||
@@ -126,6 +127,7 @@ public class DictionaryModelTypeTest extends BaseAlfrescoSpringTest
|
|||||||
this.dictionaryService = (DictionaryService)this.applicationContext.getBean("dictionaryService");
|
this.dictionaryService = (DictionaryService)this.applicationContext.getBean("dictionaryService");
|
||||||
this.namespaceService = (NamespaceService)this.applicationContext.getBean("namespaceService");
|
this.namespaceService = (NamespaceService)this.applicationContext.getBean("namespaceService");
|
||||||
this.cociService = (CheckOutCheckInService)this.applicationContext.getBean("checkOutCheckInService");
|
this.cociService = (CheckOutCheckInService)this.applicationContext.getBean("checkOutCheckInService");
|
||||||
|
this.dictionaryDAO = (DictionaryDAO)this.applicationContext.getBean("dictionaryDAO");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,4 +226,125 @@ public class DictionaryModelTypeTest extends BaseAlfrescoSpringTest
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testIsActiveFlagAndDelete()
|
||||||
|
{
|
||||||
|
this.dictionaryDAO.removeModel(TEST_MODEL_ONE);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check that the model has not yet been loaded into the dictionary
|
||||||
|
this.dictionaryService.getModel(TEST_MODEL_ONE);
|
||||||
|
fail("This model has not yet been loaded into the dictionary service");
|
||||||
|
}
|
||||||
|
catch (DictionaryException exception)
|
||||||
|
{
|
||||||
|
// We expect this exception
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a model node
|
||||||
|
PropertyMap properties = new PropertyMap(1);
|
||||||
|
final NodeRef modelNode = this.nodeService.createNode(
|
||||||
|
this.rootNodeRef,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "dictionaryModels"),
|
||||||
|
ContentModel.TYPE_DICTIONARY_MODEL,
|
||||||
|
properties).getChildRef();
|
||||||
|
assertNotNull(modelNode);
|
||||||
|
|
||||||
|
// Add the model content to the model node
|
||||||
|
ContentWriter contentWriter = this.contentService.getWriter(modelNode, ContentModel.PROP_CONTENT, true);
|
||||||
|
contentWriter.setEncoding("UTF-8");
|
||||||
|
contentWriter.setMimetype(MimetypeMap.MIMETYPE_XML);
|
||||||
|
contentWriter.putContent(MODEL_ONE_XML);
|
||||||
|
|
||||||
|
// End the transaction to force update
|
||||||
|
setComplete();
|
||||||
|
endTransaction();
|
||||||
|
|
||||||
|
TransactionUtil.executeInUserTransaction(this.transactionService, new TransactionUtil.TransactionWork<Object>()
|
||||||
|
{
|
||||||
|
public Object doWork() throws Exception
|
||||||
|
{
|
||||||
|
// The model should not yet be loaded
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check that the model has not yet been loaded into the dictionary
|
||||||
|
DictionaryModelTypeTest.this.dictionaryService.getModel(TEST_MODEL_ONE);
|
||||||
|
fail("This model has not yet been loaded into the dictionary service");
|
||||||
|
}
|
||||||
|
catch (DictionaryException exception)
|
||||||
|
{
|
||||||
|
// We expect this exception
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the isActive flag
|
||||||
|
DictionaryModelTypeTest.this.nodeService.setProperty(modelNode, ContentModel.PROP_MODEL_ACTIVE, true);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
TransactionUtil.executeInUserTransaction(this.transactionService, new TransactionUtil.TransactionWork<Object>()
|
||||||
|
{
|
||||||
|
public Object doWork() throws Exception
|
||||||
|
{
|
||||||
|
// The model should now be loaded
|
||||||
|
assertNotNull(DictionaryModelTypeTest.this.dictionaryService.getModel(TEST_MODEL_ONE));
|
||||||
|
|
||||||
|
// Set the isActive flag
|
||||||
|
DictionaryModelTypeTest.this.nodeService.setProperty(modelNode, ContentModel.PROP_MODEL_ACTIVE, false);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
TransactionUtil.executeInUserTransaction(this.transactionService, new TransactionUtil.TransactionWork<Object>()
|
||||||
|
{
|
||||||
|
public Object doWork() throws Exception
|
||||||
|
{
|
||||||
|
// The model should not be loaded
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check that the model has not yet been loaded into the dictionary
|
||||||
|
DictionaryModelTypeTest.this.dictionaryService.getModel(TEST_MODEL_ONE);
|
||||||
|
fail("This model has not yet been loaded into the dictionary service");
|
||||||
|
}
|
||||||
|
catch (DictionaryException exception)
|
||||||
|
{
|
||||||
|
// We expect this exception
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the isActive flag
|
||||||
|
DictionaryModelTypeTest.this.nodeService.setProperty(modelNode, ContentModel.PROP_MODEL_ACTIVE, true);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
TransactionUtil.executeInUserTransaction(this.transactionService, new TransactionUtil.TransactionWork<Object>()
|
||||||
|
{
|
||||||
|
public Object doWork() throws Exception
|
||||||
|
{
|
||||||
|
// The model should now be loaded
|
||||||
|
assertNotNull(DictionaryModelTypeTest.this.dictionaryService.getModel(TEST_MODEL_ONE));
|
||||||
|
|
||||||
|
DictionaryModelTypeTest.this.nodeService.deleteNode(modelNode);
|
||||||
|
|
||||||
|
// The model should not be loaded
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check that the model has not yet been loaded into the dictionary
|
||||||
|
DictionaryModelTypeTest.this.dictionaryService.getModel(TEST_MODEL_ONE);
|
||||||
|
fail("This model has not yet been loaded into the dictionary service");
|
||||||
|
}
|
||||||
|
catch (DictionaryException exception)
|
||||||
|
{
|
||||||
|
// We expect this exception
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user