1 package org
.argeo
.slc
.core
.execution
;
3 import java
.util
.Comparator
;
4 import java
.util
.HashMap
;
6 import java
.util
.SortedSet
;
7 import java
.util
.TreeMap
;
8 import java
.util
.TreeSet
;
10 import org
.apache
.commons
.logging
.Log
;
11 import org
.apache
.commons
.logging
.LogFactory
;
12 import org
.argeo
.slc
.SlcException
;
13 import org
.argeo
.slc
.UnsupportedException
;
14 import org
.argeo
.slc
.execution
.ExecutionFlow
;
15 import org
.argeo
.slc
.execution
.ExecutionFlowDescriptor
;
16 import org
.argeo
.slc
.execution
.ExecutionFlowDescriptorConverter
;
17 import org
.argeo
.slc
.execution
.ExecutionModuleDescriptor
;
18 import org
.argeo
.slc
.execution
.ExecutionSpec
;
19 import org
.argeo
.slc
.execution
.ExecutionSpecAttribute
;
20 import org
.springframework
.aop
.scope
.ScopedObject
;
21 import org
.springframework
.beans
.BeansException
;
22 import org
.springframework
.beans
.factory
.config
.BeanDefinition
;
23 import org
.springframework
.beans
.factory
.config
.ConfigurableListableBeanFactory
;
24 import org
.springframework
.context
.ApplicationContext
;
25 import org
.springframework
.context
.ApplicationContextAware
;
26 import org
.springframework
.context
.ConfigurableApplicationContext
;
27 import org
.springframework
.util
.Assert
;
28 import org
.springframework
.util
.StringUtils
;
30 public class DefaultExecutionFlowDescriptorConverter
implements
31 ExecutionFlowDescriptorConverter
, ApplicationContextAware
{
32 public final static String REF_VALUE_TYPE_BEAN_NAME
= "beanName";
34 /** Workaround for https://www.spartadn.com/bugzilla/show_bug.cgi?id=206 */
35 private final static String REF_VALUE_INTERNAL
= "[internal]";
37 private final static Log log
= LogFactory
38 .getLog(DefaultExecutionFlowDescriptorConverter
.class);
40 private ApplicationContext applicationContext
;
42 public Map
<String
, Object
> convertValues(
43 ExecutionFlowDescriptor executionFlowDescriptor
) {
44 Map
<String
, Object
> values
= executionFlowDescriptor
.getValues();
45 Map
<String
, Object
> convertedValues
= new HashMap
<String
, Object
>();
46 ExecutionSpec executionSpec
= executionFlowDescriptor
49 if (executionSpec
== null && log
.isTraceEnabled())
50 log
.warn("Execution spec is null for " + executionFlowDescriptor
);
52 if (values
!= null && executionSpec
!= null) {
53 values
: for (String key
: values
.keySet()) {
54 ExecutionSpecAttribute attribute
= executionSpec
55 .getAttributes().get(key
);
57 if (attribute
.getIsFrozen())
60 Object value
= values
.get(key
);
61 if (value
instanceof PrimitiveValue
) {
62 PrimitiveValue primitiveValue
= (PrimitiveValue
) value
;
63 // TODO: check class <=> type
64 convertedValues
.put(key
, primitiveValue
.getValue());
65 } else if (value
instanceof RefValue
) {
66 RefValue refValue
= (RefValue
) value
;
67 String type
= refValue
.getType();
68 if (REF_VALUE_TYPE_BEAN_NAME
.equals(type
)) {
69 // FIXME: UI should send all information about spec
72 // String executionSpecName = executionSpec.getName();
73 // ExecutionSpec localSpec = (ExecutionSpec)
75 // .getBean(executionSpecName);
76 // RefSpecAttribute localAttr = (RefSpecAttribute)
78 // .getAttributes().get(key);
79 // Class<?> targetClass = localAttr.getTargetClass();
81 // String primitiveType = PrimitiveUtils
82 // .classAsType(targetClass);
83 String primitiveType
= null;
84 if (primitiveType
!= null) {
86 String ref
= refValue
.getRef();
87 Object obj
= PrimitiveUtils
.convert(primitiveType
,
89 convertedValues
.put(key
, obj
);
91 String ref
= refValue
.getRef();
92 if (ref
!= null && !ref
.equals(REF_VALUE_INTERNAL
)) {
94 if (applicationContext
.containsBean(ref
)) {
95 obj
= applicationContext
.getBean(ref
);
97 // FIXME: hack in order to pass primitive
100 convertedValues
.put(key
, obj
);
102 log
.warn("Cannot interpret " + refValue
);
105 } else if (PrimitiveUtils
.typeAsClass(type
) != null) {
106 String ref
= refValue
.getRef();
107 Object obj
= PrimitiveUtils
.convert(type
, ref
);
108 convertedValues
.put(key
, obj
);
110 throw new UnsupportedException("Ref value type",
116 return convertedValues
;
119 public void addFlowsToDescriptor(ExecutionModuleDescriptor md
,
120 Map
<String
, ExecutionFlow
> executionFlows
) {
121 SortedSet
<ExecutionFlowDescriptor
> set
= new TreeSet
<ExecutionFlowDescriptor
>(
122 new ExecutionFlowDescriptorComparator());
123 for (String name
: executionFlows
.keySet()) {
124 ExecutionFlow executionFlow
= executionFlows
.get(name
);
126 Assert
.notNull(executionFlow
.getName());
127 Assert
.state(name
.equals(executionFlow
.getName()));
129 ExecutionSpec executionSpec
= executionFlow
.getExecutionSpec();
130 Assert
.notNull(executionSpec
);
131 Assert
.notNull(executionSpec
.getName());
133 Map
<String
, Object
> values
= new TreeMap
<String
, Object
>();
134 for (String key
: executionSpec
.getAttributes().keySet()) {
135 ExecutionSpecAttribute attribute
= executionSpec
136 .getAttributes().get(key
);
138 if (attribute
instanceof PrimitiveSpecAttribute
) {
139 if (executionFlow
.isSetAsParameter(key
)) {
140 Object value
= executionFlow
.getParameter(key
);
141 PrimitiveValue primitiveValue
= new PrimitiveValue();
143 .setType(((PrimitiveSpecAttribute
) attribute
)
145 primitiveValue
.setValue(value
);
146 values
.put(key
, primitiveValue
);
148 // no need to add a primitive value if it is not set,
149 // all necessary information is in the spec
151 } else if (attribute
instanceof RefSpecAttribute
) {
152 if (attribute
.getIsFrozen()) {
153 values
.put(key
, new RefValue(REF_VALUE_INTERNAL
));
155 values
.put(key
, buildRefValue(
156 (RefSpecAttribute
) attribute
, executionFlow
,
159 throw new SlcException("Unkown spec attribute type "
160 + attribute
.getClass());
165 ExecutionFlowDescriptor efd
= new ExecutionFlowDescriptor(name
,
166 values
, executionSpec
);
167 if (executionFlow
.getPath() != null)
168 efd
.setPath(executionFlow
.getPath());
172 // Takes description from spring
173 BeanDefinition bd
= getBeanFactory().getBeanDefinition(name
);
174 efd
.setDescription(bd
.getDescription());
176 // Add execution spec if necessary
177 if (!md
.getExecutionSpecs().contains(executionSpec
))
178 md
.getExecutionSpecs().add(executionSpec
);
180 // Add execution flow
182 // md.getExecutionFlows().add(efd);
184 md
.getExecutionFlows().addAll(set
);
187 @SuppressWarnings(value
= { "unchecked" })
188 protected RefValue
buildRefValue(RefSpecAttribute rsa
,
189 ExecutionFlow executionFlow
, String key
) {
190 RefValue refValue
= new RefValue();
191 // FIXME: UI should be able to deal with other types
192 refValue
.setType(REF_VALUE_TYPE_BEAN_NAME
);
193 Class targetClass
= rsa
.getTargetClass();
194 String primitiveType
= PrimitiveUtils
.classAsType(targetClass
);
195 if (primitiveType
!= null) {
196 if (executionFlow
.isSetAsParameter(key
)) {
197 Object value
= executionFlow
.getParameter(key
);
198 refValue
.setRef(value
.toString());
200 refValue
.setType(primitiveType
);
204 if (executionFlow
.isSetAsParameter(key
)) {
206 Object value
= executionFlow
.getParameter(key
);
207 if (applicationContext
== null) {
209 .warn("No application context declared, cannot scan ref value.");
210 ref
= value
.toString();
213 // look for a ref to the value
214 Map
<String
, Object
> beans
= getBeanFactory()
215 .getBeansOfType(targetClass
, false, false);
216 // TODO: also check scoped beans
217 beans
: for (String beanName
: beans
.keySet()) {
218 Object obj
= beans
.get(beanName
);
219 if (value
instanceof ScopedObject
) {
220 // don't call methods of the target of the scope
221 if (obj
instanceof ScopedObject
)
227 if (obj
.equals(value
)) {
236 .warn("Cannot define reference for ref spec attribute "
243 + " If it is an inner bean consider put it frozen.");
244 ref
= REF_VALUE_INTERNAL
;
246 if (log
.isDebugEnabled())
248 + " is the reference for ref spec attribute "
249 + key
+ " in " + executionFlow
+ " (" + rsa
252 refValue
.setRef(ref
);
258 private ConfigurableListableBeanFactory
getBeanFactory() {
259 return ((ConfigurableApplicationContext
) applicationContext
)
263 /** Must be use within the execution application context */
264 public void setApplicationContext(ApplicationContext applicationContext
)
265 throws BeansException
{
266 this.applicationContext
= applicationContext
;
269 private static class ExecutionFlowDescriptorComparator
implements
270 Comparator
<ExecutionFlowDescriptor
> {
271 public int compare(ExecutionFlowDescriptor o1
,
272 ExecutionFlowDescriptor o2
) {
273 // TODO: write unit tests for this
274 if (StringUtils
.hasText(o1
.getPath())
275 && StringUtils
.hasText(o2
.getPath())) {
276 if (o1
.getPath().equals(o2
.getPath()))
277 return o1
.getName().compareTo(o2
.getName());
278 else if (o1
.getPath().startsWith(o2
.getPath()))
280 else if (o2
.getPath().startsWith(o1
.getPath()))
283 return o1
.getPath().compareTo(o2
.getPath());
284 } else if (!StringUtils
.hasText(o1
.getPath())
285 && StringUtils
.hasText(o2
.getPath())) {
287 } else if (StringUtils
.hasText(o1
.getPath())
288 && !StringUtils
.hasText(o2
.getPath())) {
290 } else if (!StringUtils
.hasText(o1
.getPath())
291 && !StringUtils
.hasText(o2
.getPath())) {
292 return o1
.getName().compareTo(o2
.getName());