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