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