diff --git a/config/alfresco/form-services-context.xml b/config/alfresco/form-services-context.xml index f477d3c37e..9e5ba3340f 100644 --- a/config/alfresco/form-services-context.xml +++ b/config/alfresco/form-services-context.xml @@ -109,6 +109,22 @@ ref="nodeFilterRegistry" /> --> + + + + ${system.workflow.jbpm.comment.property.max.length} + + + + + + + ${system.workflow.jbpm.comment.property.max.length} + + + diff --git a/config/alfresco/model/bpmModel.xml b/config/alfresco/model/bpmModel.xml index 4eaa018e66..d8fec9e32b 100644 --- a/config/alfresco/model/bpmModel.xml +++ b/config/alfresco/model/bpmModel.xml @@ -64,6 +64,15 @@ + + + 0 + + + 4000 + + + @@ -169,6 +178,9 @@ d:text + + + diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index b1cbf7a3e3..f671759f27 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -70,6 +70,8 @@ system.workflow.jbpm.config.location=classpath:org/alfresco/repo/workflow/jbpm/j # any in-flight JBPM workflows to be completed. system.workflow.engine.jbpm.definitions.visible=false +system.workflow.jbpm.comment.property.max.length=4000 + #Determines if Activiti definitions are visible system.workflow.engine.activiti.definitions.visible=true diff --git a/source/java/org/alfresco/repo/forms/processor/workflow/WorkflowFormFilter.java b/source/java/org/alfresco/repo/forms/processor/workflow/WorkflowFormFilter.java new file mode 100644 index 0000000000..b48fe57e8e --- /dev/null +++ b/source/java/org/alfresco/repo/forms/processor/workflow/WorkflowFormFilter.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.forms.processor.workflow; + +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.forms.Form; +import org.alfresco.repo.forms.FormData; +import org.alfresco.repo.forms.FormData.FieldData; +import org.alfresco.repo.forms.processor.AbstractFilter; +import org.alfresco.repo.workflow.PropertyValueSizeIsMoreMaxLengthException; + +public class WorkflowFormFilter extends AbstractFilter +{ + + private static final String PROP_BPM_COMMENT = "prop_bpm_comment"; + + private int maxLengthBpmCommentProperty = 4000; + + public void setMaxLengthBpmCommentProperty(int maxLengthBpmCommentProperty) + { + this.maxLengthBpmCommentProperty = maxLengthBpmCommentProperty; + } + + @Override + public void beforeGenerate(ItemType item, List fields, List forcedFields, Form form, Map context) + { + // TODO Auto-generated method stub + + } + + @Override + public void afterGenerate(ItemType item, List fields, List forcedFields, Form form, Map context) + { + // TODO Auto-generated method stub + + } + + @Override + public void beforePersist(ItemType item, FormData data) + { + FieldData bpmComment = data.getFieldData(PROP_BPM_COMMENT); + if (bpmComment != null) + { + int value = ((String) bpmComment.getValue()).getBytes().length; + + if (maxLengthBpmCommentProperty < value) + { + throw new PropertyValueSizeIsMoreMaxLengthException(PROP_BPM_COMMENT); + } + } + + } + + @Override + public void afterPersist(ItemType item, FormData data, PersistType persistedObject) + { + // TODO Auto-generated method stub + + } + +} diff --git a/source/java/org/alfresco/repo/workflow/PropertyValueSizeIsMoreMaxLengthException.java b/source/java/org/alfresco/repo/workflow/PropertyValueSizeIsMoreMaxLengthException.java new file mode 100644 index 0000000000..34f6a0852f --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/PropertyValueSizeIsMoreMaxLengthException.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.workflow; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.namespace.QName; + +public class PropertyValueSizeIsMoreMaxLengthException extends AlfrescoRuntimeException +{ + private static final long serialVersionUID = 5722742734237891185L; + + public PropertyValueSizeIsMoreMaxLengthException(QName name) + { + super("Property '" + name.getLocalName() + "' has size more than max value."); + } + + public PropertyValueSizeIsMoreMaxLengthException(String name) + { + super("Property '" + name + "' has size more than max value."); + } +} \ No newline at end of file diff --git a/source/test-java/org/alfresco/repo/forms/processor/workflow/FormProcessorTest.java b/source/test-java/org/alfresco/repo/forms/processor/workflow/FormProcessorTest.java new file mode 100644 index 0000000000..62ce10899d --- /dev/null +++ b/source/test-java/org/alfresco/repo/forms/processor/workflow/FormProcessorTest.java @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.forms.processor.workflow; + +import static org.alfresco.repo.forms.processor.node.FormFieldConstants.*; +import static org.alfresco.repo.workflow.WorkflowModel.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.alfresco.repo.forms.FieldDefinition; +import org.alfresco.repo.forms.Form; +import org.alfresco.repo.forms.FormData; +import org.alfresco.repo.forms.FormData.FieldData; +import org.alfresco.repo.forms.Item; +import org.alfresco.repo.forms.processor.FilterRegistry; +import org.alfresco.repo.forms.processor.node.DefaultFieldProcessor; +import org.alfresco.repo.forms.processor.node.MockClassAttributeDefinition; +import org.alfresco.repo.forms.processor.node.MockFieldProcessorRegistry; +import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.QNamePattern; + +import junit.framework.TestCase; + +public class FormProcessorTest extends TestCase +{ + protected static final String TASK_DEF_NAME = "TaskDef"; + protected static final QName DESC_NAME = PROP_DESCRIPTION; + protected static final QName STATUS_NAME = PROP_STATUS; + protected static final QName PROP_WITH_ = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "some_prop"); + protected static final QName ACTORS_NAME = ASSOC_POOLED_ACTORS; + protected static final QName ASSIGNEE_NAME = ASSOC_ASSIGNEE; + protected static final QName ASSOC_WITH_ = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "some_assoc"); + protected static final NodeRef FAKE_NODE = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode"); + protected static final NodeRef FAKE_NODE2 = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode2"); + protected static final NodeRef FAKE_NODE3 = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode3"); + protected static final NodeRef PCKG_NODE = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakePackage"); + + protected WorkflowService workflowService; + protected NodeService nodeService; + protected NamespaceService namespaceService; + protected AbstractWorkflowFormProcessor processor; + protected Item item; + + protected void setUp() throws Exception + { + super.setUp(); + } + + protected DefaultFieldProcessor makeDefaultFieldProcessor(DictionaryService dictionaryService) throws Exception + { + DefaultFieldProcessor defaultProcessor = new DefaultFieldProcessor(); + defaultProcessor.setDictionaryService(dictionaryService); + defaultProcessor.setNamespaceService(namespaceService); + defaultProcessor.afterPropertiesSet(); + return defaultProcessor; + } + + public void testPersistPropertyComment(String taskId) throws Exception + { + // MNT-11809 Activiti losses data with large Aspect or Type property values + // wiki Hamlet text + StringBuilder wikiHamlet = new StringBuilder(); + wikiHamlet.append("Hamlet is the son of the King of Denmark. When Hamlet`s father dies, his uncle Claudius becomes king and marries Hamlet`s mother (Gertrude)."); + wikiHamlet.append("Hamlet`s father appears as a ghost and tells Hamlet that he was murdered by Claudius. Hamlet is not sure that the ghost is really his father."); + wikiHamlet.append("He gets some travelling actors to perform a play which shows the murder of a king in the same way Hamlet`s father said he was killed."); + wikiHamlet.append("When Claudius reacts badly to seeing this, Hamlet believes he is guilty."); + wikiHamlet.append("Hamlet tells his mother that he knows about the murder. While there he kills Polonius, who is the king`s advisor, because he thinks he is Claudius."); + wikiHamlet.append("Rosencrantz and Guildenstern were Hamlet`s childhood friends."); + wikiHamlet + .append("Claudius sends Rosencrantz and Guildenstern with Hamlet to England to have Hamlet killed, but their ship is attacked by pirates who take Hamlet prisoner but then return him to Denmark."); + wikiHamlet + .append("Rosencrantz and Guildenstern are taken to England where they die. Ophelia is Polonius` daughter . After her father, Polonius, is killed by Hamlet she goes mad."); + wikiHamlet.append("Then she falls into a river and drowns. Hamlet returns just as her funeral is happening. Laertes, her brother, decides to kill Hamlet in revenge."); + wikiHamlet + .append("He challenges Hamlet to a sword fight, and puts poison on his own sword. Claudius makes some poisoned wine for Hamlet to drink in case that does not work."); + wikiHamlet.append("At first Hamlet wins the sword fight, and in the meantime his mother drinks the poisoned wine without knowing, and dies."); + wikiHamlet + .append("On the other hand Laertes falsely pierces Hamlet with a poisoned blade, but then Hamlet stabs Laertes with the same sword. Laertes tells Hamlet about the plot and then dies."); + wikiHamlet.append("Hamlet kills Claudius with the poisoned sword. Horatio, Hamlet`s friend, tells everyone about the murder of the old king."); + wikiHamlet.append("Hamlet tells everyone that the Norwegian prince, Fortinbras, should be king, and then dies from the poison."); + wikiHamlet.append("When Fortinbras arrives, Horatio recounts the tale and Fortinbras orders Hamlet`s body borne off in honour."); + wikiHamlet.append("Hamlet is one of the hardest parts for an actor to perform. It is one of the largest roles written by Shakespeare."); + wikiHamlet.append("Many people disagree about what Hamlet is really thinking. For many actors, playing Hamlet is one of the most important parts of their career."); + + // Get max length of jbpm_comment property from repository.properties + String maxLength = "4000"; + + String dir = System.getProperty("user.dir"); + File propFile = new File(dir + File.separator + "config" + File.separator + "alfresco" + File.separator + "repository.properties"); + + if (propFile.exists()) + { + InputStream propStream = null; + try + { + propStream = new FileInputStream(propFile); + Properties properties = new Properties(); + properties.load(propStream); + + maxLength = properties.getProperty("system.workflow.jbpm.comment.property.max.length"); + } + finally + { + if (propStream != null) + { + propStream.close(); + } + } + } + + // Convert value of property to int + int maxLengthPropery; + try + { + maxLengthPropery = Integer.valueOf(maxLength); + } + catch (NumberFormatException e) + { + maxLengthPropery = 4000; + } + + FormData data = new FormData(); + boolean repeatTest = true; + String test = wikiHamlet.toString(); + Item item = new Item("task", taskId); + + while (repeatTest) + { + data.addFieldData("prop_bpm_comment", test); + + int value = test.getBytes().length; + + try + { + processor.persist(item, data); + + assertTrue("Value is " + value, value < maxLengthPropery); + } + catch (Exception e) + { + assertTrue("Caught Exception, value is " + value, value > maxLengthPropery); + } + + if (value < maxLengthPropery) + { + test += wikiHamlet.toString(); + } + else + { + repeatTest = false; + } + } + } + + protected AbstractWorkflowFormProcessor makeTaskFormProcessor(AbstractWorkflowFormProcessor processor1, DictionaryService dictionaryService, + MockFieldProcessorRegistry fieldProcessorRegistry, DefaultFieldProcessor defaultProcessor) + { + processor1.setWorkflowService(workflowService); + processor1.setNodeService(nodeService); + processor1.setNamespaceService(namespaceService); + processor1.setDictionaryService(dictionaryService); + processor1.setFieldProcessorRegistry(fieldProcessorRegistry); + processor1.setBehaviourFilter(mock(BehaviourFilter.class)); + // MNT-11809 Activiti losses data with large Aspect or Type property values + FilterRegistry filterRegistry = new FilterRegistry(); + filterRegistry.addFilter(new WorkflowFormFilter()); + processor1.setFilterRegistry(filterRegistry); + return processor1; + } + + protected void mockPackageItems(NodeRef... children) + { + ArrayList results = new ArrayList(children.length); + for (NodeRef nodeRef : children) + { + ChildAssociationRef child = new ChildAssociationRef(ASSOC_PACKAGE_CONTAINS, PCKG_NODE, null, nodeRef); + results.add(child); + } + when(nodeService.getChildAssocs(eq(PCKG_NODE), (QNamePattern) any(), (QNamePattern) any())).thenReturn(results); + + } + + protected void checkRemovedPackageItem(NodeRef child, boolean wasCalled) + { + int times = wasCalled ? 1 : 0; + verify(nodeService, times(times)).removeChild(PCKG_NODE, child); + } + + protected void checkAddPackageItem(NodeRef child, boolean wasCalled) + { + int times = wasCalled ? 1 : 0; + verify(nodeService, times(times)).addChild(eq(PCKG_NODE), eq(child), eq(ASSOC_PACKAGE_CONTAINS), (QName) any()); + } + + protected void checkSingleProperty(Form form, String fieldName, Serializable fieldData) + { + String expDataKey = makeDataKeyName(fieldName); + checkSingleField(form, fieldName, fieldData, expDataKey); + } + + protected void checkSingleAssociation(Form form, String fieldName, Serializable fieldData) + { + String expDataKey = makeAssociationDataKey(fieldName); + checkSingleField(form, fieldName, fieldData, expDataKey); + } + + protected void checkSingleField(Form form, String fieldName, Serializable fieldData, String expDataKey) + { + List fieldDefs = form.getFieldDefinitions(); + assertEquals(1, fieldDefs.size()); + FieldDefinition fieldDef = fieldDefs.get(0); + assertEquals(fieldName, fieldDef.getName()); + String dataKey = fieldDef.getDataKeyName(); + assertEquals(expDataKey, dataKey); + FieldData data = form.getFormData().getFieldData(dataKey); + if (fieldData != null && data != null) + { + assertEquals(fieldData, data.getValue()); + } + else + { + assertNull(data); + } + } + + protected String makeDataKeyName(String fieldName) + { + return PROP_DATA_PREFIX + fieldName.replace(":", "_"); + } + + protected String makeDataKeyName(String fieldName, boolean added) + { + String assocDataKey = makeAssociationDataKey(fieldName); + String suffix = added ? ASSOC_DATA_ADDED_SUFFIX : ASSOC_DATA_REMOVED_SUFFIX; + return assocDataKey + suffix; + } + + protected String makeAssociationDataKey(String fieldName) + { + return ASSOC_DATA_PREFIX + fieldName.replace(":", "_"); + } + + protected Map makeTaskAssociationDefs() + { + Map associations = new HashMap(); + QName actorName = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "Actor"); + + // Add Assigneee association + MockClassAttributeDefinition assigneeDef = MockClassAttributeDefinition.mockAssociationDefinition(ASSIGNEE_NAME, actorName); + associations.put(ASSIGNEE_NAME, assigneeDef); + + // Add Assigneee association + MockClassAttributeDefinition actorsDef = MockClassAttributeDefinition.mockAssociationDefinition(ACTORS_NAME, actorName); + associations.put(ACTORS_NAME, actorsDef); + + // Add association with _ + MockClassAttributeDefinition with_ = MockClassAttributeDefinition.mockAssociationDefinition(ASSOC_WITH_, actorName); + associations.put(ASSOC_WITH_, with_); + + return associations; + } + +} diff --git a/source/test-java/org/alfresco/repo/forms/processor/workflow/TaskFormProcessorTest.java b/source/test-java/org/alfresco/repo/forms/processor/workflow/TaskFormProcessorTest.java index d1a1c8b3b6..bff72d5726 100644 --- a/source/test-java/org/alfresco/repo/forms/processor/workflow/TaskFormProcessorTest.java +++ b/source/test-java/org/alfresco/repo/forms/processor/workflow/TaskFormProcessorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2014 Alfresco Software Limited. * * This file is part of Alfresco * @@ -19,13 +19,11 @@ package org.alfresco.repo.forms.processor.workflow; -import static org.alfresco.repo.forms.processor.node.FormFieldConstants.*; import static org.alfresco.repo.workflow.WorkflowModel.*; import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import java.io.Serializable; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -33,10 +31,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import junit.framework.TestCase; - import org.alfresco.model.ContentModel; -import org.alfresco.repo.forms.FieldDefinition; import org.alfresco.repo.forms.Form; import org.alfresco.repo.forms.FormData; import org.alfresco.repo.forms.FormNotFoundException; @@ -45,13 +40,11 @@ import org.alfresco.repo.forms.FormData.FieldData; import org.alfresco.repo.forms.processor.node.DefaultFieldProcessor; import org.alfresco.repo.forms.processor.node.MockClassAttributeDefinition; import org.alfresco.repo.forms.processor.node.MockFieldProcessorRegistry; -import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition; -import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthenticationService; @@ -68,7 +61,6 @@ import org.alfresco.service.cmr.workflow.WorkflowTransition; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceServiceMemoryImpl; import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.QNamePattern; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -78,28 +70,13 @@ import org.mockito.stubbing.Answer; * @author Nick Smith * */ -public class TaskFormProcessorTest extends TestCase +public class TaskFormProcessorTest extends FormProcessorTest { - private static final String TASK_DEF_NAME = "TaskDef"; private static final String TASK_ID = "foo$Real Id"; - private static final QName DESC_NAME = PROP_DESCRIPTION; - private static final QName STATUS_NAME = PROP_STATUS; - private static final QName PROP_WITH_ = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "some_prop"); - private static final QName ACTORS_NAME = ASSOC_POOLED_ACTORS; - private static final QName ASSIGNEE_NAME = ASSOC_ASSIGNEE; - private static final QName ASSOC_WITH_ = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "some_assoc"); - private static final NodeRef FAKE_NODE = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode"); - private static final NodeRef FAKE_NODE2 = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode2"); - private static final NodeRef FAKE_NODE3 = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode3"); - private static final NodeRef PCKG_NODE = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakePackage"); private static final NodeRef USER_NODE = new NodeRef(NamespaceService.CONTENT_MODEL_1_0_URI + "/admin"); private static final String NO_MESSAGE = "(No Message)"; - private WorkflowService workflowService; - private NodeService nodeService; - private TaskFormProcessor processor; private WorkflowTask task; - private NamespaceService namespaceService; private AuthenticationService authenticationService; private PersonService personService; private WorkflowTask newTask; @@ -129,22 +106,19 @@ public class TaskFormProcessorTest extends TestCase // Do nothing! } - Item item = new Item("task", TASK_ID); - WorkflowTask result = processor.getTypedItem(item); + WorkflowTask result = ((TaskFormProcessor) processor).getTypedItem(item); assertNotNull(result); assertEquals(TASK_ID, result.getId()); // Check URI-encoded id. - item = new Item("task", TASK_ID); - result = processor.getTypedItem(item); + result = ((TaskFormProcessor) processor).getTypedItem(item); assertNotNull(result); assertEquals(TASK_ID, result.getId()); } public void testGenerateSetsItemAndUrl() throws Exception { - Item item = new Item("task", TASK_ID); - Form form = processor.generate(item, null, null, null); + Form form = ((TaskFormProcessor) processor).generate(item, null, null, null); Item formItem = form.getItem(); assertEquals(item.getId(), formItem.getId()); assertEquals(item.getKind(), formItem.getKind()); @@ -412,7 +386,6 @@ public class TaskFormProcessorTest extends TestCase data.addFieldData("prop_bpm_foo", "bar"); String dataKey = makeDataKeyName(TransitionFieldProcessor.KEY); data.addFieldData(dataKey, "foo"); - Item item = new Item("task", TASK_ID); WorkflowTask persistedItem = (WorkflowTask) processor.persist(item, data); // make sure task is correct and update and endTask were called @@ -421,6 +394,11 @@ public class TaskFormProcessorTest extends TestCase verify(workflowService, times(1)).endTask(TASK_ID, "foo"); } + public void testPersistPropertyComment() throws Exception + { + super.testPersistPropertyComment(TASK_ID); + } + public void testPersistPackageItemsAdded() throws Exception { mockPackageItems(FAKE_NODE3); @@ -476,41 +454,10 @@ public class TaskFormProcessorTest extends TestCase } } - private void mockPackageItems(NodeRef... children) - { - ArrayList results = new ArrayList(children.length); - for (NodeRef nodeRef : children) - { - ChildAssociationRef child = new ChildAssociationRef(ASSOC_PACKAGE_CONTAINS, PCKG_NODE, null, nodeRef); - results.add(child); - } - when(nodeService.getChildAssocs(eq(PCKG_NODE), (QNamePattern)any(), (QNamePattern)any())) - .thenReturn(results); - - } - - private void checkRemovedPackageItem(NodeRef child, boolean wasCalled) - { - int times = wasCalled ? 1 : 0; - verify(nodeService, times(times)) - .removeChild(PCKG_NODE, child); - } - - private void checkAddPackageItem(NodeRef child, boolean wasCalled) - { - int times = wasCalled ? 1 : 0; - verify(nodeService, times(times)) - .addChild(eq(PCKG_NODE), - eq(child), - eq(ASSOC_PACKAGE_CONTAINS), - (QName)any()); - } - private void processPersist(String dataKey, String value) { FormData data = new FormData(); data.addFieldData(dataKey, value); - Item item = new Item("task", TASK_ID); WorkflowTask persistedItem = (WorkflowTask) processor.persist(item, data); assertEquals(newTask, persistedItem); } @@ -522,8 +469,7 @@ public class TaskFormProcessorTest extends TestCase private Form processForm(List fields) { - Item item = new Item("task", TASK_ID); - Form form = processor.generate(item, fields, null, null); + Form form = ((TaskFormProcessor) processor).generate(item, fields, null, null); return form; } @@ -537,54 +483,6 @@ public class TaskFormProcessorTest extends TestCase assertEquals("read_package_item_actions", pckgItemActionData.getValue()); } - private void checkSingleProperty(Form form, String fieldName, Serializable fieldData) - { - String expDataKey = makeDataKeyName(fieldName); - checkSingleField(form, fieldName, fieldData, expDataKey); - } - - private void checkSingleAssociation(Form form, String fieldName, Serializable fieldData) - { - String expDataKey = makeAssociationDataKey(fieldName); - checkSingleField(form, fieldName, fieldData, expDataKey); - } - - private void checkSingleField(Form form, String fieldName, Serializable fieldData, String expDataKey) - { - List fieldDefs = form.getFieldDefinitions(); - assertEquals(1, fieldDefs.size()); - FieldDefinition fieldDef = fieldDefs.get(0); - assertEquals(fieldName, fieldDef.getName()); - String dataKey = fieldDef.getDataKeyName(); - assertEquals(expDataKey, dataKey); - FieldData data = form.getFormData().getFieldData(dataKey); - if (fieldData != null && data != null) - { - assertEquals(fieldData, data.getValue()); - } - else - { - assertNull(data); - } - } - - private String makeDataKeyName(String fieldName) - { - return PROP_DATA_PREFIX + fieldName.replace(":", "_"); - } - - private String makeDataKeyName(String fieldName, boolean added) - { - String assocDataKey = makeAssociationDataKey(fieldName); - String suffix = added ? ASSOC_DATA_ADDED_SUFFIX : ASSOC_DATA_REMOVED_SUFFIX; - return assocDataKey + suffix; - } - - private String makeAssociationDataKey(String fieldName) - { - return ASSOC_DATA_PREFIX + fieldName.replace(":", "_"); - } - /* * @see junit.framework.TestCase#setUp() */ @@ -592,43 +490,33 @@ public class TaskFormProcessorTest extends TestCase protected void setUp() throws Exception { super.setUp(); + super.item = new Item("task", TASK_ID); task = makeTask(); - workflowService = makeWorkflowService(); - nodeService = makeNodeService(); + super.workflowService = makeWorkflowService(); + super.nodeService = makeNodeService(); DictionaryService dictionaryService = makeDictionaryService(); - namespaceService = makeNamespaceService(); + super.namespaceService = makeNamespaceService(); authenticationService = makeAuthenticationService(); personService = makePersonService(); MockFieldProcessorRegistry fieldProcessorRegistry = new MockFieldProcessorRegistry(namespaceService, dictionaryService); - DefaultFieldProcessor defaultProcessor = makeDefaultFieldProcessor(dictionaryService); - processor = makeTaskFormProcessor(dictionaryService, fieldProcessorRegistry, defaultProcessor); + DefaultFieldProcessor defaultProcessor = super.makeDefaultFieldProcessor(dictionaryService); + super.processor = makeTaskFormProcessor(dictionaryService, fieldProcessorRegistry, defaultProcessor); } private TaskFormProcessor makeTaskFormProcessor(DictionaryService dictionaryService, MockFieldProcessorRegistry fieldProcessorRegistry, DefaultFieldProcessor defaultProcessor) { TaskFormProcessor processor1 = new TaskFormProcessor(); - processor1.setWorkflowService(workflowService); - processor1.setNodeService(nodeService); - processor1.setNamespaceService(namespaceService); - processor1.setDictionaryService(dictionaryService); + processor1 =(TaskFormProcessor) super.makeTaskFormProcessor(processor1, dictionaryService, + fieldProcessorRegistry, defaultProcessor); + processor1.setAuthenticationService(authenticationService); processor1.setPersonService(personService); - processor1.setFieldProcessorRegistry(fieldProcessorRegistry); - processor1.setBehaviourFilter(mock(BehaviourFilter.class)); + return processor1; } - private DefaultFieldProcessor makeDefaultFieldProcessor(DictionaryService dictionaryService) throws Exception - { - DefaultFieldProcessor defaultProcessor = new DefaultFieldProcessor(); - defaultProcessor.setDictionaryService(dictionaryService); - defaultProcessor.setNamespaceService(namespaceService); - defaultProcessor.afterPropertiesSet(); - return defaultProcessor; - } - private WorkflowTask makeTask(WorkflowTransition... transitions) { String id = TASK_ID; @@ -721,29 +609,6 @@ public class TaskFormProcessorTest extends TestCase return properties; } - private Map makeTaskAssociationDefs() - { - Map associations = new HashMap(); - QName actorName = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "Actor"); - - // Add Assigneee association - MockClassAttributeDefinition assigneeDef = MockClassAttributeDefinition.mockAssociationDefinition( - ASSIGNEE_NAME, actorName); - associations.put(ASSIGNEE_NAME, assigneeDef); - - // Add Assigneee association - MockClassAttributeDefinition actorsDef = MockClassAttributeDefinition.mockAssociationDefinition(ACTORS_NAME, - actorName); - associations.put(ACTORS_NAME, actorsDef); - - // Add association with _ - MockClassAttributeDefinition with_ = MockClassAttributeDefinition.mockAssociationDefinition(ASSOC_WITH_, - actorName); - associations.put(ASSOC_WITH_, with_); - - return associations; - } - private NamespaceService makeNamespaceService() { NamespaceServiceMemoryImpl nsService = new NamespaceServiceMemoryImpl(); diff --git a/source/test-java/org/alfresco/repo/forms/processor/workflow/WorkflowFormProcessorTest.java b/source/test-java/org/alfresco/repo/forms/processor/workflow/WorkflowFormProcessorTest.java index 0b590a28d9..0005fd1c62 100644 --- a/source/test-java/org/alfresco/repo/forms/processor/workflow/WorkflowFormProcessorTest.java +++ b/source/test-java/org/alfresco/repo/forms/processor/workflow/WorkflowFormProcessorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2014 Alfresco Software Limited. * * This file is part of Alfresco * @@ -19,30 +19,18 @@ package org.alfresco.repo.forms.processor.workflow; -import static org.alfresco.repo.forms.processor.node.FormFieldConstants.ASSOC_DATA_ADDED_SUFFIX; -import static org.alfresco.repo.forms.processor.node.FormFieldConstants.ASSOC_DATA_PREFIX; -import static org.alfresco.repo.forms.processor.node.FormFieldConstants.ASSOC_DATA_REMOVED_SUFFIX; -import static org.alfresco.repo.forms.processor.node.FormFieldConstants.PROP_DATA_PREFIX; import static org.alfresco.repo.workflow.WorkflowModel.ASPECT_WORKFLOW_PACKAGE; -import static org.alfresco.repo.workflow.WorkflowModel.ASSOC_ASSIGNEE; import static org.alfresco.repo.workflow.WorkflowModel.ASSOC_PACKAGE; -import static org.alfresco.repo.workflow.WorkflowModel.ASSOC_PACKAGE_CONTAINS; -import static org.alfresco.repo.workflow.WorkflowModel.ASSOC_POOLED_ACTORS; -import static org.alfresco.repo.workflow.WorkflowModel.PROP_DESCRIPTION; import static org.alfresco.repo.workflow.WorkflowModel.PROP_PACKAGE_ACTION_GROUP; import static org.alfresco.repo.workflow.WorkflowModel.PROP_PACKAGE_ITEM_ACTION_GROUP; import static org.alfresco.repo.workflow.WorkflowModel.PROP_WORKFLOW_PRIORITY; -import static org.alfresco.repo.workflow.WorkflowModel.PROP_STATUS; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyMap; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.Serializable; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -50,9 +38,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import junit.framework.TestCase; - -import org.alfresco.repo.forms.FieldDefinition; import org.alfresco.repo.forms.Form; import org.alfresco.repo.forms.FormData; import org.alfresco.repo.forms.FormNotFoundException; @@ -61,15 +46,12 @@ import org.alfresco.repo.forms.FormData.FieldData; import org.alfresco.repo.forms.processor.node.DefaultFieldProcessor; import org.alfresco.repo.forms.processor.node.MockClassAttributeDefinition; import org.alfresco.repo.forms.processor.node.MockFieldProcessorRegistry; -import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; import org.alfresco.service.cmr.workflow.WorkflowInstance; @@ -81,7 +63,6 @@ import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceServiceMemoryImpl; import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.QNamePattern; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -91,27 +72,11 @@ import org.mockito.stubbing.Answer; * @author Nick Smith * */ -public class WorkflowFormProcessorTest extends TestCase +public class WorkflowFormProcessorTest extends FormProcessorTest { - private static final String TASK_DEF_NAME = "TaskDef"; private static final String WF_DEF_NAME = "foo$wf:bar"; private static final QName PRIORITY_NAME = PROP_WORKFLOW_PRIORITY; - private static final QName DESC_NAME = PROP_DESCRIPTION; - private static final QName STATUS_NAME = PROP_STATUS; - private static final QName PROP_WITH_ = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "some_prop"); - private static final QName ACTORS_NAME = ASSOC_POOLED_ACTORS; - private static final QName ASSIGNEE_NAME = ASSOC_ASSIGNEE; - private static final QName ASSOC_WITH_ = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "some_assoc"); - private static final NodeRef FAKE_NODE = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode"); - private static final NodeRef FAKE_NODE2 = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode2"); - private static final NodeRef FAKE_NODE3 = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode3"); - private static final NodeRef PCKG_NODE = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakePackage"); - private static final Item item = new Item("workflow", WF_DEF_NAME); - private NamespaceService namespaceService; - private NodeService nodeService; - private WorkflowService workflowService; - private WorkflowFormProcessor processor; private WorkflowInstance newInstance; private WorkflowDefinition definition; private Map actualProperties = null; @@ -138,14 +103,19 @@ public class WorkflowFormProcessorTest extends TestCase // Do nothing! } - WorkflowDefinition result = processor.getTypedItem(item); + WorkflowDefinition result = ((WorkflowFormProcessor) processor).getTypedItem(item); assertNotNull(result); assertEquals(WF_DEF_NAME, result.getName()); } + public void testPersistPropertyComment() throws Exception + { + super.testPersistPropertyComment(item.getId()); + } + public void testGenerateSetsItemAndUrl() throws Exception { - Form form = processor.generate(item, null, null, null); + Form form = ((WorkflowFormProcessor) processor).generate(item, null, null, null); Item formItem = form.getItem(); assertEquals(item.getId(), formItem.getId()); assertEquals(item.getKind(), formItem.getKind()); @@ -324,36 +294,6 @@ public class WorkflowFormProcessorTest extends TestCase checkRemovedPackageItem(FAKE_NODE3, false); } - private void mockPackageItems(NodeRef... children) - { - ArrayList results = new ArrayList(children.length); - for (NodeRef nodeRef : children) - { - ChildAssociationRef child = new ChildAssociationRef(ASSOC_PACKAGE_CONTAINS, PCKG_NODE, null, nodeRef); - results.add(child); - } - when(nodeService.getChildAssocs(eq(PCKG_NODE), (QNamePattern)any(), (QNamePattern)any())) - .thenReturn(results); - - } - - private void checkRemovedPackageItem(NodeRef child, boolean wasCalled) - { - int times = wasCalled ? 1 : 0; - verify(nodeService, times(times)) - .removeChild(PCKG_NODE, child); - } - - private void checkAddPackageItem(NodeRef child, boolean wasCalled) - { - int times = wasCalled ? 1 : 0; - verify(nodeService, times(times)) - .addChild(eq(PCKG_NODE), - eq(child), - eq(ASSOC_PACKAGE_CONTAINS), - (QName)any()); - } - private void processPersist(String dataKey, String value) { FormData data = new FormData(); @@ -369,7 +309,7 @@ public class WorkflowFormProcessorTest extends TestCase private Form processForm(List fields) { - return processor.generate(item, fields, null, null); + return ((WorkflowFormProcessor) processor).generate(item, fields, null, null); } private void checkPackageActionGroups(FormData formData) @@ -381,50 +321,7 @@ public class WorkflowFormProcessorTest extends TestCase assertNotNull(pckgItemActionData); assertEquals("start_package_item_actions", pckgItemActionData.getValue()); } - - private void checkSingleProperty(Form form, String fieldName, Serializable fieldData) - { - String expDataKey = makeDataKeyName(fieldName); - checkSingleField(form, fieldName, fieldData, expDataKey); - - } - - private void checkSingleAssociation(Form form, String fieldName, Serializable fieldData) - { - String expDataKey = makeAssociationDataKey(fieldName); - checkSingleField(form, fieldName, fieldData, expDataKey); - } - - private void checkSingleField(Form form, String fieldName, Serializable fieldData, String expDataKey) - { - List fieldDefs = form.getFieldDefinitions(); - assertEquals(1, fieldDefs.size()); - FieldDefinition fieldDef = fieldDefs.get(0); - assertEquals(fieldName, fieldDef.getName()); - String dataKey = fieldDef.getDataKeyName(); - assertEquals(expDataKey, dataKey); - FieldData data = form.getFormData().getFieldData(dataKey); - assertEquals(fieldData, data.getValue()); - } - - - private String makeDataKeyName(String fieldName) - { - return PROP_DATA_PREFIX + fieldName.replace(":", "_"); - } - - private String makeDataKeyName(String fieldName, boolean added) - { - String assocDataKey = makeAssociationDataKey(fieldName); - String suffix = added ? ASSOC_DATA_ADDED_SUFFIX : ASSOC_DATA_REMOVED_SUFFIX; - return assocDataKey + suffix; - } - - private String makeAssociationDataKey(String fieldName) - { - return ASSOC_DATA_PREFIX + fieldName.replace(":", "_"); - } - + /* * @see junit.framework.TestCase#setUp() */ @@ -432,39 +329,27 @@ public class WorkflowFormProcessorTest extends TestCase protected void setUp() throws Exception { super.setUp(); + super.item = new Item("workflow", WF_DEF_NAME); definition = makeWorkflowDefinition(); - workflowService = makeWorkflowService(); - nodeService = makeNodeService(); + super.workflowService = makeWorkflowService(); + super.nodeService = makeNodeService(); DictionaryService dictionaryService = makeDictionaryService(); - namespaceService = makeNamespaceService(); + super.namespaceService = makeNamespaceService(); MockFieldProcessorRegistry fieldProcessorRegistry = new MockFieldProcessorRegistry(namespaceService, dictionaryService); - DefaultFieldProcessor defaultProcessor = makeDefaultFieldProcessor(dictionaryService); - processor = makeWorkflowFormProcessor(dictionaryService, fieldProcessorRegistry, defaultProcessor); + DefaultFieldProcessor defaultProcessor = super.makeDefaultFieldProcessor(dictionaryService); + super.processor = makeWorkflowFormProcessor(dictionaryService, fieldProcessorRegistry, defaultProcessor); } private WorkflowFormProcessor makeWorkflowFormProcessor(DictionaryService dictionaryService, MockFieldProcessorRegistry fieldProcessorRegistry, DefaultFieldProcessor defaultProcessor) { WorkflowFormProcessor processor1 = new WorkflowFormProcessor(); - processor1.setWorkflowService(workflowService); - processor1.setNodeService(nodeService); - processor1.setNamespaceService(namespaceService); - processor1.setDictionaryService(dictionaryService); - processor1.setFieldProcessorRegistry(fieldProcessorRegistry); - processor1.setBehaviourFilter(mock(BehaviourFilter.class)); + processor1 =(WorkflowFormProcessor) super.makeTaskFormProcessor(processor1, dictionaryService, + fieldProcessorRegistry, defaultProcessor); return processor1; } - private DefaultFieldProcessor makeDefaultFieldProcessor(DictionaryService dictionaryService) throws Exception - { - DefaultFieldProcessor defaultProcessor = new DefaultFieldProcessor(); - defaultProcessor.setDictionaryService(dictionaryService); - defaultProcessor.setNamespaceService(namespaceService); - defaultProcessor.afterPropertiesSet(); - return defaultProcessor; - } - private WorkflowDefinition makeWorkflowDefinition() { String id = "foo$workflowDefId"; @@ -537,29 +422,6 @@ public class WorkflowFormProcessorTest extends TestCase return properties; } - private Map makeTaskAssociationDefs() - { - Map associations = new HashMap(); - QName actorName = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "Actor"); - - // Add Assigneee association - MockClassAttributeDefinition assigneeDef = MockClassAttributeDefinition.mockAssociationDefinition( - ASSIGNEE_NAME, actorName); - associations.put(ASSIGNEE_NAME, assigneeDef); - - // Add Assigneee association - MockClassAttributeDefinition actorsDef = MockClassAttributeDefinition.mockAssociationDefinition(ACTORS_NAME, - actorName); - associations.put(ACTORS_NAME, actorsDef); - - // Add association with _ - MockClassAttributeDefinition with_ = MockClassAttributeDefinition.mockAssociationDefinition(ASSOC_WITH_, - actorName); - associations.put(ASSOC_WITH_, with_); - - return associations; - } - private NamespaceService makeNamespaceService() { NamespaceServiceMemoryImpl nsService = new NamespaceServiceMemoryImpl();