From 9bec2b070be9cdba66ea83b5e1488bf3d8c57a54 Mon Sep 17 00:00:00 2001 From: Gavin Cornwell Date: Wed, 14 Jul 2010 22:20:54 +0000 Subject: [PATCH] Merged BRANCHES/DEV/BELARUS/HEAD-2010_07_09 to HEAD (with modifications) 21156: Implemented GET /api/task-instances/{task_instance_id} git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21181 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../workflow/task-instance.get.desc.xml | 8 + .../workflow/task-instance.get.json.ftl | 6 + .../workflow/task-instances.get.json.ftl | 2 +- .../alfresco/repository/workflow/task.lib.ftl | 55 +++++- .../web-scripts-application-context.xml | 5 + .../web/scripts/workflow/TaskInstanceGet.java | 59 +++++++ .../workflow/WorkflowModelBuilder.java | 162 +++++++++++++++--- .../workflow/WorkflowModelBuilderTest.java | 105 +++++++++++- .../scripts/workflow/WorkflowRestApiTest.java | 112 +++++++++++- 9 files changed, 462 insertions(+), 52 deletions(-) create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instance.get.desc.xml create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instance.get.json.ftl create mode 100644 source/java/org/alfresco/repo/web/scripts/workflow/TaskInstanceGet.java diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instance.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instance.get.desc.xml new file mode 100644 index 0000000000..79b0864287 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instance.get.desc.xml @@ -0,0 +1,8 @@ + + Gets Workflow Task Instance + Gets the details of a task. + /api/task-instances/{task_instance_id} + + user + required + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instance.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instance.get.json.ftl new file mode 100644 index 0000000000..557cbd0d2d --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instance.get.json.ftl @@ -0,0 +1,6 @@ +<#-- Workflow Task Instance in details --> + +<#import "task.lib.ftl" as taskLib /> +{ + "data": <@taskLib.taskJSON task=workflowTask detailed=true/> +} \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instances.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instances.get.json.ftl index ecbe22df49..7bd20c283c 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instances.get.json.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task-instances.get.json.ftl @@ -5,7 +5,7 @@ "data": [ <#list taskInstances as task> - <@taskLib.taskJSON task=task /> + <@taskLib.taskJSON task=task detailed=false /> <#if task_has_next>, ] diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task.lib.ftl index cb983462ae..8c2ab048d5 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task.lib.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/task.lib.ftl @@ -1,5 +1,6 @@ <#-- Renders a task instance. --> -<#macro taskJSON task > +<#macro taskJSON task detailed=false> +<#escape x as jsonUtils.encodeJSONString(x)> { "id": "${task.id}", "url": "${task.url}", @@ -17,20 +18,57 @@ "lastName": "${task.owner.lastName}" }, <#else> - null, + null, "properties": <@propertiesJSON properties=task.properties /> - } + <#if detailed>, + "path": "${task.path}", + "definition": + { + "id": "${task.definition.id}", + "url": "${task.definition.url}", + "type": + { + "name": "${shortQName(task.definition.type.name?string)}", + "title": "${task.definition.type.title}", + "description": "${task.definition.type.description}", + "url": "${task.definition.type.url}" + }, + "node": + { + "name": "${task.definition.node.name}", + "title": "${task.definition.node.title}", + "description": "${task.definition.node.description}", + "isTaskNode": ${task.definition.node.isTaskNode?string}, + "transitions": + [ + <#list task.definition.node.transitions as transition> + { + "id": "${transition.id}", + "title": "${transition.title}", + "description": "${transition.description}", + "isDefault": ${transition.isDefault?string}, + "isHidden": ${transition.isHidden?string} + } + <#if transition_has_next>, + + ] + } + } + + } + <#-- Renders a map of properties --> <#macro propertiesJSON properties> - { - <#list properties?keys as key> - "${key}" : - <#if properties[key]??> - <#assign val=properties[key]> +<#escape x as jsonUtils.encodeJSONString(x)> + { + <#list properties?keys as key> + "${key}": + <#if properties[key]??> + <#assign val=properties[key]> <#if val?is_boolean == true> ${val?string} <#elseif val?is_number == true> @@ -50,4 +88,5 @@ <#if (key_has_next)>, } + diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index 24e3a3a87e..f18f5a79b7 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -789,6 +789,11 @@ parent="abstractWorkflowWebScript"> + + + . + */ +package org.alfresco.repo.web.scripts.workflow; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.service.cmr.workflow.WorkflowTask; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * @author unknown + * + */ +public class TaskInstanceGet extends AbstractWorkflowWebscript +{ + + @Override + protected Map buildModel(WorkflowModelBuilder modelBuilder, WebScriptRequest req, Status status, Cache cache) + { + Map params = req.getServiceMatch().getTemplateVars(); + + String taskId = params.get("task_instance_id"); + + WorkflowTask workflowTask = workflowService.getTaskById(taskId); + + if (workflowTask == null) + { + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find workflow task with id: " + taskId); + } + + Map model = new HashMap(); + model.put("workflowTask", modelBuilder.buildDetailed(workflowTask)); + + return model; + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilder.java b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilder.java index f09747e6e8..412e90de97 100644 --- a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilder.java +++ b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilder.java @@ -32,12 +32,16 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; +import org.alfresco.service.cmr.workflow.WorkflowNode; import org.alfresco.service.cmr.workflow.WorkflowTask; +import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition; +import org.alfresco.service.cmr.workflow.WorkflowTransition; import org.alfresco.service.namespace.NamespaceException; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -62,18 +66,42 @@ public class WorkflowModelBuilder public static final String TASK_URL = "url"; public static final String TASK_IS_POOLED = "isPooled"; public static final String TASK_ID = "id"; - + public static final String TASK_PATH = "path"; + public static final String TASK_DEFINITION = "definition"; + + public static final String TASK_DEFINITION_ID = "id"; + public static final String TASK_DEFINITION_URL = "url"; + public static final String TASK_DEFINITION_TYPE = "type"; + public static final String TASK_DEFINITION_NODE = "node"; + + public static final String TYPE_DEFINITION_NAME = "name"; + public static final String TYPE_DEFINITION_TITLE = "title"; + public static final String TYPE_DEFINITION_DESCRIPTION = "description"; + public static final String TYPE_DEFINITION_URL = "url"; + + public static final String WORKFLOW_NODE_NAME = "name"; + public static final String WORKFLOW_NODE_TITLE = "title"; + public static final String WORKFLOW_NODE_DESCRIPTION = "description"; + public static final String WORKFLOW_NODE_IS_TASK_NODE = "isTaskNode"; + public static final String WORKFLOW_NODE_TRANSITIONS = "transitions"; + + public static final String WORKFLOW_NODE_TRANSITION_ID = "id"; + public static final String WORKFLOW_NODE_TRANSITION_TITLE = "title"; + public static final String WORKFLOW_NODE_TRANSITION_DESCRIPTION = "description"; + public static final String WORKFLOW_NODE_TRANSITION_IS_DEFAULT = "isDefault"; + public static final String WORKFLOW_NODE_TRANSITION_IS_HIDDEN = "isHidden"; + public static final String WORKFLOW_DEFINITION_ID = "id"; public static final String WORKFLOW_DEFINITION_URL = "url"; public static final String WORKFLOW_DEFINITION_NAME = "name"; public static final String WORKFLOW_DEFINITION_TITLE = "title"; public static final String WORKFLOW_DEFINITION_DESCRIPTION = "description"; - + private static final String PREFIX_SEPARATOR = Character.toString(QName.NAMESPACE_PREFIX); private final NamespaceService namespaceService; - private final NodeService nodeService; - private final PersonService personService; + private final NodeService nodeService; + private final PersonService personService; public WorkflowModelBuilder(NamespaceService namespaceService, NodeService nodeService, PersonService personService) { @@ -102,11 +130,28 @@ public class WorkflowModelBuilder model.put(TASK_IS_POOLED, isPooled(task.properties)); Serializable owner = task.properties.get(ContentModel.PROP_OWNER); model.put(TASK_OWNER, getPersonModel((String) owner)); - + model.put(TASK_PROPERTIES, buildProperties(task, propertyFilters)); return model; } + /** + * Returns a detailed representation of a {@link WorkflowTask}. + * @param workflowTask The task to be represented. + * @return + */ + public Map buildDetailed(WorkflowTask workflowTask) + { + Map model = buildSimple(workflowTask, null); + + model.put(TASK_PATH, getUrl(workflowTask) + "/paths/" + workflowTask.path.id); + + // definition part + model.put(TASK_DEFINITION, buildTaskDefinition(workflowTask.definition, workflowTask)); + + return model; + } + /** * Returns a simple representation of a {@link WorkflowDefinition}. * @@ -116,20 +161,20 @@ public class WorkflowModelBuilder public Map buildSimple(WorkflowDefinition workflowDefinition) { HashMap model = new HashMap(); - + model.put(WORKFLOW_DEFINITION_ID, workflowDefinition.id); model.put(WORKFLOW_DEFINITION_URL, getUrl(workflowDefinition)); model.put(WORKFLOW_DEFINITION_NAME, workflowDefinition.name); model.put(WORKFLOW_DEFINITION_TITLE, workflowDefinition.title); - model.put(WORKFLOW_DEFINITION_DESCRIPTION, workflowDefinition.description); - + model.put(WORKFLOW_DEFINITION_DESCRIPTION, workflowDefinition.description); + return model; } private Object isPooled(Map properties) { Collection actors = (Collection) properties.get(WorkflowModel.ASSOC_POOLED_ACTORS); - return actors!=null && !actors.isEmpty(); + return actors != null && !actors.isEmpty(); } private Map buildProperties(WorkflowTask task, Collection propertyFilters) @@ -166,18 +211,15 @@ public class WorkflowModelBuilder private Object convertValue(Object value) { - if(value == null - || value instanceof Boolean - || value instanceof Number - || value instanceof String) + if (value == null || value instanceof Boolean || value instanceof Number || value instanceof String) { return value; } - if(value instanceof Collection) + if (value instanceof Collection) { - Collection collection = (Collection)value; + Collection collection = (Collection) value; ArrayList results = new ArrayList(collection.size()); - for (Object obj : collection) + for (Object obj : collection) { results.add(convertValue(obj)); } @@ -189,16 +231,17 @@ public class WorkflowModelBuilder private Collection buildQNameKeys(Collection keys) { List qKeys = new ArrayList(keys.size()); - for (String key : keys) + for (String key : keys) { String prefixedName = key.replaceFirst("_", PREFIX_SEPARATOR); try { QName qKey = QName.createQName(prefixedName, namespaceService); qKeys.add(qKey); - } catch(NamespaceException e) + } + catch (NamespaceException e) { - throw new AlfrescoRuntimeException("Invalid property key: "+key, e); + throw new AlfrescoRuntimeException("Invalid property key: " + key, e); } } return qKeys; @@ -221,14 +264,69 @@ public class WorkflowModelBuilder return model; } -// private String getURl(WorkflowPath path) -// { -// StringBuilder builder = new StringBuilder("api/workflow-instances/"); -// builder.append(path.instance.id); -// builder.append("/paths/"); -// builder.append(path.id); -// return builder.toString(); -// } + private Map buildTaskDefinition(WorkflowTaskDefinition workflowTaskDefinition, WorkflowTask workflowTask) + { + Map model = new HashMap(); + + model.put(TASK_DEFINITION_ID, workflowTaskDefinition.id); + model.put(TASK_DEFINITION_URL, getUrl(workflowTaskDefinition)); + model.put(TASK_DEFINITION_TYPE, buildTypeDefinition(workflowTaskDefinition.metadata)); + model.put(TASK_DEFINITION_NODE, buildWorkflowNode(workflowTaskDefinition.node, workflowTask)); + + return model; + } + + private Map buildTypeDefinition(TypeDefinition typeDefinition) + { + Map model = new HashMap(); + + model.put(TYPE_DEFINITION_NAME, typeDefinition.getName()); + model.put(TYPE_DEFINITION_TITLE, typeDefinition.getTitle()); + model.put(TYPE_DEFINITION_DESCRIPTION, typeDefinition.getDescription()); + model.put(TYPE_DEFINITION_URL, getUrl(typeDefinition)); + + return model; + } + + private Map buildWorkflowNode(WorkflowNode workflowNode, WorkflowTask workflowTask) + { + Map model = new HashMap(); + + model.put(WORKFLOW_NODE_NAME, workflowNode.name); + model.put(WORKFLOW_NODE_TITLE, workflowNode.title); + model.put(WORKFLOW_NODE_DESCRIPTION, workflowNode.description); + model.put(WORKFLOW_NODE_IS_TASK_NODE, workflowNode.isTaskNode); + + List> results = new ArrayList>(); + + Object hiddenTransitions = workflowTask.properties.get(WorkflowModel.PROP_HIDDEN_TRANSITIONS); + + for (WorkflowTransition workflowTransition : workflowNode.transitions) + { + Map transitionMap = new HashMap(); + + transitionMap.put(WORKFLOW_NODE_TRANSITION_ID, workflowTransition.id); + transitionMap.put(WORKFLOW_NODE_TRANSITION_TITLE, workflowTransition.title); + transitionMap.put(WORKFLOW_NODE_TRANSITION_DESCRIPTION, workflowTransition.description); + transitionMap.put(WORKFLOW_NODE_TRANSITION_IS_DEFAULT, workflowTransition.isDefault); + transitionMap.put(WORKFLOW_NODE_TRANSITION_IS_HIDDEN, (hiddenTransitions == null ? false : hiddenTransitions.toString().contains(workflowTransition.id))); + + results.add(transitionMap); + } + + model.put(WORKFLOW_NODE_TRANSITIONS, results); + + return model; + } + + // private String getURl(WorkflowPath path) + // { + // StringBuilder builder = new StringBuilder("api/workflow-instances/"); + // builder.append(path.instance.id); + // builder.append("/paths/"); + // builder.append(path.id); + // return builder.toString(); + // } private String getUrl(WorkflowTask task) { @@ -240,4 +338,14 @@ public class WorkflowModelBuilder return "api/workflow-definitions/" + workflowDefinition.id; } + private String getUrl(WorkflowTaskDefinition workflowTaskDefinition) + { + return "api/task-definitions/" + workflowTaskDefinition.id; + } + + private String getUrl(TypeDefinition typeDefinition) + { + return "api/classes/" + typeDefinition.getName().toPrefixString().replace(PREFIX_SEPARATOR, "_"); + } + } diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilderTest.java b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilderTest.java index decfa31ebe..464e84c8ff 100644 --- a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilderTest.java +++ b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilderTest.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import junit.framework.TestCase; @@ -38,9 +39,12 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; +import org.alfresco.service.cmr.workflow.WorkflowNode; +import org.alfresco.service.cmr.workflow.WorkflowPath; 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; @@ -92,7 +96,7 @@ public class WorkflowModelBuilderTest extends TestCase Object id = model.get(WorkflowModelBuilder.TASK_ID); assertEquals(task.id, id); Object url = model.get(WorkflowModelBuilder.TASK_URL); - assertEquals("api/task-instances/"+task.id, url); + assertEquals("api/task-instances/" + task.id, url); assertEquals(task.name, model.get(WorkflowModelBuilder.TASK_NAME)); assertEquals(task.title, model.get(WorkflowModelBuilder.TASK_TITLE)); assertEquals(task.description, model.get(WorkflowModelBuilder.TASK_DESCRIPTION)); @@ -101,9 +105,9 @@ public class WorkflowModelBuilderTest extends TestCase assertEquals(false, model.get(WorkflowModelBuilder.TASK_IS_POOLED)); Map owner = (Map) model.get(WorkflowModelBuilder.TASK_OWNER); - assertEquals( userName, owner.get(WorkflowModelBuilder.PERSON_USER_NAME)); - assertEquals( firstName, owner.get(WorkflowModelBuilder.PERSON_FIRST_NAME)); - assertEquals( lastName, owner.get(WorkflowModelBuilder.PERSON_LAST_NAME)); + assertEquals(userName, owner.get(WorkflowModelBuilder.PERSON_USER_NAME)); + assertEquals(firstName, owner.get(WorkflowModelBuilder.PERSON_FIRST_NAME)); + assertEquals(lastName, owner.get(WorkflowModelBuilder.PERSON_LAST_NAME)); Map props = (Map) model.get(WorkflowModelBuilder.TASK_PROPERTIES); assertEquals(task.properties.size(), props.size()); @@ -126,7 +130,7 @@ public class WorkflowModelBuilderTest extends TestCase model = builder.buildSimple(task, Arrays.asList("test_int", "test_string")); //Check task owner still created properly. owner = (Map) model.get(WorkflowModelBuilder.TASK_OWNER); - assertEquals( userName, owner.get(WorkflowModelBuilder.PERSON_USER_NAME)); + assertEquals(userName, owner.get(WorkflowModelBuilder.PERSON_USER_NAME)); // Check properties populated correctly props = (Map) model.get(WorkflowModelBuilder.TASK_PROPERTIES); @@ -134,12 +138,99 @@ public class WorkflowModelBuilderTest extends TestCase assertEquals(5, props.get("test_int")); assertEquals("foo bar", props.get("test_string")); } + + @SuppressWarnings("unchecked") + public void testBuildWorkflowTaskDetailed() throws Exception + { + WorkflowTask workflowTask = new WorkflowTask(); + workflowTask.id = "testId$1"; + workflowTask.name = "Task Name"; + workflowTask.title = "Task Title"; + workflowTask.description = "The Description"; + workflowTask.state = WorkflowTaskState.IN_PROGRESS; + + workflowTask.path = new WorkflowPath(); + workflowTask.path.id = "pathId$1"; + + workflowTask.definition = new WorkflowTaskDefinition(); + workflowTask.definition.id = "The Definition Id"; + workflowTask.definition.metadata = mock(TypeDefinition.class); + when(workflowTask.definition.metadata.getName()).thenReturn(QName.createQName("The Type Name")); + when(workflowTask.definition.metadata.getTitle()).thenReturn("The Type Title"); + when(workflowTask.definition.metadata.getDescription()).thenReturn("The Type Description"); + + WorkflowNode workflowNode = new WorkflowNode(); + workflowNode.name = "The Node Name"; + workflowNode.title = "The Node Title"; + workflowNode.description = "The Node Description"; + workflowNode.isTaskNode = true; + WorkflowTransition workflowTransition = new WorkflowTransition(); + workflowTransition.id = "The Transition Id"; + workflowTransition.title = "The Transition Title"; + workflowTransition.description = "The Transition Description"; + workflowTransition.isDefault = true; + workflowNode.transitions = new WorkflowTransition[] { workflowTransition }; + workflowTask.definition.node = workflowNode; + + workflowTask.properties = new HashMap(); + workflowTask.properties.put(ContentModel.PROP_OWNER, userName); + + Map model = builder.buildDetailed(workflowTask); + + Object id = model.get(WorkflowModelBuilder.TASK_ID); + assertEquals(workflowTask.id, id); + Object url = model.get(WorkflowModelBuilder.TASK_URL); + assertEquals("api/task-instances/" + workflowTask.id, url); + assertEquals(workflowTask.name, model.get(WorkflowModelBuilder.TASK_NAME)); + assertEquals(workflowTask.title, model.get(WorkflowModelBuilder.TASK_TITLE)); + assertEquals(workflowTask.description, model.get(WorkflowModelBuilder.TASK_DESCRIPTION)); + assertEquals(workflowTask.state.name(), model.get(WorkflowModelBuilder.TASK_STATE)); + assertEquals(workflowTask.definition.metadata.getTitle(), model.get(WorkflowModelBuilder.TASK_TYPE_DEFINITION_TITLE)); + assertEquals(false, model.get(WorkflowModelBuilder.TASK_IS_POOLED)); + + Map owner = (Map) model.get(WorkflowModelBuilder.TASK_OWNER); + assertEquals(userName, owner.get(WorkflowModelBuilder.PERSON_USER_NAME)); + assertEquals(firstName, owner.get(WorkflowModelBuilder.PERSON_FIRST_NAME)); + assertEquals(lastName, owner.get(WorkflowModelBuilder.PERSON_LAST_NAME)); + + Map props = (Map) model.get(WorkflowModelBuilder.TASK_PROPERTIES); + assertEquals(workflowTask.properties.size(), props.size()); + + Map definition = (Map) model.get(WorkflowModelBuilder.TASK_DEFINITION); + + assertEquals(workflowTask.definition.id, definition.get(WorkflowModelBuilder.TASK_DEFINITION_ID)); + + Map type = (Map) definition.get(WorkflowModelBuilder.TASK_DEFINITION_TYPE); + + assertEquals(workflowTask.definition.metadata.getName(), type.get(WorkflowModelBuilder.TYPE_DEFINITION_NAME)); + assertEquals(workflowTask.definition.metadata.getTitle(), type.get(WorkflowModelBuilder.TYPE_DEFINITION_TITLE)); + assertEquals(workflowTask.definition.metadata.getDescription(), type.get(WorkflowModelBuilder.TYPE_DEFINITION_DESCRIPTION)); + + Map node = (Map) definition.get(WorkflowModelBuilder.TASK_DEFINITION_NODE); + + assertEquals(workflowTask.definition.node.name, node.get(WorkflowModelBuilder.WORKFLOW_NODE_NAME)); + assertEquals(workflowTask.definition.node.title, node.get(WorkflowModelBuilder.WORKFLOW_NODE_TITLE)); + assertEquals(workflowTask.definition.node.description, node.get(WorkflowModelBuilder.WORKFLOW_NODE_DESCRIPTION)); + assertEquals(workflowTask.definition.node.isTaskNode, node.get(WorkflowModelBuilder.WORKFLOW_NODE_IS_TASK_NODE)); + + List> transitions = (List>) node.get(WorkflowModelBuilder.WORKFLOW_NODE_TRANSITIONS); + + int i = 0; + for (Map transition : transitions) + { + assertEquals(workflowTask.definition.node.transitions[i].id, transition.get(WorkflowModelBuilder.WORKFLOW_NODE_TRANSITION_ID)); + assertEquals(workflowTask.definition.node.transitions[i].title, transition.get(WorkflowModelBuilder.WORKFLOW_NODE_TRANSITION_TITLE)); + assertEquals(workflowTask.definition.node.transitions[i].description, transition.get(WorkflowModelBuilder.WORKFLOW_NODE_TRANSITION_DESCRIPTION)); + assertEquals(workflowTask.definition.node.transitions[i].isDefault, transition.get(WorkflowModelBuilder.WORKFLOW_NODE_TRANSITION_IS_DEFAULT)); + assertEquals(false, transition.get(WorkflowModelBuilder.WORKFLOW_NODE_TRANSITION_IS_HIDDEN)); + i++; + } + } public void testBuildWorkflowDefinition() throws Exception { WorkflowTaskDefinition workflowTaskDefinition = new WorkflowTaskDefinition(); - WorkflowDefinition workflowDefinition = new WorkflowDefinition( - "The Id", "The Name", "The Version", "The Title", "The Description", workflowTaskDefinition); + WorkflowDefinition workflowDefinition = new WorkflowDefinition("The Id", "The Name", "The Version", "The Title", "The Description", workflowTaskDefinition); Map model = builder.buildSimple(workflowDefinition); assertEquals(workflowDefinition.id, model.get(WorkflowModelBuilder.WORKFLOW_DEFINITION_ID)); diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowRestApiTest.java b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowRestApiTest.java index f8ce6a0937..75a321e679 100644 --- a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowRestApiTest.java +++ b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowRestApiTest.java @@ -27,15 +27,19 @@ import java.util.Map; import org.alfresco.repo.security.person.TestPersonManager; import org.alfresco.repo.web.scripts.BaseWebScriptTest; import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; +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.QName; import org.alfresco.util.GUID; import org.json.JSONArray; @@ -51,9 +55,9 @@ import org.springframework.extensions.webscripts.TestWebScriptServer.Response; */ public class WorkflowRestApiTest extends BaseWebScriptTest { - private final static String USER1 = "Bob"+GUID.generate(); - private final static String USER2 = "Jane"+GUID.generate(); - private static final String URL_TASKS = "api/task-instance"; + private final static String USER1 = "Bob" + GUID.generate(); + private final static String USER2 = "Jane" + GUID.generate(); + private static final String URL_TASKS = "api/task-instances"; private static final String URL_WORKFLOW_DEFINITIONS = "api/workflow-definitions"; private TestPersonManager personManager; @@ -70,9 +74,9 @@ public class WorkflowRestApiTest extends BaseWebScriptTest JSONObject json = new JSONObject(jsonStr); JSONArray results = json.getJSONArray("data"); assertNotNull(results); - assertTrue(results.length()==0); + assertTrue(results.length() == 0); - //Start workflow as USER1 and assign task to USER2. + // Start workflow as USER1 and assign task to USER2. personManager.setUser(USER1); WorkflowDefinition adhocDef = workflowService.getDefinitionByName("jbpm$wf:adhoc"); Map params = new HashMap(); @@ -97,10 +101,10 @@ public class WorkflowRestApiTest extends BaseWebScriptTest json = new JSONObject(jsonStr); results = json.getJSONArray("data"); assertNotNull(results); - assertTrue(results.length()==tasks.size()); + assertTrue(results.length() == tasks.size()); JSONObject result = results.getJSONObject(0); - String expUrl = "api/task-instance/"+task.id; + String expUrl = "api/task-instances/" + task.id; assertEquals(expUrl, result.getString("url")); assertEquals(task.name, result.getString("name")); assertEquals(task.title, result.getString("title")); @@ -118,6 +122,96 @@ public class WorkflowRestApiTest extends BaseWebScriptTest //TODO Add more tests to check property filtering and pooled actors. } + + public void testTaskInstanceGet() throws Exception + { + //Start workflow as USER1 and assign task to USER2. + personManager.setUser(USER1); + WorkflowDefinition adhocDef = workflowService.getDefinitionByName("jbpm$wf:adhoc"); + Map params = new HashMap(); + params.put(WorkflowModel.ASSOC_ASSIGNEE, personManager.get(USER2)); + params.put(WorkflowModel.PROP_DUE_DATE, new Date()); + params.put(WorkflowModel.PROP_PRIORITY, 1); + params.put(WorkflowModel.ASSOC_PACKAGE, packageRef); + + WorkflowPath adhocPath = workflowService.startWorkflow(adhocDef.id, params); + WorkflowTask startTask = workflowService.getTasksForWorkflowPath(adhocPath.id).get(0); + + Response response = sendRequest(new GetRequest(URL_TASKS + "/" + startTask.id), 200); + assertEquals(Status.STATUS_OK, response.getStatus()); + String jsonStr = response.getContentAsString(); + JSONObject json = new JSONObject(jsonStr); + JSONObject result = json.getJSONObject("data"); + assertNotNull(result); + + assertEquals(startTask.id, result.getString("id")); + assertEquals(URL_TASKS + "/" + startTask.id, result.getString("url")); + assertEquals(startTask.name, result.getString("name")); + assertEquals(startTask.title, result.getString("title")); + assertEquals(startTask.description, result.getString("description")); + assertEquals(startTask.state.name(), result.getString("state")); + assertEquals(URL_TASKS + "/" + startTask.id + "/paths/" + adhocPath.id, result.getString("path")); + assertEquals(false, result.getBoolean("isPooled")); + + JSONObject owner = result.getJSONObject("owner"); + assertEquals(USER1, owner.getString("userName")); + assertEquals(personManager.getFirstName(USER1), owner.getString("firstName")); + assertEquals(personManager.getLastName(USER1), owner.getString("lastName")); + + JSONObject properties = result.getJSONObject("properties"); + + assertNotNull(properties); + + JSONObject definition = result.getJSONObject("definition"); + WorkflowTaskDefinition startDefinitiont = startTask.definition; + + assertNotNull(definition); + + assertEquals(startDefinitiont.id, definition.getString("id")); + assertTrue(definition.has("url")); + + JSONObject type = definition.getJSONObject("type"); + TypeDefinition startType = startDefinitiont.metadata; + + assertNotNull(type); + + assertEquals(startType.getName().toPrefixString(), type.getString("name")); + assertEquals(startType.getTitle(), type.getString("title")); + assertEquals(startType.getDescription(), type.getString("description")); + assertTrue(type.has("url")); + + JSONObject node = definition.getJSONObject("node"); + WorkflowNode startNode = startDefinitiont.node; + + assertNotNull(node); + + assertEquals(startNode.name, node.getString("name")); + assertEquals(startNode.title, node.getString("title")); + assertEquals(startNode.description, node.getString("description")); + assertEquals(startNode.isTaskNode, node.getBoolean("isTaskNode")); + + JSONArray transitions = node.getJSONArray("transitions"); + WorkflowTransition[] startTransitions = startNode.transitions; + + assertNotNull(transitions); + + assertEquals(startTransitions.length, transitions.length()); + + for (int i = 0; i < transitions.length(); i++) + { + JSONObject transition = transitions.getJSONObject(i); + WorkflowTransition startTransition = startTransitions[i]; + + assertNotNull(transition); + + assertEquals(startTransition.id, transition.getString("id")); + assertEquals(startTransition.title, transition.getString("title")); + assertEquals(startTransition.description, transition.getString("description")); + assertEquals(startTransition.isDefault, transition.getBoolean("isDefault")); + assertTrue(transition.has("isHidden")); + } + + } public void testWorkflowDefinitionsGet() throws Exception { @@ -137,7 +231,7 @@ public class WorkflowRestApiTest extends BaseWebScriptTest assertTrue(workflowDefinitionJSON.has("url")); String url = workflowDefinitionJSON.getString("url"); assertTrue(url.length() > 0); - assertTrue(url.startsWith("api/workflow-definition/")); + assertTrue(url.startsWith("api/workflow-definitions/")); assertTrue(workflowDefinitionJSON.has("name")); assertTrue(workflowDefinitionJSON.getString("name").length() > 0); @@ -165,7 +259,7 @@ public class WorkflowRestApiTest extends BaseWebScriptTest personManager.createPerson(USER1); personManager.createPerson(USER2); - packageRef = workflowService.createPackage(null); + packageRef = workflowService.createPackage(null); } /* (non-Javadoc)