/* * Copyright 2012 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jbpm.kie.services.impl; import static java.util.Objects.requireNonNull; import static org.kie.internal.query.QueryParameterIdentifiers.FILTER; import static org.jbpm.kie.services.impl.CommonUtils.*; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.jbpm.kie.services.api.DeploymentIdResolver; import org.jbpm.kie.services.impl.model.ProcessAssetDesc; import org.jbpm.kie.services.impl.security.DeploymentRolesManager; import org.jbpm.services.api.DeploymentEvent; import org.jbpm.services.api.DeploymentEventListener; import org.jbpm.services.api.RuntimeDataService; import org.jbpm.services.api.TaskNotFoundException; import org.jbpm.services.api.model.DeployedAsset; import org.jbpm.services.api.model.NodeInstanceDesc; import org.jbpm.services.api.model.ProcessDefinition; import org.jbpm.services.api.model.ProcessInstanceDesc; import org.jbpm.services.api.model.UserTaskInstanceDesc; import org.jbpm.services.api.model.VariableDesc; import org.jbpm.services.task.audit.service.TaskAuditService; import org.jbpm.services.task.impl.TaskSummaryQueryBuilderImpl; import org.jbpm.shared.services.impl.QueryManager; import org.jbpm.shared.services.impl.TransactionalCommandService; import org.jbpm.shared.services.impl.commands.QueryNameCommand; import org.kie.api.runtime.process.ProcessInstance; import org.kie.api.runtime.query.QueryContext; import org.kie.api.task.TaskService; import org.kie.api.task.model.Status; import org.kie.api.task.model.TaskSummary; import org.kie.internal.identity.IdentityProvider; import org.kie.internal.process.CorrelationKey; import org.kie.internal.query.QueryFilter; import org.kie.internal.task.api.AuditTask; import org.kie.internal.task.api.model.TaskEvent; import org.kie.internal.task.query.TaskSummaryQueryBuilder; public class RuntimeDataServiceImpl implements RuntimeDataService, DeploymentEventListener { private static final String DEPLOYMENT_ID_MUST_NOT_BE_NULL = "DeploymentId must not be null"; private static final String TASK_NOT_FOUND ="No task found with id {0}"; protected Set<String> deploymentIds = new HashSet<String>(); protected Set<ProcessDefinition> availableProcesses = new HashSet<ProcessDefinition>(); private TransactionalCommandService commandService; private IdentityProvider identityProvider; protected TaskService taskService; protected TaskAuditService taskAuditService; private DeploymentRolesManager deploymentRolesManager = new DeploymentRolesManager(); private static final List<Status> allActiveStatus = Arrays.asList(new Status[]{ Status.Created, Status.Ready, Status.Reserved, Status.InProgress, Status.Suspended }); public RuntimeDataServiceImpl() { QueryManager.get().addNamedQueries("META-INF/Servicesorm.xml"); QueryManager.get().addNamedQueries("META-INF/TaskAuditorm.xml"); QueryManager.get().addNamedQueries("META-INF/Taskorm.xml"); } public void setCommandService(TransactionalCommandService commandService) { this.commandService = commandService; } public void setIdentityProvider(IdentityProvider identityProvider) { this.identityProvider = identityProvider; } public void setTaskService(TaskService taskService) { this.taskService = taskService; } public void setTaskAuditService(TaskAuditService taskAuditService) { this.taskAuditService = taskAuditService; } public void setDeploymentRolesManager(DeploymentRolesManager deploymentRolesManager) { this.deploymentRolesManager = deploymentRolesManager; } private void addProcessDefinition( ProcessAssetDesc asset) { availableProcesses.add(asset); deploymentIds.add(asset.getDeploymentId()); } private void removeAllProcessDefinitions( Collection<ProcessAssetDesc> assets) { Iterator<ProcessAssetDesc> iter = assets.iterator(); while( iter.hasNext() ) { ProcessAssetDesc asset = iter.next(); availableProcesses.remove(asset); deploymentIds.remove(asset.getDeploymentId()); } } private String getLatestDeploymentId(String deploymentId) { String matched = deploymentId; if (deploymentId != null && deploymentId.toLowerCase().endsWith("latest")) { matched = DeploymentIdResolver.matchAndReturnLatest(deploymentId, deploymentIds); } return matched; } /* * start * helper methods to index data upon deployment */ public void onDeploy(DeploymentEvent event) { Collection<DeployedAsset> assets = event.getDeployedUnit().getDeployedAssets(); List<String> roles = null; for( DeployedAsset asset : assets ) { if( asset instanceof ProcessAssetDesc ) { addProcessDefinition((ProcessAssetDesc) asset); if (roles == null) { roles = ((ProcessAssetDesc) asset).getRoles(); } } } if (roles == null) { roles = Collections.emptyList(); } deploymentRolesManager.addRolesForDeployment(event.getDeploymentId(), roles); } public void onUnDeploy(DeploymentEvent event) { Collection<ProcessAssetDesc> outputCollection = new HashSet<ProcessAssetDesc>(); CollectionUtils.select(availableProcesses, new UnsecureByDeploymentIdPredicate(event.getDeploymentId()), outputCollection); removeAllProcessDefinitions(outputCollection); deploymentRolesManager.removeRolesForDeployment(event.getDeploymentId()); } @Override public void onActivate(DeploymentEvent event) { Collection<ProcessAssetDesc> outputCollection = new HashSet<ProcessAssetDesc>(); CollectionUtils.select(availableProcesses, new UnsecureByDeploymentIdPredicate(event.getDeploymentId()), outputCollection); for (ProcessAssetDesc process : outputCollection) { process.setActive(true); } } @Override public void onDeactivate(DeploymentEvent event) { Collection<ProcessAssetDesc> outputCollection = new HashSet<ProcessAssetDesc>(); CollectionUtils.select(availableProcesses, new UnsecureByDeploymentIdPredicate(event.getDeploymentId()), outputCollection); for (ProcessAssetDesc process : outputCollection) { process.setActive(false); } } protected void applyQueryContext(Map<String, Object> params, QueryContext queryContext) { if (queryContext != null) { params.put("firstResult", queryContext.getOffset()); params.put("maxResults", queryContext.getCount()); if (queryContext.getOrderBy() != null && !queryContext.getOrderBy().isEmpty()) { params.put(QueryManager.ORDER_BY_KEY, queryContext.getOrderBy()); if (queryContext.isAscending()) { params.put(QueryManager.ASCENDING_KEY, "true"); } else { params.put(QueryManager.DESCENDING_KEY, "true"); } } } } protected void applyDeploymentFilter(Map<String, Object> params) { List<String> deploymentIdForUser = deploymentRolesManager.getDeploymentsForUser(identityProvider); if (deploymentIdForUser != null && !deploymentIdForUser.isEmpty()) { params.put(FILTER, " log.externalId in (:deployments) "); params.put("deployments", deploymentIdForUser); } } protected <T> Collection<T> applyPaginition(List<T> input, QueryContext queryContext) { if (queryContext != null) { int start = queryContext.getOffset(); int end = start + queryContext.getCount(); if (input.size() < start) { // no elements in given range return new ArrayList<T>(); } else if (input.size() >= end) { return Collections.unmodifiableCollection(new ArrayList<T>(input.subList(start, end))); } else if (input.size() < end) { return Collections.unmodifiableCollection(new ArrayList<T>(input.subList(start, input.size()))); } } return Collections.unmodifiableCollection(input); } protected void applySorting(List<ProcessDefinition> input, final QueryContext queryContext) { if (queryContext != null && queryContext.getOrderBy() != null && !queryContext.getOrderBy().isEmpty()) { Collections.sort(input, new Comparator<ProcessDefinition>() { @Override public int compare(ProcessDefinition o1, ProcessDefinition o2) { if ("ProcessName".equals(queryContext.getOrderBy())) { return o1.getName().compareTo(o2.getName()); } else if ("ProcessVersion".equals(queryContext.getOrderBy())) { return o1.getVersion().compareTo(o2.getVersion()); } else if ("Project".equals(queryContext.getOrderBy())) { return o1.getDeploymentId().compareTo(o2.getDeploymentId()); } return 0; } }); if (!queryContext.isAscending()) { Collections.reverse(input); } } } /* * end * helper methods to index data upon deployment */ /* * start * process definition methods */ public Collection<ProcessDefinition> getProcessesByDeploymentId(String deploymentId, QueryContext queryContext) { deploymentId = getLatestDeploymentId(requireNonNull(deploymentId, DEPLOYMENT_ID_MUST_NOT_BE_NULL)); List<ProcessDefinition> outputCollection = new ArrayList<ProcessDefinition>(); CollectionUtils.select(availableProcesses, new ByDeploymentIdPredicate(deploymentId, identityProvider.getRoles()), outputCollection); applySorting(outputCollection, queryContext); return applyPaginition(outputCollection, queryContext); } public ProcessDefinition getProcessesByDeploymentIdProcessId(String deploymentId, String processId) { deploymentId = getLatestDeploymentId(requireNonNull(deploymentId, DEPLOYMENT_ID_MUST_NOT_BE_NULL)); List<ProcessDefinition> outputCollection = new ArrayList<ProcessDefinition>(); CollectionUtils.select(availableProcesses, new ByDeploymentIdProcessIdPredicate(deploymentId, processId, identityProvider.getRoles(), true), outputCollection); if (!outputCollection.isEmpty()) { return outputCollection.iterator().next(); } return null; } public Collection<ProcessDefinition> getProcessesByFilter(String filter, QueryContext queryContext) { List<ProcessDefinition> outputCollection = new ArrayList<ProcessDefinition>(); CollectionUtils.select(availableProcesses, new RegExPredicate("(?i)^.*"+filter+".*$", identityProvider.getRoles()), outputCollection); applySorting(outputCollection, queryContext); return applyPaginition(outputCollection, queryContext); } @Deprecated public ProcessDefinition getProcessById(String processId){ Collection<ProcessDefinition> definitions = getProcessesById(processId); if (!definitions.isEmpty()) { return definitions.iterator().next(); } return null; } public Collection<ProcessDefinition> getProcessesById(String processId){ Collection<ProcessDefinition> outputCollection = new HashSet<ProcessDefinition>(); CollectionUtils.select(availableProcesses, new ByProcessIdPredicate(processId, identityProvider.getRoles()), outputCollection); return outputCollection; } public Collection<ProcessDefinition> getProcesses(QueryContext queryContext) { List<ProcessDefinition> outputCollection = new ArrayList<ProcessDefinition>(); CollectionUtils.select(availableProcesses, new SecurePredicate(identityProvider.getRoles(), false), outputCollection); applySorting(outputCollection, queryContext); return applyPaginition(outputCollection, queryContext); } @Override public Collection<String> getProcessIds(String deploymentId, QueryContext queryContext) { deploymentId = getLatestDeploymentId(requireNonNull(deploymentId, DEPLOYMENT_ID_MUST_NOT_BE_NULL)); List<String> processIds = new ArrayList<String>(availableProcesses.size()); if( deploymentId == null || deploymentId.isEmpty() ) { return processIds; } for( ProcessDefinition procAssetDesc : availableProcesses ) { if( ((ProcessAssetDesc)procAssetDesc).getDeploymentId().equals(deploymentId) && ((ProcessAssetDesc)procAssetDesc).isActive()) { processIds.add(procAssetDesc.getId()); } } return applyPaginition(processIds, queryContext); } /* * end * process definition methods */ /* * start * process instances methods */ public Collection<ProcessInstanceDesc> getProcessInstances(QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); applyQueryContext(params, queryContext); applyDeploymentFilter(params); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstances", params)); return Collections.unmodifiableCollection(processInstances); } public Collection<ProcessInstanceDesc> getProcessInstances(List<Integer> states, String initiator, QueryContext queryContext) { List<ProcessInstanceDesc> processInstances = null; Map<String, Object> params = new HashMap<String, Object>(); params.put("states", states); applyQueryContext(params, queryContext); applyDeploymentFilter(params); if (initiator == null) { processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByStatus", params)); } else { params.put("initiator", initiator); processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByStatusAndInitiator", params)); } return Collections.unmodifiableCollection(processInstances); } public Collection<ProcessInstanceDesc> getProcessInstancesByDeploymentId(String deploymentId, List<Integer> states, QueryContext queryContext) { deploymentId = getLatestDeploymentId(requireNonNull(deploymentId, DEPLOYMENT_ID_MUST_NOT_BE_NULL)); Map<String, Object> params = new HashMap<String, Object>(); params.put("externalId", deploymentId); params.put("states", states); applyQueryContext(params, queryContext); applyDeploymentFilter(params); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByDeploymentId", params)); return Collections.unmodifiableCollection(processInstances); } public Collection<ProcessInstanceDesc> getProcessInstancesByProcessDefinition(String processDefId, QueryContext queryContext){ Map<String, Object> params = new HashMap<String, Object>(); params.put("processDefId", processDefId); applyQueryContext(params, queryContext); applyDeploymentFilter(params); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByProcessDefinition", params)); return Collections.unmodifiableCollection(processInstances); } @Override public Collection<ProcessInstanceDesc> getProcessInstancesByProcessDefinition(String processDefId, List<Integer> states, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processId", processDefId); params.put("states", states); applyQueryContext(params, queryContext); applyDeploymentFilter(params); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByProcessIdAndStatus", params)); return Collections.unmodifiableCollection(processInstances); } public ProcessInstanceDesc getProcessInstanceById(long processId) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processId", processId); params.put("maxResults", 1); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstanceById", params)); if (!processInstances.isEmpty()) { ProcessInstanceDesc desc = processInstances.iterator().next(); List<String> statuses = new ArrayList<String>(); statuses.add(Status.Ready.name()); statuses.add(Status.Reserved.name()); statuses.add(Status.InProgress.name()); params = new HashMap<String, Object>(); params.put("processInstanceId", desc.getId()); params.put("statuses", statuses); List<UserTaskInstanceDesc> tasks = commandService.execute( new QueryNameCommand<List<UserTaskInstanceDesc>>("getTaskInstancesByProcessInstanceId", params)); ((org.jbpm.kie.services.impl.model.ProcessInstanceDesc)desc).setActiveTasks(tasks); return desc; } return null; } @Override public ProcessInstanceDesc getProcessInstanceByCorrelationKey(CorrelationKey correlationKey) { Map<String, Object> params = new HashMap<String, Object>(); params.put("correlationKey", correlationKey.toExternalForm()); params.put("maxResults", 1); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstanceByCorrelationKey", params)); if (!processInstances.isEmpty()) { ProcessInstanceDesc desc = processInstances.iterator().next(); List<String> statuses = new ArrayList<String>(); statuses.add(Status.Ready.name()); statuses.add(Status.Reserved.name()); statuses.add(Status.InProgress.name()); params = new HashMap<String, Object>(); params.put("processInstanceId", desc.getId()); params.put("statuses", statuses); List<UserTaskInstanceDesc> tasks = commandService.execute( new QueryNameCommand<List<UserTaskInstanceDesc>>("getTaskInstancesByProcessInstanceId", params)); ((org.jbpm.kie.services.impl.model.ProcessInstanceDesc)desc).setActiveTasks(tasks); return desc; } return null; } @Override public Collection<ProcessInstanceDesc> getProcessInstancesByCorrelationKey(CorrelationKey correlationKey, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("correlationKey", correlationKey.toExternalForm() + "%"); applyQueryContext(params, queryContext); applyDeploymentFilter(params); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByCorrelationKey", params)); return processInstances; } @Override public Collection<ProcessInstanceDesc> getProcessInstancesByCorrelationKeyAndStatus(CorrelationKey correlationKey, List<Integer> states, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("correlationKey", correlationKey.toExternalForm() + "%"); params.put("states", states); applyQueryContext(params, queryContext); applyDeploymentFilter(params); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByCorrelationKeyAndStatus", params)); return processInstances; } @Override public Collection<ProcessInstanceDesc> getProcessInstancesByProcessId(List<Integer> states, String processId, String initiator, QueryContext queryContext) { List<ProcessInstanceDesc> processInstances = null; Map<String, Object> params = new HashMap<String, Object>(); params.put("states", states); params.put("processId", processId); applyQueryContext(params, queryContext); applyDeploymentFilter(params); if (initiator == null) { processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByProcessIdAndStatus", params)); } else { params.put("initiator", initiator); processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByProcessIdAndStatusAndInitiator", params)); } return Collections.unmodifiableCollection(processInstances); } @Override public Collection<ProcessInstanceDesc> getProcessInstancesByProcessName( List<Integer> states, String processName, String initiator, QueryContext queryContext) { List<ProcessInstanceDesc> processInstances = null; Map<String, Object> params = new HashMap<String, Object>(); params.put("states", states); params.put("processName", processName); applyQueryContext(params, queryContext); applyDeploymentFilter(params); if (initiator == null) { processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByProcessNameAndStatus", params)); } else { params.put("initiator", initiator); processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByProcessNameAndStatusAndInitiator", params)); } return Collections.unmodifiableCollection(processInstances); } @Override public Collection<ProcessInstanceDesc> getProcessInstancesByVariable(String variableName, List<Integer> states, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); if (states == null || states.isEmpty()) { states = new ArrayList<Integer>(); states.add(ProcessInstance.STATE_ACTIVE); } params.put("states", states); params.put("variable", variableName); applyQueryContext(params, queryContext); applyDeploymentFilter(params); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByVariableName", params)); return Collections.unmodifiableCollection(processInstances); } @Override public Collection<ProcessInstanceDesc> getProcessInstancesByVariableAndValue(String variableName, String variableValue, List<Integer> states, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); if (states == null || states.isEmpty()) { states = new ArrayList<Integer>(); states.add(ProcessInstance.STATE_ACTIVE); } params.put("states", states); params.put("variable", variableName); params.put("variableValue", variableValue); applyQueryContext(params, queryContext); applyDeploymentFilter(params); List<ProcessInstanceDesc> processInstances = commandService.execute( new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByVariableNameAndValue", params)); return Collections.unmodifiableCollection(processInstances); } @Override public Collection<ProcessInstanceDesc> getProcessInstancesByParent(Long parentProcessInstanceId, List<Integer> states, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); if (states == null || states.isEmpty()) { states = new ArrayList<Integer>(); states.add(ProcessInstance.STATE_ACTIVE); } params.put("states", states); params.put("parentId", parentProcessInstanceId); applyQueryContext(params, queryContext); applyDeploymentFilter(params); List<ProcessInstanceDesc> processInstances = commandService.execute(new QueryNameCommand<List<ProcessInstanceDesc>>("getProcessInstancesByParent", params)); return processInstances; } /* * end * process instances methods */ /* * start * node instances methods */ @Override public Collection<NodeInstanceDesc> getProcessInstanceHistoryActive(long processId, QueryContext queryContext) { return getProcessInstanceHistory(processId, false, queryContext); } @Override public Collection<NodeInstanceDesc> getProcessInstanceHistoryCompleted(long processId, QueryContext queryContext) { return getProcessInstanceHistory(processId, true, queryContext); } protected Collection<NodeInstanceDesc> getProcessInstanceHistory(long processId, boolean completed, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processId", processId); applyQueryContext(params, queryContext); List<NodeInstanceDesc> nodeInstances = Collections.emptyList(); if (completed) { nodeInstances = commandService.execute( new QueryNameCommand<List<NodeInstanceDesc>>("getProcessInstanceCompletedNodes", params)); } else { nodeInstances = commandService.execute( new QueryNameCommand<List<NodeInstanceDesc>>("getProcessInstanceActiveNodes", params)); } return nodeInstances; } @Override public Collection<NodeInstanceDesc> getProcessInstanceFullHistory(long processId, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processId", processId); applyQueryContext(params, queryContext); List<NodeInstanceDesc> nodeInstances = commandService.execute( new QueryNameCommand<List<NodeInstanceDesc>>("getProcessInstanceFullHistory", params)); return nodeInstances; } @Override public Collection<NodeInstanceDesc> getProcessInstanceFullHistoryByType(long processId, EntryType type, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processId", processId); params.put("type", type.getValue()); applyQueryContext(params, queryContext); List<NodeInstanceDesc> nodeInstances = commandService.execute( new QueryNameCommand<List<NodeInstanceDesc>>("getProcessInstanceFullHistoryByType", params)); return nodeInstances; } @Override public NodeInstanceDesc getNodeInstanceForWorkItem(Long workItemId) { Map<String, Object> params = new HashMap<String, Object>(); params.put("workItemId", workItemId); params.put("maxResults", 1); List<NodeInstanceDesc> nodeInstances = commandService.execute( new QueryNameCommand<List<NodeInstanceDesc>>("getNodeInstanceForWorkItem", params)); if (!nodeInstances.isEmpty()) { return nodeInstances.iterator().next(); } return null; } @Override public Collection<NodeInstanceDesc> getNodeInstancesByNodeType(long processInstanceId, List<String> nodeTypes, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processInstanceId", processInstanceId); params.put("nodeTypes", nodeTypes); applyQueryContext(params, queryContext); List<NodeInstanceDesc> nodeInstances = commandService.execute( new QueryNameCommand<List<NodeInstanceDesc>>("getNodeInstancesByNodeType", params)); return nodeInstances; } @Override public Collection<NodeInstanceDesc> getNodeInstancesByCorrelationKeyNodeType(CorrelationKey correlationKey, List<Integer> states, List<String> nodeTypes, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("correlationKey", correlationKey.toExternalForm() + "%"); params.put("states", states); params.put("nodeTypes", nodeTypes); List<NodeInstanceDesc> nodeInstances = commandService.execute( new QueryNameCommand<List<NodeInstanceDesc>>("getNodeInstancesByCorrelationKeyAndNodeType", params)); return nodeInstances; } /* * end * node instances methods */ /* * start * variable methods */ public Collection<VariableDesc> getVariablesCurrentState(long processInstanceId) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processInstanceId", processInstanceId); List<VariableDesc> variablesState = commandService.execute( new QueryNameCommand<List<VariableDesc>>("getVariablesCurrentState", params)); return variablesState; } public Collection<VariableDesc> getVariableHistory(long processInstanceId, String variableId, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processInstanceId", processInstanceId); params.put("variableId", variableId); applyQueryContext(params, queryContext); List<VariableDesc> variablesState = commandService.execute( new QueryNameCommand<List<VariableDesc>>("getVariableHistory", params)); return variablesState; } /* * end * variable methods */ /* * start * task methods */ @Override public UserTaskInstanceDesc getTaskByWorkItemId(Long workItemId) { Map<String, Object> params = new HashMap<String, Object>(); params.put("workItemId", workItemId); params.put("maxResults", 1); List<UserTaskInstanceDesc> tasks = commandService.execute( new QueryNameCommand<List<UserTaskInstanceDesc>>("getTaskInstanceByWorkItemId", params)); if (!tasks.isEmpty()) { return tasks.iterator().next(); } return null; } @Override public UserTaskInstanceDesc getTaskById(Long taskId) { Map<String, Object> params = new HashMap<String, Object>(); params.put("taskId", taskId); params.put("maxResults", 1); List<UserTaskInstanceDesc> tasks = commandService.execute( new QueryNameCommand<List<UserTaskInstanceDesc>>("getTaskInstanceById", params)); if (!tasks.isEmpty()) { return tasks.iterator().next(); } return null; } @Override public List<TaskSummary> getTasksAssignedAsBusinessAdministrator(String userId, QueryFilter filter) { return getTasksAssignedAsBusinessAdministratorByStatus(userId, null, filter); } @Override public List<TaskSummary> getTasksAssignedAsPotentialOwner(String userId, QueryFilter filter) { Map<String, Object> params = new HashMap<String, Object>(); params.put("userId", userId); params.put("groupIds", getAuthenticatedUserRoles(identityProvider)); params.put("status", allActiveStatus); applyQueryContext(params, filter); applyQueryFilter(params, filter); return (List<TaskSummary>) commandService.execute(new QueryNameCommand<List<TaskSummary>>("NewTasksAssignedAsPotentialOwner",params)); } @Override public List<TaskSummary> getTasksAssignedAsPotentialOwner(String userId, List<String> groupIds, QueryFilter filter) { Map<String, Object> params = new HashMap<String, Object>(); params.put("userId", userId); params.put("groupIds", getAuthenticatedUserRoles(identityProvider)); applyQueryContext(params, filter); applyQueryFilter(params, filter); return (List<TaskSummary>) commandService.execute(new QueryNameCommand<List<TaskSummary>>("TasksAssignedAsPotentialOwnerWithGroups",params)); } @Override public List<TaskSummary> getTasksAssignedAsPotentialOwner(String userId, List<String> groupIds, List<Status> status, QueryFilter filter) { Map<String, Object> params = new HashMap<String, Object>(); params.put("userId", userId); params.put("groupIds", adoptList(groupIds, getAuthenticatedUserRoles(identityProvider))); params.put("status", adoptList(status, allActiveStatus)); applyQueryContext(params, filter); applyQueryFilter(params, filter); return (List<TaskSummary>) commandService.execute(new QueryNameCommand<List<TaskSummary>>("NewTasksAssignedAsPotentialOwner",params)); } @Override public List<TaskSummary> getTasksAssignedAsPotentialOwnerByStatus(String userId, List<Status> status, QueryFilter filter) { Map<String, Object> params = new HashMap<String, Object>(); params.put("userId", userId); params.put("groupIds", getAuthenticatedUserRoles(identityProvider)); params.put("status", adoptList(status, allActiveStatus)); applyQueryContext(params, filter); applyQueryFilter(params, filter); return (List<TaskSummary>) commandService.execute(new QueryNameCommand<List<TaskSummary>>("NewTasksAssignedAsPotentialOwner",params)); } @Override public List<TaskSummary> getTasksAssignedAsPotentialOwnerByExpirationDateOptional( String userId, List<Status> status, Date from, QueryFilter filter) { List<TaskSummary> taskSummaries = null; if (from != null) { Map<String, Object> params = new HashMap<String, Object>(); params.put("expirationDate", from); QueryFilter qf = new QueryFilter( "(t.taskData.expirationTime = :expirationDate or t.taskData.expirationTime is null)", params, "order by t.id DESC", filter.getOffset(), filter.getCount()); taskSummaries = getTasksAssignedAsPotentialOwnerByStatus(userId, status, qf); } else { QueryFilter qf = new QueryFilter(filter.getOffset(), filter.getCount()); taskSummaries = getTasksAssignedAsPotentialOwnerByStatus(userId, status, qf); } return taskSummaries; } @Override public List<TaskSummary> getTasksOwnedByExpirationDateOptional(String userId, List<Status> strStatuses, Date from, QueryFilter filter) { List<TaskSummary> taskSummaries = null; if (from != null) { Map<String, Object> params = new HashMap<String, Object>(); params.put("expirationDate", from); QueryFilter qf = new QueryFilter( "(t.taskData.expirationTime = :expirationDate or t.taskData.expirationTime is null)", params, "order by t.id DESC", filter.getOffset(), filter.getCount()); taskSummaries = getTasksOwnedByStatus(userId, strStatuses, qf); } else { QueryFilter qf = new QueryFilter(filter.getOffset(), filter.getCount()); taskSummaries = getTasksOwnedByStatus(userId, strStatuses, qf); } return taskSummaries; } @Override public List<TaskSummary> getTasksOwned(String userId, QueryFilter filter) { return getTasksOwnedByStatus(userId, null, filter); } @Override public List<TaskSummary> getTasksOwnedByStatus(String userId, List<Status> status, QueryFilter filter) { Map<String, Object> params = new HashMap<String, Object>(); params.put("userId", userId); params.put("status", adoptList(status, allActiveStatus)); applyQueryContext(params, filter); applyQueryFilter(params, filter); return (List<TaskSummary>) commandService.execute(new QueryNameCommand<List<TaskSummary>>("NewTasksOwned",params)); } @Override public List<Long> getTasksByProcessInstanceId(Long processInstanceId) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processInstanceId", processInstanceId); return (List<Long>) commandService.execute(new QueryNameCommand<List<Long>>("TasksByProcessInstanceId",params)); } @Override public List<TaskSummary> getTasksByStatusByProcessInstanceId(Long processInstanceId, List<Status> status, QueryFilter filter) { if (status == null || status.isEmpty()) { status = new ArrayList<Status>(); status.add(Status.Created); status.add(Status.Ready); status.add(Status.Reserved); status.add(Status.InProgress); status.add(Status.Suspended); } Map<String, Object> params = new HashMap<String, Object>(); params.put("processInstanceId", processInstanceId); params.put("status", status); applyQueryContext(params, filter); applyQueryFilter(params, filter); return (List<TaskSummary>) commandService.execute(new QueryNameCommand<List<TaskSummary>>("TasksByStatusByProcessId", params)); } @Override public List<TaskSummary> getTasksAssignedAsBusinessAdministratorByStatus(String userId, List<Status> statuses, QueryFilter filter) { Map<String, Object> params = new HashMap<String, Object>(); params.put("userId", userId); params.put("status", adoptList(statuses, allActiveStatus)); params.put("groupIds", getAuthenticatedUserRoles(identityProvider)); applyQueryContext(params, filter); applyQueryFilter(params, filter); return (List<TaskSummary>) commandService.execute( new QueryNameCommand<List<TaskSummary>>("TasksAssignedAsBusinessAdministratorByStatus",params)); } @Override public TaskSummaryQueryBuilder taskSummaryQuery(String userId) { return new TaskSummaryQueryBuilderImpl(userId, taskService); } @Override public List<TaskSummary> getTasksByVariable( String userId, String variableName, List<Status> statuses, QueryContext queryContext ) { TaskSummaryQueryBuilder queryBuilder = new TaskSummaryQueryBuilderImpl(userId, taskService).intersect(); addVariableNameAndVariableValueParameters(queryBuilder, variableName); if( statuses != null && ! statuses.isEmpty() ) { queryBuilder.status(statuses.toArray(new Status[statuses.size()])); } setQueryContextOptions(queryContext, queryBuilder); return queryBuilder.build().getResultList(); } @Override public List<TaskSummary> getTasksByVariableAndValue( String userId, String variableName, String variableValue, List<Status> statuses, QueryContext queryContext ) { TaskSummaryQueryBuilder queryBuilder = new TaskSummaryQueryBuilderImpl(userId, taskService).intersect(); addVariableNameAndVariableValueParameters(queryBuilder, variableName, variableValue); if( statuses != null && ! statuses.isEmpty() ) { queryBuilder.status(statuses.toArray(new Status[statuses.size()])); } setQueryContextOptions(queryContext, queryBuilder); return queryBuilder.build().getResultList(); } private void setQueryContextOptions(QueryContext queryContext, TaskSummaryQueryBuilder queryBuilder) { if( queryContext != null ) { Integer param = queryContext.getOffset(); if( param != null ) { queryBuilder.offset(param); } param = queryContext.getCount(); if( param != null ) { queryBuilder.maxResults(param); } String orderBy = queryContext.getOrderBy(); if( orderBy != null ) { orderBy = orderBy.toLowerCase(); boolean orderBySet = false; for( TaskSummaryQueryBuilder.OrderBy orderByEnum: TaskSummaryQueryBuilder.OrderBy.values() ) { if( orderBy.equals(orderByEnum.toString().toLowerCase()) ) { if (queryContext.isAscending()) { queryBuilder.ascending(orderByEnum); } else { queryBuilder.descending(orderByEnum); } orderBySet = true; break; } } if( ! orderBySet ) { throw new IllegalArgumentException("Unsupported QueryContext.orderBy value: \"" + orderBy + "\""); } } } } private void addVariableNameAndVariableValueParameters(TaskSummaryQueryBuilder queryBuilder, String... variableNameOrValue) { if( variableNameOrValue.length > 0 ) { if( variableNameOrValue[0].contains("*") || variableNameOrValue[0].contains("?") ) { queryBuilder.regex(); } queryBuilder.variableName(variableNameOrValue[0]).equals(); } if( variableNameOrValue.length > 1 ) { if( variableNameOrValue[1].contains("*") || variableNameOrValue[1].contains("?") ) { queryBuilder.regex(); } queryBuilder.variableValue(variableNameOrValue[1]).equals(); } if( variableNameOrValue.length > 2 ) { throw new IllegalStateException("Only String arguments expected for the " + Thread.currentThread().getStackTrace()[0].getMethodName() + " method!"); } } /* * end * task methods */ /* * start * task audit queries */ @Override public List<AuditTask> getAllAuditTask(String userId, QueryFilter filter){ Map<String, Object> params = new HashMap<String, Object>(); params.put("owner", userId); applyQueryContext(params, filter); applyQueryFilter(params, filter); List<AuditTask> auditTasks = commandService.execute( new QueryNameCommand<List<AuditTask>>("getAllAuditTasksByUser", params)); return auditTasks; } @Override public List<AuditTask> getAllAuditTaskByStatus(String userId, QueryFilter filter){ Map<String, Object> params = new HashMap<String, Object>(); params.put("owner", userId); params.put("statuses", filter.getParams().get("statuses")); applyQueryContext(params, filter); applyQueryFilter(params, filter); List<AuditTask> auditTasks = commandService.execute( new QueryNameCommand<List<AuditTask>>("getAllAuditTasksByStatus", params)); return auditTasks; } @Override public List<AuditTask> getAllGroupAuditTask(String userId, QueryFilter filter){ List<String> owners = new ArrayList<String>(); owners.add(userId); owners.addAll(getAuthenticatedUserRoles(identityProvider)); Map<String, Object> params = new HashMap<String, Object>(); params.put("potentialOwners", owners); applyQueryContext(params, filter); applyQueryFilter(params, filter); List<AuditTask> auditTasks = commandService.execute(new QueryNameCommand<List<AuditTask>>("getAllGroupAuditTasksByUser", params)); return auditTasks; } @Override public List<AuditTask> getAllAdminAuditTask(String userId, QueryFilter filter){ List<String> businessAdmins = new ArrayList<String>(); businessAdmins.add(userId); businessAdmins.addAll(getAuthenticatedUserRoles(identityProvider)); Map<String, Object> params = new HashMap<String, Object>(); params.put("businessAdmins", businessAdmins); applyQueryContext(params, filter); applyQueryFilter(params, filter); List<AuditTask> auditTasks = commandService.execute(new QueryNameCommand<List<AuditTask>>("getAllAdminAuditTasksByUser", params)); return auditTasks; } public List<TaskEvent> getTaskEvents(long taskId, QueryFilter filter) { Map<String, Object> params = new HashMap<String, Object>(); params.put("taskId", taskId); applyQueryContext(params, filter); applyQueryFilter(params, filter); List<TaskEvent> taskEvents = commandService.execute( new QueryNameCommand<List<TaskEvent>>("getAllTasksEvents", params)); if(taskEvents == null || taskEvents.size() < 1) { throw new TaskNotFoundException( MessageFormat.format(TASK_NOT_FOUND, taskId) ); } return taskEvents; } /* * end * task audit queries */ /* * start * predicates for collection filtering */ private class RegExPredicate extends SecurePredicate { private String pattern; private RegExPredicate(String pattern, List<String> roles) { super(roles, false); this.pattern = pattern; } @Override public boolean evaluate(Object object) { if (object instanceof ProcessAssetDesc) { ProcessAssetDesc pDesc = (ProcessAssetDesc) object; boolean hasAccess = super.evaluate(object); if (!hasAccess) { return false; } if (pDesc.getId().matches(pattern) || pDesc.getName().matches(pattern)) { return true; } } return false; } } private class ByDeploymentIdPredicate extends SecurePredicate { private String deploymentId; private ByDeploymentIdPredicate(String deploymentId, List<String> roles) { super(roles, false); this.deploymentId = deploymentId; } @Override public boolean evaluate(Object object) { if (object instanceof ProcessAssetDesc) { ProcessAssetDesc pDesc = (ProcessAssetDesc) object; boolean hasAccess = super.evaluate(object); if (!hasAccess) { return false; } if (pDesc.getDeploymentId().equals(deploymentId)) { return true; } } return false; } } private class ByProcessIdPredicate extends SecurePredicate { private String processId; private ByProcessIdPredicate(String processId, List<String> roles) { super(roles, false); this.processId = processId; } @Override public boolean evaluate(Object object) { if (object instanceof ProcessAssetDesc) { ProcessAssetDesc pDesc = (ProcessAssetDesc) object; boolean hasAccess = super.evaluate(object); if (!hasAccess) { return false; } if (pDesc.getId().equals(processId)) { return true; } } return false; } } private class ByDeploymentIdProcessIdPredicate extends SecurePredicate { private String processId; private String depoymentId; private ByDeploymentIdProcessIdPredicate(String depoymentId, String processId, List<String> roles) { super(roles, false); this.depoymentId = depoymentId; this.processId = processId; } private ByDeploymentIdProcessIdPredicate(String depoymentId, String processId, List<String> roles, boolean skipActiveCheck) { super(roles, skipActiveCheck); this.depoymentId = depoymentId; this.processId = processId; } @Override public boolean evaluate(Object object) { if (object instanceof ProcessAssetDesc) { ProcessAssetDesc pDesc = (ProcessAssetDesc) object; boolean hasAccess = super.evaluate(object); if (!hasAccess) { return false; } if (pDesc.getId().equals(processId) && pDesc.getDeploymentId().equals(depoymentId)) { return true; } } return false; } } private class SecurePredicate extends ActiveOnlyPredicate { private List<String> roles; private boolean skipActivCheck; private SecurePredicate(List<String> roles, boolean skipActivCheck) { this.roles = roles; this.skipActivCheck = skipActivCheck; } public boolean evaluate(Object object) { if (!skipActivCheck) { boolean isActive = super.evaluate(object); if (!isActive) { return false; } } ProcessAssetDesc pDesc = (ProcessAssetDesc) object; if (this.roles == null || this.roles.isEmpty() || pDesc.getRoles() == null || pDesc.getRoles().isEmpty()) { return true; } return CollectionUtils.containsAny(roles, pDesc.getRoles()); } } private class UnsecureByDeploymentIdPredicate implements Predicate { private String deploymentId; private UnsecureByDeploymentIdPredicate(String deploymentId) { this.deploymentId = deploymentId; } @Override public boolean evaluate(Object object) { if (object instanceof ProcessAssetDesc) { ProcessAssetDesc pDesc = (ProcessAssetDesc) object; if (pDesc.getDeploymentId().equals(deploymentId)) { return true; } } return false; } } private class ActiveOnlyPredicate implements Predicate { private ActiveOnlyPredicate() { } @Override public boolean evaluate(Object object) { if (object instanceof ProcessAssetDesc) { ProcessAssetDesc pDesc = (ProcessAssetDesc) object; if (pDesc.isActive()) { return true; } } return false; } } /* * end * predicates for collection filtering */ protected void applyQueryFilter(Map<String, Object> params, QueryFilter queryFilter) { if (queryFilter != null) { applyQueryContext(params, queryFilter); if (queryFilter.getFilterParams() != null && !queryFilter.getFilterParams().isEmpty()) { params.put(FILTER, queryFilter.getFilterParams()); for(String key : queryFilter.getParams().keySet()){ params.put(key, queryFilter.getParams().get(key)); } } } } protected List<?> adoptList(List<?> source, List<?> values) { if (source == null || source.isEmpty()) { List<Object> data = new ArrayList<Object>(); for (Object value : values) { data.add(value); } return data; } return source; } }