X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.slc.spring%2Fsrc%2Forg%2Fargeo%2Fslc%2Fcore%2Fexecution%2Fgenerator%2FRunnableCallFlow.java;fp=org.argeo.slc.spring%2Fsrc%2Forg%2Fargeo%2Fslc%2Fcore%2Fexecution%2Fgenerator%2FRunnableCallFlow.java;h=695606c210f803dafda009d5f97c18b078e72f32;hb=e14154d2baba78852915304d51cbb56bed1d3d3e;hp=0000000000000000000000000000000000000000;hpb=aba0f1135009d9014c42368ecea338088e6d2be1;p=gpl%2Fargeo-slc.git diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/generator/RunnableCallFlow.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/generator/RunnableCallFlow.java new file mode 100644 index 000000000..695606c21 --- /dev/null +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/generator/RunnableCallFlow.java @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.slc.core.execution.generator; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.core.execution.DefaultExecutionSpec; +import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionSpec; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +/** + * Execution Flow calling a list of Runnable (identified by their + * bean name in the Spring Application Context) after configuring the Execution + * context and a Map potentially shared by the called Runnable + * + */ +public class RunnableCallFlow implements ExecutionFlow, ApplicationContextAware { + + private final static Log log = LogFactory.getLog(RunnableCallFlow.class); + + /** + * Key in the execution context for the index of the call (e.g. 0 for the + * first runnable called, ...) + */ + public final static String VAR_CALL_INDEX = "slcVar.runnableCallFlow.callIndex"; + + /** + * Name of the flow. Also bean name + */ + private String name; + + /** + * Path of the flow + */ + private String path; + + /** + * Whether an exception in a Runnable shall stop the execution + * of the flow + */ + private Boolean failOnError = true; + + /** + * List of Runnable to call, with bean name, execution + * variables and context values + */ + private List runnableCalls; + + /** + * Map potentially referenced by called flows. Updated with the context + * values of a Runnable before calling it. + */ + private Map sharedContextValuesMap; + + /** + * ExecutionSpec of the flow. Does not contain any attribute. + */ + private ExecutionSpec executionSpec = new DefaultExecutionSpec(); + + /** + * Reference to the ExecutionContext + */ + private ExecutionContext executionContext; + + /** + * Reference to the Spring ApplicationContext. Set via + * setApplicationContext, the class implementing + * ApplicationContextAware + */ + private ApplicationContext applicationContext; + + /** + * Runs a Runnable after configuring the Execution Context and + * sharedContextValuesMap + * + * @param runnable + * the Runnable to call + * @param executionVariables + * the variables to add to the ExecutionContext + * @param contextValues + * the variables to add to sharedContextValuesMap + * @param callIndex + * index of the call (0 for the first called + * Runnable) set as variable of the + * ExecutionContext + */ + private void run(Runnable runnable, Map executionVariables, + Map contextValues, int callIndex) { + // add all variables to the Execution Context + for (Map.Entry entry : executionVariables.entrySet()) { + executionContext.setVariable(entry.getKey(), entry.getValue()); + } + + // add call Index Variable + executionContext.setVariable(VAR_CALL_INDEX, callIndex); + + // clear sharedContextValues and add all values of contextValues + if (sharedContextValuesMap != null) { + sharedContextValuesMap.clear(); + sharedContextValuesMap.putAll(contextValues); + } + + // then run the runnable + doExecuteRunnable(runnable); + } + + public void doExecuteRunnable(Runnable runnable) { + runnable.run(); + } + + /** + * Executes the flow. For each RunnableCall, the corresponding + * flow is retrieved from the Spring Application Context, the + * ExecutionContext and sharedContextValuesMap are + * configured and the Runnable is called. + */ + public void run() { + if (applicationContext == null) { + throw new SlcException("No ApplicationContext defined"); + } + + try { + for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) { + RunnableCall runnableCall = runnableCalls.get(callIndex); + Object bean = applicationContext.getBean( + runnableCall.getBeanName(), Runnable.class); + if (log.isDebugEnabled()) + log.debug("Running flow '" + runnableCall.getBeanName() + + "'"); + run((Runnable) bean, runnableCall.getExecutionVariables(), + runnableCall.getContextValues(), callIndex); + } + } catch (RuntimeException e) { + if (failOnError) + throw e; + else { + log.error("Execution flow failed," + + " but process did not fail" + + " because failOnError property" + + " is set to false: " + e); + if (log.isTraceEnabled()) + e.printStackTrace(); + } + } + } + + public Iterator runnables() { + List runnables = new ArrayList(); + for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) { + RunnableCall runnableCall = runnableCalls.get(callIndex); + Object bean = applicationContext.getBean( + runnableCall.getBeanName(), Runnable.class); + runnables.add((Runnable) bean); + } + return runnables.iterator(); + } + + public Runnable getRunnable() { + if (runnableCalls.size() == 1) + return runnables().next(); + else + throw new SlcException("There are " + runnableCalls.size() + + " runnables in flow " + getName()); + } + + @Override + public String toString() { + return new StringBuffer("RunnableCallFlow ").append(name).toString(); + } + + public ExecutionSpec getExecutionSpec() { + return executionSpec; + } + + public String getName() { + return name; + } + + public Object getParameter(String key) { + throw new SlcException("RunnableCallFlow have no parameters"); + } + + public String getPath() { + return path; + } + + public Boolean isSetAsParameter(String key) { + // The ExecutionSpec having no attribute, + // always return false + return false; + } + + public void setName(String name) { + this.name = name; + } + + public void setPath(String path) { + this.path = path; + } + + public void setExecutionContext(ExecutionContext executionContext) { + this.executionContext = executionContext; + } + + public void setRunnableCalls(List runnableCalls) { + this.runnableCalls = runnableCalls; + } + + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + public void setSharedContextValuesMap(Map contextValues) { + this.sharedContextValuesMap = contextValues; + } + + public void setFailOnError(Boolean failOnError) { + this.failOnError = failOnError; + } + +}