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:
Samuel Langlois
2013-08-20 17:17:31 +00:00
parent 0a36e2af67
commit ab4ca7177f
1576 changed files with 36419 additions and 8603 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}
});
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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)
*/

View File

@@ -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;
}
}

View File

@@ -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"));
}
}

View File

@@ -65,6 +65,8 @@ public class TaskFormProcessor extends AbstractWorkflowFormProcessor<WorkflowTas
{
super();
}
// Constructor for tests.
public TaskFormProcessor(WorkflowService workflowService, NamespaceService namespaceService,

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();