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