]> 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
Minimal Hello World execution module
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / execution / generator / RunnableCallFlow.java
1 /*
2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.argeo.slc.core.execution.generator;
18
19 import java.util.List;
20 import java.util.Map;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.argeo.slc.SlcException;
25 import org.argeo.slc.core.execution.DefaultExecutionSpec;
26 import org.argeo.slc.execution.ExecutionContext;
27 import org.argeo.slc.execution.ExecutionFlow;
28 import org.argeo.slc.execution.ExecutionSpec;
29 import org.springframework.context.ApplicationContext;
30 import org.springframework.context.ApplicationContextAware;
31
32 /**
33 * Execution Flow calling a list of <code>Runnable</code> (identified by their
34 * bean name in the Spring Application Context) after configuring the Execution
35 * context and a Map potentially shared by the called <code>Runnable</code>
36 *
37 */
38 public class RunnableCallFlow implements ExecutionFlow, ApplicationContextAware {
39
40 private final static Log log = LogFactory.getLog(RunnableCallFlow.class);
41
42 /**
43 * Key in the execution context for the index of the call (e.g. 0 for the
44 * first runnable called, ...)
45 */
46 public final static String VAR_CALL_INDEX = "slcVar.runnableCallFlow.callIndex";
47
48 /**
49 * Name of the flow. Also bean name
50 */
51 private String name;
52
53 /**
54 * Path of the flow
55 */
56 private String path;
57
58 /**
59 * Whether an exception in a <code>Runnable</code> shall stop the execution
60 * of the flow
61 */
62 private Boolean failOnError = true;
63
64 /**
65 * List of <code>Runnable</code> to call, with bean name, execution
66 * variables and context values
67 */
68 private List<RunnableCall> runnableCalls;
69
70 /**
71 * Map potentially referenced by called flows. Updated with the context
72 * values of a Runnable before calling it.
73 */
74 private Map<String, Object> sharedContextValuesMap;
75
76 /**
77 * ExecutionSpec of the flow. Does not contain any attribute.
78 */
79 private ExecutionSpec executionSpec = new DefaultExecutionSpec();
80
81 /**
82 * Reference to the ExecutionContext
83 */
84 private ExecutionContext executionContext;
85
86 /**
87 * Reference to the Spring <code>ApplicationContext</code>. Set via
88 * <code>setApplicationContext</code>, the class implementing
89 * <code>ApplicationContextAware</code>
90 */
91 private ApplicationContext applicationContext;
92
93 /**
94 * Runs a <code>Runnable</code> after configuring the Execution Context and
95 * <code>sharedContextValuesMap</code>
96 *
97 * @param runnable
98 * the <code>Runnable</code> to call
99 * @param executionVariables
100 * the variables to add to the <code>ExecutionContext</code>
101 * @param contextValues
102 * the variables to add to <code>sharedContextValuesMap</code>
103 * @param callIndex
104 * index of the call (0 for the first called
105 * <code>Runnable</code>) set as variable of the
106 * <code>ExecutionContext</code>
107 */
108 private void run(Runnable runnable, Map<String, Object> executionVariables,
109 Map<String, Object> contextValues, int callIndex) {
110 // add all variables to the Execution Context
111 for (Map.Entry<String, Object> entry : executionVariables.entrySet()) {
112 executionContext.setVariable(entry.getKey(), entry.getValue());
113 }
114
115 // add call Index Variable
116 executionContext.setVariable(VAR_CALL_INDEX, callIndex);
117
118 // clear sharedContextValues and add all values of contextValues
119 if (sharedContextValuesMap != null) {
120 sharedContextValuesMap.clear();
121 sharedContextValuesMap.putAll(contextValues);
122 }
123
124 // then run the runnable
125 doExecuteRunnable(runnable);
126 }
127
128 public void doExecuteRunnable(Runnable runnable) {
129 runnable.run();
130 }
131
132 /**
133 * Executes the flow. For each <code>RunnableCall</code>, the corresponding
134 * flow is retrieved from the Spring Application Context, the
135 * <code>ExecutionContext</code> and <code>sharedContextValuesMap</code> are
136 * configured and the <code>Runnable</code> is called.
137 */
138 public void run() {
139 if (applicationContext == null) {
140 throw new SlcException("No ApplicationContext defined");
141 }
142
143 try {
144 for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) {
145 RunnableCall runnableCall = runnableCalls.get(callIndex);
146 Object bean = applicationContext.getBean(runnableCall
147 .getBeanName(), Runnable.class);
148 if (log.isDebugEnabled())
149 log.debug("Running flow '" + runnableCall.getBeanName()
150 + "'");
151 run((Runnable) bean, runnableCall.getExecutionVariables(),
152 runnableCall.getContextValues(), callIndex);
153 }
154 } catch (RuntimeException e) {
155 if (failOnError)
156 throw e;
157 else {
158 log.error("Execution flow failed,"
159 + " but process did not fail"
160 + " because failOnError property"
161 + " is set to false: " + e);
162 if (log.isTraceEnabled())
163 e.printStackTrace();
164 }
165 }
166 }
167
168 @Override
169 public String toString() {
170 return new StringBuffer("RunnableCallFlow ").append(name).toString();
171 }
172
173 public ExecutionSpec getExecutionSpec() {
174 return executionSpec;
175 }
176
177 public String getName() {
178 return name;
179 }
180
181 public Object getParameter(String key) {
182 throw new SlcException("RunnableCallFlow have no parameters");
183 }
184
185 public String getPath() {
186 return path;
187 }
188
189 public Boolean isSetAsParameter(String key) {
190 // The ExecutionSpec having no attribute,
191 // always return false
192 return false;
193 }
194
195 public void setName(String name) {
196 this.name = name;
197 }
198
199 public void setPath(String path) {
200 this.path = path;
201 }
202
203 public void setExecutionContext(ExecutionContext executionContext) {
204 this.executionContext = executionContext;
205 }
206
207 public void setRunnableCalls(List<RunnableCall> runnableCalls) {
208 this.runnableCalls = runnableCalls;
209 }
210
211 public void setApplicationContext(ApplicationContext applicationContext) {
212 this.applicationContext = applicationContext;
213 }
214
215 public void setSharedContextValuesMap(Map<String, Object> contextValues) {
216 this.sharedContextValuesMap = contextValues;
217 }
218
219 public void setFailOnError(Boolean failOnError) {
220 this.failOnError = failOnError;
221 }
222
223 }