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