]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java
Modular distributions
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / execution / DefaultExecutionFlowDescriptorConverter.java
1 package org.argeo.slc.core.execution;
2
3 import java.util.HashMap;
4 import java.util.Map;
5 import java.util.TreeMap;
6
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;
25
26 public class DefaultExecutionFlowDescriptorConverter implements
27 ExecutionFlowDescriptorConverter, ApplicationContextAware {
28 public final static String REF_VALUE_TYPE_BEAN_NAME = "beanName";
29
30 /** Workaround for https://www.spartadn.com/bugzilla/show_bug.cgi?id=206 */
31 private final static String REF_VALUE_IS_FROZEN = "__frozen";
32
33 private final static Log log = LogFactory
34 .getLog(DefaultExecutionFlowDescriptorConverter.class);
35
36 private ApplicationContext applicationContext;
37
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
43 if (values != null) {
44 values: for (String key : values.keySet()) {
45 ExecutionSpecAttribute attribute = executionFlowDescriptor
46 .getExecutionSpec().getAttributes().get(key);
47
48 if (attribute.getIsFrozen())
49 continue values;
50
51 Object value = values.get(key);
52 if (value instanceof PrimitiveValue) {
53 PrimitiveValue primitiveValue = (PrimitiveValue) value;
54 // TODO: check class <=> type
55 convertedValues.put(key, primitiveValue.getValue());
56 } else if (value instanceof RefValue) {
57 RefValue refValue = (RefValue) value;
58
59 if (REF_VALUE_TYPE_BEAN_NAME.equals(refValue.getType()))
60 if (refValue.getRef() != null) {
61 Object obj = applicationContext.getBean(refValue
62 .getRef());
63 convertedValues.put(key, obj);
64 } else {
65 log.warn("Cannot interpret " + refValue);
66 }
67 else
68 throw new UnsupportedException("Ref value type",
69 refValue.getType());
70 }
71 }
72 }
73 return convertedValues;
74 }
75
76 public void addFlowsToDescriptor(ExecutionModuleDescriptor md,
77 Map<String, ExecutionFlow> executionFlows) {
78 for (String name : executionFlows.keySet()) {
79 ExecutionFlow executionFlow = executionFlows.get(name);
80
81 Assert.notNull(executionFlow.getName());
82 Assert.state(name.equals(executionFlow.getName()));
83
84 ExecutionSpec executionSpec = executionFlow.getExecutionSpec();
85 Assert.notNull(executionSpec);
86 Assert.notNull(executionSpec.getName());
87
88 Map<String, Object> values = new TreeMap<String, Object>();
89 for (String key : executionSpec.getAttributes().keySet()) {
90 ExecutionSpecAttribute attribute = executionSpec
91 .getAttributes().get(key);
92
93 if (attribute instanceof PrimitiveSpecAttribute) {
94 if (executionFlow.isSetAsParameter(key)) {
95 Object value = executionFlow.getParameter(key);
96 PrimitiveValue primitiveValue = new PrimitiveValue();
97 primitiveValue
98 .setType(((PrimitiveSpecAttribute) attribute)
99 .getType());
100 primitiveValue.setValue(value);
101 values.put(key, primitiveValue);
102 } else {
103 // no need to add a primitive value if it is not set,
104 // all necessary information is in the spec
105 }
106 } else if (attribute instanceof RefSpecAttribute) {
107 if (attribute.getIsFrozen()) {
108 values.put(key, new RefValue(REF_VALUE_IS_FROZEN));
109 } else
110 values.put(key, buildRefValue(
111 (RefSpecAttribute) attribute, executionFlow,
112 key));
113 } else {
114 throw new SlcException("Unkown spec attribute type "
115 + attribute.getClass());
116 }
117
118 }
119
120 ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(name,
121 values, executionSpec);
122 if (executionFlow.getPath() != null)
123 efd.setPath(executionFlow.getPath());
124
125 // Takes description from spring
126 BeanDefinition bd = getBeanFactory().getBeanDefinition(name);
127 efd.setDescription(bd.getDescription());
128
129 // Add execution spec if necessary
130 if (!md.getExecutionSpecs().contains(executionSpec))
131 md.getExecutionSpecs().add(executionSpec);
132
133 // Add execution flow
134 md.getExecutionFlows().add(efd);
135 }
136 }
137
138 @SuppressWarnings(value = { "unchecked" })
139 protected RefValue buildRefValue(RefSpecAttribute rsa,
140 ExecutionFlow executionFlow, String key) {
141 RefValue refValue = new RefValue();
142 refValue.setType(REF_VALUE_TYPE_BEAN_NAME);
143
144 if (executionFlow.isSetAsParameter(key)) {
145 String ref = null;
146 Object value = executionFlow.getParameter(key);
147 if (applicationContext == null) {
148 log
149 .warn("No application context declared, cannot scan ref value.");
150 ref = value.toString();
151 } else {
152
153 // look for a ref to the value
154 Map<String, Object> beans = getBeanFactory().getBeansOfType(
155 rsa.getTargetClass(), false, false);
156 // TODO: also check scoped beans
157 beans: for (String beanName : beans.keySet()) {
158 Object obj = beans.get(beanName);
159 if (value instanceof ScopedObject) {
160 // don't call methods of the target of the scope
161 if (obj instanceof ScopedObject)
162 if (value == obj) {
163 ref = beanName;
164 break beans;
165 }
166 } else {
167 if (obj.equals(value)) {
168 ref = beanName;
169 break beans;
170 }
171 }
172 }
173 }
174 if (ref == null) {
175 if (log.isTraceEnabled())
176 log.warn("Cannot define reference for ref spec attribute "
177 + key + " in " + executionFlow + " (" + rsa + ")");
178 } else if (log.isDebugEnabled())
179 log.debug(ref + " is the reference for ref spec attribute "
180 + key + " in " + executionFlow + " (" + rsa + ")");
181 refValue.setRef(ref);
182 }
183 return refValue;
184 }
185
186 private ConfigurableListableBeanFactory getBeanFactory() {
187 return ((ConfigurableApplicationContext) applicationContext)
188 .getBeanFactory();
189 }
190
191 /** Must be use within the execution application context */
192 public void setApplicationContext(ApplicationContext applicationContext)
193 throws BeansException {
194 this.applicationContext = applicationContext;
195 }
196
197 }