]> 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
Remove usage of flow path in ExecutionFlowGenerator
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / execution / generator / ExecutionFlowGenerator.java
1 /*
2 * Copyright (C) 2007-2012 Mathieu Baudier
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", flowDescriptor.getPath() + "/" + beanName);
128
129 mpv.addPropertyValue("executionContext", new RuntimeBeanReference(executionContextBeanName));
130
131 flowBean.setPropertyValues(mpv);
132
133 // register it
134 if(log.isDebugEnabled()) {
135 log.debug("Registering bean definition for RunnableCallFlow " + beanName);
136 }
137 registry.registerBeanDefinition(beanName, flowBean);
138 }
139
140 /**
141 * Creates the Context Values bean and register it in the
142 * <code>BeanDefinitionRegistry</code>
143 * @param registry
144 */
145 private void createAndRegisterContextValuesBean(BeanDefinitionRegistry registry) {
146 GenericBeanDefinition contextValuesBean = new GenericBeanDefinition();
147 contextValuesBean.setBeanClass(HashMap.class);
148
149 BeanDefinitionHolder bdh = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(contextValuesBean, contextValuesBeanName), registry, true);
150 registry.registerBeanDefinition(contextValuesBeanName, bdh.getBeanDefinition());
151 }
152
153 public int getOrder() {
154 return order;
155 }
156
157 public void setOrder(int order) {
158 this.order = order;
159 }
160
161 public void setSource(ExecutionFlowGeneratorSource source) {
162 this.source = source;
163 }
164
165 public void setRunnableFactory(RunnableFactory runnableFactory) {
166 this.runnableFactory = runnableFactory;
167 }
168
169 public void setExecutionContextBeanName(String executionContextBeanName) {
170 this.executionContextBeanName = executionContextBeanName;
171 }
172
173 public void setContextValuesBeanName(String contextValuesBeanName) {
174 this.contextValuesBeanName = contextValuesBeanName;
175 }
176
177 public void setFlowBeanNamesPrefix(String flowBeanNamesPrefix) {
178 this.flowBeanNamesPrefix = flowBeanNamesPrefix;
179 }
180 }