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 6760864ded..da0a78fa51 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,3 +1,5 @@
+<#import "workflow-definition.lib.ftl" as worflowDefinitionLib />
+
<#-- Renders a task instance. -->
<#macro taskJSON task detailed=false>
<#escape x as jsonUtils.encodeJSONString(x)>
@@ -24,28 +26,7 @@
<@propertiesJSON properties=task.properties />
<#if detailed>,
"path": "${task.path}",
- "workflowInstance":
- {
- "id": "${task.workflowInstance.id}",
- "url": "${task.workflowInstance.url}",
- "name": "${task.workflowInstance.name}",
- "title": "${task.workflowInstance.title}",
- "description": "${task.workflowInstance.description}",
- "isActive": ${task.workflowInstance.isActive?string},
- "startDate": "${task.workflowInstance.startDate}",
- "endDate": <#if task.workflowInstance.endDate??>"${task.workflowInstance.endDate}"<#else>null#if>,
- "initiator":
- <#if task.workflowInstance.initiator??>
- {
- "userName": "${task.workflowInstance.initiator.userName}",
- "firstName": "${task.workflowInstance.initiator.firstName}",
- "lastName": "${task.workflowInstance.initiator.lastName}"
- },
- <#else>
- null,
- #if>
- "definitionUrl": "${task.workflowInstance.definitionUrl}"
- },
+ "workflowInstance": <@workflowInstanceJSON workflowInstance=task.workflowInstance/>,
"definition":
{
"id": "${task.definition.id}",
@@ -112,3 +93,47 @@
}
#escape>
#macro>
+
+<#-- Renders a workflow instance. -->
+<#macro workflowInstanceJSON workflowInstance detailed=false>
+<#escape x as jsonUtils.encodeJSONString(x)>
+ {
+ "id": "${workflowInstance.id}",
+ "url": "${workflowInstance.url}",
+ "name": "${workflowInstance.name}",
+ "title": "${workflowInstance.title}",
+ "description": "${workflowInstance.description}",
+ "isActive": ${workflowInstance.isActive?string},
+ "startDate": "${workflowInstance.startDate}",
+ "endDate": <#if workflowInstance.endDate??>"${workflowInstance.endDate}"<#else>null#if>,
+ "initiator":
+ <#if workflowInstance.initiator??>
+ {
+ "userName": "${workflowInstance.initiator.userName}",
+ "firstName": "${workflowInstance.initiator.firstName}",
+ "lastName": "${workflowInstance.initiator.lastName}"
+ },
+ <#else>
+ null,
+ #if>
+ "definitionUrl": "${workflowInstance.definitionUrl}"
+ <#if detailed>,
+ "dueDate": <#if workflowInstance.dueDate??>"${workflowInstance.dueDate}"<#else>null#if>,
+ "priority": <#if workflowInstance.priority??>${workflowInstance.priority?c}<#else>null#if>,
+ "context": <#if workflowInstance.context??>"${workflowInstance.context}"<#else>null#if>,
+ "package": "${workflowInstance.package}",
+ "startTaskInstanceId": "${workflowInstance.startTaskInstanceId}",
+ "definition": <@worflowDefinitionLib.workflowDefinitionJSON workflowDefinition=workflowInstance.definition detailed=true/>
+ <#if workflowInstance.tasks??>,
+ "tasks":
+ [
+ <#list workflowInstance.tasks as task>
+ <@taskJSON task=task/>
+ <#if task_has_next>,#if>
+ #list>
+ ]
+ #if>
+ #if>
+ }
+#escape>
+#macro>
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-definition.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-definition.lib.ftl
index 8674e9880f..c1a6a80275 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-definition.lib.ftl
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-definition.lib.ftl
@@ -1,5 +1,5 @@
<#-- Renders a workflow definition. -->
-<#macro workflowDefinitionJSON workflowDefinition>
+<#macro workflowDefinitionJSON workflowDefinition detailed=false>
<#escape x as jsonUtils.encodeJSONString(x)>
{
"id" : "${workflowDefinition.id}",
@@ -7,6 +7,21 @@
"name": "${workflowDefinition.name}",
"title": "${workflowDefinition.title}",
"description": "${workflowDefinition.description}"
+ <#if detailed>,
+ "version": "${workflowDefinition.version}",
+ "startTaskDefinitionUrl": "${workflowDefinition.startTaskDefinitionUrl}",
+ "startTaskDefinitionType": "${shortQName(workflowDefinition.startTaskDefinitionType)}",
+ "taskDefinitions":
+ [
+ <#list workflowDefinition.taskDefinitions as taskDefinition>
+ {
+ "url": "${taskDefinition.url}",
+ "type": "${shortQName(taskDefinition.type)}"
+ }
+ <#if taskDefinition_has_next>,#if>
+ #list>
+ ]
+ #if>
}
#escape>
#macro>
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instance.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instance.get.desc.xml
new file mode 100644
index 0000000000..e7da1fd660
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instance.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Get Workflow Instance
+ Retrieves a specific workflow instance, optionally with all the tasks.
+ /api/workflow-instances/{workflow_instance_id}?includeTasks={includeTasks?}
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instance.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instance.get.json.ftl
new file mode 100644
index 0000000000..8da05e3f60
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow-instance.get.json.ftl
@@ -0,0 +1,6 @@
+<#-- Workflow Instance in details -->
+
+<#import "task.lib.ftl" as taskLib />
+{
+ "data": <@taskLib.workflowInstanceJSON workflowInstance=workflowInstance detailed=true/>
+}
\ No newline at end of file
diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml
index 3fd10b4592..c0edbc988d 100644
--- a/config/alfresco/web-scripts-application-context.xml
+++ b/config/alfresco/web-scripts-application-context.xml
@@ -811,6 +811,11 @@
class="org.alfresco.repo.web.scripts.workflow.WorkflowDefinitionsGet"
parent="abstractWorkflowWebScript">
+
+
+
diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/AbstractWorkflowWebscript.java b/source/java/org/alfresco/repo/web/scripts/workflow/AbstractWorkflowWebscript.java
index c60654df0a..434845c8d7 100644
--- a/source/java/org/alfresco/repo/web/scripts/workflow/AbstractWorkflowWebscript.java
+++ b/source/java/org/alfresco/repo/web/scripts/workflow/AbstractWorkflowWebscript.java
@@ -48,7 +48,7 @@ public abstract class AbstractWorkflowWebscript extends DeclarativeWebScript
@Override
protected Map executeImpl(WebScriptRequest req, Status status, Cache cache)
{
- WorkflowModelBuilder modelBuilder = new WorkflowModelBuilder(namespaceService, nodeService, personService);
+ WorkflowModelBuilder modelBuilder = new WorkflowModelBuilder(namespaceService, nodeService, personService, workflowService);
return buildModel(modelBuilder, req, status, cache);
}
diff --git a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstanceGet.java b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstanceGet.java
new file mode 100644
index 0000000000..a216836a78
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowInstanceGet.java
@@ -0,0 +1,86 @@
+/*
+ * 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 .
+ */
+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.WorkflowInstance;
+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
+ * @since 3.4
+ *
+ */
+public class WorkflowInstanceGet extends AbstractWorkflowWebscript
+{
+
+ public static final String PARAM_INCLUDE_TASKS = "includeTasks";
+
+ @Override
+ protected Map buildModel(WorkflowModelBuilder modelBuilder, WebScriptRequest req, Status status, Cache cache)
+ {
+ Map params = req.getServiceMatch().getTemplateVars();
+
+ // getting workflow instance id from request parameters
+ String workflowInstanceId = params.get("workflow_instance_id");
+
+ boolean includeTasks = getIncludeTasks(req);
+
+ WorkflowInstance workflowInstance = workflowService.getWorkflowById(workflowInstanceId);
+
+ // task was not found -> return 404
+ if (workflowInstance == null)
+ {
+ throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find workflow instance with id: " + workflowInstanceId);
+ }
+
+ Map model = new HashMap();
+ // build the model for ftl
+ model.put("workflowInstance", modelBuilder.buildDetailed(workflowInstance, includeTasks));
+
+ return model;
+ }
+
+ private boolean getIncludeTasks(WebScriptRequest req)
+ {
+ String includeTasks = req.getParameter(PARAM_INCLUDE_TASKS);
+ if (includeTasks != null)
+ {
+ try
+ {
+ return Boolean.valueOf(includeTasks);
+ }
+ catch (Exception e)
+ {
+ // do nothing, false will be returned
+ }
+ }
+
+ // Defaults to false.
+ return false;
+ }
+
+}
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 097518db6e..9df8931afa 100644
--- a/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilder.java
+++ b/source/java/org/alfresco/repo/web/scripts/workflow/WorkflowModelBuilder.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -42,8 +43,11 @@ 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.cmr.workflow.WorkflowTaskQuery;
+import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.cmr.workflow.WorkflowTransition;
import org.alfresco.service.namespace.NamespaceException;
import org.alfresco.service.namespace.NamespaceService;
@@ -87,8 +91,15 @@ public class WorkflowModelBuilder
public static final String TASK_WORKFLOW_INSTANCE_DESCRIPTION = "description";
public static final String TASK_WORKFLOW_INSTANCE_IS_ACTIVE = "isActive";
public static final String TASK_WORKFLOW_INSTANCE_START_DATE = "startDate";
+ public static final String TASK_WORKFLOW_INSTANCE_DUE_DATE = "dueDate";
public static final String TASK_WORKFLOW_INSTANCE_END_DATE = "endDate";
+ public static final String TASK_WORKFLOW_INSTANCE_PRIORITY = "priority";
public static final String TASK_WORKFLOW_INSTANCE_INITIATOR = "initiator";
+ public static final String TASK_WORKFLOW_INSTANCE_CONTEXT = "context";
+ public static final String TASK_WORKFLOW_INSTANCE_PACKAGE = "package";
+ public static final String TASK_WORKFLOW_INSTANCE_START_TASK_INSTANCE_ID = "startTaskInstanceId";
+ public static final String TASK_WORKFLOW_INSTANCE_DEFINITION = "definition";
+ public static final String TASK_WORKFLOW_INSTANCE_TASKS = "tasks";
public static final String TASK_WORKFLOW_INSTANCE_DEFINITION_URL = "definitionUrl";
public static final String TASK_WORKFLOW_INSTANCE_INITIATOR_USERNAME = "userName";
@@ -117,18 +128,24 @@ public class WorkflowModelBuilder
public static final String WORKFLOW_DEFINITION_NAME = "name";
public static final String WORKFLOW_DEFINITION_TITLE = "title";
public static final String WORKFLOW_DEFINITION_DESCRIPTION = "description";
+ public static final String WORKFLOW_DEFINITION_VERSION = "version";
+ public static final String WORKFLOW_DEFINITION_START_TASK_DEFINITION_URL = "startTaskDefinitionUrl";
+ public static final String WORKFLOW_DEFINITION_START_TASK_DEFINITION_TYPE = "startTaskDefinitionType";
+ public static final String WORKFLOW_DEFINITION_TASK_DEFINITIONS = "taskDefinitions";
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 WorkflowService workflowService;
- public WorkflowModelBuilder(NamespaceService namespaceService, NodeService nodeService, PersonService personService)
+ public WorkflowModelBuilder(NamespaceService namespaceService, NodeService nodeService, PersonService personService, WorkflowService workflowService)
{
this.namespaceService = namespaceService;
this.nodeService = nodeService;
this.personService = personService;
+ this.workflowService = workflowService;
}
/**
@@ -168,10 +185,148 @@ public class WorkflowModelBuilder
model.put(TASK_PATH, getUrl(workflowTask.getPath()));
// workflow instance part
- model.put(TASK_WORKFLOW_INSTANCE, buildWorkflowInstance(workflowTask.path.instance));
+ model.put(TASK_WORKFLOW_INSTANCE, buildSimple(workflowTask.getPath().getInstance()));
// definition part
- model.put(TASK_DEFINITION, buildTaskDefinition(workflowTask.definition, workflowTask));
+ model.put(TASK_DEFINITION, buildTaskDefinition(workflowTask.getDefinition(), workflowTask));
+
+ return model;
+ }
+
+ /**
+ * Returns a simple representation of a {@link WorkflowInstance}.
+ * @param workflowInstance The workflow instance to be represented.
+ * @return
+ */
+ public Map buildSimple(WorkflowInstance workflowInstance)
+ {
+ Map model = new HashMap();
+
+ model.put(TASK_WORKFLOW_INSTANCE_ID, workflowInstance.getId());
+ model.put(TASK_WORKFLOW_INSTANCE_URL, getUrl(workflowInstance));
+ model.put(TASK_WORKFLOW_INSTANCE_NAME, workflowInstance.getDefinition().getName());
+ model.put(TASK_WORKFLOW_INSTANCE_TITLE, workflowInstance.getDefinition().getTitle());
+ model.put(TASK_WORKFLOW_INSTANCE_DESCRIPTION, workflowInstance.getDefinition().getDescription());
+ model.put(TASK_WORKFLOW_INSTANCE_IS_ACTIVE, workflowInstance.isActive());
+
+ if (workflowInstance.getStartDate() == null)
+ {
+ model.put(TASK_WORKFLOW_INSTANCE_START_DATE, workflowInstance.getStartDate());
+ }
+ else
+ {
+ model.put(TASK_WORKFLOW_INSTANCE_START_DATE, ISO8601DateFormat.format(workflowInstance.getStartDate()));
+ }
+
+ if (workflowInstance.getEndDate() == null)
+ {
+ model.put(TASK_WORKFLOW_INSTANCE_END_DATE, workflowInstance.getEndDate());
+ }
+ else
+ {
+ model.put(TASK_WORKFLOW_INSTANCE_END_DATE, ISO8601DateFormat.format(workflowInstance.getEndDate()));
+ }
+
+ if (workflowInstance.getInitiator() == null)
+ {
+ model.put(TASK_WORKFLOW_INSTANCE_INITIATOR, null);
+ }
+ else
+ {
+ model.put(TASK_WORKFLOW_INSTANCE_INITIATOR, getPersonModel(nodeService.getProperty(workflowInstance.initiator, ContentModel.PROP_USERNAME)));
+ }
+ model.put(TASK_WORKFLOW_INSTANCE_DEFINITION_URL, getUrl(workflowInstance.getDefinition()));
+
+ return model;
+ }
+
+ /**
+ * Returns a detailed representation of a {@link WorkflowInstance}.
+ * @param workflowInstance The workflow instance to be represented.
+ * @param includeTasks should we include task in model?
+ * @return
+ */
+ public Map buildDetailed(WorkflowInstance workflowInstance, boolean includeTasks)
+ {
+ Map model = buildSimple(workflowInstance);
+
+ Serializable dueDate = null;
+ Serializable priority = null;
+ Serializable startTaskId = null;
+
+ // get all active tasks
+ List activeTasks = workflowService.queryTasks(new WorkflowTaskQuery());
+ // get all completed tasks
+ WorkflowTaskQuery completedTasksQuery = new WorkflowTaskQuery();
+ completedTasksQuery.setTaskState(WorkflowTaskState.COMPLETED);
+ completedTasksQuery.setActive(null);
+ List completedTasks = workflowService.queryTasks(completedTasksQuery);
+
+ ArrayList