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
;
19 import java
.util
.ArrayList
;
20 import java
.util
.HashMap
;
21 import java
.util
.List
;
24 import org
.apache
.commons
.logging
.Log
;
25 import org
.apache
.commons
.logging
.LogFactory
;
26 import org
.argeo
.slc
.SlcException
;
27 import org
.argeo
.slc
.core
.structure
.tree
.TreeSPath
;
28 import org
.argeo
.slc
.core
.structure
.tree
.TreeSRegistry
;
29 import org
.argeo
.slc
.execution
.ExecutionFlow
;
30 import org
.argeo
.slc
.execution
.ExecutionSpec
;
31 import org
.argeo
.slc
.execution
.ExecutionSpecAttribute
;
32 import org
.argeo
.slc
.structure
.StructureAware
;
33 import org
.argeo
.slc
.structure
.StructureRegistry
;
34 import org
.springframework
.aop
.scope
.ScopedObject
;
35 import org
.springframework
.beans
.factory
.BeanNameAware
;
36 import org
.springframework
.beans
.factory
.InitializingBean
;
37 import org
.springframework
.validation
.MapBindingResult
;
39 public class DefaultExecutionFlow
implements ExecutionFlow
, InitializingBean
,
41 private final static Log log
= LogFactory
42 .getLog(DefaultExecutionFlow
.class);
44 private final ExecutionSpec executionSpec
;
45 private String name
= null;
46 private Map
<String
, Object
> parameters
= new HashMap
<String
, Object
>();
47 private List
<Runnable
> executables
= new ArrayList
<Runnable
>();
50 private StructureRegistry
<TreeSPath
> registry
= new TreeSRegistry();
52 private Boolean failOnError
= true;
54 public DefaultExecutionFlow() {
55 this.executionSpec
= new DefaultExecutionSpec();
58 public DefaultExecutionFlow(ExecutionSpec executionSpec
) {
59 this.executionSpec
= executionSpec
;
62 public DefaultExecutionFlow(ExecutionSpec executionSpec
,
63 Map
<String
, Object
> parameters
) {
64 // be sure to have an execution spec
65 this.executionSpec
= (executionSpec
== null) ?
new DefaultExecutionSpec()
68 // only parameters contained in the executionSpec can be set
69 for (String parameter
: parameters
.keySet()) {
70 if (!executionSpec
.getAttributes().containsKey(parameter
)) {
71 throw new SlcException("Parameter " + parameter
72 + " is not defined in the ExecutionSpec");
77 this.parameters
.putAll(parameters
);
79 // check that all the required parameters are defined
80 MapBindingResult errors
= new MapBindingResult(parameters
, "execution#"
82 for (String key
: executionSpec
.getAttributes().keySet()) {
83 ExecutionSpecAttribute attr
= executionSpec
.getAttributes()
86 if (attr
.getIsParameter() && !isSetAsParameter(key
)) {
87 errors
.rejectValue(key
, "Parameter not set");
91 if (attr
.getIsFrozen() && !isSetAsParameter(key
)) {
92 errors
.rejectValue(key
, "Frozen but not set as parameter");
96 if (attr
.getIsHidden() && !isSetAsParameter(key
)) {
97 errors
.rejectValue(key
, "Hidden but not set as parameter");
102 if (errors
.hasErrors())
103 throw new SlcException("Could not prepare execution flow: "
104 + errors
.toString());
110 for (Runnable executable
: executables
) {
111 this.doExecuteRunnable(executable
);
113 } catch (RuntimeException e
) {
117 log
.error("Execution flow failed,"
118 + " but process did not fail"
119 + " because failOnError property"
120 + " is set to false: " + e
);
121 if (log
.isTraceEnabled())
127 public void doExecuteRunnable(Runnable runnable
) {
131 @SuppressWarnings(value
= { "unchecked" })
132 public void afterPropertiesSet() throws Exception
{
134 if (name
.charAt(0) == '/') {
135 path
= name
.substring(0, name
.lastIndexOf('/'));
140 for (Runnable executable
: executables
) {
141 if (executable
instanceof StructureAware
142 && !(executable
instanceof ScopedObject
)) {
143 ((StructureAware
<TreeSPath
>) executable
).notifyCurrentPath(
144 registry
, new TreeSPath(path
));
145 } else if (executable
instanceof DefaultExecutionFlow
) {
146 // so we don't need to have DefaultExecutionFlow
147 // implementing StructureAware
148 // FIXME: probably has side effects
149 DefaultExecutionFlow flow
= (DefaultExecutionFlow
) executable
;
150 String newPath
= path
+ '/' + flow
.getName();
151 flow
.setPath(newPath
);
152 log
.warn(newPath
+ " was forcibly set on " + flow
);
158 public void setBeanName(String name
) {
162 public void setExecutables(List
<Runnable
> executables
) {
163 this.executables
= executables
;
166 public void setParameters(Map
<String
, Object
> attributes
) {
167 this.parameters
= attributes
;
170 public String
getName() {
174 public ExecutionSpec
getExecutionSpec() {
175 return executionSpec
;
178 public Object
getParameter(String parameterName
) {
179 // Verify that there is a spec attribute
180 ExecutionSpecAttribute specAttr
= null;
181 if (executionSpec
.getAttributes().containsKey(parameterName
)) {
182 specAttr
= executionSpec
.getAttributes().get(parameterName
);
184 throw new SlcException("Key " + parameterName
185 + " is not defined in the specifications of " + toString());
188 if (parameters
.containsKey(parameterName
)) {
189 Object paramValue
= parameters
.get(parameterName
);
192 if (specAttr
.getValue() != null) {
193 return specAttr
.getValue();
196 throw new SlcException("Key " + parameterName
197 + " is not set as parameter in " + toString());
200 public Boolean
isSetAsParameter(String key
) {
201 return parameters
.containsKey(key
)
202 || (executionSpec
.getAttributes().containsKey(key
) && executionSpec
203 .getAttributes().get(key
).getValue() != null);
207 public String
toString() {
208 return new StringBuffer("Execution flow ").append(name
).toString();
212 public boolean equals(Object obj
) {
213 return ((ExecutionFlow
) obj
).getName().equals(name
);
217 public int hashCode() {
218 return name
.hashCode();
221 public String
getPath() {
225 public void setPath(String path
) {
229 public void setRegistry(StructureRegistry
<TreeSPath
> registry
) {
230 this.registry
= registry
;
233 public Boolean
getFailOnError() {
237 public void setFailOnError(Boolean failOnError
) {
238 this.failOnError
= failOnError
;