]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java
Add generate script
[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 = "[internal]";
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 ExecutionSpec executionSpec = executionFlowDescriptor
43 .getExecutionSpec();
44
45 if (executionSpec == null)
46 log.warn("Execution spec is null for " + executionFlowDescriptor);
47
48 if (values != null && executionSpec != null) {
49 values: for (String key : values.keySet()) {
50 ExecutionSpecAttribute attribute = executionSpec
51 .getAttributes().get(key);
52
53 if (attribute.getIsFrozen())
54 continue values;
55
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;
63
64 if (REF_VALUE_TYPE_BEAN_NAME.equals(refValue.getType()))
65 if (refValue.getRef() != null) {
66 Object obj = applicationContext.getBean(refValue
67 .getRef());
68 convertedValues.put(key, obj);
69 } else {
70 log.warn("Cannot interpret " + refValue);
71 }
72 else
73 throw new UnsupportedException("Ref value type",
74 refValue.getType());
75 }
76 }
77 }
78 return convertedValues;
79 }
80
81 public void addFlowsToDescriptor(ExecutionModuleDescriptor md,
82 Map<String, ExecutionFlow> executionFlows) {
83 for (String name : executionFlows.keySet()) {
84 ExecutionFlow executionFlow = executionFlows.get(name);
85
86 Assert.notNull(executionFlow.getName());
87 Assert.state(name.equals(executionFlow.getName()));
88
89 ExecutionSpec executionSpec = executionFlow.getExecutionSpec();
90 Assert.notNull(executionSpec);
91 Assert.notNull(executionSpec.getName());
92
93 Map<String, Object> values = new TreeMap<String, Object>();
94 for (String key : executionSpec.getAttributes().keySet()) {
95 ExecutionSpecAttribute attribute = executionSpec
96 .getAttributes().get(key);
97
98 if (attribute instanceof PrimitiveSpecAttribute) {
99 if (executionFlow.isSetAsParameter(key)) {
100 Object value = executionFlow.getParameter(key);
101 PrimitiveValue primitiveValue = new PrimitiveValue();
102 primitiveValue
103 .setType(((PrimitiveSpecAttribute) attribute)
104 .getType());
105 primitiveValue.setValue(value);
106 values.put(key, primitiveValue);
107 } else {
108 // no need to add a primitive value if it is not set,
109 // all necessary information is in the spec
110 }
111 } else if (attribute instanceof RefSpecAttribute) {
112 if (attribute.getIsFrozen()) {
113 values.put(key, new RefValue(REF_VALUE_IS_FROZEN));
114 } else
115 values.put(key, buildRefValue(
116 (RefSpecAttribute) attribute, executionFlow,
117 key));
118 } else {
119 throw new SlcException("Unkown spec attribute type "
120 + attribute.getClass());
121 }
122
123 }
124
125 ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(name,
126 values, executionSpec);
127 if (executionFlow.getPath() != null)
128 efd.setPath(executionFlow.getPath());
129
130 // Takes description from spring
131 BeanDefinition bd = getBeanFactory().getBeanDefinition(name);
132 efd.setDescription(bd.getDescription());
133
134 // Add execution spec if necessary
135 if (!md.getExecutionSpecs().contains(executionSpec))
136 md.getExecutionSpecs().add(executionSpec);
137
138 // Add execution flow
139 md.getExecutionFlows().add(efd);
140 }
141 }
142
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);
148
149 if (executionFlow.isSetAsParameter(key)) {
150 String ref = null;
151 Object value = executionFlow.getParameter(key);
152 if (applicationContext == null) {
153 log
154 .warn("No application context declared, cannot scan ref value.");
155 ref = value.toString();
156 } else {
157
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)
167 if (value == obj) {
168 ref = beanName;
169 break beans;
170 }
171 } else {
172 if (obj.equals(value)) {
173 ref = beanName;
174 break beans;
175 }
176 }
177 }
178 }
179 if (ref == null) {
180 log.warn("Cannot define reference for ref spec attribute "
181 + key + " in " + executionFlow + " (" + rsa + ")."
182 + " If it is an inner bean consider put it frozen.");
183 } else {
184 if (log.isDebugEnabled())
185 log.debug(ref + " is the reference for ref spec attribute "
186 + key + " in " + executionFlow + " (" + rsa + ")");
187 }
188 refValue.setRef(ref);
189 }
190 return refValue;
191 }
192
193 private ConfigurableListableBeanFactory getBeanFactory() {
194 return ((ConfigurableApplicationContext) applicationContext)
195 .getBeanFactory();
196 }
197
198 /** Must be use within the execution application context */
199 public void setApplicationContext(ApplicationContext applicationContext)
200 throws BeansException {
201 this.applicationContext = applicationContext;
202 }
203
204 }