mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-21 18:09:20 +00:00
Created api/task-instances GET for Workflow REST API. Gets a list of task instances for specified authority.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20933 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>List Workflow Tasks</shortname>
|
||||||
|
<description>
|
||||||
|
Lists all Workflow Task Instances associated with an authority and of a given State.
|
||||||
|
The list of returned tasks also includes pooled tasks which the specified authority is eligible to claim.
|
||||||
|
</description>
|
||||||
|
<url>/api/task-instance</url>
|
||||||
|
<url>/api/task-instance?autority={authority?}</url>
|
||||||
|
<url>/api/task-instance?state={state?}</url>
|
||||||
|
<url>/api/task-instance?properties={properties?}</url>
|
||||||
|
<url>/api/task-instance?autority={authority?}&?state={state?}</url>
|
||||||
|
<url>/api/task-instance?authority={authority?}&?properties={properties?}</url>
|
||||||
|
<url>/api/task-instance?state={state?}&?properties={properties?}</url>
|
||||||
|
<url>/api/task-instance?authority={authority?}&?state={state?}&?properties={properties?}</url>
|
||||||
|
<format default="json"/>
|
||||||
|
<authentication>user</authentication>
|
||||||
|
<transaction allow="readonly">required</transaction>
|
||||||
|
</webscript>
|
@@ -0,0 +1,11 @@
|
|||||||
|
<#-- List Workflow Task Instances -->
|
||||||
|
|
||||||
|
<#import "task.lib.ftl" as taskLib />
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
<#list taskInstances as task>
|
||||||
|
<@taskLib.taskJSON task=task />
|
||||||
|
<#if task_has_next>,</#if>
|
||||||
|
</#list>
|
||||||
|
]
|
||||||
|
}
|
@@ -0,0 +1,50 @@
|
|||||||
|
<#-- Renders a task instance. -->
|
||||||
|
<#macro taskJSON task >
|
||||||
|
{
|
||||||
|
"url": "${task.url}",
|
||||||
|
"name": "${task.name}",
|
||||||
|
"title": "${task.title}",
|
||||||
|
"description": "${task.description}",
|
||||||
|
"state": "${task.state}",
|
||||||
|
"typeDefinitionTitle": "${task.typeDefinitionTitle}",
|
||||||
|
"isPooled": ${task.isPooled?string},
|
||||||
|
<#if task.owner??>
|
||||||
|
"owner":
|
||||||
|
{
|
||||||
|
"userName": "${task.owner.userName}",
|
||||||
|
"firstName": "${task.owner.firstName}",
|
||||||
|
"lastName": "${task.owner.lastName}"
|
||||||
|
},
|
||||||
|
</#if>
|
||||||
|
"properties":
|
||||||
|
<@propertiesJSON properties=task.properties />
|
||||||
|
}
|
||||||
|
</#macro>
|
||||||
|
|
||||||
|
<#-- Renders a map of properties -->
|
||||||
|
<#macro propertiesJSON properties>
|
||||||
|
{
|
||||||
|
<#list properties?keys as key>
|
||||||
|
<#if properties[key]??>
|
||||||
|
<#assign val=properties[key]>
|
||||||
|
"${key}" :
|
||||||
|
<#if val?is_boolean == true>
|
||||||
|
${val?string}
|
||||||
|
<#elseif val?is_number == true>
|
||||||
|
${val?c}
|
||||||
|
<#elseif val?is_sequence>
|
||||||
|
[
|
||||||
|
<#list val as element>
|
||||||
|
"${jsonUtils.encodeJSONString(element?string)}"<#if (element_has_next)>,</#if>
|
||||||
|
</#list>
|
||||||
|
]
|
||||||
|
<#else>
|
||||||
|
"${jsonUtils.encodeJSONString(shortQName(val?string))}"
|
||||||
|
</#if>
|
||||||
|
<#if (key_has_next)>,</#if>
|
||||||
|
</#if>
|
||||||
|
</#list>
|
||||||
|
}
|
||||||
|
</#macro>
|
||||||
|
|
||||||
|
|
@@ -731,7 +731,28 @@
|
|||||||
<bean id="webscript.org.alfresco.repository.rule.actionConstraint.get" class="org.alfresco.repo.web.scripts.rule.ActionConstraintGet" parent="abstractRuleWebScript">
|
<bean id="webscript.org.alfresco.repository.rule.actionConstraint.get" class="org.alfresco.repo.web.scripts.rule.ActionConstraintGet" parent="abstractRuleWebScript">
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- adds a new action to the execution queue. -->
|
<!-- adds a new action to the execution queue. -->
|
||||||
<bean id="webscript.org.alfresco.repository.rule.actionQueue.post" class="org.alfresco.repo.web.scripts.rule.ActionQueuePost" parent="abstractRuleWebScript">
|
<bean id="webscript.org.alfresco.repository.rule.actionQueue.post" class="org.alfresco.repo.web.scripts.rule.ActionQueuePost" parent="abstractRuleWebScript">
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- -->
|
||||||
|
<!-- Workflow Service REST API -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<!-- abstract workflow web script -->
|
||||||
|
<bean id="abstractWorkflowWebScript"
|
||||||
|
class="org.alfresco.repo.web.scripts.rule.AbstractRuleWebScript"
|
||||||
|
parent="webscript" abstract="true">
|
||||||
|
<property name="namespaceService" ref="NamespaceService" />
|
||||||
|
<property name="nodeService" ref="NodeService"/>
|
||||||
|
<property name="personService" ref="PersonService"/>
|
||||||
|
<property name="workflowService" ref="WorkflowService"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Lists the task instances, filtered by task owner and state. -->
|
||||||
|
<bean id="webscript.org.alfresco.repository.workflow.task-instances.get"
|
||||||
|
class="org.alfresco.repo.web.scripts.workflow.TaskInstancesGet"
|
||||||
|
parent="abstractWorkflowWebScript">
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* 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.web.scripts.workflow;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
|
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nick Smith
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class AbstractWorkflowWebscript extends DeclarativeWebScript
|
||||||
|
{
|
||||||
|
|
||||||
|
private NamespaceService namespaceService;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private PersonService personService;
|
||||||
|
protected WorkflowService workflowService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||||
|
{
|
||||||
|
WorkflowModelBuilder modelBuilder = new WorkflowModelBuilder(namespaceService, nodeService, personService);
|
||||||
|
return buildModel(modelBuilder, req, status, cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNamespaceService(NamespaceService namespaceService)
|
||||||
|
{
|
||||||
|
this.namespaceService = namespaceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonService(PersonService personService)
|
||||||
|
{
|
||||||
|
this.personService = personService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWorkflowService(WorkflowService workflowService)
|
||||||
|
{
|
||||||
|
this.workflowService = workflowService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method uses a {@link WorkflowModelBuilder} to build up the model to return.
|
||||||
|
* @param modelBuilder A {@link WorkflowModelBuilder}.
|
||||||
|
* @param req the {@link WebScriptRequest}
|
||||||
|
* @param status the {@link Status}
|
||||||
|
* @param cache the {@link Cache}
|
||||||
|
* @return the data model.
|
||||||
|
*/
|
||||||
|
protected abstract Map<String, Object> buildModel(
|
||||||
|
WorkflowModelBuilder modelBuilder,
|
||||||
|
WebScriptRequest req,
|
||||||
|
Status status, Cache cache);
|
||||||
|
}
|
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* 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.web.scripts.workflow;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||||
|
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 Nick Smith
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TaskInstancesGet extends AbstractWorkflowWebscript
|
||||||
|
{
|
||||||
|
public static final String PARAM_AUTHORITY = "authority";
|
||||||
|
public static final String PARAM_STATUS= "status";
|
||||||
|
public static final String PARAM_PROPERTIES= "properties";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Object> buildModel(WorkflowModelBuilder modelBuilder, WebScriptRequest req, Status status,
|
||||||
|
Cache cache)
|
||||||
|
{
|
||||||
|
String authority = getAuthority(req);
|
||||||
|
WorkflowTaskState state = getState(req);
|
||||||
|
List<String> properties = getProperties(req);
|
||||||
|
|
||||||
|
//TODO Handle possible thrown exceptions here?
|
||||||
|
List<WorkflowTask> tasks = workflowService.getAssignedTasks(authority, state);
|
||||||
|
List<WorkflowTask> pooledTasks= workflowService.getPooledTasks(authority);
|
||||||
|
ArrayList<WorkflowTask> allTasks = new ArrayList<WorkflowTask>(tasks.size() + pooledTasks.size());
|
||||||
|
allTasks.addAll(tasks);
|
||||||
|
allTasks.addAll(pooledTasks);
|
||||||
|
|
||||||
|
ArrayList<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
|
||||||
|
for (WorkflowTask task : allTasks)
|
||||||
|
{
|
||||||
|
results.add(modelBuilder.buildSimple(task, properties));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>();
|
||||||
|
model.put("taskInstances", results);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getProperties(WebScriptRequest req)
|
||||||
|
{
|
||||||
|
String propertiesStr = req.getParameter(PARAM_PROPERTIES);
|
||||||
|
if(propertiesStr != null)
|
||||||
|
{
|
||||||
|
return Arrays.asList(propertiesStr.split(","));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the specified {@link WorkflowTaskState}, defaults to IN_PROGRESS.
|
||||||
|
* @param req
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private WorkflowTaskState getState(WebScriptRequest req)
|
||||||
|
{
|
||||||
|
String stateName= req.getParameter(PARAM_STATUS);
|
||||||
|
if(stateName != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return WorkflowTaskState.valueOf(stateName.toUpperCase());
|
||||||
|
}
|
||||||
|
catch(IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
String msg = "Unrecognised State parameter: "+stateName;
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Defaults to IN_PROGRESS.
|
||||||
|
return WorkflowTaskState.IN_PROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the specified authority. If no authority is specified then returns the current Fully Authenticated user.
|
||||||
|
* @param req
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getAuthority(WebScriptRequest req)
|
||||||
|
{
|
||||||
|
String authority = req.getParameter(PARAM_AUTHORITY);
|
||||||
|
if(authority == null)
|
||||||
|
{
|
||||||
|
authority = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||||
|
}
|
||||||
|
return authority;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* 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.web.scripts.workflow;
|
||||||
|
|
||||||
|
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.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.workflow.WorkflowModel;
|
||||||
|
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.WorkflowTask;
|
||||||
|
import org.alfresco.service.namespace.NamespaceException;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nick Smith
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class WorkflowModelBuilder
|
||||||
|
{
|
||||||
|
public static final String PERSON_LAST_NAME = "lastName";
|
||||||
|
public static final String PERSON_FIRST_NAME = "firstName";
|
||||||
|
public static final String PERSON_USER_NAME = "userName";
|
||||||
|
|
||||||
|
public static final String TASK_PROPERTIES = "properties";
|
||||||
|
public static final String TASK_OWNER = "owner";
|
||||||
|
public static final String TASK_TYPE_DEFINITION_TITLE = "typeDefinitionTitle";
|
||||||
|
public static final String TASK_STATE = "state";
|
||||||
|
public static final String TASK_DESCRIPTION = "description";
|
||||||
|
public static final String TASK_TITLE = "title";
|
||||||
|
public static final String TASK_NAME = "name";
|
||||||
|
public static final String TASK_URL = "url";
|
||||||
|
public static final String TASK_IS_POOLED = "isPooled";
|
||||||
|
|
||||||
|
private static final String PREFIX_SEPARATOR = Character.toString(QName.NAMESPACE_PREFIX);
|
||||||
|
|
||||||
|
private final NamespaceService namespaceService;
|
||||||
|
private final NodeService nodeService;
|
||||||
|
private final PersonService personService;
|
||||||
|
|
||||||
|
public WorkflowModelBuilder(NamespaceService namespaceService, NodeService nodeService, PersonService personService)
|
||||||
|
{
|
||||||
|
this.namespaceService = namespaceService;
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
this.personService = personService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a simple representation of a {@link WorkflowTask}.
|
||||||
|
* @param task The task to be represented.
|
||||||
|
* @param propertyFilters Specify which properties to include.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, Object> buildSimple(WorkflowTask task, Collection<String> propertyFilters)
|
||||||
|
{
|
||||||
|
HashMap<String, Object> model = new HashMap<String, Object>();
|
||||||
|
model.put(TASK_URL, getUrl(task));
|
||||||
|
model.put(TASK_NAME, task.name);
|
||||||
|
model.put(TASK_TITLE, task.title);
|
||||||
|
model.put(TASK_DESCRIPTION, task.description);
|
||||||
|
model.put(TASK_STATE, task.state.name());
|
||||||
|
model.put(TASK_TYPE_DEFINITION_TITLE, task.definition.metadata.getTitle());
|
||||||
|
|
||||||
|
model.put(TASK_IS_POOLED, isPooled(task.properties));
|
||||||
|
Serializable owner = task.properties.get(ContentModel.PROP_OWNER);
|
||||||
|
if (owner != null && owner instanceof String) {
|
||||||
|
model.put(TASK_OWNER, getPersonModel((String) owner));
|
||||||
|
}
|
||||||
|
|
||||||
|
model.put(TASK_PROPERTIES, buildProperties(task.properties, propertyFilters));
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object isPooled(Map<QName, Serializable> properties)
|
||||||
|
{
|
||||||
|
Collection<?> actors = (Collection<?>) properties.get(WorkflowModel.ASSOC_POOLED_ACTORS);
|
||||||
|
return actors!=null && !actors.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> buildProperties(Map<QName, Serializable> properties, Collection<String> propertyFilters)
|
||||||
|
{
|
||||||
|
Collection<QName> keys;
|
||||||
|
if (propertyFilters == null || propertyFilters.size() == 0)
|
||||||
|
keys = properties.keySet();
|
||||||
|
else
|
||||||
|
keys = buildQNameKeys(propertyFilters);
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>();
|
||||||
|
for (QName key : keys)
|
||||||
|
{
|
||||||
|
Object value = convertValue(properties.get(key));
|
||||||
|
String preixedKey = key.toPrefixString(namespaceService);
|
||||||
|
String strKey = preixedKey.replace(PREFIX_SEPARATOR, "_");
|
||||||
|
model.put(strKey, value);
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object convertValue(Object value)
|
||||||
|
{
|
||||||
|
if(value == null
|
||||||
|
|| value instanceof Boolean
|
||||||
|
|| value instanceof Number
|
||||||
|
|| value instanceof String)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if(value instanceof Collection<?>)
|
||||||
|
{
|
||||||
|
Collection<?> collection = (Collection<?>)value;
|
||||||
|
ArrayList<Object> results = new ArrayList<Object>(collection.size());
|
||||||
|
for (Object obj : collection)
|
||||||
|
{
|
||||||
|
results.add(convertValue(obj));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
return DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<QName> buildQNameKeys(Collection<String> keys)
|
||||||
|
{
|
||||||
|
List<QName> qKeys = new ArrayList<QName>(keys.size());
|
||||||
|
for (String key : keys)
|
||||||
|
{
|
||||||
|
String prefixedName = key.replaceFirst("_", PREFIX_SEPARATOR);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
QName qKey = QName.createQName(prefixedName, namespaceService);
|
||||||
|
qKeys.add(qKey);
|
||||||
|
} catch(NamespaceException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Invalid property key: "+key, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return qKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getPersonModel(String name)
|
||||||
|
{
|
||||||
|
NodeRef person = personService.getPerson(name);
|
||||||
|
Map<QName, Serializable> properties = nodeService.getProperties(person);
|
||||||
|
|
||||||
|
// TODO Person URL?
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>();
|
||||||
|
model.put(PERSON_USER_NAME, name);
|
||||||
|
model.put(PERSON_FIRST_NAME, properties.get(ContentModel.PROP_FIRSTNAME));
|
||||||
|
model.put(PERSON_LAST_NAME, properties.get(ContentModel.PROP_LASTNAME));
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return "api/task-instance/" + task.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* 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.web.scripts.workflow;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
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.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
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.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceServiceMemoryImpl;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.ISO8601DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nick Smith
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class WorkflowModelBuilderTest extends TestCase
|
||||||
|
{
|
||||||
|
private static final String URI = "http://test";
|
||||||
|
private static final String userName = "joeBloggs";
|
||||||
|
private static final String firstName = "Joe";
|
||||||
|
private static final String lastName = "Bloggs";
|
||||||
|
private static final NodeRef person = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, userName);
|
||||||
|
|
||||||
|
private NamespaceService namespaceService;
|
||||||
|
private PersonService personService;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private WorkflowModelBuilder builder;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testBuildWorkflowTask() throws Exception
|
||||||
|
{
|
||||||
|
WorkflowTask task = new WorkflowTask();
|
||||||
|
task.definition = new WorkflowTaskDefinition();
|
||||||
|
task.definition.metadata = mock(TypeDefinition.class);
|
||||||
|
when(task.definition.metadata.getTitle()).thenReturn("Type Title");
|
||||||
|
task.description = "Task Desc";
|
||||||
|
task.id = "testId$1";
|
||||||
|
task.name = "Task Name";
|
||||||
|
task.state = WorkflowTaskState.IN_PROGRESS;
|
||||||
|
task.title = "Task Title";
|
||||||
|
task.properties = new HashMap<QName, Serializable>();
|
||||||
|
task.properties.put(ContentModel.PROP_OWNER, userName);
|
||||||
|
|
||||||
|
QName testInt = QName.createQName(URI, "int");
|
||||||
|
task.properties.put(testInt, 5);
|
||||||
|
QName testBoolean = QName.createQName(URI, "boolean");
|
||||||
|
task.properties.put(testBoolean, false);
|
||||||
|
QName testString = QName.createQName(URI, "string");
|
||||||
|
task.properties.put(testString, "foo bar");
|
||||||
|
QName testDate = QName.createQName(URI, "date");
|
||||||
|
Date date = new Date();
|
||||||
|
task.properties.put(testDate, date);
|
||||||
|
|
||||||
|
Map<String, Object> model = builder.buildSimple(task, null);
|
||||||
|
Object url = model.get(WorkflowModelBuilder.TASK_URL);
|
||||||
|
assertEquals("api/task-instance/"+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));
|
||||||
|
assertEquals(task.state.name(), model.get(WorkflowModelBuilder.TASK_STATE));
|
||||||
|
assertEquals(task.definition.metadata.getTitle(), model.get(WorkflowModelBuilder.TASK_TYPE_DEFINITION_TITLE));
|
||||||
|
assertEquals(false, model.get(WorkflowModelBuilder.TASK_IS_POOLED));
|
||||||
|
|
||||||
|
Map<String, Object> owner = (Map<String, Object>) 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<String, Object> props = (Map<String, Object>) model.get(WorkflowModelBuilder.TASK_PROPERTIES);
|
||||||
|
assertEquals(task.properties.size(), props.size());
|
||||||
|
assertEquals(5, props.get("test_int"));
|
||||||
|
assertEquals(false, props.get("test_boolean"));
|
||||||
|
assertEquals("foo bar", props.get("test_string"));
|
||||||
|
String dateStr = (String) props.get("test_date");
|
||||||
|
assertEquals(date, ISO8601DateFormat.parse(dateStr));
|
||||||
|
|
||||||
|
task.properties.put(WorkflowModel.ASSOC_POOLED_ACTORS, new ArrayList<NodeRef>(0));
|
||||||
|
model = builder.buildSimple(task, null);
|
||||||
|
assertEquals(false, model.get(WorkflowModelBuilder.TASK_IS_POOLED));
|
||||||
|
|
||||||
|
ArrayList<NodeRef> actors = new ArrayList<NodeRef>(1);
|
||||||
|
actors.add(person);
|
||||||
|
task.properties.put(WorkflowModel.ASSOC_POOLED_ACTORS, actors);
|
||||||
|
model = builder.buildSimple(task, null);
|
||||||
|
assertEquals(true, model.get(WorkflowModelBuilder.TASK_IS_POOLED));
|
||||||
|
|
||||||
|
model = builder.buildSimple(task, Arrays.asList("test_int", "test_string"));
|
||||||
|
//Check task owner still created properly.
|
||||||
|
owner = (Map<String, Object>) model.get(WorkflowModelBuilder.TASK_OWNER);
|
||||||
|
assertEquals( userName, owner.get(WorkflowModelBuilder.PERSON_USER_NAME));
|
||||||
|
|
||||||
|
// Check properties populated correctly
|
||||||
|
props = (Map<String, Object>) model.get(WorkflowModelBuilder.TASK_PROPERTIES);
|
||||||
|
assertEquals(2, props.size());
|
||||||
|
assertEquals(5, props.get("test_int"));
|
||||||
|
assertEquals("foo bar", props.get("test_string"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
namespaceService = new NamespaceServiceMemoryImpl();
|
||||||
|
namespaceService.registerNamespace("test", URI);
|
||||||
|
namespaceService.registerNamespace(NamespaceService.CONTENT_MODEL_PREFIX, NamespaceService.CONTENT_MODEL_1_0_URI);
|
||||||
|
namespaceService.registerNamespace(NamespaceService.BPM_MODEL_PREFIX, NamespaceService.BPM_MODEL_1_0_URI);
|
||||||
|
|
||||||
|
personService = mock(PersonService.class);
|
||||||
|
when(personService.getPerson(userName)).thenReturn(person);
|
||||||
|
|
||||||
|
nodeService = mock(NodeService.class);
|
||||||
|
Map<QName, Serializable> personProps = new HashMap<QName, Serializable>();
|
||||||
|
personProps.put(ContentModel.PROP_USERNAME, userName);
|
||||||
|
personProps.put(ContentModel.PROP_FIRSTNAME, firstName);
|
||||||
|
personProps.put(ContentModel.PROP_LASTNAME, lastName);
|
||||||
|
when(nodeService.getProperties(person)).thenReturn(personProps);
|
||||||
|
|
||||||
|
builder = new WorkflowModelBuilder(namespaceService, nodeService, personService);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* 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.web.scripts.workflow;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
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.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.WorkflowPath;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||||
|
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest;
|
||||||
|
import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nick Smith
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
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 TestPersonManager personManager;
|
||||||
|
private WorkflowService workflowService;
|
||||||
|
private NodeRef packageRef;
|
||||||
|
|
||||||
|
public void testTaskInstancesGet() throws Exception
|
||||||
|
{
|
||||||
|
// Check USER2 starts with no tasks.
|
||||||
|
personManager.setUser(USER2);
|
||||||
|
Response response = sendRequest(new GetRequest(URL_TASKS), 200);
|
||||||
|
assertEquals(Status.STATUS_OK, response.getStatus());
|
||||||
|
JSONObject json = new JSONObject(response.getContentAsString());
|
||||||
|
JSONArray results = json.getJSONArray("data");
|
||||||
|
assertNotNull(results);
|
||||||
|
assertTrue(results.length()==0);
|
||||||
|
|
||||||
|
//Start workflow as USER1 and assign task to USER2.
|
||||||
|
personManager.setUser(USER1);
|
||||||
|
WorkflowDefinition adhocDef = workflowService.getDefinitionByName("jbpm$wf:adhoc");
|
||||||
|
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||||
|
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);
|
||||||
|
workflowService.endTask(startTask.id, null);
|
||||||
|
|
||||||
|
// Check USER2 now has one task.
|
||||||
|
List<WorkflowTask> tasks = workflowService.getAssignedTasks(USER2, WorkflowTaskState.IN_PROGRESS);
|
||||||
|
WorkflowTask task = tasks.get(0);
|
||||||
|
|
||||||
|
Serializable actors = task.properties.get(WorkflowModel.ASSOC_POOLED_ACTORS);
|
||||||
|
System.out.println("Pooled Actors: " + actors);
|
||||||
|
|
||||||
|
personManager.setUser(USER2);
|
||||||
|
response = sendRequest(new GetRequest(URL_TASKS), 200);
|
||||||
|
assertEquals(Status.STATUS_OK, response.getStatus());
|
||||||
|
json = new JSONObject(response.getContentAsString());
|
||||||
|
results = json.getJSONArray("data");
|
||||||
|
assertNotNull(results);
|
||||||
|
assertTrue(results.length()==tasks.size());
|
||||||
|
JSONObject result = results.getJSONObject(0);
|
||||||
|
|
||||||
|
String expUrl = "api/task-instance/"+task.id;
|
||||||
|
assertEquals(expUrl, result.getString("url"));
|
||||||
|
assertEquals(task.name, result.getString("name"));
|
||||||
|
assertEquals(task.title, result.getString("title"));
|
||||||
|
assertEquals(task.description, result.getString("description"));
|
||||||
|
assertEquals(task.state.name(), result.getString("state"));
|
||||||
|
assertEquals(task.definition.metadata.getTitle(), result.getString("typeDefinitionTitle"));
|
||||||
|
assertEquals(false, result.getBoolean("isPooled"));
|
||||||
|
|
||||||
|
JSONObject owner = result.getJSONObject("owner");
|
||||||
|
assertEquals(USER2, owner.getString("userName"));
|
||||||
|
assertEquals(personManager.getFirstName(USER2), owner.getString("firstName"));
|
||||||
|
assertEquals(personManager.getLastName(USER2), owner.getString("lastName"));
|
||||||
|
|
||||||
|
JSONObject properties = result.getJSONObject("properties");
|
||||||
|
Collection<Serializable> values = task.properties.values();
|
||||||
|
while(values.contains(null))
|
||||||
|
{
|
||||||
|
values.remove(null);
|
||||||
|
}
|
||||||
|
assertEquals(values.size(), properties.length());
|
||||||
|
|
||||||
|
//TODO Add more tests to check property filtering and pooled actors.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
ApplicationContext appContext = getServer().getApplicationContext();
|
||||||
|
|
||||||
|
workflowService = (WorkflowService)appContext.getBean("WorkflowService");
|
||||||
|
MutableAuthenticationService authenticationService = (MutableAuthenticationService)appContext.getBean("AuthenticationService");
|
||||||
|
PersonService personService = (PersonService)appContext.getBean("PersonService");
|
||||||
|
NodeService nodeService = (NodeService)appContext.getBean("NodeService");
|
||||||
|
personManager = new TestPersonManager(authenticationService, personService, nodeService);
|
||||||
|
|
||||||
|
personManager.createPerson(USER1);
|
||||||
|
personManager.createPerson(USER2);
|
||||||
|
|
||||||
|
packageRef = workflowService.createPackage(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see junit.framework.TestCase#tearDown()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
super.tearDown();
|
||||||
|
personManager.clearPeople();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user