/* * Copyright (c) NASK, NCSC * * This file is part of HoneySpider Network 2.1. * * This is a free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package pl.nask.hsn2.workflow.engine; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import org.activiti.engine.impl.pvm.PvmExecution; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.pvm.runtime.ExecutionImpl; import pl.nask.hsn2.activiti.ExtendedExecutionImpl; import pl.nask.hsn2.framework.suppressor.JobSuppressorHelper; import pl.nask.hsn2.framework.workflow.engine.WorkflowDescriptor; import pl.nask.hsn2.framework.workflow.job.DefaultTasksStatistics; import pl.nask.hsn2.framework.workflow.job.TasksStatistics; public final class ExecutionWrapper { // used by ExtendedExecutionImpl public final static String TASK_ID = "task_id"; public final static String PARENT_EXECUTION = "parent_execution"; public final static String CHILD_EXECUTIONS = "child_executions"; public final static String PROCESS_CONTEXT= "process_context"; private final PvmExecution pvmExecution; private final ActivityExecution activityExecution; private ProcessContext processContext; public ExecutionWrapper(PvmExecution exec) { this.pvmExecution = exec; activityExecution = null; } public ExecutionWrapper(ActivityExecution exec) { this.activityExecution = exec; pvmExecution = null; } public void initProcessState(long jobId, long objectId, Map<String, Properties> userConfig, WorkflowDescriptor wdf, JobSuppressorHelper jobSuppressorHelper) { initProcessState(jobId, objectId, userConfig, wdf, new DefaultTasksStatistics(), jobSuppressorHelper); } public void initProcessState(long jobId, long objectId, Map<String, Properties> userConfig, WorkflowDescriptor wdf, TasksStatistics stats, JobSuppressorHelper jobSuppressorHelper) { if (pvmExecution == null) throw new IllegalStateException("Process variables can be initialized in the PvmExecution only"); if (getProcessContext() != null) throw new IllegalStateException("Process variables are already initialized"); ProcessContext subprocessContext = new ProcessContext(jobId, userConfig, new SubprocessParameters(wdf, objectId), stats, jobSuppressorHelper); pvmExecution.setVariable(PROCESS_CONTEXT, subprocessContext); } public ProcessContext getProcessContext() { if (processContext == null) { processContext = (ProcessContext) getVariable(PROCESS_CONTEXT); } return processContext; } public void initProcessState(long jobId, JobSuppressorHelper jobSuppressorHelper) { initProcessState(jobId, 0, null, null, jobSuppressorHelper); } public void markTaskAsAccepted() { getProcessContext().markTaskAsAccepted(); } private void setVariable(String variableName, Object value) { if (pvmExecution != null) { pvmExecution.setVariable(variableName, value); } else { activityExecution.setVariableLocal(variableName, value); } } private Object getVariable(String variableName) { if (pvmExecution != null) { return pvmExecution.getVariable(variableName); } else { return activityExecution.getVariable(variableName); } } /** * * @return taskId value which has been assigned to the execution */ public int setNewTaskId() { int tid = getProcessContext().newTaskId(); setVariable(TASK_ID, tid); return tid; } public Long getJobId() { return getProcessContext().getJobId(); } public Integer getTaskId() { return getProcessContext().getTaskId(); } public Map<String, Properties> getUserConfig() { return getProcessContext().getUserConfig(); } /** * initialize process state by copying the state of the process given as an argument. * @param execution * @param subprocessParams */ public void initProcessStateFrom(ActivityExecution execution, SubprocessParameters subprocessParams) { if (pvmExecution == null) { throw new IllegalStateException("process may be only initialized from within PvmExecution"); } setVariable(PROCESS_CONTEXT, new ExecutionWrapper(execution).getProcessContext().subprocessContext(subprocessParams)); setVariable(PARENT_EXECUTION, execution); getChildExecutions(execution).add(pvmExecution); } public void signal(String signalName, Object requestId) { if (pvmExecution != null) { pvmExecution.signal(signalName, requestId); } } public void signal(String signalName) { if (pvmExecution != null) { pvmExecution.signal(signalName, null); } else { ((ExtendedExecutionImpl) activityExecution).signal(signalName, null); } if ("resume".equals(signalName)) { List<ExecutionWrapper> waiting = getWaitingOnResume(); while (waiting.size() > 0) { ExecutionWrapper wrapper = waiting.remove(waiting.size() - 1); wrapper.signal(signalName); } } else { for (PvmExecution exec: getChildExecutions()) { new ExecutionWrapper(exec).signal(signalName); } } } public void subprocess(WorkflowDescriptor wdf, long objectDataId) { SubprocessParameters params = new SubprocessParameters(wdf, objectDataId); pvmExecution.signal("subprocess", params); } public int countActiveSubprocesses() { int active = 0; List<PvmExecution> execs = getChildExecutions(); for (PvmExecution exec: execs) { ExecutionImpl execImpl = (ExecutionImpl) exec; if (!execImpl.isEnded()) { active ++; ExecutionWrapper wrapper = new ExecutionWrapper(exec); active += wrapper.countActiveSubprocesses(); } } return active; } public List<PvmExecution> getChildExecutions() { if (pvmExecution != null) { List<PvmExecution> execs = getChildExecutions(pvmExecution); return Collections.unmodifiableList(execs); } else { List<PvmExecution> execs = getChildExecutions(activityExecution); return Collections.unmodifiableList(execs); } } private List<PvmExecution> getChildExecutions(ActivityExecution execution) { @SuppressWarnings("unchecked") List<PvmExecution> executions = (List<PvmExecution>) execution.getVariable(CHILD_EXECUTIONS); if (executions == null) { executions = new LinkedList<PvmExecution>(); execution.setVariableLocal(CHILD_EXECUTIONS, executions); } return executions; } private List<PvmExecution> getChildExecutions(PvmExecution execution) { @SuppressWarnings("unchecked") List<PvmExecution> executions = (List<PvmExecution>) execution.getVariable(CHILD_EXECUTIONS); if (executions == null) { executions = new LinkedList<PvmExecution>(); execution.setVariable(CHILD_EXECUTIONS, executions); } return executions; } public SubprocessParameters getSubprocessParameters() { return getProcessContext().getSubprocessParameters(); } private List<ExecutionWrapper> getWaitingOnResume() { return getProcessContext().getWaitingForResume(); } public TasksStatistics getJobStats() { return getProcessContext().getJobStats(); } public void schedule() { getWaitingOnResume().add(this); } }