]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCallFlow.java
Improve SystemCall
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / execution / generator / RunnableCallFlow.java
1 package org.argeo.slc.core.execution.generator;
2
3 import java.util.List;
4 import java.util.Map;
5
6 import org.apache.commons.logging.Log;
7 import org.apache.commons.logging.LogFactory;
8 import org.argeo.slc.SlcException;
9 import org.argeo.slc.core.execution.DefaultExecutionSpec;
10 import org.argeo.slc.execution.ExecutionContext;
11 import org.argeo.slc.execution.ExecutionFlow;
12 import org.argeo.slc.execution.ExecutionSpec;
13 import org.springframework.context.ApplicationContext;
14 import org.springframework.context.ApplicationContextAware;
15
16 /**
17 * Execution Flow calling a list of <code>Runnable</code> (identified by their bean
18 * name in the Spring Application Context) after configuring the Execution
19 * context and a Map potentially shared by the called <code>Runnable</code>
20 *
21 */
22 public class RunnableCallFlow implements ExecutionFlow, ApplicationContextAware {
23
24 private final static Log log = LogFactory.getLog(RunnableCallFlow.class);
25
26 /**
27 * Key in the execution context for the index of the call (e.g. 0
28 * for the first runnable called, ...)
29 */
30 public final static String VAR_CALL_INDEX = "slcVar.runnableCallFlow.callIndex";
31
32 /**
33 * Name of the flow. Also bean name
34 */
35 private String name;
36
37 /**
38 * Path of the flow
39 */
40 private String path;
41
42 /**
43 * Whether an exception in a <code>Runnable</code> shall
44 * stop the execution of the flow
45 */
46 private Boolean failOnError = true;
47
48 /**
49 * List of <code>Runnable</code> to call, with bean name, execution variables and
50 * context values
51 */
52 private List<RunnableCall> runnableCalls;
53
54 /**
55 * Map potentially referenced by called flows. Updated with
56 * the context values of a Runnable before calling it.
57 */
58 private Map<String, Object> sharedContextValuesMap;
59
60 /**
61 * ExecutionSpec of the flow. Does not contain any
62 * attribute.
63 */
64 private ExecutionSpec executionSpec = new DefaultExecutionSpec();
65
66 /**
67 * Reference to the ExecutionContext
68 */
69 private ExecutionContext executionContext;
70
71 /**
72 * Reference to the Spring <code>ApplicationContext</code>.
73 * Set via <code>setApplicationContext</code>, the class implementing
74 * <code>ApplicationContextAware</code>
75 */
76 private ApplicationContext applicationContext;
77
78 /**
79 * Runs a <code>Runnable</code> after configuring the Execution Context
80 * and <code>sharedContextValuesMap</code>
81 * @param runnable the <code>Runnable</code> to call
82 * @param executionVariables the variables to add to the <code>ExecutionContext</code>
83 * @param contextValues the variables to add to <code>sharedContextValuesMap</code>
84 * @param callIndex index of the call (0 for the first called <code>Runnable</code>)
85 * set as variable of the <code>ExecutionContext</code>
86 */
87 private void run(Runnable runnable, Map<String, Object> executionVariables, Map<String, Object> contextValues, int callIndex) {
88 // add all variables to the Execution Context
89 for(Map.Entry<String,Object> entry : executionVariables.entrySet()) {
90 executionContext.setVariable(entry.getKey(), entry.getValue());
91 }
92
93 // add call Index Variable
94 executionContext.setVariable(VAR_CALL_INDEX, callIndex);
95
96 // clear sharedContextValues and add all values of contextValues
97 if(sharedContextValuesMap != null) {
98 sharedContextValuesMap.clear();
99 sharedContextValuesMap.putAll(contextValues);
100 }
101
102 // then run the runnable
103 runnable.run();
104 }
105
106 /**
107 * Executes the flow.
108 * For each <code>RunnableCall</code>, the corresponding flow
109 * is retrieved from the Spring Application Context, the
110 * <code>ExecutionContext</code> and <code>sharedContextValuesMap</code>
111 * are configured and the <code>Runnable</code> is called.
112 */
113 public void run() {
114 if (applicationContext == null) {
115 throw new SlcException("No ApplicationContext defined");
116 }
117
118 try {
119 for(int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) {
120 RunnableCall runnableCall = runnableCalls.get(callIndex);
121 Object bean = applicationContext.getBean(runnableCall.getBeanName(), Runnable.class);
122 if(log.isDebugEnabled())
123 log.debug("Running flow '" + runnableCall.getBeanName() + "'");
124 run((Runnable)bean, runnableCall.getExecutionVariables(), runnableCall.getContextValues(), callIndex);
125 }
126 } catch (RuntimeException e) {
127 if (failOnError)
128 throw e;
129 else {
130 log.error("Execution flow failed,"
131 + " but process did not fail"
132 + " because failOnError property"
133 + " is set to false: " + e);
134 if (log.isTraceEnabled())
135 e.printStackTrace();
136 }
137 }
138 }
139
140 public ExecutionSpec getExecutionSpec() {
141 return executionSpec;
142 }
143
144 public String getName() {
145 return name;
146 }
147
148 public Object getParameter(String key) {
149 throw new SlcException("RunnableCallFlow have no parameters");
150 }
151
152 public String getPath() {
153 return path;
154 }
155
156 public Boolean isSetAsParameter(String key) {
157 // The ExecutionSpec having no attribute,
158 // always return false
159 return false;
160 }
161
162 public void setName(String name) {
163 this.name = name;
164 }
165
166 public void setPath(String path) {
167 this.path = path;
168 }
169
170 public void setExecutionContext(ExecutionContext executionContext) {
171 this.executionContext = executionContext;
172 }
173
174 public void setRunnableCalls(List<RunnableCall> runnableCalls) {
175 this.runnableCalls = runnableCalls;
176 }
177
178 public void setApplicationContext(ApplicationContext applicationContext) {
179 this.applicationContext = applicationContext;
180 }
181
182 public void setSharedContextValuesMap(Map<String, Object> contextValues) {
183 this.sharedContextValuesMap = contextValues;
184 }
185
186 public void setFailOnError(Boolean failOnError) {
187 this.failOnError = failOnError;
188 }
189
190 }