/* * Copyright 2016 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.admin; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jbpm.kie.services.impl.admin.commands.CancelNodeInstanceCommand; import org.jbpm.kie.services.impl.admin.commands.ListNodesCommand; import org.jbpm.kie.services.impl.admin.commands.ListTimersCommand; import org.jbpm.kie.services.impl.admin.commands.RetriggerNodeInstanceCommand; import org.jbpm.kie.services.impl.admin.commands.TriggerNodeCommand; import org.jbpm.process.instance.command.RelativeUpdateTimerCommand; import org.jbpm.process.instance.command.UpdateTimerCommand; import org.jbpm.runtime.manager.impl.AbstractRuntimeManager; import org.jbpm.services.api.NodeInstanceNotFoundException; import org.jbpm.services.api.NodeNotFoundException; import org.jbpm.services.api.ProcessInstanceNotFoundException; import org.jbpm.services.api.ProcessService; import org.jbpm.services.api.RuntimeDataService; import org.jbpm.services.api.admin.ExecutionErrorNotFoundException; import org.jbpm.services.api.admin.ProcessInstanceAdminService; import org.jbpm.services.api.admin.ProcessNode; import org.jbpm.services.api.admin.TimerInstance; import org.jbpm.services.api.model.NodeInstanceDesc; import org.jbpm.services.api.model.ProcessInstanceDesc; 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.manager.RuntimeManager; import org.kie.api.runtime.query.QueryContext; import org.kie.internal.identity.IdentityProvider; import org.kie.internal.runtime.error.ExecutionError; import org.kie.internal.runtime.manager.RuntimeManagerRegistry; import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext; public class ProcessInstanceAdminServiceImpl implements ProcessInstanceAdminService { private ProcessService processService; private RuntimeDataService runtimeDataService; private IdentityProvider identityProvider; private TransactionalCommandService commandService; public void setProcessService(ProcessService processService) { this.processService = processService; } public void setRuntimeDataService(RuntimeDataService runtimeDataService) { this.runtimeDataService = runtimeDataService; } public void setIdentityProvider(IdentityProvider identityProvider) { this.identityProvider = identityProvider; } public void setCommandService(TransactionalCommandService commandService) { this.commandService = commandService; } @Override public Collection<ProcessNode> getProcessNodes(long processInstanceId) throws ProcessInstanceNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null) { throw new ProcessInstanceNotFoundException("Process instance with id " + processInstanceId + " not found"); } Collection<ProcessNode> nodes = processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new ListNodesCommand(processInstanceId)); return nodes; } @Override public void cancelNodeInstance(long processInstanceId, long nodeInstanceId) throws NodeInstanceNotFoundException, ProcessInstanceNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null) { throw new ProcessInstanceNotFoundException("Process instance with id " + processInstanceId + " not found"); } processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new CancelNodeInstanceCommand(processInstanceId, nodeInstanceId)); } @Override public void retriggerNodeInstance(long processInstanceId, long nodeInstanceId) throws NodeInstanceNotFoundException, ProcessInstanceNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null) { throw new ProcessInstanceNotFoundException("Process instance with id " + processInstanceId + " not found"); } processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new RetriggerNodeInstanceCommand(processInstanceId, nodeInstanceId)); } @Override public void updateTimer(long processInstanceId, long timerId, long delay, long period, int repeatLimit) throws NodeInstanceNotFoundException, ProcessInstanceNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null) { throw new ProcessInstanceNotFoundException("Process instance with id " + processInstanceId + " not found"); } processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new UpdateTimerCommand(processInstanceId, timerId, delay, period, repeatLimit)); } @Override public void updateTimerRelative(long processInstanceId, long timerId, long delay, long period, int repeatLimit) throws NodeInstanceNotFoundException, ProcessInstanceNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null) { throw new ProcessInstanceNotFoundException("Process instance with id " + processInstanceId + " not found"); } processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new RelativeUpdateTimerCommand(processInstanceId, timerId, delay, period, repeatLimit)); } @Override public Collection<TimerInstance> getTimerInstances(long processInstanceId) throws ProcessInstanceNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null) { throw new ProcessInstanceNotFoundException("Process instance with id " + processInstanceId + " not found"); } Collection<TimerInstance> timers = processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new ListTimersCommand(processInstanceId)); return timers; } @Override public void triggerNode(long processInstanceId, long nodeId) throws NodeNotFoundException, ProcessInstanceNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null) { throw new ProcessInstanceNotFoundException("Process instance with id " + processInstanceId + " not found"); } processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new TriggerNodeCommand(processInstanceId, nodeId)); } @Override public Collection<NodeInstanceDesc> getActiveNodeInstances(long processInstanceId) throws ProcessInstanceNotFoundException { return runtimeDataService.getProcessInstanceHistoryActive(processInstanceId, new QueryContext(0, 1000)); } @Override public void acknowledgeError(String... errorId) throws ExecutionErrorNotFoundException { for (String error : errorId) { Map<String, Object> params = new HashMap<String, Object>(); params.put("errorId", error); params.put("ack", false); List<ExecutionError> execErrors = commandService.execute(new QueryNameCommand<List<ExecutionError>>("getErrorById",params)); if (execErrors.isEmpty()) { throw new ExecutionErrorNotFoundException("No execution error found for id " + errorId); } ExecutionError errorInstance = execErrors.get(0); RuntimeManager runtimeManager = RuntimeManagerRegistry.get().getManager(errorInstance.getDeploymentId()); if (runtimeManager != null) { ((AbstractRuntimeManager) runtimeManager).getExecutionErrorManager().getStorage().acknowledge(identityProvider.getName(), errorInstance.getErrorId()); } } } @Override public ExecutionError getError(String errorId) throws ExecutionErrorNotFoundException { Map<String, Object> params = new HashMap<String, Object>(); params.put("errorId", errorId); List<ExecutionError> execErrors = commandService.execute(new QueryNameCommand<List<ExecutionError>>("getErrorByIdSkipAckCheck",params)); if (execErrors.isEmpty()) { throw new ExecutionErrorNotFoundException("No execution error found for id " + errorId); } ExecutionError error = execErrors.get(0); return error; } @Override public List<ExecutionError> getErrors(boolean includeAcknowledged, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("ack", getAckMode(includeAcknowledged)); applyQueryContext(params, queryContext); List<ExecutionError> execErrors = commandService.execute(new QueryNameCommand<List<ExecutionError>>("getErrors",params)); return execErrors; } @Override public List<ExecutionError> getErrorsByProcessId(String deploymentId, String processId, boolean includeAcknowledged, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("deploymentId", deploymentId); params.put("processId", processId); params.put("ack", getAckMode(includeAcknowledged)); applyQueryContext(params, queryContext); List<ExecutionError> execErrors = commandService.execute(new QueryNameCommand<List<ExecutionError>>("getErrorsByProcessId",params)); return execErrors; } @Override public List<ExecutionError> getErrorsByProcessInstanceId(long processInstanceId, boolean includeAcknowledged, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processInstanceId", processInstanceId); params.put("ack", getAckMode(includeAcknowledged)); applyQueryContext(params, queryContext); List<ExecutionError> execErrors = commandService.execute(new QueryNameCommand<List<ExecutionError>>("getErrorsByProcessInstanceId",params)); return execErrors; } @Override public List<ExecutionError> getErrorsByProcessInstanceId(long processInstanceId, String nodeName, boolean includeAcknowledged, QueryContext queryContext) { Map<String, Object> params = new HashMap<String, Object>(); params.put("processInstanceId", processInstanceId); params.put("nodeName", nodeName); params.put("ack", getAckMode(includeAcknowledged)); applyQueryContext(params, queryContext); List<ExecutionError> execErrors = commandService.execute(new QueryNameCommand<List<ExecutionError>>("getErrorsByProcessInstanceIdNodeName",params)); return execErrors; } /* * Helper methods */ 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 List<Boolean> getAckMode(boolean includeAcknowledged) { List<Boolean> ackMode = new ArrayList<>(); ackMode.add(false); if (includeAcknowledged) { ackMode.add(true); } return ackMode; } }