From 896bfd8986a81f9cc7060b49a31e080f6b34c49a Mon Sep 17 00:00:00 2001 From: Gavin Cornwell Date: Wed, 10 Jun 2009 09:33:58 +0000 Subject: [PATCH] Completion of MOB-837 (type support in forms) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14621 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/form-services-context.xml | 9 +- .../org/alfresco/repo/forms/FormService.java | 3 +- .../alfresco/repo/forms/FormServiceImpl.java | 4 +- .../repo/forms/FormServiceImplTest.java | 101 +++++++++++++++++- .../processor/FilteredFormProcessor.java | 5 +- .../repo/forms/processor/FormProcessor.java | 3 +- .../processor/node/TypeFormProcessor.java | 98 ++++++++++++++++- 7 files changed, 210 insertions(+), 13 deletions(-) diff --git a/config/alfresco/form-services-context.xml b/config/alfresco/form-services-context.xml index 588d9efdc0..7463dfe738 100644 --- a/config/alfresco/form-services-context.xml +++ b/config/alfresco/form-services-context.xml @@ -54,6 +54,9 @@ + + - + @@ -98,7 +101,9 @@ diff --git a/source/java/org/alfresco/repo/forms/FormService.java b/source/java/org/alfresco/repo/forms/FormService.java index 34794193b1..45609a0013 100644 --- a/source/java/org/alfresco/repo/forms/FormService.java +++ b/source/java/org/alfresco/repo/forms/FormService.java @@ -78,6 +78,7 @@ public interface FormService * * @param item The item to persist the form for * @param data An object representing the form data to persist + * @return The object persisted */ - public void saveForm(Item item, FormData data); + public Object saveForm(Item item, FormData data); } diff --git a/source/java/org/alfresco/repo/forms/FormServiceImpl.java b/source/java/org/alfresco/repo/forms/FormServiceImpl.java index 46912e259d..ea8e81aee1 100644 --- a/source/java/org/alfresco/repo/forms/FormServiceImpl.java +++ b/source/java/org/alfresco/repo/forms/FormServiceImpl.java @@ -98,7 +98,7 @@ public class FormServiceImpl implements FormService /* * @see org.alfresco.repo.forms.FormService#saveForm(org.alfresco.repo.forms.Item, org.alfresco.repo.forms.FormData) */ - public void saveForm(Item item, FormData data) + public Object saveForm(Item item, FormData data) { if (this.processorRegistry == null) { @@ -116,7 +116,7 @@ public class FormServiceImpl implements FormService } else { - processor.persist(item, data); + return processor.persist(item, data); } } } diff --git a/source/java/org/alfresco/repo/forms/FormServiceImplTest.java b/source/java/org/alfresco/repo/forms/FormServiceImplTest.java index e90f703d80..1e422634ac 100644 --- a/source/java/org/alfresco/repo/forms/FormServiceImplTest.java +++ b/source/java/org/alfresco/repo/forms/FormServiceImplTest.java @@ -713,7 +713,7 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest } @SuppressWarnings("unchecked") - public void testSaveForm() throws Exception + public void testSaveNodeForm() throws Exception { // create FormData object containing the values to update FormData data = new FormData(); @@ -804,8 +804,7 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest */ } - // TODO: enable this once the RM caveat stuff is fixed - public void xtestGetAllCreateForm() throws Exception + public void testGetAllCreateForm() throws Exception { // get a form for the cm:content type Form form = this.formService.getForm(new Item(TYPE_FORM_ITEM_KIND, "cm:content")); @@ -853,6 +852,102 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest assertNotNull("Expecting to find the cm:modifier field", modifierField); } + public void testGetSelectedFieldsCreateForm() throws Exception + { + // define a list of fields to retrieve from the node + List fields = new ArrayList(8); + fields.add("cm:name"); + fields.add("cm:title"); + + // get a form for the cm:content type + Form form = this.formService.getForm(new Item(TYPE_FORM_ITEM_KIND, "cm:content"), fields); + + // check a form got returned + assertNotNull("Expecting form to be present", form); + + // check item identifier matches + assertEquals(TYPE_FORM_ITEM_KIND, form.getItem().getKind()); + assertEquals("cm:content", form.getItem().getId()); + + // check the type is correct + assertEquals(ContentModel.TYPE_CONTENT.toPrefixString(this.namespaceService), + form.getItem().getType()); + + // check there is no group info + assertNull("Expecting the form groups to be null!", form.getFieldGroups()); + + // check the field definitions + Collection fieldDefs = form.getFieldDefinitions(); + assertNotNull("Expecting to find fields", fieldDefs); + assertEquals("Expecting to find 1 field", 1, fieldDefs.size()); + + // create a Map of the field definitions + // NOTE: we can safely do this as we know there are no duplicate field names and we're not + // concerned with ordering! + Map fieldDefMap = new HashMap(fieldDefs.size()); + for (FieldDefinition fieldDef : fieldDefs) + { + fieldDefMap.put(fieldDef.getName(), fieldDef); + } + + // find the fields + PropertyFieldDefinition nameField = (PropertyFieldDefinition)fieldDefMap.get("cm:name"); + assertNotNull("Expecting to find the cm:name field", nameField); + + // now force the title field to be present and check + List forcedFields = new ArrayList(2); + forcedFields.add("cm:title"); + // get a form for the cm:content type + form = this.formService.getForm(new Item(TYPE_FORM_ITEM_KIND, "cm:content"), fields, forcedFields); + fieldDefs = form.getFieldDefinitions(); + assertNotNull("Expecting to find fields", fieldDefs); + assertEquals("Expecting to find 2 fields", 2, fieldDefs.size()); + + } + + public void testSaveTypeForm() throws Exception + { + // create FormData object containing the values to update + FormData data = new FormData(); + + // supply the name + String name = "new-" + this.documentName; + data.addData("prop_cm_name", name); + + // supply the title property + String title = "This is the title property"; + data.addData("prop_cm_title", title); + + // persist the data (without a destination and make sure it fails) + try + { + this.formService.saveForm(new Item(TYPE_FORM_ITEM_KIND, "cm:content"), data); + + fail("Expected the persist to fail as there was no destination"); + } + catch (FormException fe) + { + // expected + } + + // supply the destination + data.addData("destination", this.folder.toString()); + + // persist the data + NodeRef newNode = (NodeRef)this.formService.saveForm(new Item(TYPE_FORM_ITEM_KIND, "cm:content"), data); + + // retrieve the data directly from the node service to ensure its there + Map props = this.nodeService.getProperties(newNode); + String newName = (String)props.get(ContentModel.PROP_NAME); + String newTitle = (String)props.get(ContentModel.PROP_TITLE); + assertEquals(name, newName); + assertEquals(title, newTitle); + + // check the titled aspect was automatically applied + assertTrue("Expecting the cm:titled to have been applied", + this.nodeService.hasAspect(this.document, ContentModel.ASPECT_TITLED)); + } + public void testNoForm() throws Exception { // test that a form can not be retrieved for a non-existent item diff --git a/source/java/org/alfresco/repo/forms/processor/FilteredFormProcessor.java b/source/java/org/alfresco/repo/forms/processor/FilteredFormProcessor.java index 929510f1dd..9b625e7bf5 100644 --- a/source/java/org/alfresco/repo/forms/processor/FilteredFormProcessor.java +++ b/source/java/org/alfresco/repo/forms/processor/FilteredFormProcessor.java @@ -98,8 +98,9 @@ public abstract class FilteredFormProcessor extends AbstractFormProcessor * @see org.alfresco.repo.forms.processor.FormProcessor#persist(org.alfresco.repo.forms.Item, org.alfresco.repo.forms.FormData) * @param item The item to save the form for * @param data The object representing the form data + * @return The object persisted */ - public void persist(Item item, FormData data) + public Object persist(Item item, FormData data) { // get the typed object representing the item Object typedItem = getTypedItem(item); @@ -124,6 +125,8 @@ public abstract class FilteredFormProcessor extends AbstractFormProcessor filter.afterPersist(typedItem, data, persistedObject); } } + + return persistedObject; } /** diff --git a/source/java/org/alfresco/repo/forms/processor/FormProcessor.java b/source/java/org/alfresco/repo/forms/processor/FormProcessor.java index 6f145f8fed..bbf6c40388 100644 --- a/source/java/org/alfresco/repo/forms/processor/FormProcessor.java +++ b/source/java/org/alfresco/repo/forms/processor/FormProcessor.java @@ -77,6 +77,7 @@ public interface FormProcessor * * @param item The item to generate a Form object for * @param data An object representing the data of the form + * @return The object persisted */ - public void persist(Item item, FormData data); + public Object persist(Item item, FormData data); } diff --git a/source/java/org/alfresco/repo/forms/processor/node/TypeFormProcessor.java b/source/java/org/alfresco/repo/forms/processor/node/TypeFormProcessor.java index f47b770775..a2f0ed41b1 100644 --- a/source/java/org/alfresco/repo/forms/processor/node/TypeFormProcessor.java +++ b/source/java/org/alfresco/repo/forms/processor/node/TypeFormProcessor.java @@ -24,19 +24,27 @@ */ package org.alfresco.repo.forms.processor.node; +import java.io.Serializable; +import java.util.HashMap; import java.util.List; import java.util.Map; +import org.alfresco.model.ContentModel; import org.alfresco.repo.forms.Form; import org.alfresco.repo.forms.FormData; +import org.alfresco.repo.forms.FormException; import org.alfresco.repo.forms.FormNotFoundException; import org.alfresco.repo.forms.Item; +import org.alfresco.repo.forms.FormData.FieldData; import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.InvalidQNameException; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,6 +59,12 @@ public class TypeFormProcessor extends NodeFormProcessor /** Logger */ private static Log logger = LogFactory.getLog(TypeFormProcessor.class); + protected static final String DESTINATION = "destination"; + protected static final String NAME_PROP_DATA = PROP + DATA_KEY_SEPARATOR + "cm" + DATA_KEY_SEPARATOR + "name"; + + /* + * @see org.alfresco.repo.forms.processor.node.NodeFormProcessor#getTypedItem(org.alfresco.repo.forms.Item) + */ @Override protected Object getTypedItem(Item item) { @@ -80,6 +94,9 @@ public class TypeFormProcessor extends NodeFormProcessor return typeDef; } + /* + * @see org.alfresco.repo.forms.processor.node.NodeFormProcessor#internalGenerate(java.lang.Object, java.util.List, java.util.List, org.alfresco.repo.forms.Form) + */ @Override protected void internalGenerate(Object item, List fields, List forcedFields, Form form) { @@ -178,6 +195,9 @@ public class TypeFormProcessor extends NodeFormProcessor } } + /* + * @see org.alfresco.repo.forms.processor.node.NodeFormProcessor#internalPersist(java.lang.Object, org.alfresco.repo.forms.FormData) + */ @Override protected Object internalPersist(Object item, FormData data) { @@ -187,10 +207,82 @@ public class TypeFormProcessor extends NodeFormProcessor // cast to the expected NodeRef representation TypeDefinition typeDef = (TypeDefinition)item; - if (logger.isWarnEnabled()) - logger.warn("Persisting of 'type' form items has not been implemented yet!"); + // create a new instance of the type + NodeRef nodeRef = createNode(typeDef, data); - return item; + // persist the form data + persistNode(nodeRef, data); + + // return the newly created node + return nodeRef; } + /** + * Creates a new instance of the given type. + *

+ * If the form data has the name property present it is used as + * the name of the node. + *

+ * The new node is placed in the location defined by the "destination" + * data item in the form data (this will usually be a hidden field), + * this will also be the NodeRef representation of the parent for the + * new node. + *

+ * + * @param typeDef The type defintion of the type to create + * @param data The form data + * @return NodeRef representing the newly created node + */ + protected NodeRef createNode(TypeDefinition typeDef, FormData data) + { + NodeRef nodeRef = null; + + if (data != null) + { + Map fieldData = data.getData(); + if (fieldData != null) + { + // firstly, ensure we have a destination to create the node in + NodeRef parentRef = null; + FieldData destination = fieldData.get(DESTINATION); + if (destination == null) + { + throw new FormException("Failed to persist form for '" + + typeDef.getName().toPrefixString(this.namespaceService) + + "' as destination data was not present."); + } + + // create the parent NodeRef + parentRef = new NodeRef((String)destination.getValue()); + + // TODO: determine what association to use when creating the node in the destination, + // defaults to ContentModel.ASSOC_CONTAINS + + // if a name property is present in the form data use it as the node name, + // otherwise generate a guid + String nodeName = null; + FieldData nameData = fieldData.get(NAME_PROP_DATA); + if (nameData != null) + { + nodeName = (String)nameData.getValue(); + + // remove the name data otherwise 'rename' gets called in persistNode + fieldData.remove(NAME_PROP_DATA); + } + if (nodeName == null || nodeName.length() == 0) + { + nodeName = GUID.generate(); + } + + // create the node + Map nodeProps = new HashMap(1); + nodeProps.put(ContentModel.PROP_NAME, nodeName); + nodeRef = this.nodeService.createNode(parentRef, ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(nodeName)), + typeDef.getName(), nodeProps).getChildRef(); + } + } + + return nodeRef; + } }