1 package org
.argeo
.slc
.core
.execution
;
3 import java
.util
.HashMap
;
5 import java
.util
.TreeMap
;
7 import org
.apache
.commons
.logging
.Log
;
8 import org
.apache
.commons
.logging
.LogFactory
;
9 import org
.argeo
.slc
.SlcException
;
10 import org
.argeo
.slc
.UnsupportedException
;
11 import org
.argeo
.slc
.execution
.ExecutionFlow
;
12 import org
.argeo
.slc
.execution
.ExecutionFlowDescriptor
;
13 import org
.argeo
.slc
.execution
.ExecutionFlowDescriptorConverter
;
14 import org
.argeo
.slc
.execution
.ExecutionModuleDescriptor
;
15 import org
.argeo
.slc
.execution
.ExecutionSpec
;
16 import org
.argeo
.slc
.execution
.ExecutionSpecAttribute
;
17 import org
.springframework
.aop
.scope
.ScopedObject
;
18 import org
.springframework
.beans
.BeansException
;
19 import org
.springframework
.beans
.factory
.config
.BeanDefinition
;
20 import org
.springframework
.beans
.factory
.config
.ConfigurableListableBeanFactory
;
21 import org
.springframework
.context
.ApplicationContext
;
22 import org
.springframework
.context
.ApplicationContextAware
;
23 import org
.springframework
.context
.ConfigurableApplicationContext
;
24 import org
.springframework
.util
.Assert
;
26 public class DefaultExecutionFlowDescriptorConverter
implements
27 ExecutionFlowDescriptorConverter
, ApplicationContextAware
{
28 public final static String REF_VALUE_TYPE_BEAN_NAME
= "beanName";
30 /** Workaround for https://www.spartadn.com/bugzilla/show_bug.cgi?id=206 */
31 private final static String REF_VALUE_IS_FROZEN
= "__frozen";
33 private final static Log log
= LogFactory
34 .getLog(DefaultExecutionFlowDescriptorConverter
.class);
36 private ApplicationContext applicationContext
;
38 public Map
<String
, Object
> convertValues(
39 ExecutionFlowDescriptor executionFlowDescriptor
) {
40 Map
<String
, Object
> values
= executionFlowDescriptor
.getValues();
41 Map
<String
, Object
> convertedValues
= new HashMap
<String
, Object
>();
42 ExecutionSpec executionSpec
= executionFlowDescriptor
45 if (executionSpec
== null)
46 log
.warn("Execution spec is null for " + executionFlowDescriptor
);
48 if (values
!= null && executionSpec
!= null) {
49 values
: for (String key
: values
.keySet()) {
50 ExecutionSpecAttribute attribute
= executionSpec
51 .getAttributes().get(key
);
53 if (attribute
.getIsFrozen())
56 Object value
= values
.get(key
);
57 if (value
instanceof PrimitiveValue
) {
58 PrimitiveValue primitiveValue
= (PrimitiveValue
) value
;
59 // TODO: check class <=> type
60 convertedValues
.put(key
, primitiveValue
.getValue());
61 } else if (value
instanceof RefValue
) {
62 RefValue refValue
= (RefValue
) value
;
64 if (REF_VALUE_TYPE_BEAN_NAME
.equals(refValue
.getType()))
65 if (refValue
.getRef() != null) {
66 Object obj
= applicationContext
.getBean(refValue
68 convertedValues
.put(key
, obj
);
70 log
.warn("Cannot interpret " + refValue
);
73 throw new UnsupportedException("Ref value type",
78 return convertedValues
;
81 public void addFlowsToDescriptor(ExecutionModuleDescriptor md
,
82 Map
<String
, ExecutionFlow
> executionFlows
) {
83 for (String name
: executionFlows
.keySet()) {
84 ExecutionFlow executionFlow
= executionFlows
.get(name
);
86 Assert
.notNull(executionFlow
.getName());
87 Assert
.state(name
.equals(executionFlow
.getName()));
89 ExecutionSpec executionSpec
= executionFlow
.getExecutionSpec();
90 Assert
.notNull(executionSpec
);
91 Assert
.notNull(executionSpec
.getName());
93 Map
<String
, Object
> values
= new TreeMap
<String
, Object
>();
94 for (String key
: executionSpec
.getAttributes().keySet()) {
95 ExecutionSpecAttribute attribute
= executionSpec
96 .getAttributes().get(key
);
98 if (attribute
instanceof PrimitiveSpecAttribute
) {
99 if (executionFlow
.isSetAsParameter(key
)) {
100 Object value
= executionFlow
.getParameter(key
);
101 PrimitiveValue primitiveValue
= new PrimitiveValue();
103 .setType(((PrimitiveSpecAttribute
) attribute
)
105 primitiveValue
.setValue(value
);
106 values
.put(key
, primitiveValue
);
108 // no need to add a primitive value if it is not set,
109 // all necessary information is in the spec
111 } else if (attribute
instanceof RefSpecAttribute
) {
112 if (attribute
.getIsFrozen()) {
113 values
.put(key
, new RefValue(REF_VALUE_IS_FROZEN
));
115 values
.put(key
, buildRefValue(
116 (RefSpecAttribute
) attribute
, executionFlow
,
119 throw new SlcException("Unkown spec attribute type "
120 + attribute
.getClass());
125 ExecutionFlowDescriptor efd
= new ExecutionFlowDescriptor(name
,
126 values
, executionSpec
);
127 if (executionFlow
.getPath() != null)
128 efd
.setPath(executionFlow
.getPath());
130 // Takes description from spring
131 BeanDefinition bd
= getBeanFactory().getBeanDefinition(name
);
132 efd
.setDescription(bd
.getDescription());
134 // Add execution spec if necessary
135 if (!md
.getExecutionSpecs().contains(executionSpec
))
136 md
.getExecutionSpecs().add(executionSpec
);
138 // Add execution flow
139 md
.getExecutionFlows().add(efd
);
143 @SuppressWarnings(value
= { "unchecked" })
144 protected RefValue
buildRefValue(RefSpecAttribute rsa
,
145 ExecutionFlow executionFlow
, String key
) {
146 RefValue refValue
= new RefValue();
147 refValue
.setType(REF_VALUE_TYPE_BEAN_NAME
);
149 if (executionFlow
.isSetAsParameter(key
)) {
151 Object value
= executionFlow
.getParameter(key
);
152 if (applicationContext
== null) {
154 .warn("No application context declared, cannot scan ref value.");
155 ref
= value
.toString();
158 // look for a ref to the value
159 Map
<String
, Object
> beans
= getBeanFactory().getBeansOfType(
160 rsa
.getTargetClass(), false, false);
161 // TODO: also check scoped beans
162 beans
: for (String beanName
: beans
.keySet()) {
163 Object obj
= beans
.get(beanName
);
164 if (value
instanceof ScopedObject
) {
165 // don't call methods of the target of the scope
166 if (obj
instanceof ScopedObject
)
172 if (obj
.equals(value
)) {
180 if (log
.isTraceEnabled())
181 log
.warn("Cannot define reference for ref spec attribute "
182 + key
+ " in " + executionFlow
+ " (" + rsa
+ ")");
183 } else if (log
.isDebugEnabled())
184 log
.debug(ref
+ " is the reference for ref spec attribute "
185 + key
+ " in " + executionFlow
+ " (" + rsa
+ ")");
186 refValue
.setRef(ref
);
191 private ConfigurableListableBeanFactory
getBeanFactory() {
192 return ((ConfigurableApplicationContext
) applicationContext
)
196 /** Must be use within the execution application context */
197 public void setApplicationContext(ApplicationContext applicationContext
)
198 throws BeansException
{
199 this.applicationContext
= applicationContext
;