-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.argeo.slc.SlcException;\r
-import org.argeo.slc.core.execution.DefaultExecutionSpec;\r
-import org.argeo.slc.execution.ExecutionContext;\r
-import org.argeo.slc.execution.ExecutionFlow;\r
-import org.argeo.slc.execution.ExecutionSpec;\r
-import org.springframework.context.ApplicationContext;\r
-import org.springframework.context.ApplicationContextAware;\r
-\r
-/**\r
- * Execution Flow calling a list of <code>Runnable</code> (identified by their\r
- * bean name in the Spring Application Context) after configuring the Execution\r
- * context and a Map potentially shared by the called <code>Runnable</code>\r
- * \r
- */\r
-public class RunnableCallFlow implements ExecutionFlow, ApplicationContextAware {\r
-\r
- private final static Log log = LogFactory.getLog(RunnableCallFlow.class);\r
-\r
- /**\r
- * Key in the execution context for the index of the call (e.g. 0 for the\r
- * first runnable called, ...)\r
- */\r
- public final static String VAR_CALL_INDEX = "slcVar.runnableCallFlow.callIndex";\r
-\r
- /**\r
- * Name of the flow. Also bean name\r
- */\r
- private String name;\r
-\r
- /**\r
- * Path of the flow\r
- */\r
- private String path;\r
-\r
- /**\r
- * Whether an exception in a <code>Runnable</code> shall stop the execution\r
- * of the flow\r
- */\r
- private Boolean failOnError = true;\r
-\r
- /**\r
- * List of <code>Runnable</code> to call, with bean name, execution\r
- * variables and context values\r
- */\r
- private List<RunnableCall> runnableCalls;\r
-\r
- /**\r
- * Map potentially referenced by called flows. Updated with the context\r
- * values of a Runnable before calling it.\r
- */\r
- private Map<String, Object> sharedContextValuesMap;\r
-\r
- /**\r
- * ExecutionSpec of the flow. Does not contain any attribute.\r
- */\r
- private ExecutionSpec executionSpec = new DefaultExecutionSpec();\r
-\r
- /**\r
- * Reference to the ExecutionContext\r
- */\r
- private ExecutionContext executionContext;\r
-\r
- /**\r
- * Reference to the Spring <code>ApplicationContext</code>. Set via\r
- * <code>setApplicationContext</code>, the class implementing\r
- * <code>ApplicationContextAware</code>\r
- */\r
- private ApplicationContext applicationContext;\r
-\r
- /**\r
- * Runs a <code>Runnable</code> after configuring the Execution Context and\r
- * <code>sharedContextValuesMap</code>\r
- * \r
- * @param runnable\r
- * the <code>Runnable</code> to call\r
- * @param executionVariables\r
- * the variables to add to the <code>ExecutionContext</code>\r
- * @param contextValues\r
- * the variables to add to <code>sharedContextValuesMap</code>\r
- * @param callIndex\r
- * index of the call (0 for the first called\r
- * <code>Runnable</code>) set as variable of the\r
- * <code>ExecutionContext</code>\r
- */\r
- private void run(Runnable runnable, Map<String, Object> executionVariables,\r
- Map<String, Object> contextValues, int callIndex) {\r
- // add all variables to the Execution Context\r
- for (Map.Entry<String, Object> entry : executionVariables.entrySet()) {\r
- executionContext.setVariable(entry.getKey(), entry.getValue());\r
- }\r
-\r
- // add call Index Variable\r
- executionContext.setVariable(VAR_CALL_INDEX, callIndex);\r
-\r
- // clear sharedContextValues and add all values of contextValues\r
- if (sharedContextValuesMap != null) {\r
- sharedContextValuesMap.clear();\r
- sharedContextValuesMap.putAll(contextValues);\r
- }\r
-\r
- // then run the runnable\r
- doExecuteRunnable(runnable);\r
- }\r
-\r
- public void doExecuteRunnable(Runnable runnable) {\r
- runnable.run();\r
- }\r
-\r
- /**\r
- * Executes the flow. For each <code>RunnableCall</code>, the corresponding\r
- * flow is retrieved from the Spring Application Context, the\r
- * <code>ExecutionContext</code> and <code>sharedContextValuesMap</code> are\r
- * configured and the <code>Runnable</code> is called.\r
- */\r
- public void run() {\r
- if (applicationContext == null) {\r
- throw new SlcException("No ApplicationContext defined");\r
- }\r
-\r
- try {\r
- for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) {\r
- RunnableCall runnableCall = runnableCalls.get(callIndex);\r
- Object bean = applicationContext.getBean(\r
- runnableCall.getBeanName(), Runnable.class);\r
- if (log.isDebugEnabled())\r
- log.debug("Running flow '" + runnableCall.getBeanName()\r
- + "'");\r
- run((Runnable) bean, runnableCall.getExecutionVariables(),\r
- runnableCall.getContextValues(), callIndex);\r
- }\r
- } catch (RuntimeException e) {\r
- if (failOnError)\r
- throw e;\r
- else {\r
- log.error("Execution flow failed,"\r
- + " but process did not fail"\r
- + " because failOnError property"\r
- + " is set to false: " + e);\r
- if (log.isTraceEnabled())\r
- e.printStackTrace();\r
- }\r
- }\r
- }\r
-\r
- public Iterator<Runnable> runnables() {\r
- List<Runnable> runnables = new ArrayList<Runnable>();\r
- for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) {\r
- RunnableCall runnableCall = runnableCalls.get(callIndex);\r
- Object bean = applicationContext.getBean(\r
- runnableCall.getBeanName(), Runnable.class);\r
- runnables.add((Runnable) bean);\r
- }\r
- return runnables.iterator();\r
- }\r
-\r
- public Runnable getRunnable() {\r
- if (runnableCalls.size() == 1)\r
- return runnables().next();\r
- else\r
- throw new SlcException("There are " + runnableCalls.size()\r
- + " runnables in flow " + getName());\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return new StringBuffer("RunnableCallFlow ").append(name).toString();\r
- }\r
-\r
- public ExecutionSpec getExecutionSpec() {\r
- return executionSpec;\r
- }\r
-\r
- public String getName() {\r
- return name;\r
- }\r
-\r
- public Object getParameter(String key) {\r
- throw new SlcException("RunnableCallFlow have no parameters");\r
- }\r
-\r
- public String getPath() {\r
- return path;\r
- }\r
-\r
- public Boolean isSetAsParameter(String key) {\r
- // The ExecutionSpec having no attribute,\r
- // always return false\r
- return false;\r
- }\r
-\r
- public void setName(String name) {\r
- this.name = name;\r
- }\r
-\r
- public void setPath(String path) {\r
- this.path = path;\r
- }\r
-\r
- public void setExecutionContext(ExecutionContext executionContext) {\r
- this.executionContext = executionContext;\r
- }\r
-\r
- public void setRunnableCalls(List<RunnableCall> runnableCalls) {\r
- this.runnableCalls = runnableCalls;\r
- }\r
-\r
- public void setApplicationContext(ApplicationContext applicationContext) {\r
- this.applicationContext = applicationContext;\r
- }\r
-\r
- public void setSharedContextValuesMap(Map<String, Object> contextValues) {\r
- this.sharedContextValuesMap = contextValues;\r
- }\r
-\r
- public void setFailOnError(Boolean failOnError) {\r
- this.failOnError = failOnError;\r
- }\r
-\r
-}\r
+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 <code>Runnable</code> (identified by their
+ * bean name in the Spring Application Context) after configuring the Execution
+ * context and a Map potentially shared by the called <code>Runnable</code>
+ *
+ */
+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 <code>Runnable</code> shall stop the execution
+ * of the flow
+ */
+ private Boolean failOnError = true;
+
+ /**
+ * List of <code>Runnable</code> to call, with bean name, execution
+ * variables and context values
+ */
+ private List<RunnableCall> runnableCalls;
+
+ /**
+ * Map potentially referenced by called flows. Updated with the context
+ * values of a Runnable before calling it.
+ */
+ private Map<String, Object> 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 <code>ApplicationContext</code>. Set via
+ * <code>setApplicationContext</code>, the class implementing
+ * <code>ApplicationContextAware</code>
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * Runs a <code>Runnable</code> after configuring the Execution Context and
+ * <code>sharedContextValuesMap</code>
+ *
+ * @param runnable
+ * the <code>Runnable</code> to call
+ * @param executionVariables
+ * the variables to add to the <code>ExecutionContext</code>
+ * @param contextValues
+ * the variables to add to <code>sharedContextValuesMap</code>
+ * @param callIndex
+ * index of the call (0 for the first called
+ * <code>Runnable</code>) set as variable of the
+ * <code>ExecutionContext</code>
+ */
+ private void run(Runnable runnable, Map<String, Object> executionVariables,
+ Map<String, Object> contextValues, int callIndex) {
+ // add all variables to the Execution Context
+ for (Map.Entry<String, Object> 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 <code>RunnableCall</code>, the corresponding
+ * flow is retrieved from the Spring Application Context, the
+ * <code>ExecutionContext</code> and <code>sharedContextValuesMap</code> are
+ * configured and the <code>Runnable</code> 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<Runnable> runnables() {
+ List<Runnable> runnables = new ArrayList<Runnable>();
+ 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<RunnableCall> runnableCalls) {
+ this.runnableCalls = runnableCalls;
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ public void setSharedContextValuesMap(Map<String, Object> contextValues) {
+ this.sharedContextValuesMap = contextValues;
+ }
+
+ public void setFailOnError(Boolean failOnError) {
+ this.failOnError = failOnError;
+ }
+
+}