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