mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-QA to HEAD (4.2) (including moving test classes into separate folders)
51903 to 54309 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@54310 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,332 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.forms.processor.action;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.executer.MoveActionExecuter;
|
||||
import org.alfresco.repo.action.executer.TransformActionExecuter;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.forms.AssociationFieldDefinition;
|
||||
import org.alfresco.repo.forms.FieldDefinition;
|
||||
import org.alfresco.repo.forms.Form;
|
||||
import org.alfresco.repo.forms.FormNotFoundException;
|
||||
import org.alfresco.repo.forms.FormService;
|
||||
import org.alfresco.repo.forms.Item;
|
||||
import org.alfresco.repo.forms.PropertyFieldDefinition;
|
||||
import org.alfresco.repo.forms.PropertyFieldDefinition.FieldConstraint;
|
||||
import org.alfresco.repo.forms.processor.AbstractFormProcessor;
|
||||
import org.alfresco.repo.forms.processor.node.FormFieldConstants;
|
||||
import org.alfresco.repo.model.Repository;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Test class for the {@link ActionFormProcessor}.
|
||||
*
|
||||
* @author Neil Mc Erlean
|
||||
* @since 4.0
|
||||
*/
|
||||
public class ActionFormProcessorTest
|
||||
{
|
||||
private static final ApplicationContext testContext = ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
// injected services
|
||||
private static ContentService CONTENT_SERVICE;
|
||||
private static FormService FORM_SERVICE;
|
||||
private static NamespaceService NAMESPACE_SERVICE;
|
||||
private static NodeService NODE_SERVICE;
|
||||
private static Repository REPOSITORY_HELPER;
|
||||
private static RetryingTransactionHelper TRANSACTION_HELPER;
|
||||
|
||||
private NodeRef testNode;
|
||||
private List<NodeRef> testNodesToBeTidiedUp;
|
||||
|
||||
@BeforeClass public static void initTestsContext() throws Exception
|
||||
{
|
||||
CONTENT_SERVICE = (ContentService)testContext.getBean("ContentService");
|
||||
FORM_SERVICE = (FormService)testContext.getBean("FormService");
|
||||
NAMESPACE_SERVICE = (NamespaceService)testContext.getBean("NamespaceService");
|
||||
NODE_SERVICE = (NodeService)testContext.getBean("NodeService");
|
||||
REPOSITORY_HELPER = (Repository)testContext.getBean("repositoryHelper");
|
||||
TRANSACTION_HELPER = (RetryingTransactionHelper)testContext.getBean("retryingTransactionHelper");
|
||||
|
||||
// Set the current security context as admin
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create some content that can have actions run on it.
|
||||
*/
|
||||
@Before public void createTestObjects() throws Exception
|
||||
{
|
||||
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
// Create some content which we will run actions on.
|
||||
NodeRef companyHome = REPOSITORY_HELPER.getCompanyHome();
|
||||
testNode = createNode(companyHome,
|
||||
"testDoc" + ActionFormProcessorTest.class.getSimpleName() + ".txt",
|
||||
ContentModel.TYPE_CONTENT);
|
||||
ContentWriter writer = CONTENT_SERVICE.getWriter(testNode, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.putContent("Irrelevant content");
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
testNodesToBeTidiedUp = new ArrayList<NodeRef>();
|
||||
testNodesToBeTidiedUp.add(testNode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a node of the specified content type, under the specified parent node with the specified cm:name.
|
||||
*/
|
||||
private NodeRef createNode(NodeRef parentNode, String name, QName type)
|
||||
{
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(ContentModel.PROP_NAME, name);
|
||||
QName docContentQName = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, name);
|
||||
NodeRef node = NODE_SERVICE.createNode(parentNode,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
docContentQName,
|
||||
type,
|
||||
props).getChildRef();
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deletes any nodes which were created during test execution.
|
||||
*/
|
||||
@After public void tidyUpTestNodes() throws Exception
|
||||
{
|
||||
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||||
|
||||
for (NodeRef node : testNodesToBeTidiedUp)
|
||||
{
|
||||
if (NODE_SERVICE.exists(node)) NODE_SERVICE.deleteNode(node);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test(expected=FormNotFoundException.class) public void requestFormForNonExistentAction() throws Exception
|
||||
{
|
||||
FORM_SERVICE.getForm(new Item(ActionFormProcessor.ITEM_KIND, "noSuchActionBean"));
|
||||
}
|
||||
|
||||
|
||||
@Test public void generateDefaultFormForParameterlessAction() throws Exception
|
||||
{
|
||||
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
Form form = FORM_SERVICE.getForm(new Item(ActionFormProcessor.ITEM_KIND, "extract-metadata"));
|
||||
|
||||
// check a form got returned
|
||||
assertNotNull("Expecting form to be present", form);
|
||||
|
||||
// get the fields into a Map
|
||||
Collection<FieldDefinition> fieldDefs = form.getFieldDefinitions();
|
||||
|
||||
assertEquals("Wrong number of fieldDefs", 1, fieldDefs.size());
|
||||
|
||||
Map<String, FieldDefinition> fieldDefMap = new HashMap<String, FieldDefinition>(fieldDefs.size());
|
||||
for (FieldDefinition fieldDef : fieldDefs)
|
||||
{
|
||||
fieldDefMap.put(fieldDef.getName(), fieldDef);
|
||||
}
|
||||
|
||||
validateExecuteAsynchronouslyField(fieldDefMap);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test public void generateDefaultFormForActionWithNodeRefParam() throws Exception
|
||||
{
|
||||
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
Form form = FORM_SERVICE.getForm(new Item(ActionFormProcessor.ITEM_KIND, "script"));
|
||||
|
||||
// check a form got returned
|
||||
assertNotNull("Expecting form to be present", form);
|
||||
|
||||
// get the fields into a Map
|
||||
Collection<FieldDefinition> fieldDefs = form.getFieldDefinitions();
|
||||
|
||||
assertEquals("Wrong number of fieldDefs", 2, fieldDefs.size());
|
||||
Map<String, FieldDefinition> fieldDefMap = new HashMap<String, FieldDefinition>(fieldDefs.size());
|
||||
for (FieldDefinition fieldDef : fieldDefs)
|
||||
{
|
||||
fieldDefMap.put(fieldDef.getName(), fieldDef);
|
||||
}
|
||||
|
||||
// First of all, we'll check the fields that come from the Action class.
|
||||
validateExecuteAsynchronouslyField(fieldDefMap);
|
||||
|
||||
// One defined parameter for this action.
|
||||
PropertyFieldDefinition scriptRef = (PropertyFieldDefinition)fieldDefMap.get("script-ref");
|
||||
assertNotNull("'script-ref' field defn was missing.", scriptRef);
|
||||
assertEquals("script-ref", scriptRef.getName());
|
||||
assertEquals("Script", scriptRef.getLabel());
|
||||
assertEquals("script-ref", scriptRef.getDescription());
|
||||
assertEquals("text", scriptRef.getDataType());
|
||||
assertTrue(scriptRef.isMandatory());
|
||||
List<FieldConstraint> constraints = scriptRef.getConstraints();
|
||||
assertEquals(1, constraints.size());
|
||||
assertEquals("LIST", constraints.get(0).getType());
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void validateExecuteAsynchronouslyField(Map<String, FieldDefinition> fieldDefMap)
|
||||
{
|
||||
// executeAsynchronously
|
||||
PropertyFieldDefinition execAsync = (PropertyFieldDefinition)fieldDefMap.get("executeAsynchronously");
|
||||
assertNotNull("'executeAsynchronously' field defn was missing.", execAsync);
|
||||
assertEquals("'executeAsynchronously' name was wrong", "executeAsynchronously", execAsync.getName());
|
||||
assertEquals("'executeAsynchronously' label was wrong", "executeAsynchronously", execAsync.getLabel());
|
||||
assertNull("'executeAsynchronously' description was wrong", execAsync.getDescription());
|
||||
assertEquals("'executeAsynchronously' datatype was wrong", "boolean", execAsync.getDataType());
|
||||
}
|
||||
|
||||
|
||||
@Test public void generateFormWithSelectedFields() throws Exception
|
||||
{
|
||||
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
// request a certain set of fields
|
||||
List<String> fields = new ArrayList<String>();
|
||||
fields.add(MoveActionExecuter.PARAM_DESTINATION_FOLDER);
|
||||
fields.add(ActionFormProcessor.EXECUTE_ASYNCHRONOUSLY);
|
||||
|
||||
Form form = FORM_SERVICE.getForm(new Item(ActionFormProcessor.ITEM_KIND, "move"), fields);
|
||||
|
||||
// check a form got returned
|
||||
assertNotNull("Expecting form to be present", form);
|
||||
|
||||
// get the fields into a Map
|
||||
Collection<FieldDefinition> fieldDefs = form.getFieldDefinitions();
|
||||
Map<String, FieldDefinition> fieldDefMap = new HashMap<String, FieldDefinition>(fieldDefs.size());
|
||||
for (FieldDefinition fieldDef : fieldDefs)
|
||||
{
|
||||
fieldDefMap.put(fieldDef.getName(), fieldDef);
|
||||
}
|
||||
|
||||
// check there are 2 field
|
||||
assertEquals(2, fieldDefMap.size());
|
||||
|
||||
// check the 2 fields are the correct ones!
|
||||
AssociationFieldDefinition destFolderField = (AssociationFieldDefinition)fieldDefMap.get(MoveActionExecuter.PARAM_DESTINATION_FOLDER);
|
||||
assertNotNull(destFolderField);
|
||||
PropertyFieldDefinition execAsyncField = (PropertyFieldDefinition)fieldDefMap.get(ActionFormProcessor.EXECUTE_ASYNCHRONOUSLY);
|
||||
assertNotNull(execAsyncField);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test public void persistForm_executeTransformAction() throws Exception
|
||||
{
|
||||
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
Form form = FORM_SERVICE.getForm(new Item(ActionFormProcessor.ITEM_KIND, "transform"));
|
||||
|
||||
// This is the actionedUponNodeRef. A special parameter with no prop_ prefix
|
||||
form.addData(AbstractFormProcessor.DESTINATION, testNode.toString());
|
||||
|
||||
// transform the node (which is text/plain to xml in the same folder)
|
||||
form.addData(FormFieldConstants.PROP_DATA_PREFIX + TransformActionExecuter.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_XML);
|
||||
form.addData(FormFieldConstants.PROP_DATA_PREFIX + TransformActionExecuter.PARAM_DESTINATION_FOLDER, REPOSITORY_HELPER.getCompanyHome().toString());
|
||||
form.addData(FormFieldConstants.PROP_DATA_PREFIX + TransformActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS.toPrefixString(NAMESPACE_SERVICE));
|
||||
form.addData(FormFieldConstants.PROP_DATA_PREFIX + TransformActionExecuter.PARAM_ASSOC_QNAME, ContentModel.ASSOC_CONTAINS.toPrefixString(NAMESPACE_SERVICE));
|
||||
|
||||
FORM_SERVICE.saveForm(form.getItem(), form.getFormData());
|
||||
|
||||
for (ChildAssociationRef chAssRef : NODE_SERVICE.getChildAssocs(REPOSITORY_HELPER.getCompanyHome()))
|
||||
{
|
||||
System.err.println(NODE_SERVICE.getProperty(chAssRef.getChildRef(), ContentModel.PROP_NAME));
|
||||
}
|
||||
|
||||
Serializable cmName = NODE_SERVICE.getProperty(testNode, ContentModel.PROP_NAME);
|
||||
String transformedNodeName = ((String)cmName).replace(".txt", ".xml");
|
||||
|
||||
NodeRef expectedTransformedNode = NODE_SERVICE.getChildByName(REPOSITORY_HELPER.getCompanyHome(), ContentModel.ASSOC_CONTAINS, transformedNodeName);
|
||||
assertNotNull("transformed node was missing", expectedTransformedNode);
|
||||
|
||||
testNodesToBeTidiedUp.add(expectedTransformedNode);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.forms.processor.node;
|
||||
|
||||
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.ASSOC;
|
||||
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.PROP;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.repo.forms.AssociationFieldDefinition;
|
||||
import org.alfresco.repo.forms.Field;
|
||||
import org.alfresco.repo.forms.PropertyFieldDefinition;
|
||||
import org.alfresco.repo.forms.AssociationFieldDefinition.Direction;
|
||||
import org.alfresco.repo.forms.processor.FormCreationData;
|
||||
import org.alfresco.repo.forms.processor.FormCreationDataImpl;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.NamespaceServiceMemoryImpl;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 3.4
|
||||
* @author Nick Smith
|
||||
*
|
||||
*/
|
||||
public class FieldProcessorTest extends TestCase
|
||||
{
|
||||
private static final String PREFIX = "test";
|
||||
private static final String URI = "http://test/";
|
||||
private static final String NAME1 = "Name1";
|
||||
private static final String NAME2 = "Name2";
|
||||
private static final String DESCRIPTION1 = "Description";
|
||||
private static final String DESCRIPTION2 = "Another Description";
|
||||
private static final String TITLE = "Title";
|
||||
private static final QName qName1 = QName.createQName(URI, NAME1);
|
||||
private static final QName qName2 = QName.createQName(URI, NAME2);
|
||||
|
||||
private NamespaceService namespaceService;
|
||||
private FormCreationData data;
|
||||
|
||||
public void testMakeAssociationFieldDefinition() throws Exception
|
||||
{
|
||||
AssociationFieldProcessor processor = new AssociationFieldProcessor();
|
||||
processor.setNamespaceService(namespaceService);
|
||||
|
||||
String name1 = ASSOC + ":"+ PREFIX +":"+ NAME1;
|
||||
Field field = processor.generateField(name1, data);
|
||||
AssociationFieldDefinition assocFieldDef = (AssociationFieldDefinition) field.getFieldDefinition();
|
||||
|
||||
assertNotNull(assocFieldDef);
|
||||
assertEquals("assoc_" + PREFIX + "_" + NAME1, assocFieldDef.getDataKeyName());
|
||||
assertEquals(PREFIX + ":" + NAME1, assocFieldDef.getName());
|
||||
assertEquals(PREFIX + ":" + NAME1, assocFieldDef.getLabel());
|
||||
assertEquals(Direction.TARGET, assocFieldDef.getEndpointDirection());
|
||||
assertEquals(PREFIX + ":Target", assocFieldDef.getEndpointType());
|
||||
assertEquals(DESCRIPTION1, assocFieldDef.getDescription());
|
||||
assertFalse(assocFieldDef.isProtectedField());
|
||||
assertFalse(assocFieldDef.isEndpointMandatory());
|
||||
assertFalse(assocFieldDef.isEndpointMany());
|
||||
|
||||
// Repeat using different params to ensuere the fieldDefinition values
|
||||
// are dependant on the AssociationDefinition values.
|
||||
String name2 = ASSOC + ":" + PREFIX +":"+ NAME2;
|
||||
field = processor.generateField(name2, data);
|
||||
assocFieldDef = (AssociationFieldDefinition) field.getFieldDefinition();
|
||||
|
||||
assertEquals(TITLE, assocFieldDef.getLabel());
|
||||
assertEquals(DESCRIPTION2, assocFieldDef.getDescription());
|
||||
assertTrue(assocFieldDef.isProtectedField());
|
||||
assertTrue(assocFieldDef.isEndpointMandatory());
|
||||
assertTrue(assocFieldDef.isEndpointMany());
|
||||
}
|
||||
|
||||
public void testMakePropertyFieldDefinition() throws Exception
|
||||
{
|
||||
PropertyFieldProcessor processor = new PropertyFieldProcessor();
|
||||
processor.setNamespaceService(namespaceService);
|
||||
|
||||
String name1 = PROP+ ":" + PREFIX + ":" + NAME1;
|
||||
Field field = processor.generateField(name1, data);
|
||||
PropertyFieldDefinition propFieldDef = (PropertyFieldDefinition) field.getFieldDefinition();
|
||||
assertNotNull(propFieldDef);
|
||||
assertEquals("prop_" + PREFIX + "_" + NAME1, propFieldDef.getDataKeyName());
|
||||
assertEquals(PREFIX + ":" + NAME1, propFieldDef.getName());
|
||||
assertEquals(PREFIX + ":" + NAME1, propFieldDef.getLabel());
|
||||
assertEquals("Default1", propFieldDef.getDefaultValue());
|
||||
assertEquals(DESCRIPTION1, propFieldDef.getDescription());
|
||||
assertFalse(propFieldDef.isProtectedField());
|
||||
assertFalse(propFieldDef.isMandatory());
|
||||
assertFalse(propFieldDef.isRepeating());// Maps to isMultiValued() on
|
||||
|
||||
// Repeat using different params to ensuere the fieldDefinition values
|
||||
// are dependant on the PropertyDefinition values.
|
||||
String name2 = PROP + ":" + PREFIX + ":" + NAME2;
|
||||
field = processor.generateField(name2, data);
|
||||
propFieldDef = (PropertyFieldDefinition) field.getFieldDefinition();
|
||||
assertEquals(TITLE, propFieldDef.getLabel());
|
||||
assertEquals(DESCRIPTION2, propFieldDef.getDescription());
|
||||
assertEquals("Default2", propFieldDef.getDefaultValue());
|
||||
assertTrue(propFieldDef.isProtectedField());
|
||||
assertTrue(propFieldDef.isMandatory());
|
||||
assertTrue(propFieldDef.isRepeating());
|
||||
}
|
||||
|
||||
/*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
namespaceService = makeNamespaceService();
|
||||
data = new FormCreationDataImpl(makeItemData(), null, null);
|
||||
}
|
||||
|
||||
private ContentModelItemData<Void> makeItemData()
|
||||
{
|
||||
Map<QName, PropertyDefinition> propDefs = makePropertyDefs();
|
||||
Map<QName, AssociationDefinition> assocDefs = makeAssociationDefs();
|
||||
|
||||
Map<QName, Serializable> propValues = new HashMap<QName, Serializable>();
|
||||
Map<QName, Serializable> assocValues = new HashMap<QName, Serializable>();
|
||||
Map<String, Object> transientValues = new HashMap<String, Object>();
|
||||
return new ContentModelItemData<Void>(null, propDefs, assocDefs, propValues, assocValues, transientValues);
|
||||
}
|
||||
|
||||
private Map<QName, AssociationDefinition> makeAssociationDefs()
|
||||
{
|
||||
QName targetClass = QName.createQName(URI, "Target");
|
||||
AssociationDefinition assocDef1 = MockClassAttributeDefinition.mockAssociationDefinition(
|
||||
qName1, targetClass,
|
||||
null,// Defalt title, so sets label to be same as name.
|
||||
DESCRIPTION1, false, false, false);
|
||||
MockClassAttributeDefinition assocDef2 = MockClassAttributeDefinition.mockAssociationDefinition(
|
||||
qName2, targetClass,
|
||||
TITLE, DESCRIPTION2,
|
||||
true, true, true);
|
||||
Map<QName, AssociationDefinition> assocDefs = new HashMap<QName, AssociationDefinition>();
|
||||
assocDefs.put(qName1, assocDef1);
|
||||
assocDefs.put(qName2, assocDef2);
|
||||
return assocDefs;
|
||||
}
|
||||
|
||||
private Map<QName, PropertyDefinition> makePropertyDefs()
|
||||
{
|
||||
QName dataTypeName = QName.createQName(URI, "Type");
|
||||
PropertyDefinition propDef1 = MockClassAttributeDefinition.mockPropertyDefinition(
|
||||
qName1, dataTypeName,
|
||||
null,// Defalt title, so sets label to be same as name.
|
||||
DESCRIPTION1, false,
|
||||
"Default1", false, false);
|
||||
PropertyDefinition propDef2 = MockClassAttributeDefinition.mockPropertyDefinition(
|
||||
qName2, dataTypeName,
|
||||
TITLE,
|
||||
DESCRIPTION2, true,
|
||||
"Default2", true, true);
|
||||
Map<QName, PropertyDefinition> propDefs = new HashMap<QName, PropertyDefinition>();
|
||||
propDefs.put(qName1, propDef1);
|
||||
propDefs.put(qName2, propDef2);
|
||||
return propDefs;
|
||||
}
|
||||
|
||||
private NamespaceService makeNamespaceService()
|
||||
{
|
||||
NamespaceServiceMemoryImpl nsService = new NamespaceServiceMemoryImpl();
|
||||
nsService.registerNamespace(PREFIX, URI);
|
||||
return nsService;
|
||||
}
|
||||
|
||||
}
|
@@ -1,332 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.forms.processor.node;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.alfresco.repo.dictionary.IndexTokenisationMode;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ModelDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.i18n.MessageLookup;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Mock implementation of the repository ClassDefinition.
|
||||
*
|
||||
* @since 3.4
|
||||
* @author Nick Smith
|
||||
*/
|
||||
public class MockClassAttributeDefinition implements PropertyDefinition, AssociationDefinition
|
||||
{
|
||||
|
||||
private final QName name;
|
||||
private DataTypeDefinition dataType = mock(DataTypeDefinition.class);
|
||||
private ClassDefinition targetClass = mock(ClassDefinition.class);
|
||||
private String description = null;
|
||||
private String defaultValue = null;
|
||||
private String title = null;
|
||||
|
||||
private boolean targetMandatory = false;
|
||||
private boolean targetMany = false;
|
||||
private boolean isProtected = false;
|
||||
private boolean mandatory = false;
|
||||
private boolean multiValued = false;
|
||||
|
||||
private MockClassAttributeDefinition(QName name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private MockClassAttributeDefinition(QName name, String title, String description, boolean isProtected)
|
||||
{
|
||||
this(name);
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.isProtected = isProtected;
|
||||
}
|
||||
|
||||
public static MockClassAttributeDefinition mockPropertyDefinition(QName name, QName dataTypeName)
|
||||
{
|
||||
MockClassAttributeDefinition mock = new MockClassAttributeDefinition(name);
|
||||
mockDataTypeName(mock, dataTypeName, null);
|
||||
return mock;
|
||||
}
|
||||
|
||||
public static MockClassAttributeDefinition mockPropertyDefinition(QName name, QName dataTypeName, String defaultValue)
|
||||
{
|
||||
return mockPropertyDefinition(name, dataTypeName, null, defaultValue);
|
||||
}
|
||||
|
||||
public static MockClassAttributeDefinition mockPropertyDefinition(QName name, QName dataTypeName, Class<?> typeClass, String defaultValue)
|
||||
{
|
||||
MockClassAttributeDefinition mock = new MockClassAttributeDefinition(name);
|
||||
mockDataTypeName(mock, dataTypeName, typeClass);
|
||||
mock.defaultValue = defaultValue;
|
||||
return mock;
|
||||
}
|
||||
|
||||
public static MockClassAttributeDefinition mockPropertyDefinition(QName name,//
|
||||
QName dataTypeName,//
|
||||
String title,//
|
||||
String description,//
|
||||
boolean isProtected,//
|
||||
String defaultValue,//
|
||||
boolean Mandatory,//
|
||||
boolean multiValued)
|
||||
{
|
||||
MockClassAttributeDefinition mock = new MockClassAttributeDefinition(name, title, description, isProtected);
|
||||
mockDataTypeName(mock, dataTypeName, null);
|
||||
mock.defaultValue = defaultValue;
|
||||
mock.mandatory = Mandatory;
|
||||
mock.multiValued = multiValued;
|
||||
return mock;
|
||||
}
|
||||
|
||||
public static MockClassAttributeDefinition mockAssociationDefinition(QName name, QName targetClassName)
|
||||
{
|
||||
MockClassAttributeDefinition mock = new MockClassAttributeDefinition(name);
|
||||
mockTargetClassName(targetClassName, mock);
|
||||
return mock;
|
||||
}
|
||||
|
||||
public static MockClassAttributeDefinition mockAssociationDefinition(QName name,//
|
||||
QName targetClassName,//
|
||||
String title,//
|
||||
String description,//
|
||||
boolean isProtected,//
|
||||
boolean targetMandatory,//
|
||||
boolean targetMany)
|
||||
{
|
||||
MockClassAttributeDefinition mock = new MockClassAttributeDefinition(name, title, description, isProtected);
|
||||
mockTargetClassName(targetClassName, mock);
|
||||
mock.targetMandatory = targetMandatory;
|
||||
mock.targetMany = targetMany;
|
||||
return mock;
|
||||
}
|
||||
|
||||
private static void mockDataTypeName(MockClassAttributeDefinition mock, QName dataTypeName, Class<?> javaClass)
|
||||
{
|
||||
when(mock.dataType.getName()).thenReturn(dataTypeName);
|
||||
if (javaClass!=null)
|
||||
{
|
||||
when(mock.dataType.getJavaClassName()).thenReturn(javaClass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private static void mockTargetClassName(QName targetClassName, MockClassAttributeDefinition mock)
|
||||
{
|
||||
when(mock.targetClass.getName()).thenReturn(targetClassName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConstraintDefinition> getConstraints()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDefinition getContainerClass()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeDefinition getDataType()
|
||||
{
|
||||
return dataType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultValue()
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(MessageLookup messageLookup)
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexTokenisationMode getIndexTokenisationMode()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelDefinition getModel()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QName getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle(MessageLookup messageLookup)
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIndexed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIndexedAtomically()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMandatory()
|
||||
{
|
||||
return mandatory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMandatoryEnforced()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMultiValued()
|
||||
{
|
||||
return multiValued;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverride()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProtected()
|
||||
{
|
||||
return isProtected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStoredInIndex()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDefinition getSourceClass()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QName getSourceRoleName()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDefinition getTargetClass()
|
||||
{
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QName getTargetRoleName()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChild()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSourceMandatory()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSourceMany()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTargetMandatory()
|
||||
{
|
||||
return targetMandatory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTargetMandatoryEnforced()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTargetMany()
|
||||
{
|
||||
return targetMany;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.dictionary.PropertyDefinition#getAnalyserResourceBundleName()
|
||||
*/
|
||||
@Override
|
||||
public String getAnalyserResourceBundleName()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.dictionary.PropertyDefinition#resolveAnalyserClassName(java.lang.String, java.util.Locale, java.lang.ClassLoader)
|
||||
*/
|
||||
@Override
|
||||
public String resolveAnalyserClassName(Locale locale)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveAnalyserClassName()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -79,9 +79,18 @@ public abstract class QNameFieldProcessor<Type extends ClassAttributeDefinition>
|
||||
protected QName getFullName(String name)
|
||||
{
|
||||
String[] parts = name.split(FormFieldConstants.FIELD_NAME_SEPARATOR);
|
||||
String prefix = parts[1];
|
||||
String localName = parts[2];
|
||||
return QName.createQName(prefix, localName, namespaceService);
|
||||
if(parts.length == 2)
|
||||
{
|
||||
String prefix = parts[0];
|
||||
String localName = parts[1];
|
||||
return QName.createQName(prefix, localName, namespaceService);
|
||||
}
|
||||
else
|
||||
{
|
||||
String prefix = parts[1];
|
||||
String localName = parts[2];
|
||||
return QName.createQName(prefix, localName, namespaceService);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getPrefixedName(ClassAttributeDefinition attribDef)
|
||||
|
@@ -22,6 +22,7 @@ package org.alfresco.repo.forms.processor.workflow;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.forms.Field;
|
||||
import org.alfresco.repo.forms.Form;
|
||||
import org.alfresco.repo.forms.FormData;
|
||||
import org.alfresco.repo.forms.FormData.FieldData;
|
||||
@@ -51,6 +52,8 @@ public abstract class AbstractWorkflowFormProcessor<ItemType, PersistType> exten
|
||||
protected WorkflowService workflowService;
|
||||
|
||||
protected BehaviourFilter behaviourFilter;
|
||||
|
||||
private ExtendedPropertyFieldProcessor extendedPropertyFieldProcessor;
|
||||
|
||||
@Override
|
||||
protected void populateForm(Form form, List<String> fields, FormCreationData data)
|
||||
@@ -77,6 +80,55 @@ public abstract class AbstractWorkflowFormProcessor<ItemType, PersistType> exten
|
||||
return persister.persist();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Field> generateDefaultFields(FormCreationData data, List<String> fieldsToIgnore)
|
||||
{
|
||||
if(extendedPropertyFieldProcessor != null)
|
||||
{
|
||||
// Use a custom field-builder, which allows multi-valued escapes
|
||||
ExtendedFieldBuilder fieldBuilder = new ExtendedFieldBuilder(data, fieldProcessorRegistry, namespaceService, fieldsToIgnore,
|
||||
extendedPropertyFieldProcessor);
|
||||
return fieldBuilder.buildDefaultFields();
|
||||
}
|
||||
return super.generateDefaultFields(data, fieldsToIgnore);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Field> generateSelectedFields(List<String> fields, FormCreationData data)
|
||||
{
|
||||
if(extendedPropertyFieldProcessor != null)
|
||||
{
|
||||
List<Field> fieldData = new ArrayList<Field>(fields.size());
|
||||
for (String fieldName : fields)
|
||||
{
|
||||
Field field = null;
|
||||
if(extendedPropertyFieldProcessor.isApplicableForField(fieldName))
|
||||
{
|
||||
field = extendedPropertyFieldProcessor.generateField(fieldName, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
field = fieldProcessorRegistry.buildField(fieldName, data);
|
||||
}
|
||||
if (field == null)
|
||||
{
|
||||
if (getLogger().isDebugEnabled())
|
||||
{
|
||||
String msg = "Ignoring unrecognised field \"" + fieldName + "\"";
|
||||
getLogger().debug(msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldData.add(field);
|
||||
}
|
||||
}
|
||||
return fieldData;
|
||||
}
|
||||
|
||||
return super.generateSelectedFields(fields, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param workflowService the workflowService to set
|
||||
*/
|
||||
@@ -93,6 +145,15 @@ public abstract class AbstractWorkflowFormProcessor<ItemType, PersistType> exten
|
||||
this.behaviourFilter = behaviourFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param extendedPropertyFieldProcessor the processor to set
|
||||
*/
|
||||
public void setExtendedPropertyFieldProcessor(
|
||||
ExtendedPropertyFieldProcessor extendedPropertyFieldProcessor)
|
||||
{
|
||||
this.extendedPropertyFieldProcessor = extendedPropertyFieldProcessor;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see org.alfresco.repo.forms.processor.node.NodeFormProcessor#getTypedItem(org.alfresco.repo.forms.Item)
|
||||
*/
|
||||
|
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.forms.processor.workflow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.forms.Field;
|
||||
import org.alfresco.repo.forms.processor.FieldProcessorRegistry;
|
||||
import org.alfresco.repo.forms.processor.FormCreationData;
|
||||
import org.alfresco.repo.forms.processor.node.ContentModelItemData;
|
||||
import org.alfresco.repo.forms.processor.node.DefaultFieldBuilder;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
/**
|
||||
* A custom field-builder, which escapes multi-valued String-properties. The comma's in
|
||||
* the values are escaped using a '\' character. When the escape-chatacter is also used in
|
||||
* the value, it's escaped as '\\'.
|
||||
* </p>
|
||||
* @author Frederik Heremans
|
||||
*/
|
||||
public class ExtendedFieldBuilder extends DefaultFieldBuilder
|
||||
{
|
||||
private ContentModelItemData<?> data;
|
||||
private ExtendedPropertyFieldProcessor extendedPropertyFieldProcessor;
|
||||
|
||||
public ExtendedFieldBuilder(FormCreationData data, FieldProcessorRegistry registry,
|
||||
NamespaceService namespaceService, List<String> ignoredFields, ExtendedPropertyFieldProcessor extendedPropertyFieldProcessor)
|
||||
{
|
||||
super(data, registry, namespaceService, ignoredFields);
|
||||
this.data = (ContentModelItemData<?>) data.getItemData();
|
||||
this.extendedPropertyFieldProcessor = extendedPropertyFieldProcessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Field> buildDefaultPropertyFields()
|
||||
{
|
||||
return super.buildDefaultPropertyFields();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Field buildPropertyField(QName name)
|
||||
{
|
||||
if(extendedPropertyFieldProcessor.isApplicableForProperty(name))
|
||||
{
|
||||
return extendedPropertyFieldProcessor.generateField(name, data, false);
|
||||
}
|
||||
|
||||
// Revert to "normal" field-building
|
||||
return super.buildPropertyField(name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param escapedString the string containing the escaped, comma-seperated values.
|
||||
* @return the values split up and unescaped.
|
||||
*/
|
||||
public static List<String> getUnescapedValues(String escapedString)
|
||||
{
|
||||
List<String> elements = new ArrayList<String>();
|
||||
StringBuffer currentElement = new StringBuffer();
|
||||
|
||||
char currentChar;
|
||||
boolean isEscaped = false;
|
||||
for(int i = 0; i < escapedString.length(); i++)
|
||||
{
|
||||
currentChar = escapedString.charAt(i);
|
||||
|
||||
if(isEscaped)
|
||||
{
|
||||
isEscaped = false;
|
||||
currentElement.append(currentChar);
|
||||
}
|
||||
else if(currentChar == '\\')
|
||||
{
|
||||
// Escape character encountered
|
||||
isEscaped = true;
|
||||
}
|
||||
else if(currentChar == ',')
|
||||
{
|
||||
// New element encounterd
|
||||
elements.add(currentElement.toString());
|
||||
currentElement.delete(0, currentElement.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Plain character, push to current value
|
||||
currentElement.append(currentChar);
|
||||
}
|
||||
}
|
||||
|
||||
if(currentElement.length() > 0)
|
||||
{
|
||||
elements.add(currentElement.toString());
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.forms.processor.workflow;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.forms.processor.node.ContentModelItemData;
|
||||
import org.alfresco.repo.forms.processor.node.FormFieldConstants;
|
||||
import org.alfresco.repo.forms.processor.node.PropertyFieldProcessor;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link PropertyFieldProcessor} that allows certain properties to have their values escaped,
|
||||
* prior to joining them using comma's to use as form-field data.
|
||||
*
|
||||
* @author Frederik Heremans
|
||||
*/
|
||||
public class ExtendedPropertyFieldProcessor extends PropertyFieldProcessor
|
||||
{
|
||||
private Set<QName> escapedPropertyNames = new HashSet<QName>();
|
||||
private Set<String> escapedFieldNames = new HashSet<String>();
|
||||
|
||||
@Override
|
||||
public Object getValue(QName name, ContentModelItemData<?> data)
|
||||
{
|
||||
Serializable value = data.getPropertyValue(name);
|
||||
if (value != null && value instanceof List<?>)
|
||||
{
|
||||
List<?> list = (List<?>) value;
|
||||
if(!list.isEmpty() && list.get(0) instanceof String)
|
||||
{
|
||||
List<String> escapedValues = new ArrayList<String>(list.size());
|
||||
for(Object listValue : list)
|
||||
{
|
||||
escapedValues.add(escape((String)listValue));
|
||||
}
|
||||
return StringUtils.collectionToCommaDelimitedString(escapedValues);
|
||||
}
|
||||
}
|
||||
return super.getValue(name, data);
|
||||
}
|
||||
|
||||
public boolean isApplicableForProperty(QName propName)
|
||||
{
|
||||
return escapedPropertyNames != null && escapedPropertyNames.contains(propName);
|
||||
}
|
||||
|
||||
public boolean isApplicableForField(String fieldName)
|
||||
{
|
||||
return escapedFieldNames != null && escapedFieldNames.contains(fieldName);
|
||||
}
|
||||
|
||||
public void addEscapedPropertyName(QName name)
|
||||
{
|
||||
escapedPropertyNames.add(name);
|
||||
escapedFieldNames.add(name.toPrefixString());
|
||||
}
|
||||
|
||||
protected QName getFullName(String name)
|
||||
{
|
||||
String[] parts = name.split(FormFieldConstants.FIELD_NAME_SEPARATOR);
|
||||
|
||||
if(parts.length == 2)
|
||||
{
|
||||
String prefix = parts[0];
|
||||
String localName = parts[1];
|
||||
return QName.createQName(prefix, localName, namespaceService);
|
||||
}
|
||||
else
|
||||
{
|
||||
String prefix = parts[1];
|
||||
String localName = parts[2];
|
||||
return QName.createQName(prefix, localName, namespaceService);
|
||||
}
|
||||
}
|
||||
|
||||
protected String escape(String listValue)
|
||||
{
|
||||
if(listValue.indexOf('\\') > 0)
|
||||
{
|
||||
listValue = listValue.replace("\\", "\\\\");
|
||||
}
|
||||
if(listValue.indexOf(',') > 0)
|
||||
{
|
||||
listValue = listValue.replace(",", "\\,");
|
||||
}
|
||||
return listValue;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
ExtendedPropertyFieldProcessor processor = new ExtendedPropertyFieldProcessor();
|
||||
processor.addEscapedPropertyName(WorkflowModel.PROP_COMMENT);
|
||||
|
||||
System.out.println(processor.getFullName("prop:cm:content"));
|
||||
}
|
||||
}
|
@@ -65,6 +65,8 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor<WorkflowTas
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Constructor for tests.
|
||||
public TaskFormProcessor(WorkflowService workflowService, NamespaceService namespaceService,
|
||||
|
@@ -1,805 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
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;
|
||||
import org.alfresco.repo.forms.Item;
|
||||
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;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowInstance;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowNode;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 3.4
|
||||
* @author Nick Smith
|
||||
*
|
||||
*/
|
||||
public class TaskFormProcessorTest extends TestCase
|
||||
{
|
||||
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 WorkflowService workflowService;
|
||||
private NodeService nodeService;
|
||||
private TaskFormProcessor processor;
|
||||
private WorkflowTask task;
|
||||
private NamespaceService namespaceService;
|
||||
private AuthenticationService authenticationService;
|
||||
private PersonService personService;
|
||||
private WorkflowTask newTask;
|
||||
private Map<QName, Serializable> actualProperties = null;
|
||||
private Map<QName, List<NodeRef>> actualAdded= null;
|
||||
private Map<QName, List<NodeRef>> actualRemoved= null;
|
||||
|
||||
public void testGetTypedItem() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
processor.getTypedItem(null);
|
||||
fail("Should have thrown an Exception here!");
|
||||
}
|
||||
catch (FormNotFoundException e)
|
||||
{
|
||||
// Do nothing!
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
processor.getTypedItem(new Item("task", "bad id"));
|
||||
fail("Should have thrown an Exception here!");
|
||||
}
|
||||
catch (FormNotFoundException e)
|
||||
{
|
||||
// Do nothing!
|
||||
}
|
||||
|
||||
Item item = new Item("task", TASK_ID);
|
||||
WorkflowTask result = processor.getTypedItem(item);
|
||||
assertNotNull(result);
|
||||
assertEquals(TASK_ID, result.getId());
|
||||
|
||||
// Check URI-encoded id.
|
||||
item = new Item("task", TASK_ID);
|
||||
result = 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);
|
||||
Item formItem = form.getItem();
|
||||
assertEquals(item.getId(), formItem.getId());
|
||||
assertEquals(item.getKind(), formItem.getKind());
|
||||
String expType = NamespaceService.BPM_MODEL_PREFIX + ":" + TASK_DEF_NAME;
|
||||
assertEquals(expType, formItem.getType());
|
||||
assertEquals("api/task-instances/" + TASK_ID, formItem.getUrl());
|
||||
}
|
||||
|
||||
public void testGenerateSingleProperty()
|
||||
{
|
||||
// Check Status field is added to Form.
|
||||
String fieldName = STATUS_NAME.toPrefixString(namespaceService);
|
||||
List<String> fields = Arrays.asList(fieldName);
|
||||
Form form = processForm(fields);
|
||||
checkSingleProperty(form, fieldName, WorkflowTaskState.IN_PROGRESS);
|
||||
|
||||
// Check Status field is added to Form, when explicitly typed as a
|
||||
// property.
|
||||
String fullPropertyName = "prop:" + fieldName;
|
||||
fields = Arrays.asList(fullPropertyName);
|
||||
form = processForm(fields);
|
||||
checkSingleProperty(form, fieldName, WorkflowTaskState.IN_PROGRESS);
|
||||
checkPackageActionGroups(form.getFormData());
|
||||
}
|
||||
|
||||
public void testGenerateSingleAssociation()
|
||||
{
|
||||
// Check Assignee field is added to Form.
|
||||
String fieldName = ASSIGNEE_NAME.toPrefixString(namespaceService);
|
||||
List<String> fields = Arrays.asList(fieldName);
|
||||
Form form = processForm(fields);
|
||||
Serializable fieldData = (Serializable) Arrays.asList(FAKE_NODE.toString());
|
||||
checkSingleAssociation(form, fieldName, fieldData);
|
||||
|
||||
// Check Assignee field is added to Form, when explicitly typed as an
|
||||
// association.
|
||||
String fullAssociationName = "assoc:" + fieldName;
|
||||
fields = Arrays.asList(fullAssociationName);
|
||||
form = processForm(fields);
|
||||
checkSingleAssociation(form, fieldName, fieldData);
|
||||
checkPackageActionGroups(form.getFormData());
|
||||
}
|
||||
|
||||
public void testIgnoresUnknownFields() throws Exception
|
||||
{
|
||||
String fakeFieldName = NamespaceService.BPM_MODEL_PREFIX + ":" + "Fake Field";
|
||||
String statusFieldName = STATUS_NAME.toPrefixString(namespaceService);
|
||||
List<String> fields = Arrays.asList(fakeFieldName, statusFieldName);
|
||||
Form form = processForm(fields);
|
||||
checkSingleProperty(form, statusFieldName, WorkflowTaskState.IN_PROGRESS);
|
||||
checkPackageActionGroups(form.getFormData());
|
||||
}
|
||||
|
||||
public void testGenerateDefaultForm() throws Exception
|
||||
{
|
||||
Form form = processForm();
|
||||
List<String> fieldDefs = form.getFieldDefinitionNames();
|
||||
assertTrue(fieldDefs.contains(ASSIGNEE_NAME.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(ASSOC_WITH_.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(DESC_NAME.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(STATUS_NAME.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(PROP_WITH_.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(PackageItemsFieldProcessor.KEY));
|
||||
assertTrue(fieldDefs.contains(TransitionFieldProcessor.KEY));
|
||||
|
||||
// Check 'default ignored fields' are proerly removed from defaults.
|
||||
assertFalse(fieldDefs.contains(ACTORS_NAME.toPrefixString(namespaceService)));
|
||||
assertFalse(fieldDefs.contains(PROP_PACKAGE_ACTION_GROUP.toPrefixString(namespaceService)));
|
||||
assertFalse(fieldDefs.contains(PROP_PACKAGE_ITEM_ACTION_GROUP.toPrefixString(namespaceService)));
|
||||
|
||||
Serializable fieldData = (Serializable) Arrays.asList(FAKE_NODE.toString());
|
||||
FormData formData = form.getFormData();
|
||||
assertEquals(fieldData, formData.getFieldData("assoc_bpm_assignee").getValue());
|
||||
checkPackageActionGroups(formData);
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, formData.getFieldData("prop_bpm_status").getValue());
|
||||
}
|
||||
|
||||
public void testGenerateTransitions() throws Exception
|
||||
{
|
||||
// Check empty transitions
|
||||
String fieldName = TransitionFieldProcessor.KEY;
|
||||
Form form = processForm(fieldName);
|
||||
String transitionValues = "";
|
||||
checkSingleProperty(form, fieldName, transitionValues);
|
||||
|
||||
// Set up transitions
|
||||
WorkflowTransition transition1 = makeTransition("id1", "title1");
|
||||
WorkflowTransition transition2 = makeTransition("id2", "title2");
|
||||
WorkflowTransition transition3 = makeTransition("id3", "title3");
|
||||
task = makeTask(transition1, transition2, transition3);
|
||||
|
||||
// Hide transition with id3.
|
||||
Serializable hiddenValue = (Serializable) Collections.singletonList("id3");
|
||||
task.getProperties().put(PROP_HIDDEN_TRANSITIONS, hiddenValue );
|
||||
|
||||
form = processForm(fieldName);
|
||||
transitionValues = "id1|title1,id2|title2";
|
||||
checkSingleProperty(form, fieldName, transitionValues);
|
||||
}
|
||||
|
||||
public void testGenerateMessage() throws Exception
|
||||
{
|
||||
String message = null;
|
||||
String fieldName = MessageFieldProcessor.KEY;
|
||||
Form form = processForm(fieldName);
|
||||
checkSingleProperty(form, fieldName, message);
|
||||
|
||||
// add a description to the task and check it comes back
|
||||
message = "This is some text the user may have entered";
|
||||
this.task.getProperties().put(PROP_DESCRIPTION, message);
|
||||
|
||||
form = processForm(fieldName);
|
||||
checkSingleProperty(form, fieldName, message);
|
||||
|
||||
// set the description to the same as the task title
|
||||
// and make sure the message comes back as null
|
||||
this.task.getProperties().put(PROP_DESCRIPTION, this.task.getTitle());
|
||||
form = processForm(fieldName);
|
||||
checkSingleProperty(form, fieldName, null);
|
||||
}
|
||||
|
||||
public void testGenerateTaskOwner() throws Exception
|
||||
{
|
||||
// check the task owner is null
|
||||
String fieldName = TaskOwnerFieldProcessor.KEY;
|
||||
Form form = processForm(fieldName);
|
||||
checkSingleProperty(form, fieldName, null);
|
||||
|
||||
// set task owner
|
||||
this.task.getProperties().put(ContentModel.PROP_OWNER, "admin");
|
||||
|
||||
// check the task owner property is correct
|
||||
form = processForm(fieldName);
|
||||
checkSingleProperty(form, fieldName, "admin|System|Administrator");
|
||||
}
|
||||
|
||||
public void testGeneratePackageItems() throws Exception
|
||||
{
|
||||
// Check empty package
|
||||
String fieldName = PackageItemsFieldProcessor.KEY;
|
||||
Form form = processForm(fieldName);
|
||||
Serializable packageItems = (Serializable) Collections.emptyList();
|
||||
checkSingleAssociation(form, fieldName, packageItems);
|
||||
|
||||
// Effectively add 3 items to package.
|
||||
List<NodeRef> value = Arrays.asList(FAKE_NODE, FAKE_NODE2, FAKE_NODE3);
|
||||
when(workflowService.getPackageContents(TASK_ID))
|
||||
.thenReturn(value);
|
||||
|
||||
form = processForm(fieldName);
|
||||
packageItems = (Serializable) Arrays.asList(FAKE_NODE.toString(),
|
||||
FAKE_NODE2.toString(),
|
||||
FAKE_NODE3.toString());
|
||||
checkSingleAssociation(form, fieldName, packageItems);
|
||||
}
|
||||
|
||||
private WorkflowTransition makeTransition(String id, String title)
|
||||
{
|
||||
return new WorkflowTransition(
|
||||
id, title, null, false);
|
||||
}
|
||||
|
||||
public void testPersistPropertyChanged() throws Exception
|
||||
{
|
||||
String fieldName = DESC_NAME.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName);
|
||||
String value = "New Description";
|
||||
|
||||
processPersist(dataKey, value);
|
||||
|
||||
assertEquals(1, actualProperties.size());
|
||||
assertEquals(value, actualProperties.get(DESC_NAME));
|
||||
}
|
||||
|
||||
public void testPersistConvertsPropertyValueToCorrectType()
|
||||
{
|
||||
String fieldName = PROP_PRIORITY.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName);
|
||||
String value = "2"; // String value for property of type Integer!
|
||||
|
||||
processPersist(dataKey, value);
|
||||
assertEquals(2, actualProperties.get(PROP_PRIORITY));
|
||||
}
|
||||
|
||||
public void testPersistPropertyWith_() throws Exception
|
||||
{
|
||||
String fieldName = PROP_WITH_.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName);
|
||||
String value = "New _ Value";
|
||||
|
||||
processPersist(dataKey, value);
|
||||
|
||||
assertEquals(1, actualProperties.size());
|
||||
assertEquals(value, actualProperties.get(PROP_WITH_));
|
||||
}
|
||||
|
||||
public void testPersistAssociationAdded() throws Exception
|
||||
{
|
||||
String fieldName = ACTORS_NAME.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, true);
|
||||
String nodeRef1 = FAKE_NODE.toString() + "1";
|
||||
String nodeRef2 = FAKE_NODE.toString() + "2";
|
||||
String value = nodeRef1 + ", " + nodeRef2;
|
||||
processPersist(dataKey, value);
|
||||
|
||||
assertEquals(1, actualAdded.size());
|
||||
List<NodeRef> nodeRefs = actualAdded.get(ACTORS_NAME);
|
||||
assertNotNull(nodeRefs);
|
||||
assertEquals(2, nodeRefs.size());
|
||||
assertTrue(nodeRefs.contains(new NodeRef(nodeRef1)));
|
||||
assertTrue(nodeRefs.contains(new NodeRef(nodeRef2)));
|
||||
}
|
||||
|
||||
public void testPersistAssociationsRemoved() throws Exception
|
||||
{
|
||||
String fieldName = ASSIGNEE_NAME.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, false);
|
||||
String value = FAKE_NODE.toString();
|
||||
processPersist(dataKey, value);
|
||||
|
||||
assertEquals(1, actualRemoved.size());
|
||||
List<NodeRef> nodeRefs = actualRemoved.get(ASSIGNEE_NAME);
|
||||
assertNotNull(nodeRefs);
|
||||
assertEquals(1, nodeRefs.size());
|
||||
assertTrue(nodeRefs.contains(FAKE_NODE));
|
||||
}
|
||||
|
||||
public void testPersistAssociationAddedWith_() throws Exception
|
||||
{
|
||||
String fieldName = ASSOC_WITH_.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, true);
|
||||
String value = FAKE_NODE + ", " + FAKE_NODE2;
|
||||
processPersist(dataKey, value);
|
||||
assertEquals(1, actualAdded.size());
|
||||
List<NodeRef> nodeRefs = actualAdded.get(ASSOC_WITH_);
|
||||
assertNotNull(nodeRefs);
|
||||
assertEquals(2, nodeRefs.size());
|
||||
assertTrue(nodeRefs.contains(FAKE_NODE));
|
||||
assertTrue(nodeRefs.contains(FAKE_NODE2));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testPersistTransitions() throws Exception
|
||||
{
|
||||
// Check updates but doesn't transition if no transition prop set.
|
||||
processPersist("prop_bpm_foo", "foo");
|
||||
// Check endTask is never called.
|
||||
verify(workflowService, times(1)).updateTask(eq(TASK_ID), anyMap(), anyMap(), anyMap());
|
||||
verify(workflowService, never()).endTask(eq(TASK_ID), anyString());
|
||||
|
||||
// Check default transition.
|
||||
String dataKey = makeDataKeyName(TransitionFieldProcessor.KEY);
|
||||
processPersist(dataKey, null);
|
||||
verify(workflowService, times(1)).endTask(TASK_ID, null);
|
||||
|
||||
// Check specific transition.
|
||||
processPersist(dataKey, "foo");
|
||||
verify(workflowService, times(1)).endTask(TASK_ID, "foo");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testPersistPropertyAndTransition() throws Exception
|
||||
{
|
||||
FormData data = new FormData();
|
||||
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
|
||||
assertEquals(newTask, persistedItem);
|
||||
verify(workflowService, times(1)).updateTask(eq(TASK_ID), anyMap(), anyMap(), anyMap());
|
||||
verify(workflowService, times(1)).endTask(TASK_ID, "foo");
|
||||
}
|
||||
|
||||
public void testPersistPackageItemsAdded() throws Exception
|
||||
{
|
||||
mockPackageItems(FAKE_NODE3);
|
||||
String dataKey = makeDataKeyName(PackageItemsFieldProcessor.KEY, true);
|
||||
String value = FAKE_NODE + ", " + FAKE_NODE2;
|
||||
processPersist(dataKey, value);
|
||||
checkAddPackageItem(FAKE_NODE, true);
|
||||
checkAddPackageItem(FAKE_NODE2, true);
|
||||
checkAddPackageItem(FAKE_NODE3, false);
|
||||
}
|
||||
|
||||
public void testPersistPackageItemsRemoved() throws Exception
|
||||
{
|
||||
mockPackageItems(FAKE_NODE, FAKE_NODE2);
|
||||
String dataKey = makeDataKeyName(PackageItemsFieldProcessor.KEY, false);
|
||||
String value = FAKE_NODE + ", " + FAKE_NODE2+ "," + FAKE_NODE3;
|
||||
processPersist(dataKey, value);
|
||||
|
||||
// Check nodes 1 and 2 removed correctly.
|
||||
checkRemovedPackageItem(FAKE_NODE, true);
|
||||
checkRemovedPackageItem(FAKE_NODE2, true);
|
||||
|
||||
// Check node 3 is not removed as it was not in the package to start with.
|
||||
checkRemovedPackageItem(FAKE_NODE3, false);
|
||||
}
|
||||
|
||||
private void mockPackageItems(NodeRef... children)
|
||||
{
|
||||
ArrayList<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(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);
|
||||
}
|
||||
|
||||
private Form processForm(String... fields)
|
||||
{
|
||||
return processForm(Arrays.asList(fields));
|
||||
}
|
||||
|
||||
private Form processForm(List<String> fields)
|
||||
{
|
||||
Item item = new Item("task", TASK_ID);
|
||||
Form form = processor.generate(item, fields, null, null);
|
||||
return form;
|
||||
}
|
||||
|
||||
private void checkPackageActionGroups(FormData formData)
|
||||
{
|
||||
FieldData pckgActionData = formData.getFieldData("prop_bpm_packageActionGroup");
|
||||
assertNotNull(pckgActionData);
|
||||
assertEquals("", pckgActionData.getValue());
|
||||
FieldData pckgItemActionData = formData.getFieldData("prop_bpm_packageItemActionGroup");
|
||||
assertNotNull(pckgItemActionData);
|
||||
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<FieldDefinition> 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)
|
||||
{
|
||||
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()
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
task = makeTask();
|
||||
workflowService = makeWorkflowService();
|
||||
nodeService = makeNodeService();
|
||||
DictionaryService dictionaryService = makeDictionaryService();
|
||||
namespaceService = makeNamespaceService();
|
||||
authenticationService = makeAuthenticationService();
|
||||
personService = makePersonService();
|
||||
MockFieldProcessorRegistry fieldProcessorRegistry = new MockFieldProcessorRegistry(namespaceService,
|
||||
dictionaryService);
|
||||
DefaultFieldProcessor defaultProcessor = makeDefaultFieldProcessor(dictionaryService);
|
||||
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.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;
|
||||
String title = "Test";
|
||||
WorkflowTaskState state = WorkflowTaskState.IN_PROGRESS;
|
||||
WorkflowTaskDefinition taskDef = makeTaskDefinition(transitions);
|
||||
Map<QName, Serializable> properties = makeTaskProperties();
|
||||
|
||||
WorkflowDefinition definition = new WorkflowDefinition("42", "Test", "1.0", "Test", "Test", null);
|
||||
NodeRef wfPackage = PCKG_NODE;
|
||||
WorkflowInstance instance = new WorkflowInstance(null,
|
||||
definition, null,
|
||||
null, wfPackage,
|
||||
null, true, null, null);
|
||||
WorkflowNode node = new WorkflowNode("", "", "", "", true, new WorkflowTransition[0]);
|
||||
WorkflowPath path = new WorkflowPath(null, instance, node, true);
|
||||
return new WorkflowTask(id,
|
||||
taskDef, null, title, null, state, path, properties);
|
||||
}
|
||||
|
||||
private HashMap<QName, Serializable> makeTaskProperties()
|
||||
{
|
||||
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
properties.put(STATUS_NAME, WorkflowTaskState.IN_PROGRESS);
|
||||
properties.put(ASSIGNEE_NAME, FAKE_NODE);
|
||||
return properties;
|
||||
}
|
||||
|
||||
private WorkflowTaskDefinition makeTaskDefinition(WorkflowTransition... transitions)
|
||||
{
|
||||
String id = "DefinitionId";
|
||||
TypeDefinition metadata = makeTypeDef();
|
||||
WorkflowNode node = new WorkflowNode("", "", "", "", true, transitions);
|
||||
return new WorkflowTaskDefinition(id,
|
||||
node, metadata);
|
||||
}
|
||||
|
||||
private TypeDefinition makeTypeDef()
|
||||
{
|
||||
TypeDefinition typeDef = mock(TypeDefinition.class);
|
||||
QName name = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, TASK_DEF_NAME);
|
||||
when(typeDef.getName()).thenReturn(name);
|
||||
|
||||
// Set up task property definitions
|
||||
Map<QName, PropertyDefinition> propertyDefs = makeTaskPropertyDefs();
|
||||
when(typeDef.getProperties()).thenReturn(propertyDefs);
|
||||
|
||||
// Set up task association definitions.
|
||||
Map<QName, AssociationDefinition> associationDefs = makeTaskAssociationDefs();
|
||||
when(typeDef.getAssociations()).thenReturn(associationDefs);
|
||||
return typeDef;
|
||||
}
|
||||
|
||||
private Map<QName, PropertyDefinition> makeTaskPropertyDefs()
|
||||
{
|
||||
Map<QName, PropertyDefinition> properties = new HashMap<QName, PropertyDefinition>();
|
||||
QName textType = DataTypeDefinition.TEXT;
|
||||
|
||||
// Add a Description property
|
||||
PropertyDefinition descValue = MockClassAttributeDefinition.mockPropertyDefinition(DESC_NAME, textType);
|
||||
properties.put(DESC_NAME, descValue);
|
||||
|
||||
// Add a Status property
|
||||
PropertyDefinition titleValue = MockClassAttributeDefinition.mockPropertyDefinition(STATUS_NAME, textType);
|
||||
properties.put(STATUS_NAME, titleValue);
|
||||
|
||||
// Add a Status property
|
||||
PropertyDefinition with_ = MockClassAttributeDefinition.mockPropertyDefinition(PROP_WITH_, textType);
|
||||
properties.put(PROP_WITH_, with_);
|
||||
|
||||
// Add a Package Action property
|
||||
QName pckgActionGroup = PROP_PACKAGE_ACTION_GROUP;
|
||||
PropertyDefinition pckgAction = MockClassAttributeDefinition.mockPropertyDefinition(pckgActionGroup, textType,
|
||||
"");
|
||||
properties.put(pckgActionGroup, pckgAction);
|
||||
|
||||
// Add a Package Action property
|
||||
QName pckgItemActionGroup = PROP_PACKAGE_ITEM_ACTION_GROUP;
|
||||
PropertyDefinition pckgItemAction = MockClassAttributeDefinition.mockPropertyDefinition(pckgItemActionGroup,
|
||||
textType, "read_package_item_actions");
|
||||
properties.put(pckgItemActionGroup, pckgItemAction);
|
||||
|
||||
|
||||
// Add a priority property
|
||||
QName priorityName = PROP_PRIORITY;
|
||||
PropertyDefinition priorityDef =
|
||||
MockClassAttributeDefinition.mockPropertyDefinition(priorityName, DataTypeDefinition.INT, Integer.class, "0");
|
||||
properties.put(priorityName, priorityDef);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private Map<QName, AssociationDefinition> makeTaskAssociationDefs()
|
||||
{
|
||||
Map<QName, AssociationDefinition> associations = new HashMap<QName, AssociationDefinition>();
|
||||
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();
|
||||
nsService.registerNamespace(NamespaceService.SYSTEM_MODEL_PREFIX, NamespaceService.SYSTEM_MODEL_1_0_URI);
|
||||
nsService.registerNamespace(NamespaceService.RENDITION_MODEL_PREFIX, NamespaceService.RENDITION_MODEL_1_0_URI);
|
||||
nsService.registerNamespace(NamespaceService.BPM_MODEL_PREFIX, NamespaceService.BPM_MODEL_1_0_URI);
|
||||
return nsService;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private DictionaryService makeDictionaryService()
|
||||
{
|
||||
DictionaryService mock = mock(DictionaryService.class);
|
||||
when(mock.getAnonymousType((QName) any(), (Collection<QName>) any())).thenReturn(task.getDefinition().getMetadata());
|
||||
return mock;
|
||||
}
|
||||
|
||||
private AuthenticationService makeAuthenticationService()
|
||||
{
|
||||
AuthenticationService mock = mock(AuthenticationService.class);
|
||||
when(mock.getCurrentUserName()).thenReturn("admin");
|
||||
return mock;
|
||||
}
|
||||
|
||||
private PersonService makePersonService()
|
||||
{
|
||||
PersonService mock = mock(PersonService.class);
|
||||
when(mock.getPerson("admin")).thenReturn(USER_NODE);
|
||||
return mock;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private WorkflowService makeWorkflowService()
|
||||
{
|
||||
WorkflowService service = mock(WorkflowService.class);
|
||||
when(service.getTaskById(anyString())).thenAnswer(new Answer<WorkflowTask>()
|
||||
{
|
||||
public WorkflowTask answer(InvocationOnMock invocation) throws Throwable
|
||||
{
|
||||
String id = (String) invocation.getArguments()[0];
|
||||
if (TASK_ID.equals(id))
|
||||
return task;
|
||||
else
|
||||
throw new WorkflowException("Task Id not found!");
|
||||
}
|
||||
});
|
||||
|
||||
this.newTask = new WorkflowTask(TASK_ID, null, null, null, null, null, null, null);
|
||||
|
||||
when(service.updateTask(anyString(), anyMap(), anyMap(), anyMap()))
|
||||
.thenAnswer(new Answer<WorkflowTask>()
|
||||
{
|
||||
public WorkflowTask answer(InvocationOnMock invocation) throws Throwable
|
||||
{
|
||||
Object[] args = invocation.getArguments();
|
||||
Map<QName, Serializable> props = (Map<QName, Serializable>) args[1];
|
||||
actualProperties = new HashMap<QName, Serializable>(props);
|
||||
Map<QName, List<NodeRef>> added = (Map<QName, List<NodeRef>>) args[2];
|
||||
actualAdded = new HashMap<QName, List<NodeRef>>(added);
|
||||
Map<QName, List<NodeRef>> removed = (Map<QName, List<NodeRef>>) args[3];
|
||||
actualRemoved = new HashMap<QName, List<NodeRef>>(removed);
|
||||
return newTask;
|
||||
}
|
||||
});
|
||||
|
||||
when(service.endTask(eq(TASK_ID), anyString()))
|
||||
.thenReturn(newTask);
|
||||
|
||||
when(service.isTaskEditable((WorkflowTask)any(), anyString())).thenReturn(true);
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
private NodeService makeNodeService()
|
||||
{
|
||||
NodeService service = mock(NodeService.class);
|
||||
when(service.hasAspect(PCKG_NODE, ASPECT_WORKFLOW_PACKAGE))
|
||||
.thenReturn(true);
|
||||
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2);
|
||||
props.put(ContentModel.PROP_FIRSTNAME, "System");
|
||||
props.put(ContentModel.PROP_LASTNAME, "Administrator");
|
||||
|
||||
when(service.getProperties(USER_NODE)).thenReturn(props);
|
||||
return service;
|
||||
}
|
||||
|
||||
}
|
@@ -1,620 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
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;
|
||||
import org.alfresco.repo.forms.Item;
|
||||
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;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowNode;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 3.4
|
||||
* @author Nick Smith
|
||||
*
|
||||
*/
|
||||
public class WorkflowFormProcessorTest extends TestCase
|
||||
{
|
||||
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<QName, Serializable> actualProperties = null;
|
||||
|
||||
public void testGetTypedItem() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
processor.getTypedItem(null);
|
||||
fail("Should have thrown an Exception here!");
|
||||
}
|
||||
catch (FormNotFoundException e)
|
||||
{
|
||||
// Do nothing!
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
processor.getTypedItem(new Item("task", "bad id"));
|
||||
fail("Should have thrown an Exception here!");
|
||||
}
|
||||
catch (FormNotFoundException e)
|
||||
{
|
||||
// Do nothing!
|
||||
}
|
||||
|
||||
WorkflowDefinition result = processor.getTypedItem(item);
|
||||
assertNotNull(result);
|
||||
assertEquals(WF_DEF_NAME, result.getName());
|
||||
}
|
||||
|
||||
public void testGenerateSetsItemAndUrl() throws Exception
|
||||
{
|
||||
Form form = processor.generate(item, null, null, null);
|
||||
Item formItem = form.getItem();
|
||||
assertEquals(item.getId(), formItem.getId());
|
||||
assertEquals(item.getKind(), formItem.getKind());
|
||||
assertEquals(WF_DEF_NAME, formItem.getType());
|
||||
assertEquals("api/workflow-definitions/" + definition.getId(), formItem.getUrl());
|
||||
}
|
||||
|
||||
public void testGenerateSingleProperty()
|
||||
{
|
||||
// Check Status field is added to Form.
|
||||
String fieldName = PRIORITY_NAME.toPrefixString(namespaceService);
|
||||
List<String> fields = Arrays.asList(fieldName);
|
||||
Form form = processForm(fields);
|
||||
checkSingleProperty(form, fieldName, "2");
|
||||
|
||||
// Check Status field is added to Form, when explicitly typed as a
|
||||
// property.
|
||||
String fullPropertyName = "prop:" + fieldName;
|
||||
fields = Arrays.asList(fullPropertyName);
|
||||
form = processForm(fields);
|
||||
checkSingleProperty(form, fieldName, "2");
|
||||
checkPackageActionGroups(form.getFormData());
|
||||
}
|
||||
|
||||
public void testGenerateSingleAssociation()
|
||||
{
|
||||
Serializable values = (Serializable) Collections.emptyList();
|
||||
// Check Assignee field is added to Form.
|
||||
String fieldName = ASSIGNEE_NAME.toPrefixString(namespaceService);
|
||||
List<String> fields = Arrays.asList(fieldName);
|
||||
Form form = processForm(fields);
|
||||
checkSingleAssociation(form, fieldName, values);
|
||||
|
||||
// Check Assignee field is added to Form, when explicitly typed as an
|
||||
// association.
|
||||
String fullAssociationName = "assoc:" + fieldName;
|
||||
fields = Arrays.asList(fullAssociationName);
|
||||
form = processForm(fields);
|
||||
checkSingleAssociation(form, fieldName, values);
|
||||
checkPackageActionGroups(form.getFormData());
|
||||
}
|
||||
|
||||
public void testIgnoresUnknownFields() throws Exception
|
||||
{
|
||||
String fakeFieldName = NamespaceService.BPM_MODEL_PREFIX + ":" + "Fake Field";
|
||||
String priorityField = PRIORITY_NAME.toPrefixString(namespaceService);
|
||||
List<String> fields = Arrays.asList(fakeFieldName, priorityField);
|
||||
Form form = processForm(fields);
|
||||
checkSingleProperty(form, priorityField, "2");
|
||||
checkPackageActionGroups(form.getFormData());
|
||||
}
|
||||
|
||||
public void testGenerateDefaultForm() throws Exception
|
||||
{
|
||||
Form form = processForm();
|
||||
List<String> fieldDefs = form.getFieldDefinitionNames();
|
||||
assertTrue(fieldDefs.contains(ASSIGNEE_NAME.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(PRIORITY_NAME.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(PackageItemsFieldProcessor.KEY));
|
||||
|
||||
// Check 'default ignored fields' are proerly removed from defaults.
|
||||
assertFalse(fieldDefs.contains(ACTORS_NAME.toPrefixString(namespaceService)));
|
||||
assertFalse(fieldDefs.contains(PROP_PACKAGE_ACTION_GROUP.toPrefixString(namespaceService)));
|
||||
assertFalse(fieldDefs.contains(PROP_PACKAGE_ITEM_ACTION_GROUP.toPrefixString(namespaceService)));
|
||||
assertFalse(fieldDefs.contains(WorkflowModel.PROP_DESCRIPTION.toPrefixString(namespaceService)));
|
||||
assertFalse(fieldDefs.contains(WorkflowModel.PROP_DUE_DATE.toPrefixString(namespaceService)));
|
||||
assertFalse(fieldDefs.contains(WorkflowModel.PROP_PRIORITY.toPrefixString(namespaceService)));
|
||||
assertFalse(fieldDefs.contains(WorkflowModel.PROP_TASK_ID.toPrefixString(namespaceService)));
|
||||
|
||||
Serializable fieldData = (Serializable) Collections.emptyList();
|
||||
FormData formData = form.getFormData();
|
||||
assertEquals(fieldData, formData.getFieldData("assoc_bpm_assignee").getValue());
|
||||
checkPackageActionGroups(formData);
|
||||
assertEquals("2", formData.getFieldData("prop_bpm_workflowPriority").getValue());
|
||||
}
|
||||
|
||||
public void testGeneratePackageItems() throws Exception
|
||||
{
|
||||
// Check empty package
|
||||
String fieldName = PackageItemsFieldProcessor.KEY;
|
||||
Form form = processForm(fieldName);
|
||||
Serializable packageItems = (Serializable) Collections.emptyList();
|
||||
checkSingleAssociation(form, fieldName, packageItems);
|
||||
}
|
||||
|
||||
public void testPersistPropertyChanged() throws Exception
|
||||
{
|
||||
String fieldName = DESC_NAME.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName);
|
||||
String value = "New Description";
|
||||
|
||||
processPersist(dataKey, value);
|
||||
|
||||
// Check adds description property and Package.
|
||||
assertEquals(2, actualProperties.size());
|
||||
assertEquals(value, actualProperties.get(DESC_NAME));
|
||||
assertEquals(PCKG_NODE, actualProperties.get(ASSOC_PACKAGE));
|
||||
}
|
||||
|
||||
public void testPersistPropertyWith_() throws Exception
|
||||
{
|
||||
String fieldName = PROP_WITH_.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName);
|
||||
String value = "New _ Value";
|
||||
|
||||
processPersist(dataKey, value);
|
||||
|
||||
assertEquals(2, actualProperties.size());
|
||||
assertEquals(value, actualProperties.get(PROP_WITH_));
|
||||
}
|
||||
|
||||
public void testPersistAssociationAdded() throws Exception
|
||||
{
|
||||
String fieldName = ACTORS_NAME.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, true);
|
||||
String value = FAKE_NODE + ", " + FAKE_NODE2;
|
||||
processPersist(dataKey, value);
|
||||
|
||||
assertEquals(2, actualProperties.size());
|
||||
List<?> nodeRefs = (List<?>) actualProperties.get(ACTORS_NAME);
|
||||
assertNotNull(nodeRefs);
|
||||
assertEquals(2, nodeRefs.size());
|
||||
assertTrue(nodeRefs.contains(FAKE_NODE));
|
||||
assertTrue(nodeRefs.contains(FAKE_NODE2));
|
||||
}
|
||||
|
||||
public void testIgnoreAssociationsRemoved() throws Exception
|
||||
{
|
||||
String fieldName = ASSIGNEE_NAME.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, false);
|
||||
String value = FAKE_NODE.toString();
|
||||
processPersist(dataKey, value);
|
||||
|
||||
assertEquals(1, actualProperties.size());
|
||||
Serializable nodeRefs = actualProperties.get(ASSIGNEE_NAME);
|
||||
assertNull(nodeRefs);
|
||||
}
|
||||
|
||||
public void testPersistAssociationAddedWith_() throws Exception
|
||||
{
|
||||
String fieldName = ASSOC_WITH_.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, true);
|
||||
String value = FAKE_NODE+ ", " + FAKE_NODE2;
|
||||
processPersist(dataKey, value);
|
||||
|
||||
assertEquals(2, actualProperties.size());
|
||||
List<?> nodeRefs = (List<?>) actualProperties.get(ASSOC_WITH_);
|
||||
assertNotNull(nodeRefs);
|
||||
assertEquals(2, nodeRefs.size());
|
||||
assertTrue(nodeRefs.contains(FAKE_NODE));
|
||||
assertTrue(nodeRefs.contains(FAKE_NODE2));
|
||||
}
|
||||
|
||||
|
||||
public void testPersistPackageItemsAdded() throws Exception
|
||||
{
|
||||
mockPackageItems(FAKE_NODE3);
|
||||
String dataKey = makeDataKeyName(PackageItemsFieldProcessor.KEY, true);
|
||||
String value = FAKE_NODE + ", " + FAKE_NODE2;
|
||||
processPersist(dataKey, value);
|
||||
checkAddPackageItem(FAKE_NODE, true);
|
||||
checkAddPackageItem(FAKE_NODE2, true);
|
||||
checkAddPackageItem(FAKE_NODE3, false);
|
||||
}
|
||||
|
||||
public void testPersistPackageItemsRemovedIgnored() throws Exception
|
||||
{
|
||||
mockPackageItems(FAKE_NODE, FAKE_NODE2);
|
||||
String dataKey = makeDataKeyName(PackageItemsFieldProcessor.KEY, false);
|
||||
String value = FAKE_NODE + ", " + FAKE_NODE2+ "," + FAKE_NODE3;
|
||||
processPersist(dataKey, value);
|
||||
|
||||
// Check nodes 1 and 2 removed correctly.
|
||||
checkRemovedPackageItem(FAKE_NODE, false);
|
||||
checkRemovedPackageItem(FAKE_NODE2, false);
|
||||
checkRemovedPackageItem(FAKE_NODE3, false);
|
||||
}
|
||||
|
||||
private void mockPackageItems(NodeRef... children)
|
||||
{
|
||||
ArrayList<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(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);
|
||||
WorkflowInstance persistedItem = (WorkflowInstance) processor.persist(item, data);
|
||||
assertEquals(newInstance, persistedItem);
|
||||
}
|
||||
|
||||
private Form processForm(String... fields)
|
||||
{
|
||||
return processForm(Arrays.asList(fields));
|
||||
}
|
||||
|
||||
private Form processForm(List<String> fields)
|
||||
{
|
||||
return processor.generate(item, fields, null, null);
|
||||
}
|
||||
|
||||
private void checkPackageActionGroups(FormData formData)
|
||||
{
|
||||
FieldData pckgActionData = formData.getFieldData("prop_bpm_packageActionGroup");
|
||||
assertNotNull(pckgActionData);
|
||||
assertEquals("add_package_item_actions", pckgActionData.getValue());
|
||||
FieldData pckgItemActionData = formData.getFieldData("prop_bpm_packageItemActionGroup");
|
||||
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<FieldDefinition> 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()
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
definition = makeWorkflowDefinition();
|
||||
workflowService = makeWorkflowService();
|
||||
nodeService = makeNodeService();
|
||||
DictionaryService dictionaryService = makeDictionaryService();
|
||||
namespaceService = makeNamespaceService();
|
||||
MockFieldProcessorRegistry fieldProcessorRegistry = new MockFieldProcessorRegistry(namespaceService,
|
||||
dictionaryService);
|
||||
DefaultFieldProcessor defaultProcessor = makeDefaultFieldProcessor(dictionaryService);
|
||||
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));
|
||||
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";
|
||||
String name = WF_DEF_NAME;
|
||||
String version = "1.0";
|
||||
String title = "Foo Bar Title";
|
||||
String description = "Foo Bar Description";
|
||||
WorkflowTaskDefinition startTaskDefinition = makeTaskDefinition();
|
||||
return new WorkflowDefinition(id, name, version, title, description, startTaskDefinition);
|
||||
}
|
||||
|
||||
private WorkflowTaskDefinition makeTaskDefinition()
|
||||
{
|
||||
String id = "foo$startTaskDefId";
|
||||
TypeDefinition metadata = makeTypeDef();
|
||||
WorkflowNode node = new WorkflowNode("", "", "", "", false);
|
||||
return new WorkflowTaskDefinition(id,
|
||||
node, metadata);
|
||||
}
|
||||
|
||||
private TypeDefinition makeTypeDef()
|
||||
{
|
||||
TypeDefinition typeDef = mock(TypeDefinition.class);
|
||||
QName name = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, TASK_DEF_NAME);
|
||||
when(typeDef.getName()).thenReturn(name);
|
||||
|
||||
// Set up task property definitions
|
||||
Map<QName, PropertyDefinition> propertyDefs = makeTaskPropertyDefs();
|
||||
when(typeDef.getProperties()).thenReturn(propertyDefs);
|
||||
|
||||
// Set up task association definitions.
|
||||
Map<QName, AssociationDefinition> associationDefs = makeTaskAssociationDefs();
|
||||
when(typeDef.getAssociations()).thenReturn(associationDefs);
|
||||
return typeDef;
|
||||
}
|
||||
|
||||
private Map<QName, PropertyDefinition> makeTaskPropertyDefs()
|
||||
{
|
||||
Map<QName, PropertyDefinition> properties = new HashMap<QName, PropertyDefinition>();
|
||||
QName intType = DataTypeDefinition.INT;
|
||||
MockClassAttributeDefinition priorityDef = MockClassAttributeDefinition.mockPropertyDefinition(PRIORITY_NAME, intType, "2");
|
||||
properties.put(PRIORITY_NAME, priorityDef);
|
||||
|
||||
QName textType = DataTypeDefinition.TEXT;
|
||||
|
||||
// Add a Description property
|
||||
PropertyDefinition descValue = MockClassAttributeDefinition.mockPropertyDefinition(DESC_NAME, textType);
|
||||
properties.put(DESC_NAME, descValue);
|
||||
|
||||
// Add a Status property
|
||||
PropertyDefinition titleValue = MockClassAttributeDefinition.mockPropertyDefinition(STATUS_NAME, textType);
|
||||
properties.put(STATUS_NAME, titleValue);
|
||||
|
||||
// Add a Status property
|
||||
PropertyDefinition with_ = MockClassAttributeDefinition.mockPropertyDefinition(PROP_WITH_, textType);
|
||||
properties.put(PROP_WITH_, with_);
|
||||
|
||||
// Add a Package Action property
|
||||
QName pckgActionGroup = PROP_PACKAGE_ACTION_GROUP;
|
||||
PropertyDefinition pckgAction = MockClassAttributeDefinition.mockPropertyDefinition(pckgActionGroup, textType,
|
||||
"add_package_item_actions");
|
||||
properties.put(pckgActionGroup, pckgAction);
|
||||
|
||||
// Add a Package Action property
|
||||
QName pckgItemActionGroup = PROP_PACKAGE_ITEM_ACTION_GROUP;
|
||||
PropertyDefinition pckgItemAction = MockClassAttributeDefinition.mockPropertyDefinition(pckgItemActionGroup,
|
||||
textType, "start_package_item_actions");
|
||||
properties.put(pckgItemActionGroup, pckgItemAction);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private Map<QName, AssociationDefinition> makeTaskAssociationDefs()
|
||||
{
|
||||
Map<QName, AssociationDefinition> associations = new HashMap<QName, AssociationDefinition>();
|
||||
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();
|
||||
nsService.registerNamespace(NamespaceService.SYSTEM_MODEL_PREFIX, NamespaceService.SYSTEM_MODEL_1_0_URI);
|
||||
nsService.registerNamespace(NamespaceService.RENDITION_MODEL_PREFIX, NamespaceService.RENDITION_MODEL_1_0_URI);
|
||||
nsService.registerNamespace(NamespaceService.BPM_MODEL_PREFIX, NamespaceService.BPM_MODEL_1_0_URI);
|
||||
nsService.registerNamespace(NamespaceService.WORKFLOW_MODEL_PREFIX, NamespaceService.WORKFLOW_MODEL_1_0_URI);
|
||||
return nsService;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private DictionaryService makeDictionaryService()
|
||||
{
|
||||
DictionaryService mock = mock(DictionaryService.class);
|
||||
TypeDefinition taskTypeDef = definition.getStartTaskDefinition().getMetadata();
|
||||
when(mock.getAnonymousType((QName) any(), (Collection<QName>) any())).thenReturn(taskTypeDef);
|
||||
return mock;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private WorkflowService makeWorkflowService()
|
||||
{
|
||||
WorkflowService service = mock(WorkflowService.class);
|
||||
when(service.getDefinitionByName(WF_DEF_NAME)).thenReturn(definition);
|
||||
|
||||
String instanceId = "foo$instanceId";
|
||||
newInstance = new WorkflowInstance(instanceId,
|
||||
definition, null, null, null,
|
||||
null, true, null, null);
|
||||
WorkflowTask startTask = new WorkflowTask("foo$taskId", null, null, null, null, null, null, null);
|
||||
String pathId = "foo$pathId";
|
||||
final WorkflowPath path = new WorkflowPath(pathId, newInstance, null, true);
|
||||
|
||||
when(service.startWorkflow(eq(definition.getId()), anyMap()))
|
||||
.thenAnswer(new Answer<WorkflowPath>()
|
||||
{
|
||||
public WorkflowPath answer(InvocationOnMock invocation) throws Throwable
|
||||
{
|
||||
Object[] arguments = invocation.getArguments();
|
||||
actualProperties = (Map<QName, Serializable>) arguments[1];
|
||||
return path;
|
||||
}
|
||||
});
|
||||
when(service.getTasksForWorkflowPath(path.getId()))
|
||||
.thenReturn(Collections.singletonList(startTask));
|
||||
when(service.createPackage(null)).thenReturn(PCKG_NODE);
|
||||
return service;
|
||||
}
|
||||
|
||||
private NodeService makeNodeService()
|
||||
{
|
||||
NodeService service = mock(NodeService.class);
|
||||
when(service.hasAspect(PCKG_NODE, ASPECT_WORKFLOW_PACKAGE))
|
||||
.thenReturn(true);
|
||||
return service;
|
||||
}
|
||||
|
||||
}
|
@@ -1,334 +0,0 @@
|
||||
function testGetFormForNonExistentContentNode()
|
||||
{
|
||||
// Replace all the digits in the ID with an 'x'.
|
||||
// Surely that node will not exist...
|
||||
var corruptedTestDoc = testDoc.replace(/\d/g, "x");
|
||||
var form = null;
|
||||
|
||||
try
|
||||
{
|
||||
form = formService.getForm("node", corruptedTestDoc);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
|
||||
test.assertNull(form, "Form should have not been found: " + testDoc);
|
||||
}
|
||||
|
||||
function testGetFormForContentNode()
|
||||
{
|
||||
// Get a known form and check its various attributes/properties.
|
||||
var form = formService.getForm("node", testDoc);
|
||||
test.assertNotNull(form, "Form should have been found for: " + testDoc);
|
||||
|
||||
test.assertEquals("node", form.itemKind);
|
||||
test.assertEquals(testDoc, form.itemId);
|
||||
test.assertEquals('cm:content', form.itemType);
|
||||
test.assertEquals('/api/node/' + testDoc.replace(":/", ""), form.itemUrl);
|
||||
|
||||
test.assertNull(form.submissionUrl, "form.submissionUrl should be null.");
|
||||
|
||||
var fieldDefs = form.fieldDefinitions;
|
||||
test.assertNotNull(fieldDefs, "field definitions should not be null.");
|
||||
test.assertEquals(19, fieldDefs.length);
|
||||
|
||||
// as we know there are no duplicates we can safely create a map of the
|
||||
// field definitions for the purposes of this test
|
||||
var fieldDefnDataHash = {};
|
||||
var fieldDef = null;
|
||||
for (var x = 0; x < fieldDefs.length; x++)
|
||||
{
|
||||
fieldDef = fieldDefs[x];
|
||||
fieldDefnDataHash[fieldDef.name] = fieldDef;
|
||||
}
|
||||
|
||||
var nameField = fieldDefnDataHash['cm:name'];
|
||||
var titleField = fieldDefnDataHash['cm:title'];
|
||||
var descField = fieldDefnDataHash['cm:description'];
|
||||
var originatorField = fieldDefnDataHash['cm:originator'];
|
||||
var addresseeField = fieldDefnDataHash['cm:addressee'];
|
||||
var addresseesField = fieldDefnDataHash['cm:addressees'];
|
||||
var subjectField = fieldDefnDataHash['cm:subjectline'];
|
||||
var sentDateField = fieldDefnDataHash['cm:sentdate'];
|
||||
var referencesField = fieldDefnDataHash['cm:references'];
|
||||
|
||||
test.assertNotNull(nameField, "Expecting to find the cm:name field");
|
||||
test.assertNotNull(titleField, "Expecting to find the cm:title field");
|
||||
test.assertNotNull(descField, "Expecting to find the cm:description field");
|
||||
test.assertNotNull(originatorField, "Expecting to find the cm:originator field");
|
||||
test.assertNotNull(addresseeField, "Expecting to find the cm:addressee field");
|
||||
test.assertNotNull(addresseesField, "Expecting to find the cm:addressees field");
|
||||
test.assertNotNull(subjectField, "Expecting to find the cm:subjectline field");
|
||||
test.assertNotNull(sentDateField, "Expecting to find the cm:sentdate field");
|
||||
test.assertNotNull(referencesField, "Expecting to find the cm:references field");
|
||||
|
||||
// check the labels of all the fields
|
||||
test.assertEquals("Name", nameField.label);
|
||||
test.assertEquals("Title", titleField.label);
|
||||
test.assertEquals("Description", descField.label);
|
||||
test.assertEquals("Originator", originatorField.label);
|
||||
test.assertEquals("Addressee", addresseeField.label);
|
||||
test.assertEquals("Addressees", addresseesField.label);
|
||||
test.assertEquals("Subject", subjectField.label);
|
||||
test.assertEquals("Sent Date", sentDateField.label);
|
||||
test.assertEquals("References", referencesField.label);
|
||||
|
||||
// check details of name field
|
||||
test.assertEquals("text", nameField.dataType);
|
||||
test.assertTrue(nameField.mandatory);
|
||||
// Expecting cm:name to be single-valued.
|
||||
test.assertFalse(nameField.repeating, "nameField.repeating was not false.");
|
||||
|
||||
// get the constraint for the name field and check
|
||||
var constraints = nameField.constraints;
|
||||
test.assertEquals(1, constraints.size());
|
||||
var constraint = constraints.get(0);
|
||||
test.assertEquals("REGEX", constraint.type);
|
||||
var params = constraint.parameters;
|
||||
test.assertNotNull(params, "params should not be null.");
|
||||
test.assertEquals(2, params.length);
|
||||
test.assertNotNull(params["expression"], "params['expression'] should not be null.");
|
||||
test.assertNotNull(params["requiresMatch"], "params['requiresMatch'] should not be null.");
|
||||
|
||||
// check details of the addressees field
|
||||
test.assertEquals("text", addresseesField.dataType);
|
||||
test.assertFalse(addresseesField.mandatory, "addresseesField.mandatory was not false.");
|
||||
// Expecting cm:addressees to be multi-valued.
|
||||
test.assertTrue(addresseesField.repeating);
|
||||
|
||||
// check the details of the association field
|
||||
test.assertEquals("cm:content", referencesField.endpointType);
|
||||
|
||||
//TODO A raw comparison fails. Is this a JS vs. Java string?
|
||||
test.assertEquals("TARGET", "" + referencesField.endpointDirection);
|
||||
test.assertFalse(referencesField.endpointMandatory, "referencesField.endpointMandatory was not false.");
|
||||
test.assertTrue(referencesField.endpointMany, "referencesField.endpointMany was not true.");
|
||||
|
||||
// check the form data
|
||||
var formData = form.formData;
|
||||
test.assertNotNull(formData, "formData should not be null.");
|
||||
var fieldData = formData.data;
|
||||
test.assertNotNull(fieldData, "fieldData should not be null.");
|
||||
test.assertNotNull(fieldData.length, "fieldData.length should not be null.");
|
||||
|
||||
test.assertEquals(testDocName, fieldData[nameField.dataKeyName].value);
|
||||
test.assertEquals("This is the title for the test document", fieldData[titleField.dataKeyName].value);
|
||||
test.assertEquals("This is the description for the test document", fieldData[descField.dataKeyName].value);
|
||||
test.assertEquals("fred@customer.com", fieldData[originatorField.dataKeyName].value);
|
||||
test.assertEquals("bill@example.com", fieldData[addresseeField.dataKeyName].value);
|
||||
test.assertEquals("The subject is...", fieldData[subjectField.dataKeyName].value);
|
||||
|
||||
var addressees = fieldData[addresseesField.dataKeyName].value;
|
||||
test.assertNotNull(addressees);
|
||||
test.assertTrue(addressees.indexOf(",") != -1);
|
||||
var addresseesArr = addressees.split(",");
|
||||
test.assertEquals(2, addresseesArr.length);
|
||||
test.assertEquals("harry@example.com", addresseesArr[0]);
|
||||
test.assertEquals("jane@example.com", addresseesArr[1]);
|
||||
|
||||
var sentDate = fieldData[sentDateField.dataKeyName].getValue();
|
||||
test.assertTrue((typeof sentDate === "object"), "Expecting sentData to be an object");
|
||||
var month = sentDate.getMonth();
|
||||
test.assertTrue((month >= 0 && month < 12), "Expecting valid month");
|
||||
|
||||
var targets = fieldData[referencesField.dataKeyName].value;
|
||||
|
||||
test.assertNotNull(targets, "targets should not be null.");
|
||||
test.assertEquals(testAssociatedDoc, targets);
|
||||
}
|
||||
|
||||
function testGetFormForFolderNode()
|
||||
{
|
||||
// Get a known form and check its various attributes/properties.
|
||||
var form = formService.getForm("node", folder);
|
||||
test.assertNotNull(form, "Form should have been found for: " + testDoc);
|
||||
|
||||
test.assertEquals("node", form.itemKind);
|
||||
test.assertEquals(folder, form.itemId);
|
||||
test.assertEquals('cm:folder', form.itemType);
|
||||
test.assertEquals('/api/node/' + folder.replace(":/", ""), form.itemUrl);
|
||||
|
||||
test.assertNull(form.submissionUrl, "form.submissionUrl should be null.");
|
||||
|
||||
var fieldDefs = form.fieldDefinitions;
|
||||
test.assertNotNull(fieldDefs, "field definitions should not be null.");
|
||||
test.assertEquals(8, fieldDefs.length);
|
||||
|
||||
// as we know there are no duplicates we can safely create a map of the
|
||||
// field definitions for the purposes of this test
|
||||
var fieldDefnDataHash = {};
|
||||
var fieldDef = null;
|
||||
for (var x = 0; x < fieldDefs.length; x++)
|
||||
{
|
||||
fieldDef = fieldDefs[x];
|
||||
fieldDefnDataHash[fieldDef.name] = fieldDef;
|
||||
}
|
||||
|
||||
var nameField = fieldDefnDataHash['cm:name'];
|
||||
var containsField = fieldDefnDataHash['cm:contains'];
|
||||
|
||||
test.assertNotNull(nameField, "Expecting to find the cm:name field");
|
||||
test.assertNotNull(containsField, "Expecting to find the cm:contains field");
|
||||
|
||||
// check the labels of all the fields
|
||||
test.assertEquals("Name", nameField.label);
|
||||
test.assertEquals("Contains", containsField.label);
|
||||
|
||||
// check details of name field
|
||||
test.assertEquals("text", nameField.dataType);
|
||||
test.assertTrue(nameField.mandatory);
|
||||
// Expecting cm:name to be single-valued.
|
||||
test.assertFalse(nameField.repeating, "nameField.repeating was not false.");
|
||||
|
||||
// compare the association details
|
||||
test.assertEquals("TARGET", "" + containsField.endpointDirection);
|
||||
test.assertFalse(containsField.endpointMandatory, "containsField.endpointMandatory was not false.");
|
||||
test.assertTrue(containsField.endpointMany, "constainsField.endpointMany was not true.");
|
||||
|
||||
// check the form data
|
||||
var formData = form.formData;
|
||||
test.assertNotNull(formData, "formData should not be null.");
|
||||
var fieldData = formData.data;
|
||||
test.assertNotNull(fieldData, "fieldData should not be null.");
|
||||
test.assertNotNull(fieldData.length, "fieldData.length should not be null.");
|
||||
|
||||
test.assertEquals(folderName, fieldData[nameField.dataKeyName].value);
|
||||
var children = fieldData[containsField.dataKeyName].value;
|
||||
test.assertNotNull(children, "children should not be null.");
|
||||
var childrenArr = children.split(",");
|
||||
test.assertTrue(childrenArr.length == 3, "Expecting there to be 3 children");
|
||||
}
|
||||
|
||||
function testGetFormWithSelectedFields()
|
||||
{
|
||||
// Define list of fields to retrieve
|
||||
var fields = [];
|
||||
fields.push("cm:name");
|
||||
fields.push("cm:title");
|
||||
fields.push("mimetype");
|
||||
fields.push("cm:modified");
|
||||
// add field that will be missing
|
||||
fields.push("cm:author");
|
||||
|
||||
// Get a a form for the given fields
|
||||
var form = formService.getForm("node", testDoc, fields);
|
||||
test.assertNotNull(form, "Form should have been found for: " + testDoc);
|
||||
|
||||
var fieldDefs = form.fieldDefinitions;
|
||||
test.assertNotNull(fieldDefs, "field definitions should not be null.");
|
||||
test.assertEquals(4, fieldDefs.length);
|
||||
|
||||
// as we know there are no duplicates we can safely create a map of the
|
||||
// field definitions for the purposes of this test
|
||||
var fieldDefnDataHash = {};
|
||||
var fieldDef = null;
|
||||
for (var x = 0; x < fieldDefs.length; x++)
|
||||
{
|
||||
fieldDef = fieldDefs[x];
|
||||
fieldDefnDataHash[fieldDef.name] = fieldDef;
|
||||
}
|
||||
|
||||
var nameField = fieldDefnDataHash['cm:name'];
|
||||
var titleField = fieldDefnDataHash['cm:title'];
|
||||
var mimetypeField = fieldDefnDataHash['mimetype'];
|
||||
var modifiedField = fieldDefnDataHash['cm:modified'];
|
||||
var authorField = fieldDefnDataHash['cm:author'];
|
||||
|
||||
test.assertNotNull(nameField, "Expecting to find the cm:name field");
|
||||
test.assertNotNull(titleField, "Expecting to find the cm:title field");
|
||||
test.assertNotNull(mimetypeField, "Expecting to find the mimetype field");
|
||||
test.assertNotNull(modifiedField, "Expecting to find the cm:modified field");
|
||||
test.assertTrue(authorField === undefined, "Expecting cm:author field to be missing");
|
||||
|
||||
// check the labels of all the fields
|
||||
test.assertEquals("Name", nameField.label);
|
||||
test.assertEquals("Title", titleField.label);
|
||||
test.assertEquals("Mimetype", mimetypeField.label);
|
||||
test.assertEquals("Modified Date", modifiedField.label);
|
||||
|
||||
// check the form data
|
||||
var formData = form.formData;
|
||||
test.assertNotNull(formData, "formData should not be null.");
|
||||
var fieldData = formData.data;
|
||||
test.assertNotNull(fieldData, "fieldData should not be null.");
|
||||
test.assertNotNull(fieldData.length, "fieldData.length should not be null.");
|
||||
|
||||
test.assertEquals(testDocName, fieldData[nameField.dataKeyName].value);
|
||||
test.assertEquals("This is the title for the test document", fieldData[titleField.dataKeyName].value);
|
||||
}
|
||||
|
||||
function testGetFormWithForcedFields()
|
||||
{
|
||||
// Define list of fields to retrieve
|
||||
var fields = [];
|
||||
fields.push("cm:name");
|
||||
fields.push("cm:title");
|
||||
fields.push("mimetype");
|
||||
fields.push("cm:modified");
|
||||
fields.push("cm:author");
|
||||
fields.push("cm:wrong");
|
||||
|
||||
// define a list of fields to force
|
||||
var force = [];
|
||||
force.push("cm:author");
|
||||
force.push("cm:wrong");
|
||||
|
||||
// Get a a form for the given fields
|
||||
var form = formService.getForm("node", testDoc, fields, force);
|
||||
test.assertNotNull(form, "Form should have been found for: " + testDoc);
|
||||
|
||||
var fieldDefs = form.fieldDefinitions;
|
||||
test.assertNotNull(fieldDefs, "field definitions should not be null.");
|
||||
test.assertEquals(5, fieldDefs.length);
|
||||
|
||||
// as we know there are no duplicates we can safely create a map of the
|
||||
// field definitions for the purposes of this test
|
||||
var fieldDefnDataHash = {};
|
||||
var fieldDef = null;
|
||||
for (var x = 0; x < fieldDefs.length; x++)
|
||||
{
|
||||
fieldDef = fieldDefs[x];
|
||||
fieldDefnDataHash[fieldDef.name] = fieldDef;
|
||||
}
|
||||
|
||||
var nameField = fieldDefnDataHash['cm:name'];
|
||||
var titleField = fieldDefnDataHash['cm:title'];
|
||||
var mimetypeField = fieldDefnDataHash['mimetype'];
|
||||
var modifiedField = fieldDefnDataHash['cm:modified'];
|
||||
var authorField = fieldDefnDataHash['cm:author'];
|
||||
var wrongField = fieldDefnDataHash['cm:wrong'];
|
||||
|
||||
test.assertNotNull(nameField, "Expecting to find the cm:name field");
|
||||
test.assertNotNull(titleField, "Expecting to find the cm:title field");
|
||||
test.assertNotNull(mimetypeField, "Expecting to find the mimetype field");
|
||||
test.assertNotNull(modifiedField, "Expecting to find the cm:modified field");
|
||||
test.assertNotNull(authorField, "Expecting to find the cm:author field");
|
||||
test.assertTrue(wrongField === undefined, "Expecting cm:wrong field to be missing");
|
||||
|
||||
// check the labels of all the fields
|
||||
test.assertEquals("Name", nameField.label);
|
||||
test.assertEquals("Title", titleField.label);
|
||||
test.assertEquals("Mimetype", mimetypeField.label);
|
||||
test.assertEquals("Modified Date", modifiedField.label);
|
||||
test.assertEquals("Author", authorField.label);
|
||||
|
||||
// check the form data
|
||||
var formData = form.formData;
|
||||
test.assertNotNull(formData, "formData should not be null.");
|
||||
var fieldData = formData.data;
|
||||
test.assertNotNull(fieldData, "fieldData should not be null.");
|
||||
test.assertNotNull(fieldData.length, "fieldData.length should not be null.");
|
||||
|
||||
test.assertEquals(testDocName, fieldData[nameField.dataKeyName].value);
|
||||
test.assertEquals("This is the title for the test document", fieldData[titleField.dataKeyName].value);
|
||||
test.assertNull(fieldData[authorField.dataKeyName], "Expecting cm:author to be null");
|
||||
}
|
||||
|
||||
// Execute tests
|
||||
testGetFormForNonExistentContentNode();
|
||||
testGetFormForContentNode();
|
||||
testGetFormForFolderNode();
|
||||
testGetFormWithSelectedFields();
|
||||
testGetFormWithForcedFields();
|
Reference in New Issue
Block a user