]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java
Improve logging
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / execution / generator / ExecutionFlowGenerator.java
1 package org.argeo.slc.core.execution.generator;
2
3 import java.util.HashMap;
4
5 import org.apache.commons.logging.Log;
6 import org.apache.commons.logging.LogFactory;
7 import org.argeo.slc.SlcException;
8 import org.springframework.aop.scope.ScopedProxyUtils;
9 import org.springframework.beans.BeansException;
10 import org.springframework.beans.MutablePropertyValues;
11 import org.springframework.beans.factory.config.BeanDefinitionHolder;
12 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
13 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
14 import org.springframework.beans.factory.config.RuntimeBeanReference;
15 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
16 import org.springframework.beans.factory.support.GenericBeanDefinition;
17 import org.springframework.core.Ordered;
18
19 /**
20 * Generates <code>ExecutionFlows</code> and <code>Runnables</code> as
21 * beans in the Spring Application Context.
22 * Called by the Application Context as a <code>BeanFactoryPostProcessor</code>.
23 * Two kinds of beans are generated:
24 * <code>RunnableCallFlow</code>, calling a list of <code>Runnables</code> from the
25 * Application Context after configuring the <code>ExecutionContext</code>,
26 * and outputs of a <code>RunnableFactory</code>.
27 */
28 public class ExecutionFlowGenerator implements BeanFactoryPostProcessor,
29 Ordered {
30
31 private final Log log = LogFactory.getLog(getClass());
32
33 /**
34 * Source providing a list of <code>RunnableCallFlowDescriptor</code>
35 * used to create <code>RunnableCallFlow</code> and a list of
36 * <code>RunnableDataNode</code> used to create any kind of flow via a factory
37 */
38 protected ExecutionFlowGeneratorSource source;
39
40 /**
41 * Factory used to create Runnables in the Application context from
42 * the <code>RunnableDataNode</code> provided from the source.
43 */
44 protected RunnableFactory runnableFactory;
45
46 /**
47 * Bean name of the <code>ExecutionContext</code>.
48 * Used to provide the created <code>RunnableCallFlow</code> beans
49 * with a <code>RuntimeBeanReference</code> to
50 * the <code>ExecutionContext</code>
51 */
52 private String executionContextBeanName = "executionContext";
53
54 /**
55 * Bean name of the context values Map.
56 * A bean of class HashMap is created with this name, and a
57 * <code>RuntimeBeanReference</code> is provided to the created
58 * <code>RunnableCallFlow</code> beans.
59 */
60 private String contextValuesBeanName = "executionFlowGenerator.contextValues";
61
62 /**
63 * Prefix added to the bean names defined in each
64 * <code>RunnableCallFlowDescriptor</code>
65 */
66 private String flowBeanNamesPrefix = "";
67
68 private int order = Ordered.HIGHEST_PRECEDENCE;
69
70 public void postProcessBeanFactory(
71 ConfigurableListableBeanFactory beanFactory) throws BeansException {
72
73 // assert that the beanFactory is a BeanDefinitionRegistry
74 if (!(beanFactory instanceof BeanDefinitionRegistry)) {
75 throw new SlcException("Can only work on "
76 + BeanDefinitionRegistry.class);
77 }
78
79 // add bean for the Context Values Map
80 createAndRegisterContextValuesBean((BeanDefinitionRegistry) beanFactory);
81
82 // add beans for each RunnableDataNode
83 for(RunnableDataNode node : source.getRunnableDataNodes()) {
84 runnableFactory.createAndRegisterRunnable(node, (BeanDefinitionRegistry) beanFactory);
85 }
86
87 // add beans for each RunnableCallFlowDescriptor of the source to the application context
88 for (RunnableCallFlowDescriptor descriptor : source
89 .getRunnableCallFlowDescriptors()) {
90 createAndRegisterFlowFor(descriptor, (BeanDefinitionRegistry) beanFactory);
91 }
92 }
93
94 /**
95 * Creates a <code>RunnableCallFlow</code> bean
96 * for a <code>RunnableCallFlowDescriptor</code> and registers
97 * it in the <code>BeanDefinitionRegistry</code>
98 * @param flowDescriptor
99 * @param registry
100 */
101 private void createAndRegisterFlowFor(RunnableCallFlowDescriptor flowDescriptor, BeanDefinitionRegistry registry) {
102 // create the flow bean
103 GenericBeanDefinition flowBean = new GenericBeanDefinition();
104 flowBean.setBeanClass(RunnableCallFlow.class);
105
106 String beanName = flowBeanNamesPrefix + flowDescriptor.getBeanName();
107
108 MutablePropertyValues mpv = new MutablePropertyValues();
109 mpv.addPropertyValue("runnableCalls", flowDescriptor.getRunnableCalls());
110 mpv.addPropertyValue("sharedContextValuesMap", new RuntimeBeanReference(contextValuesBeanName));
111
112 mpv.addPropertyValue("name", beanName);
113 mpv.addPropertyValue("path", flowDescriptor.getPath());
114
115 mpv.addPropertyValue("executionContext", new RuntimeBeanReference(executionContextBeanName));
116
117 flowBean.setPropertyValues(mpv);
118
119 // register it
120 if(log.isDebugEnabled()) {
121 log.debug("Registering bean definition for RunnableCallFlow " + beanName);
122 }
123 registry.registerBeanDefinition(beanName, flowBean);
124 }
125
126 /**
127 * Creates the Context Values bean and register it in the
128 * <code>BeanDefinitionRegistry</code>
129 * @param registry
130 */
131 private void createAndRegisterContextValuesBean(BeanDefinitionRegistry registry) {
132 GenericBeanDefinition contextValuesBean = new GenericBeanDefinition();
133 contextValuesBean.setBeanClass(HashMap.class);
134
135 BeanDefinitionHolder bdh = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(contextValuesBean, contextValuesBeanName), registry, true);
136 registry.registerBeanDefinition(contextValuesBeanName, bdh.getBeanDefinition());
137 }
138
139 public int getOrder() {
140 return order;
141 }
142
143 public void setOrder(int order) {
144 this.order = order;
145 }
146
147 public void setSource(ExecutionFlowGeneratorSource source) {
148 this.source = source;
149 }
150
151 public void setRunnableFactory(RunnableFactory runnableFactory) {
152 this.runnableFactory = runnableFactory;
153 }
154
155 public void setExecutionContextBeanName(String executionContextBeanName) {
156 this.executionContextBeanName = executionContextBeanName;
157 }
158
159 public void setContextValuesBeanName(String contextValuesBeanName) {
160 this.contextValuesBeanName = contextValuesBeanName;
161 }
162
163 public void setFlowBeanNamesPrefix(String flowBeanNamesPrefix) {
164 this.flowBeanNamesPrefix = flowBeanNamesPrefix;
165 }
166 }