]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlow.java
Move default agent to execution package
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / execution / DefaultExecutionFlow.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;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
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.execution.ExecutionFlow;
27 import org.argeo.slc.execution.ExecutionSpec;
28 import org.argeo.slc.execution.ExecutionSpecAttribute;
29 import org.springframework.beans.factory.BeanNameAware;
30 import org.springframework.beans.factory.InitializingBean;
31 import org.springframework.validation.MapBindingResult;
32
33 /** Default implementation of an execution flow. */
34 public class DefaultExecutionFlow implements ExecutionFlow, InitializingBean,
35 BeanNameAware {
36 private final static Log log = LogFactory
37 .getLog(DefaultExecutionFlow.class);
38
39 private final ExecutionSpec executionSpec;
40 private String name = null;
41 private Map<String, Object> parameters = new HashMap<String, Object>();
42 private List<Runnable> executables = new ArrayList<Runnable>();
43
44 private String path;
45
46 private Boolean failOnError = true;
47
48 public DefaultExecutionFlow() {
49 this.executionSpec = new DefaultExecutionSpec();
50 }
51
52 public DefaultExecutionFlow(ExecutionSpec executionSpec) {
53 this.executionSpec = executionSpec;
54 }
55
56 public DefaultExecutionFlow(ExecutionSpec executionSpec,
57 Map<String, Object> parameters) {
58 // be sure to have an execution spec
59 this.executionSpec = (executionSpec == null) ? new DefaultExecutionSpec()
60 : executionSpec;
61
62 // only parameters contained in the executionSpec can be set
63 for (String parameter : parameters.keySet()) {
64 if (!executionSpec.getAttributes().containsKey(parameter)) {
65 throw new SlcException("Parameter " + parameter
66 + " is not defined in the ExecutionSpec");
67 }
68 }
69
70 // set the parameters
71 this.parameters.putAll(parameters);
72
73 // check that all the required parameters are defined
74 MapBindingResult errors = new MapBindingResult(parameters, "execution#"
75 + getName());
76 for (String key : executionSpec.getAttributes().keySet()) {
77 ExecutionSpecAttribute attr = executionSpec.getAttributes()
78 .get(key);
79
80 if (attr.getIsImmutable() && !isSetAsParameter(key)) {
81 errors.rejectValue(key, "Immutable but not set");
82 break;
83 }
84
85 if (attr.getIsConstant() && !isSetAsParameter(key)) {
86 errors.rejectValue(key, "Constant but not set as parameter");
87 break;
88 }
89
90 if (attr.getIsHidden() && !isSetAsParameter(key)) {
91 errors.rejectValue(key, "Hidden but not set as parameter");
92 break;
93 }
94 }
95
96 if (errors.hasErrors())
97 throw new SlcException("Could not prepare execution flow: "
98 + errors.toString());
99
100 }
101
102 public void run() {
103 try {
104 for (Runnable executable : executables) {
105 if (Thread.interrupted()) {
106 log.error("Flow '" + getName() + "' killed before '"
107 + executable + "'");
108 Thread.currentThread().interrupt();
109 return;
110 // throw new ThreadDeath();
111 }
112 this.doExecuteRunnable(executable);
113 }
114 } catch (RuntimeException e) {
115 if (Thread.interrupted()) {
116 log.error("Flow '" + getName()
117 + "' killed while receiving an unrelated exception", e);
118 Thread.currentThread().interrupt();
119 return;
120 // throw new ThreadDeath();
121 }
122 if (failOnError)
123 throw e;
124 else {
125 log.error("Execution flow failed,"
126 + " but process did not fail"
127 + " because failOnError property"
128 + " is set to false: " + e);
129 if (log.isTraceEnabled())
130 e.printStackTrace();
131 }
132 }
133 }
134
135 public void doExecuteRunnable(Runnable runnable) {
136 runnable.run();
137 }
138
139 public void afterPropertiesSet() throws Exception {
140 if (path == null) {
141 if (name.charAt(0) == '/') {
142 path = name.substring(0, name.lastIndexOf('/'));
143 }
144 }
145
146 if (path != null) {
147 for (Runnable executable : executables) {
148 if (executable instanceof DefaultExecutionFlow) {
149 // so we don't need to have DefaultExecutionFlow
150 // implementing StructureAware
151 // FIXME: probably has side effects
152 DefaultExecutionFlow flow = (DefaultExecutionFlow) executable;
153 String newPath = path + '/' + flow.getName();
154 flow.setPath(newPath);
155 log.warn(newPath + " was forcibly set on " + flow);
156 }
157 }
158 }
159 }
160
161 public void setBeanName(String name) {
162 this.name = name;
163 }
164
165 public void setExecutables(List<Runnable> executables) {
166 this.executables = executables;
167 }
168
169 public void setParameters(Map<String, Object> attributes) {
170 this.parameters = attributes;
171 }
172
173 public String getName() {
174 return name;
175 }
176
177 public ExecutionSpec getExecutionSpec() {
178 return executionSpec;
179 }
180
181 public Object getParameter(String parameterName) {
182 // Verify that there is a spec attribute
183 ExecutionSpecAttribute specAttr = null;
184 if (executionSpec.getAttributes().containsKey(parameterName)) {
185 specAttr = executionSpec.getAttributes().get(parameterName);
186 } else {
187 throw new SlcException("Key " + parameterName
188 + " is not defined in the specifications of " + toString());
189 }
190
191 if (parameters.containsKey(parameterName)) {
192 Object paramValue = parameters.get(parameterName);
193 return paramValue;
194 } else {
195 if (specAttr.getValue() != null) {
196 return specAttr.getValue();
197 }
198 }
199 throw new SlcException("Key " + parameterName
200 + " is not set as parameter in " + toString());
201 }
202
203 public Boolean isSetAsParameter(String key) {
204 return parameters.containsKey(key)
205 || (executionSpec.getAttributes().containsKey(key) && executionSpec
206 .getAttributes().get(key).getValue() != null);
207 }
208
209 @Override
210 public String toString() {
211 return new StringBuffer("Execution flow ").append(name).toString();
212 }
213
214 @Override
215 public boolean equals(Object obj) {
216 return ((ExecutionFlow) obj).getName().equals(name);
217 }
218
219 @Override
220 public int hashCode() {
221 return name.hashCode();
222 }
223
224 public String getPath() {
225 return path;
226 }
227
228 public void setPath(String path) {
229 this.path = path;
230 }
231
232 public Boolean getFailOnError() {
233 return failOnError;
234 }
235
236 public void setFailOnError(Boolean failOnError) {
237 this.failOnError = failOnError;
238 }
239
240 }