2 * Copyright (C) 2007-2012 Argeo GmbH
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
.ArrayList
;
19 import java
.util
.Iterator
;
20 import java
.util
.List
;
23 import org
.apache
.commons
.logging
.Log
;
24 import org
.apache
.commons
.logging
.LogFactory
;
25 import org
.argeo
.slc
.SlcException
;
26 import org
.argeo
.slc
.core
.execution
.DefaultExecutionSpec
;
27 import org
.argeo
.slc
.execution
.ExecutionContext
;
28 import org
.argeo
.slc
.execution
.ExecutionFlow
;
29 import org
.argeo
.slc
.execution
.ExecutionSpec
;
30 import org
.springframework
.context
.ApplicationContext
;
31 import org
.springframework
.context
.ApplicationContextAware
;
34 * Execution Flow calling a list of <code>Runnable</code> (identified by their
35 * bean name in the Spring Application Context) after configuring the Execution
36 * context and a Map potentially shared by the called <code>Runnable</code>
39 public class RunnableCallFlow
implements ExecutionFlow
, ApplicationContextAware
{
41 private final static Log log
= LogFactory
.getLog(RunnableCallFlow
.class);
44 * Key in the execution context for the index of the call (e.g. 0 for the
45 * first runnable called, ...)
47 public final static String VAR_CALL_INDEX
= "slcVar.runnableCallFlow.callIndex";
50 * Name of the flow. Also bean name
60 * Whether an exception in a <code>Runnable</code> shall stop the execution
63 private Boolean failOnError
= true;
66 * List of <code>Runnable</code> to call, with bean name, execution
67 * variables and context values
69 private List
<RunnableCall
> runnableCalls
;
72 * Map potentially referenced by called flows. Updated with the context
73 * values of a Runnable before calling it.
75 private Map
<String
, Object
> sharedContextValuesMap
;
78 * ExecutionSpec of the flow. Does not contain any attribute.
80 private ExecutionSpec executionSpec
= new DefaultExecutionSpec();
83 * Reference to the ExecutionContext
85 private ExecutionContext executionContext
;
88 * Reference to the Spring <code>ApplicationContext</code>. Set via
89 * <code>setApplicationContext</code>, the class implementing
90 * <code>ApplicationContextAware</code>
92 private ApplicationContext applicationContext
;
95 * Runs a <code>Runnable</code> after configuring the Execution Context and
96 * <code>sharedContextValuesMap</code>
99 * the <code>Runnable</code> to call
100 * @param executionVariables
101 * the variables to add to the <code>ExecutionContext</code>
102 * @param contextValues
103 * the variables to add to <code>sharedContextValuesMap</code>
105 * index of the call (0 for the first called
106 * <code>Runnable</code>) set as variable of the
107 * <code>ExecutionContext</code>
109 private void run(Runnable runnable
, Map
<String
, Object
> executionVariables
,
110 Map
<String
, Object
> contextValues
, int callIndex
) {
111 // add all variables to the Execution Context
112 for (Map
.Entry
<String
, Object
> entry
: executionVariables
.entrySet()) {
113 executionContext
.setVariable(entry
.getKey(), entry
.getValue());
116 // add call Index Variable
117 executionContext
.setVariable(VAR_CALL_INDEX
, callIndex
);
119 // clear sharedContextValues and add all values of contextValues
120 if (sharedContextValuesMap
!= null) {
121 sharedContextValuesMap
.clear();
122 sharedContextValuesMap
.putAll(contextValues
);
125 // then run the runnable
126 doExecuteRunnable(runnable
);
129 public void doExecuteRunnable(Runnable runnable
) {
134 * Executes the flow. For each <code>RunnableCall</code>, the corresponding
135 * flow is retrieved from the Spring Application Context, the
136 * <code>ExecutionContext</code> and <code>sharedContextValuesMap</code> are
137 * configured and the <code>Runnable</code> is called.
140 if (applicationContext
== null) {
141 throw new SlcException("No ApplicationContext defined");
145 for (int callIndex
= 0; callIndex
< runnableCalls
.size(); ++callIndex
) {
146 RunnableCall runnableCall
= runnableCalls
.get(callIndex
);
147 Object bean
= applicationContext
.getBean(
148 runnableCall
.getBeanName(), Runnable
.class);
149 if (log
.isDebugEnabled())
150 log
.debug("Running flow '" + runnableCall
.getBeanName()
152 run((Runnable
) bean
, runnableCall
.getExecutionVariables(),
153 runnableCall
.getContextValues(), callIndex
);
155 } catch (RuntimeException e
) {
159 log
.error("Execution flow failed,"
160 + " but process did not fail"
161 + " because failOnError property"
162 + " is set to false: " + e
);
163 if (log
.isTraceEnabled())
169 public Iterator
<Runnable
> runnables() {
170 List
<Runnable
> runnables
= new ArrayList
<Runnable
>();
171 for (int callIndex
= 0; callIndex
< runnableCalls
.size(); ++callIndex
) {
172 RunnableCall runnableCall
= runnableCalls
.get(callIndex
);
173 Object bean
= applicationContext
.getBean(
174 runnableCall
.getBeanName(), Runnable
.class);
175 runnables
.add((Runnable
) bean
);
177 return runnables
.iterator();
180 public Runnable
getRunnable() {
181 if (runnableCalls
.size() == 1)
182 return runnables().next();
184 throw new SlcException("There are " + runnableCalls
.size()
185 + " runnables in flow " + getName());
189 public String
toString() {
190 return new StringBuffer("RunnableCallFlow ").append(name
).toString();
193 public ExecutionSpec
getExecutionSpec() {
194 return executionSpec
;
197 public String
getName() {
201 public Object
getParameter(String key
) {
202 throw new SlcException("RunnableCallFlow have no parameters");
205 public String
getPath() {
209 public Boolean
isSetAsParameter(String key
) {
210 // The ExecutionSpec having no attribute,
211 // always return false
215 public void setName(String name
) {
219 public void setPath(String path
) {
223 public void setExecutionContext(ExecutionContext executionContext
) {
224 this.executionContext
= executionContext
;
227 public void setRunnableCalls(List
<RunnableCall
> runnableCalls
) {
228 this.runnableCalls
= runnableCalls
;
231 public void setApplicationContext(ApplicationContext applicationContext
) {
232 this.applicationContext
= applicationContext
;
235 public void setSharedContextValuesMap(Map
<String
, Object
> contextValues
) {
236 this.sharedContextValuesMap
= contextValues
;
239 public void setFailOnError(Boolean failOnError
) {
240 this.failOnError
= failOnError
;