2 * Copyright (C) 2007-2012 Mathieu Baudier
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.
16 package org
.argeo
.slc
.core
.execution
.generator
;
18 import java
.util
.List
;
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
;
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>
37 public class RunnableCallFlow
implements ExecutionFlow
, ApplicationContextAware
{
39 private final static Log log
= LogFactory
.getLog(RunnableCallFlow
.class);
42 * Key in the execution context for the index of the call (e.g. 0 for the
43 * first runnable called, ...)
45 public final static String VAR_CALL_INDEX
= "slcVar.runnableCallFlow.callIndex";
48 * Name of the flow. Also bean name
58 * Whether an exception in a <code>Runnable</code> shall stop the execution
61 private Boolean failOnError
= true;
64 * List of <code>Runnable</code> to call, with bean name, execution
65 * variables and context values
67 private List
<RunnableCall
> runnableCalls
;
70 * Map potentially referenced by called flows. Updated with the context
71 * values of a Runnable before calling it.
73 private Map
<String
, Object
> sharedContextValuesMap
;
76 * ExecutionSpec of the flow. Does not contain any attribute.
78 private ExecutionSpec executionSpec
= new DefaultExecutionSpec();
81 * Reference to the ExecutionContext
83 private ExecutionContext executionContext
;
86 * Reference to the Spring <code>ApplicationContext</code>. Set via
87 * <code>setApplicationContext</code>, the class implementing
88 * <code>ApplicationContextAware</code>
90 private ApplicationContext applicationContext
;
93 * Runs a <code>Runnable</code> after configuring the Execution Context and
94 * <code>sharedContextValuesMap</code>
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>
103 * index of the call (0 for the first called
104 * <code>Runnable</code>) set as variable of the
105 * <code>ExecutionContext</code>
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());
114 // add call Index Variable
115 executionContext
.setVariable(VAR_CALL_INDEX
, callIndex
);
117 // clear sharedContextValues and add all values of contextValues
118 if (sharedContextValuesMap
!= null) {
119 sharedContextValuesMap
.clear();
120 sharedContextValuesMap
.putAll(contextValues
);
123 // then run the runnable
124 doExecuteRunnable(runnable
);
127 public void doExecuteRunnable(Runnable runnable
) {
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.
138 if (applicationContext
== null) {
139 throw new SlcException("No ApplicationContext defined");
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()
150 run((Runnable
) bean
, runnableCall
.getExecutionVariables(),
151 runnableCall
.getContextValues(), callIndex
);
153 } catch (RuntimeException e
) {
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())
168 public String
toString() {
169 return new StringBuffer("RunnableCallFlow ").append(name
).toString();
172 public ExecutionSpec
getExecutionSpec() {
173 return executionSpec
;
176 public String
getName() {
180 public Object
getParameter(String key
) {
181 throw new SlcException("RunnableCallFlow have no parameters");
184 public String
getPath() {
188 public Boolean
isSetAsParameter(String key
) {
189 // The ExecutionSpec having no attribute,
190 // always return false
194 public void setName(String name
) {
198 public void setPath(String path
) {
202 public void setExecutionContext(ExecutionContext executionContext
) {
203 this.executionContext
= executionContext
;
206 public void setRunnableCalls(List
<RunnableCall
> runnableCalls
) {
207 this.runnableCalls
= runnableCalls
;
210 public void setApplicationContext(ApplicationContext applicationContext
) {
211 this.applicationContext
= applicationContext
;
214 public void setSharedContextValuesMap(Map
<String
, Object
> contextValues
) {
215 this.sharedContextValuesMap
= contextValues
;
218 public void setFailOnError(Boolean failOnError
) {
219 this.failOnError
= failOnError
;