mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged HEAD-QA to HEAD (4.2) - final one
r54310-54386 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@54387 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
10
source/java/org/alfresco/rest/workflow/api/Activities.java
Normal file
10
source/java/org/alfresco/rest/workflow/api/Activities.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package org.alfresco.rest.workflow.api;
|
||||
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.workflow.api.model.Activity;
|
||||
|
||||
public interface Activities
|
||||
{
|
||||
CollectionWithPagingInfo<Activity> getActivities(String processId, Parameters parameters);
|
||||
}
|
@@ -18,11 +18,12 @@
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api;
|
||||
|
||||
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.workflow.api.model.ProcessDefinition;
|
||||
import org.alfresco.rest.workflow.api.model.FormModelElement;
|
||||
import org.alfresco.rest.workflow.api.model.ProcessDefinition;
|
||||
|
||||
public interface ProcessDefinitions
|
||||
{
|
||||
@@ -30,5 +31,7 @@ public interface ProcessDefinitions
|
||||
|
||||
public ProcessDefinition getProcessDefinition(String definitionId);
|
||||
|
||||
public BinaryResource getProcessDefinitionImage(String definitionId);
|
||||
|
||||
public CollectionWithPagingInfo<FormModelElement> getStartFormModel(String definitionId, Paging paging);
|
||||
}
|
||||
|
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
@@ -47,6 +49,8 @@ public interface Processes
|
||||
CollectionWithPagingInfo<Variable> getVariables(String processId, Paging paging);
|
||||
|
||||
Variable updateVariable(String processId, Variable entity);
|
||||
|
||||
List<Variable> updateVariables(String processId, List<Variable> variables);
|
||||
|
||||
void deleteVariable(String processId, String id);
|
||||
|
||||
|
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
@@ -26,11 +28,14 @@ import org.alfresco.rest.workflow.api.model.Item;
|
||||
import org.alfresco.rest.workflow.api.model.Task;
|
||||
import org.alfresco.rest.workflow.api.model.TaskCandidate;
|
||||
import org.alfresco.rest.workflow.api.model.TaskVariable;
|
||||
import org.alfresco.rest.workflow.api.model.Variable;
|
||||
import org.alfresco.rest.workflow.api.model.VariableScope;
|
||||
|
||||
public interface Tasks
|
||||
{
|
||||
CollectionWithPagingInfo<Task> getTasks(Parameters parameters);
|
||||
|
||||
CollectionWithPagingInfo<Task> getTasks(String processId, Parameters parameters);
|
||||
|
||||
Task getTask(String taskId);
|
||||
|
||||
@@ -44,6 +49,8 @@ public interface Tasks
|
||||
CollectionWithPagingInfo<TaskVariable> getTaskVariables(String taskId, Paging paging, VariableScope scope);
|
||||
|
||||
TaskVariable updateTaskVariable(String taskId, TaskVariable taskVariable);
|
||||
|
||||
List<TaskVariable> updateTaskVariables(String taskId, List<TaskVariable> variables);
|
||||
|
||||
void deleteTaskVariable(String taskId, String variableName);
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@WebApi(name="alfresco", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
@WebApi(name="workflow", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
package org.alfresco.rest.workflow.api.deployments;
|
||||
import org.alfresco.rest.framework.Api;
|
||||
import org.alfresco.rest.framework.WebApi;
|
@@ -0,0 +1,50 @@
|
||||
package org.alfresco.rest.workflow.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.activiti.engine.history.HistoricActivityInstance;
|
||||
import org.activiti.engine.history.HistoricActivityInstanceQuery;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.workflow.api.Activities;
|
||||
import org.alfresco.rest.workflow.api.model.Activity;
|
||||
|
||||
public class ActivitiesImpl extends WorkflowRestImpl implements Activities
|
||||
{
|
||||
private static final String STATUS_ACTIVE = "active";
|
||||
private static final String STATUS_COMPLETED = "completed";
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Activity> getActivities(String processId, Parameters parameters)
|
||||
{
|
||||
Paging paging = parameters.getPaging();
|
||||
String status = parameters.getParameter("status");
|
||||
|
||||
validateIfUserAllowedToWorkWithProcess(processId);
|
||||
|
||||
HistoricActivityInstanceQuery query = activitiProcessEngine
|
||||
.getHistoryService()
|
||||
.createHistoricActivityInstanceQuery();
|
||||
|
||||
if (STATUS_ACTIVE.equals(status)) query.unfinished();
|
||||
else if (STATUS_COMPLETED.equals(status)) query.finished();
|
||||
|
||||
query.processInstanceId(processId);
|
||||
|
||||
query.orderByExecutionId().asc();
|
||||
|
||||
List<HistoricActivityInstance> activities = query.listPage(paging.getSkipCount(), paging.getMaxItems());
|
||||
|
||||
List<Activity> page = new ArrayList<Activity>(activities.size());
|
||||
for (HistoricActivityInstance activityInstance: activities)
|
||||
{
|
||||
Activity activity = new Activity(activityInstance);
|
||||
page.add(activity);
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, page, false, page.size());
|
||||
}
|
||||
|
||||
}
|
@@ -170,7 +170,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
{
|
||||
String localPropertyName = propertyName.replaceFirst("variables/", "");
|
||||
Object actualValue = null;
|
||||
if (propertyValue.contains("_") && propertyValue.contains(" "))
|
||||
if ((propertyValue.contains("_") || propertyValue.contains(":")) && propertyValue.contains(" "))
|
||||
{
|
||||
String typeDef = propertyValue.substring(0, propertyValue.indexOf(' '));
|
||||
try
|
||||
|
@@ -18,13 +18,19 @@
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.activiti.engine.form.StartFormData;
|
||||
import org.activiti.engine.impl.form.StartFormHandler;
|
||||
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.activiti.engine.repository.ProcessDefinitionQuery;
|
||||
import org.alfresco.repo.i18n.MessageService;
|
||||
@@ -34,7 +40,11 @@ import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.repo.workflow.WorkflowObjectFactory;
|
||||
import org.alfresco.repo.workflow.WorkflowQNameConverter;
|
||||
import org.alfresco.rest.antlr.WhereClauseParser;
|
||||
import org.alfresco.rest.framework.core.exceptions.ApiException;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||
import org.alfresco.rest.framework.resource.content.FileBinaryResource;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
@@ -44,6 +54,8 @@ import org.alfresco.rest.workflow.api.model.FormModelElement;
|
||||
import org.alfresco.rest.workflow.api.model.ProcessDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
public class ProcessDefinitionsImpl extends WorkflowRestImpl implements ProcessDefinitions
|
||||
{
|
||||
@@ -55,6 +67,9 @@ public class ProcessDefinitionsImpl extends WorkflowRestImpl implements ProcessD
|
||||
"category", "key", "name"
|
||||
}));
|
||||
|
||||
private static final Set<String> PROCESS_DEFINITION_COLLECTION_SORT_PROPERTIES = new HashSet<String>(Arrays.asList(
|
||||
"deploymentId", "key", "category", "id", "version", "name"
|
||||
));
|
||||
|
||||
MessageService messageService;
|
||||
String engineId;
|
||||
@@ -79,52 +94,135 @@ public class ProcessDefinitionsImpl extends WorkflowRestImpl implements ProcessD
|
||||
ProcessDefinitionQuery query = activitiProcessEngine
|
||||
.getRepositoryService()
|
||||
.createProcessDefinitionQuery()
|
||||
.processDefinitionCategoryNotEquals(WorkflowDeployer.CATEGORY_ALFRESCO_INTERNAL)
|
||||
.orderByProcessDefinitionName().asc()
|
||||
.orderByProcessDefinitionVersion().asc();
|
||||
|
||||
// Filter based on tenant, if required
|
||||
if (tenantService.isEnabled() && deployWorkflowsInTenant)
|
||||
{
|
||||
query.processDefinitionKeyLike("@" + TenantUtil.getCurrentDomain() + "@%");
|
||||
}
|
||||
.processDefinitionCategoryNotEquals(WorkflowDeployer.CATEGORY_ALFRESCO_INTERNAL);
|
||||
|
||||
MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(PROCESS_DEFINITION_COLLECTION_EQUALS_QUERY_PROPERTIES,
|
||||
PROCESS_DEFINITION_COLLECTION_MATCHES_QUERY_PROPERTIES);
|
||||
|
||||
boolean keyQueryIncluded = false;
|
||||
|
||||
if(parameters.getQuery() != null)
|
||||
{
|
||||
QueryHelper.walk(parameters.getQuery(), propertyWalker);
|
||||
|
||||
// Property equals
|
||||
if(propertyWalker.getProperty("category", WhereClauseParser.EQUALS) != null) {
|
||||
query.processDefinitionCategory(propertyWalker.getProperty("category", WhereClauseParser.EQUALS));
|
||||
String categoryProperty = propertyWalker.getProperty("category", WhereClauseParser.EQUALS);
|
||||
if (categoryProperty != null)
|
||||
{
|
||||
query.processDefinitionCategory(categoryProperty);
|
||||
}
|
||||
if(propertyWalker.getProperty("key", WhereClauseParser.EQUALS) != null) {
|
||||
query.processDefinitionKey(propertyWalker.getProperty("key", WhereClauseParser.EQUALS));
|
||||
|
||||
String keyProperty = propertyWalker.getProperty("key", WhereClauseParser.EQUALS);
|
||||
if (keyProperty != null)
|
||||
{
|
||||
query.processDefinitionKey(getProcessDefinitionKey(keyProperty));
|
||||
keyQueryIncluded = true;
|
||||
}
|
||||
if(propertyWalker.getProperty("name", WhereClauseParser.EQUALS) != null) {
|
||||
query.processDefinitionName(propertyWalker.getProperty("name", WhereClauseParser.EQUALS));
|
||||
|
||||
String nameProperty = propertyWalker.getProperty("name", WhereClauseParser.EQUALS);
|
||||
if (nameProperty != null)
|
||||
{
|
||||
query.processDefinitionName(nameProperty);
|
||||
}
|
||||
if(propertyWalker.getProperty("version", WhereClauseParser.EQUALS) != null) {
|
||||
query.processDefinitionVersion(propertyWalker.getProperty("version", WhereClauseParser.EQUALS, Integer.class));
|
||||
|
||||
Integer versionProperty = propertyWalker.getProperty("version", WhereClauseParser.EQUALS, Integer.class);
|
||||
if (versionProperty != null)
|
||||
{
|
||||
query.processDefinitionVersion(versionProperty);
|
||||
}
|
||||
if(propertyWalker.getProperty("deploymentId", WhereClauseParser.EQUALS) != null) {
|
||||
query.deploymentId(propertyWalker.getProperty("deploymentId", WhereClauseParser.EQUALS));
|
||||
|
||||
String deploymentProperty = propertyWalker.getProperty("deploymentId", WhereClauseParser.EQUALS);
|
||||
if (deploymentProperty != null)
|
||||
{
|
||||
query.deploymentId(deploymentProperty);
|
||||
}
|
||||
|
||||
// Property matches
|
||||
if(propertyWalker.getProperty("category", WhereClauseParser.MATCHES) != null) {
|
||||
query.processDefinitionCategoryLike(propertyWalker.getProperty("category", WhereClauseParser.MATCHES));
|
||||
String categoryMatchesProperty = propertyWalker.getProperty("category", WhereClauseParser.MATCHES);
|
||||
if (categoryMatchesProperty != null)
|
||||
{
|
||||
query.processDefinitionCategoryLike(categoryMatchesProperty);
|
||||
}
|
||||
if(propertyWalker.getProperty("key", WhereClauseParser.MATCHES) != null) {
|
||||
query.processDefinitionKeyLike(propertyWalker.getProperty("key", WhereClauseParser.MATCHES));
|
||||
|
||||
String keyMatchesProperty = propertyWalker.getProperty("key", WhereClauseParser.MATCHES);
|
||||
if (keyMatchesProperty != null)
|
||||
{
|
||||
query.processDefinitionKeyLike(getProcessDefinitionKey(keyMatchesProperty));
|
||||
keyQueryIncluded = true;
|
||||
}
|
||||
if(propertyWalker.getProperty("name", WhereClauseParser.MATCHES) != null) {
|
||||
query.processDefinitionNameLike(propertyWalker.getProperty("name", WhereClauseParser.MATCHES));
|
||||
|
||||
String nameLikeProperty = propertyWalker.getProperty("name", WhereClauseParser.MATCHES);
|
||||
if (nameLikeProperty != null)
|
||||
{
|
||||
query.processDefinitionNameLike(nameLikeProperty);
|
||||
}
|
||||
}
|
||||
|
||||
// Filter based on tenant, if required
|
||||
if (keyQueryIncluded == false && tenantService.isEnabled() && deployWorkflowsInTenant)
|
||||
{
|
||||
query.processDefinitionKeyLike("@" + TenantUtil.getCurrentDomain() + "@%");
|
||||
}
|
||||
|
||||
String sortParam = parameters.getParameter("sort");
|
||||
if (sortParam != null)
|
||||
{
|
||||
if (PROCESS_DEFINITION_COLLECTION_SORT_PROPERTIES.contains(sortParam))
|
||||
{
|
||||
if ("id".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessDefinitionId();
|
||||
}
|
||||
else if ("deploymentId".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByDeploymentId();
|
||||
}
|
||||
else if ("key".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessDefinitionKey();
|
||||
}
|
||||
else if ("category".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessDefinitionCategory();
|
||||
}
|
||||
else if ("version".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessDefinitionVersion();
|
||||
}
|
||||
else if ("name".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessDefinitionName();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("sort " + sortParam +
|
||||
" is not supported, supported items are " + PROCESS_DEFINITION_COLLECTION_SORT_PROPERTIES.toArray());
|
||||
}
|
||||
|
||||
String sortOrderParam = parameters.getParameter("sortOrder");
|
||||
if (sortOrderParam != null)
|
||||
{
|
||||
if ("asc".equalsIgnoreCase(sortOrderParam))
|
||||
{
|
||||
query.asc();
|
||||
}
|
||||
else if ("desc".equalsIgnoreCase(sortOrderParam))
|
||||
{
|
||||
query.desc();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("sort order " + sortOrderParam +
|
||||
" is not supported, supported items are asc and desc");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query.orderByProcessDefinitionId().asc();
|
||||
}
|
||||
|
||||
List<org.activiti.engine.repository.ProcessDefinition> processDefinitions =
|
||||
query.listPage(parameters.getPaging().getSkipCount(), parameters.getPaging().getMaxItems());
|
||||
|
||||
@@ -160,10 +258,70 @@ public class ProcessDefinitionsImpl extends WorkflowRestImpl implements ProcessD
|
||||
ProcessDefinition deploymentRest = createProcessDefinitionRest((ProcessDefinitionEntity) processDefinition);
|
||||
return deploymentRest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryResource getProcessDefinitionImage(String definitionId)
|
||||
{
|
||||
ProcessDefinitionQuery query = activitiProcessEngine
|
||||
.getRepositoryService()
|
||||
.createProcessDefinitionQuery()
|
||||
.processDefinitionId(definitionId);
|
||||
|
||||
if (tenantService.isEnabled() && deployWorkflowsInTenant)
|
||||
{
|
||||
query.processDefinitionKeyLike("@" + TenantUtil.getCurrentDomain() + "@%");
|
||||
}
|
||||
|
||||
org.activiti.engine.repository.ProcessDefinition processDefinition = query.singleResult();
|
||||
|
||||
if (processDefinition == null)
|
||||
{
|
||||
throw new EntityNotFoundException(definitionId);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
InputStream processDiagram = activitiProcessEngine.getRepositoryService().getProcessDiagram(definitionId);
|
||||
if (processDiagram != null)
|
||||
{
|
||||
File file = TempFileProvider.createTempFile(definitionId + UUID.randomUUID(), ".png");
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
IOUtils.copy(processDiagram, fos);
|
||||
fos.close();
|
||||
|
||||
return new FileBinaryResource(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ApiException("No image available for definitionId " + definitionId);
|
||||
}
|
||||
}
|
||||
catch (IOException error)
|
||||
{
|
||||
throw new ApiException("Error while getting process definition image.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<FormModelElement> getStartFormModel(String definitionId, Paging paging)
|
||||
{
|
||||
// first validate if user is allowed to access the process definition if workflows are deployed per tenant
|
||||
if (tenantService.isEnabled() && deployWorkflowsInTenant)
|
||||
{
|
||||
ProcessDefinitionQuery query = activitiProcessEngine
|
||||
.getRepositoryService()
|
||||
.createProcessDefinitionQuery()
|
||||
.processDefinitionId(definitionId);
|
||||
|
||||
query.processDefinitionKeyLike("@" + TenantUtil.getCurrentDomain() + "@%");
|
||||
org.activiti.engine.repository.ProcessDefinition processDefinition = query.singleResult();
|
||||
|
||||
if (processDefinition == null)
|
||||
{
|
||||
throw new EntityNotFoundException(definitionId);
|
||||
}
|
||||
}
|
||||
|
||||
StartFormData startFormData = activitiProcessEngine.getFormService().getStartFormData(definitionId);
|
||||
if (startFormData == null)
|
||||
{
|
||||
@@ -183,23 +341,88 @@ public class ProcessDefinitionsImpl extends WorkflowRestImpl implements ProcessD
|
||||
TypeDefinition startTaskType = workflowFactory.getTaskFullTypeDefinition(startFormData.getFormKey(), true);
|
||||
return getFormModelElements(startTaskType, paging);
|
||||
}
|
||||
|
||||
protected String getProcessDefinitionKey(String key)
|
||||
{
|
||||
String processDefKey = null;
|
||||
if (tenantService.isEnabled() && deployWorkflowsInTenant)
|
||||
{
|
||||
processDefKey = "@" + TenantUtil.getCurrentDomain() + "@" + key;
|
||||
}
|
||||
else
|
||||
{
|
||||
processDefKey = key;
|
||||
}
|
||||
return processDefKey;
|
||||
}
|
||||
|
||||
protected String getLocalProcessDefinitionKey(String key)
|
||||
{
|
||||
String processDefKey = null;
|
||||
if (tenantService.isEnabled() && deployWorkflowsInTenant)
|
||||
{
|
||||
processDefKey = key.substring(key.lastIndexOf("@") + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
processDefKey = key;
|
||||
}
|
||||
return processDefKey;
|
||||
}
|
||||
|
||||
protected ProcessDefinition createProcessDefinitionRest(ProcessDefinitionEntity processDefinition)
|
||||
{
|
||||
ProcessDefinition processDefinitionRest = new ProcessDefinition(processDefinition);
|
||||
String localKey = getLocalProcessDefinitionKey(processDefinition.getKey());
|
||||
processDefinitionRest.setKey(localKey);
|
||||
|
||||
String displayId = localKey + ".workflow";
|
||||
processDefinitionRest.setTitle(getLabel(displayId, "title"));
|
||||
processDefinitionRest.setDescription(getLabel(displayId, "description"));
|
||||
|
||||
processDefinitionRest.setGraphicNotationDefined(processDefinition.isGraphicalNotationDefined());
|
||||
if (processDefinition.hasStartFormKey())
|
||||
{
|
||||
try {
|
||||
StartFormData startFormData = activitiProcessEngine.getFormService().getStartFormData(processDefinition.getId());
|
||||
try
|
||||
{
|
||||
StartFormData startFormData = null;
|
||||
ProcessDefinitionEntity definitionEntity = getCachedProcessDefinition(processDefinition.getId());
|
||||
if (definitionEntity != null)
|
||||
{
|
||||
StartFormHandler startFormHandler = definitionEntity.getStartFormHandler();
|
||||
if (startFormHandler == null) {
|
||||
throw new ApiException("No start form defined for " + processDefinition.getId());
|
||||
}
|
||||
|
||||
startFormData = startFormHandler.createStartFormData(definitionEntity);
|
||||
}
|
||||
else
|
||||
{
|
||||
startFormData = activitiProcessEngine.getFormService().getStartFormData(processDefinition.getId());
|
||||
}
|
||||
|
||||
if (startFormData != null)
|
||||
{
|
||||
processDefinitionRest.setStartFormResourceKey(startFormData.getFormKey());
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (ApiException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ApiException("Error while retrieving start form key");
|
||||
}
|
||||
}
|
||||
return processDefinitionRest;
|
||||
}
|
||||
|
||||
protected String getLabel(String displayId, String labelKey)
|
||||
{
|
||||
String keyBase = displayId.replace(":", "_");
|
||||
String key = keyBase+ "." + labelKey;
|
||||
String label = messageService.getMessage(key);
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
@@ -39,13 +39,11 @@ import org.activiti.engine.RuntimeService;
|
||||
import org.activiti.engine.form.StartFormData;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
import org.activiti.engine.history.HistoricProcessInstanceQuery;
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.history.HistoricTaskInstanceQuery;
|
||||
import org.activiti.engine.history.HistoricVariableInstance;
|
||||
import org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator;
|
||||
import org.activiti.engine.impl.identity.Authentication;
|
||||
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.engine.repository.ProcessDefinitionQuery;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.i18n.MessageService;
|
||||
@@ -71,7 +69,6 @@ import org.alfresco.rest.antlr.WhereClauseParser;
|
||||
import org.alfresco.rest.framework.core.exceptions.ApiException;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||
import org.alfresco.rest.framework.resource.content.FileBinaryResource;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
@@ -90,12 +87,15 @@ import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
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.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.namespace.InvalidQNameException;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ISO8601DateFormat;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.alfresco.util.collections.CollectionUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -142,6 +142,10 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
"startedAt", "endedAt"
|
||||
));
|
||||
|
||||
private static final Set<String> PROCESS_COLLECTION_SORT_PROPERTIES = new HashSet<String>(Arrays.asList(
|
||||
"processDefinitionId", "businessKey", "id", "startedAt", "endedAt", "durationInMillis"
|
||||
));
|
||||
|
||||
public void setAuthorityDAO(AuthorityDAO authorityDAO)
|
||||
{
|
||||
this.authorityDAO = authorityDAO;
|
||||
@@ -303,8 +307,7 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
|
||||
final HistoricProcessInstanceQuery query = activitiProcessEngine
|
||||
.getHistoryService()
|
||||
.createHistoricProcessInstanceQuery()
|
||||
.orderByProcessInstanceStartTime().desc();
|
||||
.createHistoricProcessInstanceQuery();
|
||||
|
||||
if (processDefinitionId != null) query.processDefinitionId(processDefinitionId);
|
||||
if (businessKey != null) query.processInstanceBusinessKey(businessKey);
|
||||
@@ -400,12 +403,71 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
query.involvedUser(AuthenticationUtil.getRunAsUser());
|
||||
}
|
||||
|
||||
String sortParam = parameters.getParameter("sort");
|
||||
if (sortParam != null)
|
||||
{
|
||||
if (PROCESS_COLLECTION_SORT_PROPERTIES.contains(sortParam))
|
||||
{
|
||||
if ("processDefinitionId".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessDefinitionId();
|
||||
}
|
||||
else if ("id".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessInstanceId();
|
||||
}
|
||||
else if ("businessKey".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessInstanceBusinessKey();
|
||||
}
|
||||
else if ("startedAt".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessInstanceStartTime();
|
||||
}
|
||||
else if ("endedAt".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessInstanceEndTime();
|
||||
}
|
||||
else if ("durationInMillis".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessInstanceDuration();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("sort " + sortParam +
|
||||
" is not supported, supported items are " + PROCESS_COLLECTION_SORT_PROPERTIES.toArray());
|
||||
}
|
||||
|
||||
String sortOrderParam = parameters.getParameter("sortOrder");
|
||||
if (sortOrderParam != null)
|
||||
{
|
||||
if ("asc".equalsIgnoreCase(sortOrderParam))
|
||||
{
|
||||
query.asc();
|
||||
}
|
||||
else if ("desc".equalsIgnoreCase(sortOrderParam))
|
||||
{
|
||||
query.desc();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("sort order " + sortOrderParam +
|
||||
" is not supported, supported items are asc and desc");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query.orderByProcessInstanceStartTime().desc();
|
||||
}
|
||||
|
||||
List<HistoricProcessInstance> processInstances = query.listPage(paging.getSkipCount(), paging.getMaxItems());
|
||||
|
||||
List<ProcessInfo> page = new ArrayList<ProcessInfo>(processInstances.size());
|
||||
for (HistoricProcessInstance processInstance: processInstances)
|
||||
{
|
||||
page.add(new ProcessInfo(processInstance));
|
||||
page.add(createProcessInfo(processInstance));
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, page, false, page.size());
|
||||
@@ -419,8 +481,6 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
throw new InvalidArgumentException("processId is required to get the process info");
|
||||
}
|
||||
|
||||
validateIfUserAllowedToWorkWithProcess(processId);
|
||||
|
||||
HistoricProcessInstance processInstance = activitiProcessEngine
|
||||
.getHistoryService()
|
||||
.createHistoricProcessInstanceQuery()
|
||||
@@ -429,10 +489,10 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
|
||||
if (processInstance == null)
|
||||
{
|
||||
throw new EntityNotFoundException("could not find process for id " + processId);
|
||||
throw new EntityNotFoundException(processId);
|
||||
}
|
||||
|
||||
return new ProcessInfo(processInstance);
|
||||
return createProcessInfo(processInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -455,7 +515,7 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
ProcessDefinition definition = activitiProcessEngine
|
||||
.getRepositoryService()
|
||||
.createProcessDefinitionQuery()
|
||||
.processDefinitionKey(createProcessDefinitionKey(process.getProcessDefinitionKey()))
|
||||
.processDefinitionKey(getProcessDefinitionKey(process.getProcessDefinitionKey()))
|
||||
.latestVersion()
|
||||
.singleResult();
|
||||
|
||||
@@ -475,7 +535,17 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
if(!definitionExistingChecked)
|
||||
{
|
||||
// Check if the required definition actually exists
|
||||
if(activitiProcessEngine.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(processDefinitionId).count() == 0)
|
||||
ProcessDefinitionQuery query = activitiProcessEngine
|
||||
.getRepositoryService()
|
||||
.createProcessDefinitionQuery()
|
||||
.processDefinitionId(processDefinitionId);
|
||||
|
||||
if (tenantService.isEnabled() && deployWorkflowsInTenant)
|
||||
{
|
||||
query.processDefinitionKeyLike("@" + TenantUtil.getCurrentDomain() + "@%");
|
||||
}
|
||||
|
||||
if(query.count() == 0)
|
||||
{
|
||||
throw new InvalidArgumentException("No workflow definition could be found with id '" + processDefinitionId +"'.");
|
||||
}
|
||||
@@ -512,10 +582,14 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
if (taskAssociations.containsKey(propNameMap.get(variableName)))
|
||||
{
|
||||
AssociationDefinition associationDef = taskAssociations.get(propNameMap.get(variableName));
|
||||
if (variableValue != null && "person".equalsIgnoreCase(associationDef.getTargetClass().getTitle(dictionaryService)))
|
||||
if (variableValue != null && ContentModel.TYPE_PERSON.equals(associationDef.getTargetClass().getName()))
|
||||
{
|
||||
variableValue = getPersonNodeRef(variableValue.toString());
|
||||
}
|
||||
else if (variableValue != null && ContentModel.TYPE_AUTHORITY_CONTAINER.equals(associationDef.getTargetClass().getName()))
|
||||
{
|
||||
variableValue = authorityService.getAuthorityNodeRef(variableValue.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (variableValue instanceof Serializable)
|
||||
@@ -533,28 +607,29 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
NodeRef workflowPackageNodeRef = null;
|
||||
try
|
||||
{
|
||||
workflowPackageNodeRef = workflowPackageComponent.createPackage(null);
|
||||
startParams.put(WorkflowModel.ASSOC_PACKAGE, workflowPackageNodeRef);
|
||||
workflowPackageNodeRef = workflowPackageComponent.createPackage(null);
|
||||
startParams.put(WorkflowModel.ASSOC_PACKAGE, workflowPackageNodeRef);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ApiException("couldn't create workflow package: " + e.getMessage(), e);
|
||||
throw new ApiException("couldn't create workflow package: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (org.apache.commons.collections.CollectionUtils.isNotEmpty(process.getItems()))
|
||||
{
|
||||
try
|
||||
{
|
||||
for (String item: process.getItems())
|
||||
try
|
||||
{
|
||||
QName workflowPackageItemId = QName.createQName("wpi", item);
|
||||
nodeService.addChild(workflowPackageNodeRef, new NodeRef(item), WorkflowModel.ASSOC_PACKAGE_CONTAINS, workflowPackageItemId);
|
||||
for (String item: process.getItems())
|
||||
{
|
||||
NodeRef itemNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, item);
|
||||
QName workflowPackageItemId = QName.createQName("wpi", itemNodeRef.toString());
|
||||
nodeService.addChild(workflowPackageNodeRef, itemNodeRef, WorkflowModel.ASSOC_PACKAGE_CONTAINS, workflowPackageItemId);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ApiException("Error while adding items to package: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ApiException("Error while adding items to package: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// Set start task properties. This should be done before instance is started, since it's id will be used
|
||||
@@ -578,7 +653,7 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
}
|
||||
}
|
||||
|
||||
if(tenantService.isEnabled())
|
||||
if (tenantService.isEnabled())
|
||||
{
|
||||
// Specify which tenant domain the workflow was started in.
|
||||
variables.put(ActivitiConstants.VAR_TENANT_DOMAIN, TenantUtil.getCurrentDomain());
|
||||
@@ -598,7 +673,7 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
.processInstanceId(processInstance.getId())
|
||||
.singleResult();
|
||||
|
||||
return new ProcessInfo(historicProcessInstance);
|
||||
return createProcessInfo(historicProcessInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -673,7 +748,7 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
List<ChildAssociationRef> documentList = nodeService.getChildAssocs(packageScriptNode.getNodeRef());
|
||||
for (ChildAssociationRef childAssociationRef : documentList)
|
||||
{
|
||||
if (childAssociationRef.getChildRef().toString().equals(itemId))
|
||||
if (childAssociationRef.getChildRef().getId().equals(itemId))
|
||||
{
|
||||
item = createItemForNodeRef(childAssociationRef.getChildRef());
|
||||
break;
|
||||
@@ -718,10 +793,22 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
throw new InvalidArgumentException("process doesn't contain a workflow package variable");
|
||||
}
|
||||
|
||||
// check if noderef exists
|
||||
try
|
||||
{
|
||||
QName workflowPackageItemId = QName.createQName("wpi", item.getId());
|
||||
nodeService.addChild(packageScriptNode.getNodeRef(), new NodeRef(item.getId()), WorkflowModel.ASSOC_PACKAGE_CONTAINS, workflowPackageItemId);
|
||||
nodeService.getProperties(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, item.getId()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new EntityNotFoundException("item with id " + item.getId() + " not found");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef itemNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, item.getId());
|
||||
QName workflowPackageItemId = QName.createQName("wpi", itemNodeRef.toString());
|
||||
nodeService.addChild(packageScriptNode.getNodeRef(), itemNodeRef,
|
||||
WorkflowModel.ASSOC_PACKAGE_CONTAINS, workflowPackageItemId);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -761,13 +848,29 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
throw new InvalidArgumentException("process doesn't contain a workflow package variable");
|
||||
}
|
||||
|
||||
boolean itemIdFoundInPackage = false;
|
||||
List<ChildAssociationRef> documentList = nodeService.getChildAssocs(packageScriptNode.getNodeRef());
|
||||
for (ChildAssociationRef childAssociationRef : documentList)
|
||||
{
|
||||
if (childAssociationRef.getChildRef().getId().equals(itemId))
|
||||
{
|
||||
itemIdFoundInPackage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (itemIdFoundInPackage == false)
|
||||
{
|
||||
throw new EntityNotFoundException("Item " + itemId + " not found in the process package variable");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
nodeService.removeChild(packageScriptNode.getNodeRef(), new NodeRef(itemId));
|
||||
nodeService.removeChild(packageScriptNode.getNodeRef(), new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, itemId));
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (InvalidNodeRefException e)
|
||||
{
|
||||
throw new ApiException("could not delete item from process " + e.getMessage(), e);
|
||||
throw new EntityNotFoundException("Item " + itemId + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,6 +925,7 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
{
|
||||
formKey = startFormData.getFormKey();
|
||||
}
|
||||
|
||||
TypeDefinition startTaskTypeDefinition = workflowFactory.getTaskFullTypeDefinition(formKey, true);
|
||||
|
||||
// Convert raw variables to Variable objects
|
||||
@@ -838,12 +942,41 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
ProcessInstance processInstance = activitiProcessEngine.getRuntimeService().createProcessInstanceQuery()
|
||||
.processInstanceId(processId).singleResult();
|
||||
|
||||
if(processInstance == null)
|
||||
if (processInstance == null)
|
||||
{
|
||||
throw new EntityNotFoundException(processId);
|
||||
}
|
||||
|
||||
if(variable.getName() == null)
|
||||
return updateVariableInProcess(processId, variable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Variable> updateVariables(String processId, List<Variable> variables)
|
||||
{
|
||||
validateIfUserAllowedToWorkWithProcess(processId);
|
||||
|
||||
ProcessInstance processInstance = activitiProcessEngine.getRuntimeService().createProcessInstanceQuery()
|
||||
.processInstanceId(processId).singleResult();
|
||||
|
||||
if (processInstance == null)
|
||||
{
|
||||
throw new EntityNotFoundException(processId);
|
||||
}
|
||||
|
||||
List<Variable> updatedVariables = new ArrayList<Variable>();
|
||||
if (variables != null)
|
||||
{
|
||||
for (Variable variable : variables)
|
||||
{
|
||||
updatedVariables.add(updateVariableInProcess(processId, variable));
|
||||
}
|
||||
}
|
||||
return updatedVariables;
|
||||
}
|
||||
|
||||
protected Variable updateVariableInProcess(String processId,Variable variable)
|
||||
{
|
||||
if (variable.getName() == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Variable name is required.");
|
||||
}
|
||||
@@ -872,9 +1005,18 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
throw new InvalidArgumentException("Unsupported type of variable: '" + variable.getType() +"'.");
|
||||
}
|
||||
|
||||
Object actualValue = null;
|
||||
if ("java.util.Date".equalsIgnoreCase(dataTypeDefinition.getJavaClassName()))
|
||||
{
|
||||
// fix for different ISO 8601 Date format classes in Alfresco (org.alfresco.util and Spring Surf)
|
||||
actualValue = ISO8601DateFormat.parse((String) variable.getValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
actualValue = DefaultTypeConverter.INSTANCE.convert(dataTypeDefinition, variable.getValue());
|
||||
}
|
||||
variable.setValue(actualValue);
|
||||
|
||||
// Get raw variable value and set value
|
||||
Object actualValue = DefaultTypeConverter.INSTANCE.convert(dataTypeDefinition, variable.getValue());
|
||||
activitiProcessEngine.getRuntimeService().setVariable(processId, variable.getName(), actualValue);
|
||||
|
||||
// Set actual used type before returning
|
||||
@@ -921,13 +1063,10 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
|
||||
try
|
||||
{
|
||||
ProcessDefinition procDef = activitiProcessEngine.getRepositoryService().createProcessDefinitionQuery()
|
||||
.processDefinitionId(processInstance.getProcessDefinitionId())
|
||||
.singleResult();
|
||||
BpmnModel model = activitiProcessEngine.getRepositoryService().getBpmnModel(processInstance.getProcessDefinitionId());
|
||||
|
||||
if(((ProcessDefinitionEntity) procDef).isGraphicalNotationDefined())
|
||||
if(model != null && model.getLocationMap().size() > 0)
|
||||
{
|
||||
BpmnModel model = activitiProcessEngine.getRepositoryService().getBpmnModel(processInstance.getProcessDefinitionId());
|
||||
List<String> activeActivities = activitiProcessEngine.getRuntimeService().getActiveActivityIds(processId);
|
||||
InputStream generateDiagram = ProcessDiagramGenerator.generateDiagram(model, "png", activeActivities);
|
||||
|
||||
@@ -949,65 +1088,7 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateIfUserAllowedToWorkWithProcess(String processId)
|
||||
{
|
||||
if (tenantService.isEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
String tenantDomain = (String) activitiProcessEngine.getRuntimeService().getVariable(processId, ActivitiConstants.VAR_TENANT_DOMAIN);
|
||||
if (TenantUtil.getCurrentDomain().equals(tenantDomain) == false)
|
||||
{
|
||||
throw new PermissionDeniedException("Process is running in another tenant");
|
||||
}
|
||||
}
|
||||
catch (ActivitiObjectNotFoundException e)
|
||||
{
|
||||
throw new EntityNotFoundException(processId);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ActivitiScriptNode initiator = (ActivitiScriptNode) activitiProcessEngine.getRuntimeService().getVariable(processId, WorkflowConstants.PROP_INITIATOR);
|
||||
if (AuthenticationUtil.getRunAsUser().equals(initiator.getNodeRef().getId()))
|
||||
{
|
||||
// user is allowed
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (ActivitiObjectNotFoundException e)
|
||||
{
|
||||
throw new EntityNotFoundException(processId);
|
||||
}
|
||||
|
||||
HistoricTaskInstanceQuery query = activitiProcessEngine.getHistoryService()
|
||||
.createHistoricTaskInstanceQuery()
|
||||
.processInstanceId(processId);
|
||||
|
||||
if (authorityService.isAdminAuthority(AuthenticationUtil.getRunAsUser()))
|
||||
{
|
||||
// Admin is allowed to read all processes in the current tenant
|
||||
if (tenantService.isEnabled())
|
||||
{
|
||||
query.processVariableValueEquals(ActivitiConstants.VAR_TENANT_DOMAIN, TenantUtil.getCurrentDomain());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If non-admin user, involvement in the task is required (either owner, assignee or externally involved).
|
||||
query.taskInvolvedUser(AuthenticationUtil.getRunAsUser());
|
||||
}
|
||||
|
||||
List<HistoricTaskInstance> taskList = query.list();
|
||||
|
||||
if(org.apache.commons.collections.CollectionUtils.isEmpty(taskList))
|
||||
{
|
||||
throw new PermissionDeniedException("user is not allowed to access information about process " + processId);
|
||||
}
|
||||
}
|
||||
|
||||
protected String createProcessDefinitionKey(String paramProcessDefinitionKey)
|
||||
protected String getProcessDefinitionKey(String paramProcessDefinitionKey)
|
||||
{
|
||||
String processDefinitionKey = null;
|
||||
if (tenantService.isEnabled() && deployWorkflowsInTenant)
|
||||
@@ -1020,6 +1101,20 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
}
|
||||
return processDefinitionKey;
|
||||
}
|
||||
|
||||
protected String getLocalProcessDefinitionKey(String key)
|
||||
{
|
||||
String processDefKey = null;
|
||||
if (tenantService.isEnabled() && deployWorkflowsInTenant)
|
||||
{
|
||||
processDefKey = key.substring(key.lastIndexOf("@") + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
processDefKey = key;
|
||||
}
|
||||
return processDefKey;
|
||||
}
|
||||
|
||||
protected NodeRef getPersonNodeRef(String name)
|
||||
{
|
||||
@@ -1034,6 +1129,18 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
return authority;
|
||||
}
|
||||
|
||||
protected ProcessInfo createProcessInfo(HistoricProcessInstance processInstance)
|
||||
{
|
||||
ProcessInfo processInfo = new ProcessInfo(processInstance);
|
||||
ProcessDefinition definitionEntity = getCachedProcessDefinition(processInstance.getProcessDefinitionId());
|
||||
if (definitionEntity == null)
|
||||
{
|
||||
definitionEntity = activitiProcessEngine.getRepositoryService().getProcessDefinition(processInstance.getProcessDefinitionId());
|
||||
}
|
||||
processInfo.setProcessDefinitionKey(getLocalProcessDefinitionKey(definitionEntity.getKey()));
|
||||
return processInfo;
|
||||
}
|
||||
|
||||
protected Item createItemForNodeRef(NodeRef nodeRef) {
|
||||
Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
||||
Item item = new Item();
|
||||
@@ -1047,7 +1154,7 @@ public class ProcessesImpl extends WorkflowRestImpl implements Processes
|
||||
|
||||
ContentData contentData = (ContentData) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
|
||||
|
||||
item.setId(nodeRef.toString());
|
||||
item.setId(nodeRef.getId());
|
||||
item.setName(name);
|
||||
item.setTitle(title);
|
||||
item.setDescription(description);
|
||||
|
@@ -30,6 +30,8 @@ import org.activiti.engine.ActivitiTaskAlreadyClaimedException;
|
||||
import org.activiti.engine.form.FormData;
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.history.HistoricTaskInstanceQuery;
|
||||
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.activiti.engine.impl.task.TaskDefinition;
|
||||
import org.activiti.engine.task.IdentityLink;
|
||||
import org.activiti.engine.task.IdentityLinkType;
|
||||
import org.activiti.engine.task.TaskQuery;
|
||||
@@ -57,6 +59,7 @@ import org.alfresco.rest.workflow.api.model.FormModelElement;
|
||||
import org.alfresco.rest.workflow.api.model.Item;
|
||||
import org.alfresco.rest.workflow.api.model.Task;
|
||||
import org.alfresco.rest.workflow.api.model.TaskCandidate;
|
||||
import org.alfresco.rest.workflow.api.model.TaskStateTransition;
|
||||
import org.alfresco.rest.workflow.api.model.TaskVariable;
|
||||
import org.alfresco.rest.workflow.api.model.VariableScope;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
@@ -64,8 +67,10 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.security.AuthorityType;
|
||||
import org.alfresco.service.namespace.InvalidQNameException;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ISO8601DateFormat;
|
||||
|
||||
public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
{
|
||||
@@ -76,12 +81,12 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
* All properties that are read-only and cannot be updated on a single task-resource.
|
||||
*/
|
||||
private static final List<String> TASK_READ_ONLY_PROPERTIES = Arrays.asList(
|
||||
"id", "processId", "processDefinitionId", "actibityDefinitionId", "startedAt", "endedAt", "durationInMs", "formResourceKey"
|
||||
"id", "processId", "processDefinitionId", "activityDefinitionId", "startedAt", "endedAt", "durationInMs", "formResourceKey"
|
||||
);
|
||||
|
||||
private static final Set<String> TASK_COLLECTION_EQUALS_QUERY_PROPERTIES = new HashSet<String>(Arrays.asList(
|
||||
"status", "assignee", "owner", "candidateUser", "candidateGroup", "name", "description", "priority", "processInstanceId",
|
||||
"processInstanceBusinessKey", "activityDefinitionId", "processDefinitionId", "processDefinitionName", "startedAt", "dueAt"
|
||||
"status", "assignee", "owner", "candidateUser", "candidateGroup", "name", "description", "priority", "processId",
|
||||
"processBusinessKey", "activityDefinitionId", "processDefinitionId", "processDefinitionName", "startedAt", "dueAt"
|
||||
));
|
||||
|
||||
private static final Set<String> TASK_COLLECTION_MATCHES_QUERY_PROPERTIES = new HashSet<String>(Arrays.asList(
|
||||
@@ -104,6 +109,14 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
"priority"
|
||||
));
|
||||
|
||||
private static final Set<String> TASK_COLLECTION_RUNNING_SORT_PROPERTIES = new HashSet<String>(Arrays.asList(
|
||||
"id", "name", "description", "priority", "processId", "assignee", "startedAt", "dueAt"
|
||||
));
|
||||
|
||||
private static final Set<String> TASK_COLLECTION_HISTORY_SORT_PROPERTIES = new HashSet<String>(Arrays.asList(
|
||||
"id", "name", "description", "priority", "processId", "processDefinitionId", "assignee", "owner", "startedAt", "endedAt", "durationInMs", "dueAt"
|
||||
));
|
||||
|
||||
private RestVariableHelper restVariableHelper;
|
||||
private WorkflowObjectFactory workflowFactory;
|
||||
private WorkflowQNameConverter qNameConverter;
|
||||
@@ -155,8 +168,8 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
Integer priority = propertyWalker.getProperty("priority", WhereClauseParser.EQUALS, Integer.class);
|
||||
Integer priorityGreaterThanOrEquals = propertyWalker.getProperty("priority", WhereClauseParser.GREATERTHANOREQUALS, Integer.class);
|
||||
Integer priorityLessThanOrEquals = propertyWalker.getProperty("priority", WhereClauseParser.LESSTHANOREQUALS, Integer.class);
|
||||
String processInstanceId = propertyWalker.getProperty("processInstanceId", WhereClauseParser.EQUALS);
|
||||
String processInstanceBusinessKey = propertyWalker.getProperty("processInstanceBusinessKey", WhereClauseParser.EQUALS);
|
||||
String processInstanceId = propertyWalker.getProperty("processId", WhereClauseParser.EQUALS);
|
||||
String processInstanceBusinessKey = propertyWalker.getProperty("processBusinessKey", WhereClauseParser.EQUALS);
|
||||
String activityDefinitionId = propertyWalker.getProperty("activityDefinitionId", WhereClauseParser.EQUALS);
|
||||
String activityDefinitionIdLike = propertyWalker.getProperty("activityDefinitionId", WhereClauseParser.MATCHES);
|
||||
String processDefinitionId = propertyWalker.getProperty("processDefinitionId", WhereClauseParser.EQUALS);
|
||||
@@ -177,7 +190,30 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
|
||||
if (assignee != null) query.taskAssignee(assignee);
|
||||
if (owner != null) query.taskOwner(owner);
|
||||
if (candidateUser != null) query.taskCandidateUser(candidateUser);
|
||||
if (candidateUser != null)
|
||||
{
|
||||
Set<String> parents = authorityService.getContainingAuthorities(AuthorityType.GROUP, candidateUser, false);
|
||||
if (parents != null)
|
||||
{
|
||||
List<String> authorities = new ArrayList<String>();
|
||||
authorities.addAll(parents);
|
||||
|
||||
// there's a limitation in at least Oracle for using an IN statement with more than 1000 items
|
||||
if (parents.size() > 1000)
|
||||
{
|
||||
authorities = authorities.subList(0, 1000);
|
||||
}
|
||||
|
||||
if (authorities.size() > 0)
|
||||
{
|
||||
query.taskCandidateGroupIn(authorities);
|
||||
}
|
||||
else
|
||||
{
|
||||
query.taskCandidateUser(candidateUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (candidateGroup != null) query.taskCandidateGroup(candidateGroup);
|
||||
if (name != null) query.taskName(name);
|
||||
if (nameLike != null) query.taskNameLike(nameLike);
|
||||
@@ -208,6 +244,30 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
{
|
||||
query.taskVariableValueEquals(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.GREATERTHAN)
|
||||
{
|
||||
query.taskVariableValueGreaterThan(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.GREATERTHANOREQUALS)
|
||||
{
|
||||
query.taskVariableValueGreaterThanOrEqual(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.LESSTHAN)
|
||||
{
|
||||
query.taskVariableValueLessThan(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.LESSTHANOREQUALS)
|
||||
{
|
||||
query.taskVariableValueLessThanOrEqual(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.MATCHES)
|
||||
{
|
||||
if (queryVariableHolder.getPropertyValue() instanceof String == false)
|
||||
{
|
||||
throw new InvalidArgumentException("the matches operator can only be used with a String value for property " + queryVariableHolder.getPropertyName());
|
||||
}
|
||||
query.taskVariableValueLike(queryVariableHolder.getPropertyName(), (String) queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.NEGATION)
|
||||
{
|
||||
query.taskVariableValueNotEquals(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
@@ -285,6 +345,30 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
{
|
||||
query.taskVariableValueEquals(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.GREATERTHAN)
|
||||
{
|
||||
query.taskVariableValueGreaterThan(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.GREATERTHANOREQUALS)
|
||||
{
|
||||
query.taskVariableValueGreaterThanOrEqual(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.LESSTHAN)
|
||||
{
|
||||
query.taskVariableValueLessThan(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.LESSTHANOREQUALS)
|
||||
{
|
||||
query.taskVariableValueLessThanOrEqual(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.MATCHES)
|
||||
{
|
||||
if (queryVariableHolder.getPropertyValue() instanceof String == false)
|
||||
{
|
||||
throw new InvalidArgumentException("the matches operator can only be used with a String value for property " + queryVariableHolder.getPropertyName());
|
||||
}
|
||||
query.taskVariableValueLike(queryVariableHolder.getPropertyName(), (String) queryVariableHolder.getPropertyValue());
|
||||
}
|
||||
else if (queryVariableHolder.getOperator() == WhereClauseParser.NEGATION)
|
||||
{
|
||||
query.taskVariableValueNotEquals(queryVariableHolder.getPropertyName(), queryVariableHolder.getPropertyValue());
|
||||
@@ -325,6 +409,220 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, page, false, page.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Task> getTasks(String processId, Parameters parameters)
|
||||
{
|
||||
Paging paging = parameters.getPaging();
|
||||
String status = parameters.getParameter("status");
|
||||
|
||||
validateIfUserAllowedToWorkWithProcess(processId);
|
||||
|
||||
List<Task> page = null;
|
||||
if (status == null || STATUS_ACTIVE.equals(status))
|
||||
{
|
||||
TaskQuery query = activitiProcessEngine
|
||||
.getTaskService()
|
||||
.createTaskQuery();
|
||||
|
||||
query.processInstanceId(processId);
|
||||
|
||||
String sortParam = parameters.getParameter("sort");
|
||||
if (sortParam != null)
|
||||
{
|
||||
if (TASK_COLLECTION_RUNNING_SORT_PROPERTIES.contains(sortParam))
|
||||
{
|
||||
if ("id".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskId();
|
||||
}
|
||||
else if ("name".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskName();
|
||||
}
|
||||
else if ("description".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskDescription();
|
||||
}
|
||||
else if ("priority".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskPriority();
|
||||
}
|
||||
else if ("processId".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessInstanceId();
|
||||
}
|
||||
else if ("assignee".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskAssignee();
|
||||
}
|
||||
else if ("startedAt".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskCreateTime();
|
||||
}
|
||||
else if ("dueAt".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByDueDate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("sort " + sortParam +
|
||||
" is not supported, supported items are " + TASK_COLLECTION_RUNNING_SORT_PROPERTIES.toArray());
|
||||
}
|
||||
|
||||
String sortOrderParam = parameters.getParameter("sortOrder");
|
||||
if (sortOrderParam != null)
|
||||
{
|
||||
if ("asc".equalsIgnoreCase(sortOrderParam))
|
||||
{
|
||||
query.asc();
|
||||
}
|
||||
else if ("desc".equalsIgnoreCase(sortOrderParam))
|
||||
{
|
||||
query.desc();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("sort order " + sortOrderParam +
|
||||
" is not supported, supported items are asc and desc");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query.orderByDueDate().asc();
|
||||
}
|
||||
|
||||
List<org.activiti.engine.task.Task> tasks = query.listPage(paging.getSkipCount(), paging.getMaxItems());
|
||||
|
||||
page = new ArrayList<Task>(tasks.size());
|
||||
for (org.activiti.engine.task.Task taskInstance: tasks)
|
||||
{
|
||||
Task task = new Task(taskInstance);
|
||||
task.setFormResourceKey(getFormResourceKey(taskInstance));
|
||||
page.add(task);
|
||||
}
|
||||
}
|
||||
else if (STATUS_COMPLETED.equals(status) || STATUS_ANY.equals(status))
|
||||
{
|
||||
HistoricTaskInstanceQuery query = activitiProcessEngine
|
||||
.getHistoryService()
|
||||
.createHistoricTaskInstanceQuery();
|
||||
|
||||
if (STATUS_COMPLETED.equals(status)) query.finished();
|
||||
|
||||
query.processInstanceId(processId);
|
||||
|
||||
// Add tenant filtering
|
||||
if(tenantService.isEnabled()) {
|
||||
query.processVariableValueEquals(ActivitiConstants.VAR_TENANT_DOMAIN, TenantUtil.getCurrentDomain());
|
||||
}
|
||||
|
||||
// Add involvment filtering if user is not admin
|
||||
if(!authorityService.isAdminAuthority(AuthenticationUtil.getRunAsUser())) {
|
||||
query.taskInvolvedUser(AuthenticationUtil.getRunAsUser());
|
||||
}
|
||||
|
||||
String sortParam = parameters.getParameter("sort");
|
||||
if (sortParam != null)
|
||||
{
|
||||
if (TASK_COLLECTION_HISTORY_SORT_PROPERTIES.contains(sortParam))
|
||||
{
|
||||
if ("id".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskId();
|
||||
}
|
||||
else if ("name".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskName();
|
||||
}
|
||||
else if ("description".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskDescription();
|
||||
}
|
||||
else if ("priority".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskPriority();
|
||||
}
|
||||
else if ("processId".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessInstanceId();
|
||||
}
|
||||
else if ("processDefinitionId".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByProcessDefinitionId();
|
||||
}
|
||||
else if ("assignee".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskAssignee();
|
||||
}
|
||||
else if ("owner".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskOwner();
|
||||
}
|
||||
else if ("startedAt".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByHistoricTaskInstanceStartTime();
|
||||
}
|
||||
else if ("endedAt".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByHistoricTaskInstanceEndTime();
|
||||
}
|
||||
else if ("durationInMs".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByHistoricTaskInstanceDuration();
|
||||
}
|
||||
else if ("dueAt".equalsIgnoreCase(sortParam))
|
||||
{
|
||||
query.orderByTaskDueDate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("sort " + sortParam +
|
||||
" is not supported, supported items are " + TASK_COLLECTION_HISTORY_SORT_PROPERTIES.toArray());
|
||||
}
|
||||
|
||||
String sortOrderParam = parameters.getParameter("sortOrder");
|
||||
if (sortOrderParam != null)
|
||||
{
|
||||
if ("asc".equalsIgnoreCase(sortOrderParam))
|
||||
{
|
||||
query.asc();
|
||||
}
|
||||
else if ("desc".equalsIgnoreCase(sortOrderParam))
|
||||
{
|
||||
query.desc();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("sort order " + sortOrderParam +
|
||||
" is not supported, supported items are asc and desc");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query.orderByTaskDueDate().asc();
|
||||
}
|
||||
|
||||
List<HistoricTaskInstance> tasks = query.listPage(paging.getSkipCount(), paging.getMaxItems());
|
||||
|
||||
page = new ArrayList<Task>(tasks.size());
|
||||
for (HistoricTaskInstance taskInstance: tasks)
|
||||
{
|
||||
Task task = new Task(taskInstance);
|
||||
page.add(task);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Invalid status parameter: " + status);
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, page, false, page.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task getTask(String taskId)
|
||||
@@ -509,7 +807,7 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
}
|
||||
|
||||
// Lookup type definition for the task
|
||||
TypeDefinition taskType = workflowFactory.getTaskFullTypeDefinition(formData.getFormKey(), true);
|
||||
TypeDefinition taskType = getWorkflowFactory().getTaskFullTypeDefinition(formData.getFormKey(), true);
|
||||
return getFormModelElements(taskType, paging);
|
||||
}
|
||||
|
||||
@@ -543,7 +841,25 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
public TaskVariable updateTaskVariable(String taskId, TaskVariable taskVariable)
|
||||
{
|
||||
org.activiti.engine.task.Task taskInstance = getValidTask(taskId, true);
|
||||
|
||||
return updateVariableInTask(taskId, taskInstance, taskVariable);
|
||||
}
|
||||
|
||||
public List<TaskVariable> updateTaskVariables(String taskId, List<TaskVariable> variables)
|
||||
{
|
||||
org.activiti.engine.task.Task taskInstance = getValidTask(taskId, true);
|
||||
List<TaskVariable> updatedVariables = new ArrayList<TaskVariable>();
|
||||
if (variables != null)
|
||||
{
|
||||
for (TaskVariable variable : variables)
|
||||
{
|
||||
updatedVariables.add(updateVariableInTask(taskId, taskInstance, variable));
|
||||
}
|
||||
}
|
||||
return updatedVariables;
|
||||
}
|
||||
|
||||
protected TaskVariable updateVariableInTask(String taskId, org.activiti.engine.task.Task taskInstance, TaskVariable taskVariable)
|
||||
{
|
||||
if(taskVariable.getName() == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Variable name is required.");
|
||||
@@ -603,12 +919,22 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
}
|
||||
}
|
||||
|
||||
if(dataTypeDefinition == null)
|
||||
if (dataTypeDefinition == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Unsupported type of variable: '" + taskVariable.getType() +"'.");
|
||||
}
|
||||
|
||||
Object actualValue = DefaultTypeConverter.INSTANCE.convert(dataTypeDefinition, taskVariable.getValue());
|
||||
Object actualValue = null;
|
||||
if ("java.util.Date".equalsIgnoreCase(dataTypeDefinition.getJavaClassName()))
|
||||
{
|
||||
// fix for different ISO 8601 Date format classes in Alfresco (org.alfresco.util and Spring Surf)
|
||||
actualValue = ISO8601DateFormat.parse((String) taskVariable.getValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
actualValue = DefaultTypeConverter.INSTANCE.convert(dataTypeDefinition, taskVariable.getValue());
|
||||
}
|
||||
taskVariable.setValue(actualValue);
|
||||
|
||||
if (VariableScope.LOCAL.equals(taskVariable.getVariableScope()))
|
||||
{
|
||||
@@ -716,10 +1042,27 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
return processes.getItems(task.getProcessInstanceId(), paging);
|
||||
}
|
||||
|
||||
protected String getFormResourceKey(org.activiti.engine.task.Task task) {
|
||||
protected String getFormResourceKey(final org.activiti.engine.task.Task task)
|
||||
{
|
||||
if (task.getProcessDefinitionId() != null)
|
||||
{
|
||||
return activitiProcessEngine.getFormService().getTaskFormKey(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
ProcessDefinitionEntity definitionEntity = getCachedProcessDefinition(task.getProcessDefinitionId());
|
||||
|
||||
String formKey = null;
|
||||
if (definitionEntity != null)
|
||||
{
|
||||
TaskDefinition taskDefinition = definitionEntity.getTaskDefinitions().get(task.getTaskDefinitionKey());
|
||||
if (taskDefinition != null)
|
||||
{
|
||||
formKey = taskDefinition.getTaskFormHandler().getFormKey().getExpressionText();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
formKey = activitiProcessEngine.getFormService().getTaskFormKey(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||
}
|
||||
|
||||
return formKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -910,10 +1253,10 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
// Task is not yet finished, so potentially claimable. If user is part of a "candidateGroup", the task is accessible to the
|
||||
// user regardless of not being involved/owner/assignee
|
||||
isTaskClaimable = activitiProcessEngine.getTaskService()
|
||||
.createTaskQuery()
|
||||
.taskCandidateGroupIn(new ArrayList<String>(authorityService.getAuthoritiesForUser(AuthenticationUtil.getRunAsUser())))
|
||||
.taskId(taskId)
|
||||
.count() == 1;
|
||||
.createTaskQuery()
|
||||
.taskCandidateGroupIn(new ArrayList<String>(authorityService.getAuthoritiesForUser(AuthenticationUtil.getRunAsUser())))
|
||||
.taskId(taskId)
|
||||
.count() == 1;
|
||||
}
|
||||
|
||||
if(!isTaskClaimable)
|
||||
@@ -943,26 +1286,4 @@ public class TasksImpl extends WorkflowRestImpl implements Tasks
|
||||
}
|
||||
return workflowFactory;
|
||||
}
|
||||
|
||||
|
||||
private enum TaskStateTransition {
|
||||
|
||||
COMPLETED, CLAIMED, UNCLAIMED, DELEGATED, RESOLVED;
|
||||
|
||||
/**
|
||||
* @return the {@link TaskStateTransition} for the given string
|
||||
* @throws InvalidArgumentException when no action exists for the given string
|
||||
*/
|
||||
public static TaskStateTransition getTaskActionFromString(String action)
|
||||
{
|
||||
for(TaskStateTransition taskAction : values())
|
||||
{
|
||||
if(taskAction.name().toLowerCase().equals(action))
|
||||
{
|
||||
return taskAction;
|
||||
}
|
||||
}
|
||||
throw new InvalidArgumentException("The task state property has an invalid value: " + action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package org.alfresco.rest.workflow.api.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
@@ -9,16 +10,36 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.activiti.engine.ActivitiObjectNotFoundException;
|
||||
import org.activiti.engine.ProcessEngine;
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.history.HistoricTaskInstanceQuery;
|
||||
import org.activiti.engine.impl.ProcessEngineImpl;
|
||||
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||
import org.activiti.engine.impl.context.Context;
|
||||
import org.activiti.engine.impl.interceptor.Command;
|
||||
import org.activiti.engine.impl.interceptor.CommandContext;
|
||||
import org.activiti.engine.impl.persistence.deploy.DeploymentCache;
|
||||
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
import org.alfresco.repo.workflow.WorkflowConstants;
|
||||
import org.alfresco.repo.workflow.activiti.ActivitiConstants;
|
||||
import org.alfresco.repo.workflow.activiti.ActivitiScriptNode;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.workflow.api.model.FormModelElement;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.Constraint;
|
||||
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
@@ -42,6 +63,7 @@ public class WorkflowRestImpl
|
||||
protected DictionaryService dictionaryService;
|
||||
protected ProcessEngine activitiProcessEngine;
|
||||
protected boolean deployWorkflowsInTenant;
|
||||
protected List<String> excludeModelTypes = new ArrayList<String>(Arrays.asList("bpm_priority", "bpm_description", "bpm_dueDate"));
|
||||
|
||||
static
|
||||
{
|
||||
@@ -81,6 +103,32 @@ public class WorkflowRestImpl
|
||||
this.deployWorkflowsInTenant = deployWorkflowsInTenant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the process definition from the cache if available
|
||||
*
|
||||
* @param processDefinitionId the unique id identifier of the process definition
|
||||
*/
|
||||
public ProcessDefinitionEntity getCachedProcessDefinition(final String processDefinitionId)
|
||||
{
|
||||
ProcessEngineConfigurationImpl processConfig = (ProcessEngineConfigurationImpl) ((ProcessEngineImpl) activitiProcessEngine).getProcessEngineConfiguration();
|
||||
ProcessDefinitionEntity definitionEntity = processConfig.getCommandExecutorTxRequired().execute(new Command<ProcessDefinitionEntity>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public ProcessDefinitionEntity execute(CommandContext commandContext)
|
||||
{
|
||||
DeploymentCache<ProcessDefinitionEntity> cache = Context
|
||||
.getProcessEngineConfiguration()
|
||||
.getDeploymentManager()
|
||||
.getProcessDefinitionCache();
|
||||
|
||||
return cache.get(processDefinitionId);
|
||||
}
|
||||
|
||||
});
|
||||
return definitionEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first parameter value, converted to the requested type.
|
||||
* @param parameters used to extract parameter value from
|
||||
@@ -131,16 +179,33 @@ public class WorkflowRestImpl
|
||||
List<FormModelElement> page = new ArrayList<FormModelElement>();
|
||||
for (Entry<QName, PropertyDefinition> entry : taskProperties.entrySet())
|
||||
{
|
||||
String name = entry.getKey().toPrefixString(namespaceService).replace(':', '_');
|
||||
|
||||
// Only add properties which are not part of an excluded type
|
||||
if(!typesToExclude.contains(entry.getValue().getContainerClass().getName()))
|
||||
if(!typesToExclude.contains(entry.getValue().getContainerClass().getName()) && excludeModelTypes.contains(name) == false)
|
||||
{
|
||||
FormModelElement element = new FormModelElement();
|
||||
element.setName(entry.getKey().toPrefixString(namespaceService).replace(':', '_'));
|
||||
element.setName(name);
|
||||
element.setQualifiedName(entry.getKey().toString());
|
||||
element.setTitle(entry.getValue().getTitle(dictionaryService));
|
||||
element.setRequired(entry.getValue().isMandatory());
|
||||
element.setDataType(entry.getValue().getDataType().getName().toPrefixString(namespaceService));
|
||||
element.setDefaultValue(entry.getValue().getDefaultValue());
|
||||
if (entry.getValue().getConstraints() != null)
|
||||
{
|
||||
for (ConstraintDefinition constraintDef : entry.getValue().getConstraints())
|
||||
{
|
||||
Constraint constraint = constraintDef.getConstraint();
|
||||
if (constraint != null && constraint instanceof ListOfValuesConstraint)
|
||||
{
|
||||
ListOfValuesConstraint valuesConstraint = (ListOfValuesConstraint) constraint;
|
||||
if (valuesConstraint.getAllowedValues() != null && valuesConstraint.getAllowedValues().size() > 0)
|
||||
{
|
||||
element.setAllowedValues(valuesConstraint.getAllowedValues());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
page.add(element);
|
||||
}
|
||||
}
|
||||
@@ -174,7 +239,8 @@ public class WorkflowRestImpl
|
||||
|
||||
ClassDefinition parentClassDefinition = taskType.getParentClassDefinition();
|
||||
boolean contentClassFound = false;
|
||||
while(parentClassDefinition != null) {
|
||||
while(parentClassDefinition != null)
|
||||
{
|
||||
if(contentClassFound)
|
||||
{
|
||||
typesToExclude.add(parentClassDefinition.getName());
|
||||
@@ -190,4 +256,72 @@ public class WorkflowRestImpl
|
||||
}
|
||||
return typesToExclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if the logged in user is allowed to get information about a specific process instance.
|
||||
* If the user is not allowed an exception is thrown.
|
||||
*
|
||||
* @param processId identifier of the process instance
|
||||
*/
|
||||
protected void validateIfUserAllowedToWorkWithProcess(String processId)
|
||||
{
|
||||
if (tenantService.isEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
String tenantDomain = (String) activitiProcessEngine.getRuntimeService().getVariable(processId, ActivitiConstants.VAR_TENANT_DOMAIN);
|
||||
if (TenantUtil.getCurrentDomain().equals(tenantDomain) == false)
|
||||
{
|
||||
throw new PermissionDeniedException("Process is running in another tenant");
|
||||
}
|
||||
}
|
||||
catch (ActivitiObjectNotFoundException e)
|
||||
{
|
||||
throw new EntityNotFoundException(processId);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ActivitiScriptNode initiator = (ActivitiScriptNode) activitiProcessEngine.getRuntimeService().getVariable(processId, WorkflowConstants.PROP_INITIATOR);
|
||||
if (AuthenticationUtil.getRunAsUser().equals(initiator.getNodeRef().getId()))
|
||||
{
|
||||
// user is allowed
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (ActivitiObjectNotFoundException e)
|
||||
{
|
||||
throw new EntityNotFoundException(processId);
|
||||
}
|
||||
|
||||
HistoricTaskInstanceQuery query = activitiProcessEngine.getHistoryService()
|
||||
.createHistoricTaskInstanceQuery()
|
||||
.processInstanceId(processId);
|
||||
|
||||
if (authorityService.isAdminAuthority(AuthenticationUtil.getRunAsUser()))
|
||||
{
|
||||
// Admin is allowed to read all processes in the current tenant
|
||||
if (tenantService.isEnabled())
|
||||
{
|
||||
query.processVariableValueEquals(ActivitiConstants.VAR_TENANT_DOMAIN, TenantUtil.getCurrentDomain());
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If non-admin user, involvement in the task is required (either owner, assignee or externally involved).
|
||||
query.taskInvolvedUser(AuthenticationUtil.getRunAsUser());
|
||||
}
|
||||
|
||||
List<HistoricTaskInstance> taskList = query.list();
|
||||
|
||||
if(org.apache.commons.collections.CollectionUtils.isEmpty(taskList))
|
||||
{
|
||||
throw new PermissionDeniedException("user is not allowed to access information about process " + processId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
119
source/java/org/alfresco/rest/workflow/api/model/Activity.java
Normal file
119
source/java/org/alfresco/rest/workflow/api/model/Activity.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.activiti.engine.history.HistoricActivityInstance;
|
||||
|
||||
/**
|
||||
* Representation of an activity in the Activiti engine.
|
||||
*
|
||||
* @author Tijs Rademakers
|
||||
*/
|
||||
public class Activity
|
||||
{
|
||||
String id;
|
||||
String activityDefinitionId;
|
||||
String activityDefinitionName;
|
||||
String activityDefinitionType;
|
||||
Date startedAt;
|
||||
Date endedAt;
|
||||
Long durationInMs;
|
||||
|
||||
public Activity(HistoricActivityInstance activity) {
|
||||
this.id = activity.getId();
|
||||
this.activityDefinitionId = activity.getActivityId();
|
||||
this.activityDefinitionName = activity.getActivityName();
|
||||
this.activityDefinitionType = activity.getActivityType();
|
||||
this.startedAt = activity.getStartTime();
|
||||
this.endedAt = activity.getEndTime();
|
||||
this.durationInMs = activity.getDurationInMillis();
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getActivityDefinitionId()
|
||||
{
|
||||
return activityDefinitionId;
|
||||
}
|
||||
|
||||
public void setActivityDefinitionId(String activityDefinitionId)
|
||||
{
|
||||
this.activityDefinitionId = activityDefinitionId;
|
||||
}
|
||||
|
||||
public String getActivityDefinitionName()
|
||||
{
|
||||
return activityDefinitionName;
|
||||
}
|
||||
|
||||
public void setActivityDefinitionName(String activityDefinitionName)
|
||||
{
|
||||
this.activityDefinitionName = activityDefinitionName;
|
||||
}
|
||||
|
||||
public String getActivityDefinitionType()
|
||||
{
|
||||
return activityDefinitionType;
|
||||
}
|
||||
|
||||
public void setActivityDefinitionType(String activityDefinitionType)
|
||||
{
|
||||
this.activityDefinitionType = activityDefinitionType;
|
||||
}
|
||||
|
||||
public Date getStartedAt()
|
||||
{
|
||||
return startedAt;
|
||||
}
|
||||
|
||||
public void setStartedAt(Date startedAt)
|
||||
{
|
||||
this.startedAt = startedAt;
|
||||
}
|
||||
|
||||
public Date getEndedAt()
|
||||
{
|
||||
return endedAt;
|
||||
}
|
||||
|
||||
public void setEndedAt(Date endedAt)
|
||||
{
|
||||
this.endedAt = endedAt;
|
||||
}
|
||||
|
||||
public Long getDurationInMs()
|
||||
{
|
||||
return durationInMs;
|
||||
}
|
||||
|
||||
public void setDurationInMs(Long durationInMs)
|
||||
{
|
||||
this.durationInMs = durationInMs;
|
||||
}
|
||||
}
|
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FormModelElement
|
||||
{
|
||||
String name;
|
||||
@@ -26,6 +28,7 @@ public class FormModelElement
|
||||
String dataType;
|
||||
boolean required;
|
||||
String defaultValue;
|
||||
List<String> allowedValues;
|
||||
|
||||
public String getName()
|
||||
{
|
||||
@@ -75,4 +78,12 @@ public class FormModelElement
|
||||
{
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
public List<String> getAllowedValues()
|
||||
{
|
||||
return allowedValues;
|
||||
}
|
||||
public void setAllowedValues(List<String> allowedValues)
|
||||
{
|
||||
this.allowedValues = allowedValues;
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,8 @@ public class ProcessDefinition
|
||||
String category;
|
||||
int version;
|
||||
String deploymentId;
|
||||
|
||||
String title;
|
||||
String description;
|
||||
String startFormResourceKey;
|
||||
Boolean isGraphicNotationDefined;
|
||||
|
||||
@@ -38,7 +39,6 @@ public class ProcessDefinition
|
||||
public ProcessDefinition(org.activiti.engine.repository.ProcessDefinition processDefinition)
|
||||
{
|
||||
this.id = processDefinition.getId();
|
||||
this.key = processDefinition.getKey();
|
||||
this.name = processDefinition.getName();
|
||||
this.category = processDefinition.getCategory();
|
||||
this.version = processDefinition.getVersion();
|
||||
@@ -104,6 +104,26 @@ public class ProcessDefinition
|
||||
{
|
||||
this.deploymentId = deploymentId;
|
||||
}
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getStartFormResourceKey()
|
||||
{
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -32,10 +32,14 @@ public class ProcessInfo
|
||||
String processDefinitionKey;
|
||||
Date startedAt;
|
||||
Date endedAt;
|
||||
Long durationInMillis;
|
||||
Long durationInMs;
|
||||
String deleteReason;
|
||||
String startUserId;
|
||||
String startActivityId;
|
||||
String endActivityId;
|
||||
String businessKey;
|
||||
String superProcessInstanceId;
|
||||
boolean completed;
|
||||
|
||||
Map<String, Object> variables;
|
||||
Set<String> items;
|
||||
@@ -50,9 +54,14 @@ public class ProcessInfo
|
||||
this.processDefinitionId = processInstance.getProcessDefinitionId();
|
||||
this.startedAt = processInstance.getStartTime();
|
||||
this.endedAt = processInstance.getEndTime();
|
||||
this.durationInMillis = processInstance.getDurationInMillis();
|
||||
this.durationInMs = processInstance.getDurationInMillis();
|
||||
this.deleteReason = processInstance.getDeleteReason();
|
||||
this.startUserId = processInstance.getStartUserId();
|
||||
this.startActivityId = processInstance.getStartActivityId();
|
||||
this.endActivityId = processInstance.getEndActivityId();
|
||||
this.businessKey = processInstance.getBusinessKey();
|
||||
this.superProcessInstanceId = processInstance.getSuperProcessInstanceId();
|
||||
this.completed = (processInstance.getEndTime() != null);
|
||||
}
|
||||
|
||||
public String getId()
|
||||
@@ -75,14 +84,14 @@ public class ProcessInfo
|
||||
this.processDefinitionId = processDefinitionId;
|
||||
}
|
||||
|
||||
public Long getDurationInMillis()
|
||||
public Long getDurationInMs()
|
||||
{
|
||||
return durationInMillis;
|
||||
return durationInMs;
|
||||
}
|
||||
|
||||
public void setDurationInMillis(Long durationInMillis)
|
||||
public void setDurationInMs(Long durationInMs)
|
||||
{
|
||||
this.durationInMillis = durationInMillis;
|
||||
this.durationInMs = durationInMs;
|
||||
}
|
||||
|
||||
public String getDeleteReason()
|
||||
@@ -145,6 +154,46 @@ public class ProcessInfo
|
||||
this.endedAt = endedAt;
|
||||
}
|
||||
|
||||
public String getStartUserId()
|
||||
{
|
||||
return startUserId;
|
||||
}
|
||||
|
||||
public void setStartUserId(String startUserId)
|
||||
{
|
||||
this.startUserId = startUserId;
|
||||
}
|
||||
|
||||
public String getStartActivityId()
|
||||
{
|
||||
return startActivityId;
|
||||
}
|
||||
|
||||
public void setStartActivityId(String startActivityId)
|
||||
{
|
||||
this.startActivityId = startActivityId;
|
||||
}
|
||||
|
||||
public String getEndActivityId()
|
||||
{
|
||||
return endActivityId;
|
||||
}
|
||||
|
||||
public void setEndActivityId(String endActivityId)
|
||||
{
|
||||
this.endActivityId = endActivityId;
|
||||
}
|
||||
|
||||
public boolean isCompleted()
|
||||
{
|
||||
return completed;
|
||||
}
|
||||
|
||||
public void setCompleted(boolean completed)
|
||||
{
|
||||
this.completed = completed;
|
||||
}
|
||||
|
||||
public Map<String, Object> getVariables()
|
||||
{
|
||||
return variables;
|
||||
|
@@ -21,6 +21,7 @@ package org.alfresco.rest.workflow.api.model;
|
||||
import java.util.Date;
|
||||
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.task.DelegationState;
|
||||
|
||||
public class Task
|
||||
{
|
||||
@@ -60,6 +61,18 @@ public class Task
|
||||
this.owner = taskInstance.getOwner();
|
||||
this.assignee = taskInstance.getAssignee();
|
||||
this.formResourceKey = taskInstance.getFormKey();
|
||||
if (taskInstance.getEndTime() != null)
|
||||
{
|
||||
this.state = TaskStateTransition.COMPLETED.name().toLowerCase();
|
||||
}
|
||||
else if (taskInstance.getAssignee() != null)
|
||||
{
|
||||
this.state = TaskStateTransition.CLAIMED.name().toLowerCase();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.state = TaskStateTransition.UNCLAIMED.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public Task(org.activiti.engine.task.Task taskInstance)
|
||||
@@ -75,6 +88,18 @@ public class Task
|
||||
this.priority = taskInstance.getPriority();
|
||||
this.owner = taskInstance.getOwner();
|
||||
this.assignee = taskInstance.getAssignee();
|
||||
if (taskInstance.getDelegationState() == DelegationState.PENDING)
|
||||
{
|
||||
|
||||
}
|
||||
if (taskInstance.getAssignee() != null)
|
||||
{
|
||||
this.state = TaskStateTransition.CLAIMED.name().toLowerCase();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.state = TaskStateTransition.UNCLAIMED.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public String getId()
|
||||
|
@@ -0,0 +1,24 @@
|
||||
package org.alfresco.rest.workflow.api.model;
|
||||
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
|
||||
public enum TaskStateTransition {
|
||||
|
||||
COMPLETED, CLAIMED, UNCLAIMED, DELEGATED, RESOLVED;
|
||||
|
||||
/**
|
||||
* @return the {@link TaskStateTransition} for the given string
|
||||
* @throws InvalidArgumentException when no action exists for the given string
|
||||
*/
|
||||
public static TaskStateTransition getTaskActionFromString(String action)
|
||||
{
|
||||
for(TaskStateTransition taskAction : values())
|
||||
{
|
||||
if(taskAction.name().toLowerCase().equals(action))
|
||||
{
|
||||
return taskAction;
|
||||
}
|
||||
}
|
||||
throw new InvalidArgumentException("The task state property has an invalid value: " + action);
|
||||
}
|
||||
}
|
@@ -16,7 +16,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@WebApi(name="alfresco", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
@WebApi(name="workflow", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
package org.alfresco.rest.workflow.api;
|
||||
import org.alfresco.rest.framework.Api;
|
||||
import org.alfresco.rest.framework.WebApi;
|
@@ -18,13 +18,16 @@
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api.processdefinitions;
|
||||
|
||||
import org.alfresco.rest.framework.BinaryProperties;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.WebApiParam;
|
||||
import org.alfresco.rest.framework.WebApiParameters;
|
||||
import org.alfresco.rest.framework.core.ResourceParameter;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.resource.EntityResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
|
||||
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.workflow.api.ProcessDefinitions;
|
||||
@@ -32,7 +35,8 @@ import org.alfresco.rest.workflow.api.model.ProcessDefinition;
|
||||
|
||||
@EntityResource(name="process-definitions", title = "Process definitions")
|
||||
public class ProcessDefinitionsRestEntityResource implements EntityResourceAction.Read<ProcessDefinition>,
|
||||
EntityResourceAction.ReadById<ProcessDefinition>{
|
||||
EntityResourceAction.ReadById<ProcessDefinition>,
|
||||
BinaryResourceAction.Read {
|
||||
|
||||
ProcessDefinitions processDefinitions;
|
||||
|
||||
@@ -59,4 +63,12 @@ public class ProcessDefinitionsRestEntityResource implements EntityResourceActio
|
||||
{
|
||||
return processDefinitions.getProcessDefinition(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Get a process definition image", description = "Get a process definition image")
|
||||
@BinaryProperties({"image"})
|
||||
public BinaryResource readProperty(String id, Parameters parameters) throws EntityNotFoundException
|
||||
{
|
||||
return processDefinitions.getProcessDefinitionImage(id);
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@WebApi(name="alfresco", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
@WebApi(name="workflow", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
package org.alfresco.rest.workflow.api.processdefinitions;
|
||||
import org.alfresco.rest.framework.Api;
|
||||
import org.alfresco.rest.framework.WebApi;
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api.processes;
|
||||
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.workflow.api.Activities;
|
||||
import org.alfresco.rest.workflow.api.model.Activity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Tijs Rademakers
|
||||
*
|
||||
*/
|
||||
@RelationshipResource(name = "activities", entityResource = ProcessesRestEntityResource.class, title = "Activities for the current process")
|
||||
public class ProcessActivitiesRelation implements RelationshipResourceAction.Read<Activity>
|
||||
{
|
||||
protected Activities activities;
|
||||
|
||||
public void setActivities(Activities activities)
|
||||
{
|
||||
this.activities = activities;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the activities.
|
||||
*/
|
||||
@Override
|
||||
@WebApiDescription(title = "Get Activities", description = "Get a paged list of the activities")
|
||||
public CollectionWithPagingInfo<Activity> readAll(String processId, Parameters parameters)
|
||||
{
|
||||
return activities.getActivities(processId, parameters);
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api.processes;
|
||||
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.workflow.api.Tasks;
|
||||
import org.alfresco.rest.workflow.api.model.Task;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Tijs Rademakers
|
||||
*
|
||||
*/
|
||||
@RelationshipResource(name = "tasks", entityResource = ProcessesRestEntityResource.class, title = "Tasks for the current process")
|
||||
public class ProcessTasksRelation implements RelationshipResourceAction.Read<Task>
|
||||
{
|
||||
protected Tasks tasks;
|
||||
|
||||
public void setTasks(Tasks tasks)
|
||||
{
|
||||
this.tasks = tasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the tasks.
|
||||
*/
|
||||
@Override
|
||||
@WebApiDescription(title = "Get Tasks", description = "Get a paged list of the tasks")
|
||||
public CollectionWithPagingInfo<Task> readAll(String processId, Parameters parameters)
|
||||
{
|
||||
return tasks.getTasks(processId, parameters);
|
||||
}
|
||||
}
|
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api.processes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
@@ -32,7 +34,7 @@ import org.alfresco.rest.workflow.api.model.Variable;
|
||||
*
|
||||
*/
|
||||
@RelationshipResource(name = "variables", entityResource = ProcessesRestEntityResource.class, title = "Variables for the current process")
|
||||
public class ProcessVariablesRelation implements RelationshipResourceAction.Read<Variable>,
|
||||
public class ProcessVariablesRelation implements RelationshipResourceAction.Read<Variable>, RelationshipResourceAction.Create<Variable>,
|
||||
RelationshipResourceAction.Update<Variable>, RelationshipResourceAction.Delete
|
||||
{
|
||||
protected Processes processes;
|
||||
@@ -51,6 +53,16 @@ public class ProcessVariablesRelation implements RelationshipResourceAction.Read
|
||||
{
|
||||
return processes.getVariables(processId, parameters.getPaging());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates or updates multiple variables. If the variable name doesn't exist yet it will be created
|
||||
*/
|
||||
@Override
|
||||
@WebApiDescription(title = "Create or Update Variables", description = "Create or update multiple variable")
|
||||
public List<Variable> create(String processId, List<Variable> variables, Parameters parameters)
|
||||
{
|
||||
return processes.updateVariables(processId, variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a variable. If the variable name doesn't exist yet it will be created
|
||||
|
@@ -27,7 +27,6 @@ import org.alfresco.rest.framework.WebApiParam;
|
||||
import org.alfresco.rest.framework.WebApiParameters;
|
||||
import org.alfresco.rest.framework.core.ResourceParameter;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.resource.EntityResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
|
||||
@@ -79,16 +78,11 @@ public class ProcessesRestEntityResource implements EntityResourceAction.Read<Pr
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Updates a flocket")
|
||||
@BinaryProperties({"images"})
|
||||
public BinaryResource readProperty(String entityId, Parameters parameters)
|
||||
throws EntityNotFoundException
|
||||
@WebApiDescription(title = "Get a process instance image", description = "Get a process instance image")
|
||||
@BinaryProperties({"image"})
|
||||
public BinaryResource readProperty(String entityId, Parameters parameters) throws EntityNotFoundException
|
||||
{
|
||||
if(parameters.hasBinaryProperty("image"))
|
||||
{
|
||||
return processes.getProcessImage(entityId);
|
||||
}
|
||||
throw new InvalidArgumentException("Only image is supported property");
|
||||
return processes.getProcessImage(entityId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@WebApi(name="alfresco", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
@WebApi(name="workflow", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
package org.alfresco.rest.workflow.api.processes;
|
||||
import org.alfresco.rest.framework.Api;
|
||||
import org.alfresco.rest.framework.WebApi;
|
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api.tasks;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
@@ -35,7 +37,7 @@ import org.alfresco.rest.workflow.api.model.VariableScope;
|
||||
*
|
||||
*/
|
||||
@RelationshipResource(name = "variables", entityResource = TasksRestEntityResource.class, title = "Variables for the current task")
|
||||
public class TaskVariablesRelation implements RelationshipResourceAction.Read<TaskVariable>,
|
||||
public class TaskVariablesRelation implements RelationshipResourceAction.Read<TaskVariable>, RelationshipResourceAction.Create<TaskVariable>,
|
||||
RelationshipResourceAction.Update<TaskVariable>, RelationshipResourceAction.Delete
|
||||
{
|
||||
private Tasks tasks;
|
||||
@@ -64,6 +66,16 @@ public class TaskVariablesRelation implements RelationshipResourceAction.Read<Ta
|
||||
}
|
||||
return tasks.getTaskVariables(taskId, parameters.getPaging(), scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates or updates multiple task variables. If the variable name doesn't exist yet it will be created
|
||||
*/
|
||||
@Override
|
||||
@WebApiDescription(title = "Create or Update Variables", description = "Create or update multiple variable")
|
||||
public List<TaskVariable> create(String taskId, List<TaskVariable> variables, Parameters parameters)
|
||||
{
|
||||
return tasks.updateTaskVariables(taskId, variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a task variable. If the variable name doesn't exist yet it will be created
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@WebApi(name="alfresco", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
@WebApi(name="workflow", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
package org.alfresco.rest.workflow.api.tasks;
|
||||
import org.alfresco.rest.framework.Api;
|
||||
import org.alfresco.rest.framework.WebApi;
|
Reference in New Issue
Block a user