From aed810b0c32aec65f329290f9f79f1a90b6c9f3f Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Tue, 10 Jan 2006 14:51:45 +0000 Subject: [PATCH] - 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 --- .../repo/dictionary/DictionaryDAO.java | 8 ++ .../repo/dictionary/DictionaryDAOImpl.java | 22 +++ .../repo/dictionary/DictionaryModelType.java | 136 +++++++++++++----- .../dictionary/DictionaryModelTypeTest.java | 123 ++++++++++++++++ 4 files changed, 257 insertions(+), 32 deletions(-) diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java b/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java index cc97e12f18..bc6abbd819 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java @@ -79,4 +79,12 @@ public interface DictionaryDAO extends ModelQuery */ 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); + } diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java b/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java index a3a150a245..374ba21bcf 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java @@ -99,6 +99,28 @@ public class DictionaryDAOImpl implements DictionaryDAO // Publish new Model Definition 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); + } + } /** diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java b/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java index 7177bb5be6..5d5c48b2bf 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java @@ -44,7 +44,7 @@ public class DictionaryModelType { /** Key to the pending models */ private static final String KEY_PENDING_MODELS = "dictionaryModelType.pendingModels"; - + /** The dictionary DAO */ private DictionaryDAO dictionaryDAO; @@ -124,6 +124,18 @@ public class DictionaryModelType ContentModel.TYPE_DICTIONARY_MODEL, 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 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 */ - @SuppressWarnings("unchecked") public void onContentUpdate(NodeRef nodeRef) + { + queueModel(nodeRef); + } + + @SuppressWarnings("unchecked") + private void queueModel(NodeRef nodeRef) { Set pendingModelUpdates = (Set)AlfrescoTransactionSupport.getResource(KEY_PENDING_MODELS); if (pendingModelUpdates == null) @@ -147,9 +164,52 @@ public class DictionaryModelType 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 before, + Map 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. @@ -190,7 +250,7 @@ public class DictionaryModelType for (NodeRef nodeRef : pendingModels) { // 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); if (value != null) { @@ -198,36 +258,47 @@ public class DictionaryModelType } // Ignore if the node is a working copy or if its inactive - if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY) == false && - isActive == true) + if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY) == false) { - // 1. Compile the model and update the details on the node - // 2. Re-put the model - - ContentReader contentReader = this.contentService.getReader(nodeRef, ContentModel.PROP_CONTENT); - if (contentReader != null) + if (isActive == true) { - // Create a model from the current content - M2Model m2Model = M2Model.createModel(contentReader.getContentInputStream()); - // TODO what do we do if we don't have a model?? + // 1. Compile the model and update the details on the node + // 2. Re-put the model - // Try and compile the model - ModelDefinition modelDefintion = m2Model.compile(dictionaryDAO, namespaceDAO).getModelDefinition(); - // TODO what do we do if the model does not compile - - // Update the meta data for the model - Map props = this.nodeService.getProperties(nodeRef); - props.put(ContentModel.PROP_MODEL_NAME, modelDefintion.getName()); - props.put(ContentModel.PROP_MODEL_DESCRIPTION, modelDefintion.getDescription()); - props.put(ContentModel.PROP_MODEL_AUTHOR, modelDefintion.getAuthor()); - 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); + ContentReader contentReader = this.contentService.getReader(nodeRef, ContentModel.PROP_CONTENT); + if (contentReader != null) + { + // Create a model from the current content + M2Model m2Model = M2Model.createModel(contentReader.getContentInputStream()); + // TODO what do we do if we don't have a model?? + + // Try and compile the model + ModelDefinition modelDefintion = m2Model.compile(dictionaryDAO, namespaceDAO).getModelDefinition(); + // TODO what do we do if the model does not compile + + // Update the meta data for the model + Map props = this.nodeService.getProperties(nodeRef); + props.put(ContentModel.PROP_MODEL_NAME, modelDefintion.getName()); + props.put(ContentModel.PROP_MODEL_DESCRIPTION, modelDefintion.getDescription()); + props.put(ContentModel.PROP_MODEL_AUTHOR, modelDefintion.getAuthor()); + 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() */ + @SuppressWarnings("unchecked") public void afterRollback() { } diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryModelTypeTest.java b/source/java/org/alfresco/repo/dictionary/DictionaryModelTypeTest.java index 848a1c730e..58c02ce125 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryModelTypeTest.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryModelTypeTest.java @@ -112,6 +112,7 @@ public class DictionaryModelTypeTest extends BaseAlfrescoSpringTest private DictionaryService dictionaryService; private NamespaceService namespaceService; private CheckOutCheckInService cociService; + private DictionaryDAO dictionaryDAO; /** * On setup in transaction override @@ -126,6 +127,7 @@ public class DictionaryModelTypeTest extends BaseAlfrescoSpringTest this.dictionaryService = (DictionaryService)this.applicationContext.getBean("dictionaryService"); this.namespaceService = (NamespaceService)this.applicationContext.getBean("namespaceService"); 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() + { + 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() + { + 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() + { + 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() + { + 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; + } + }); + } }