2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org
.argeo
.slc
.core
.execution
.generator
;
19 import java
.util
.List
;
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
;
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>
38 public class RunnableCallFlow
implements ExecutionFlow
, ApplicationContextAware
{
40 private final static Log log
= LogFactory
.getLog(RunnableCallFlow
.class);
43 * Key in the execution context for the index of the call (e.g. 0 for the
44 * first runnable called, ...)
46 public final static String VAR_CALL_INDEX
= "slcVar.runnableCallFlow.callIndex";
49 * Name of the flow. Also bean name
59 * Whether an exception in a <code>Runnable</code> shall stop the execution
62 private Boolean failOnError
= true;
65 * List of <code>Runnable</code> to call, with bean name, execution
66 * variables and context values
68 private List
<RunnableCall
> runnableCalls
;
71 * Map potentially referenced by called flows. Updated with the context
72 * values of a Runnable before calling it.
74 private Map
<String
, Object
> sharedContextValuesMap
;
77 * ExecutionSpec of the flow. Does not contain any attribute.
79 private ExecutionSpec executionSpec
= new DefaultExecutionSpec();
82 * Reference to the ExecutionContext
84 private ExecutionContext executionContext
;
87 * Reference to the Spring <code>ApplicationContext</code>. Set via
88 * <code>setApplicationContext</code>, the class implementing
89 * <code>ApplicationContextAware</code>
91 private ApplicationContext applicationContext
;
94 * Runs a <code>Runnable</code> after configuring the Execution Context and
95 * <code>sharedContextValuesMap</code>
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>
104 * index of the call (0 for the first called
105 * <code>Runnable</code>) set as variable of the
106 * <code>ExecutionContext</code>
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());
115 // add call Index Variable
116 executionContext
.setVariable(VAR_CALL_INDEX
, callIndex
);
118 // clear sharedContextValues and add all values of contextValues
119 if (sharedContextValuesMap
!= null) {
120 sharedContextValuesMap
.clear();
121 sharedContextValuesMap
.putAll(contextValues
);
124 // then run the runnable
125 doExecuteRunnable(runnable
);
128 public void doExecuteRunnable(Runnable runnable
) {
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.
139 if (applicationContext
== null) {
140 throw new SlcException("No ApplicationContext defined");
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()
151 run((Runnable
) bean
, runnableCall
.getExecutionVariables(),
152 runnableCall
.getContextValues(), callIndex
);
154 } catch (RuntimeException e
) {
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())
169 public String
toString() {
170 return new StringBuffer("RunnableCallFlow ").append(name
).toString();
173 public ExecutionSpec
getExecutionSpec() {
174 return executionSpec
;
177 public String
getName() {
181 public Object
getParameter(String key
) {
182 throw new SlcException("RunnableCallFlow have no parameters");
185 public String
getPath() {
189 public Boolean
isSetAsParameter(String key
) {
190 // The ExecutionSpec having no attribute,
191 // always return false
195 public void setName(String name
) {
199 public void setPath(String path
) {
203 public void setExecutionContext(ExecutionContext executionContext
) {
204 this.executionContext
= executionContext
;
207 public void setRunnableCalls(List
<RunnableCall
> runnableCalls
) {
208 this.runnableCalls
= runnableCalls
;
211 public void setApplicationContext(ApplicationContext applicationContext
) {
212 this.applicationContext
= applicationContext
;
215 public void setSharedContextValuesMap(Map
<String
, Object
> contextValues
) {
216 this.sharedContextValuesMap
= contextValues
;
219 public void setFailOnError(Boolean failOnError
) {
220 this.failOnError
= failOnError
;