X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.slc.core%2Fsrc%2Forg%2Fargeo%2Fslc%2Fcore%2Fexecution%2Fgenerator%2FExecutionFlowGenerator.java;fp=org.argeo.slc.core%2Fsrc%2Forg%2Fargeo%2Fslc%2Fcore%2Fexecution%2Fgenerator%2FExecutionFlowGenerator.java;h=d9400e42edf8b89651b7e4d27e5c3202fa7c7436;hb=a9b97cc33383ded70277f49aa287f84903334e70;hp=0000000000000000000000000000000000000000;hpb=d1298659fe6f179d1cbbc8c89f108a0bbc5b4edf;p=gpl%2Fargeo-slc.git diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java new file mode 100644 index 000000000..d9400e42e --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import java.util.HashMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.aop.scope.ScopedProxyUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.core.Ordered; + +/** + * Generates ExecutionFlows and Runnables as + * beans in the Spring Application Context. + * Called by the Application Context as a BeanFactoryPostProcessor. + * Two kinds of beans are generated: + * RunnableCallFlow, calling a list of Runnables from the + * Application Context after configuring the ExecutionContext, + * and outputs of a RunnableFactory. + */ +public class ExecutionFlowGenerator implements BeanFactoryPostProcessor, + Ordered { + + private final Log log = LogFactory.getLog(getClass()); + + /** + * Source providing a list of RunnableCallFlowDescriptor + * used to create RunnableCallFlow and a list of + * RunnableDataNode used to create any kind of flow via a factory + */ + protected ExecutionFlowGeneratorSource source; + + /** + * Factory used to create Runnables in the Application context from + * the RunnableDataNode provided from the source. + */ + protected RunnableFactory runnableFactory; + + /** + * Bean name of the ExecutionContext. + * Used to provide the created RunnableCallFlow beans + * with a RuntimeBeanReference to + * the ExecutionContext + */ + private String executionContextBeanName = "executionContext"; + + /** + * Bean name of the context values Map. + * A bean of class HashMap is created with this name, and a + * RuntimeBeanReference is provided to the created + * RunnableCallFlow beans. + */ + private String contextValuesBeanName = "executionFlowGenerator.contextValues"; + + /** + * Prefix added to the bean names defined in each + * RunnableCallFlowDescriptor + */ + private String flowBeanNamesPrefix = ""; + + private int order = Ordered.HIGHEST_PRECEDENCE; + + public void postProcessBeanFactory( + ConfigurableListableBeanFactory beanFactory) throws BeansException { + + // assert that the beanFactory is a BeanDefinitionRegistry + if (!(beanFactory instanceof BeanDefinitionRegistry)) { + throw new SlcException("Can only work on " + + BeanDefinitionRegistry.class); + } + + // add bean for the Context Values Map + createAndRegisterContextValuesBean((BeanDefinitionRegistry) beanFactory); + + // add beans for each RunnableDataNode + for(RunnableDataNode node : source.getRunnableDataNodes()) { + runnableFactory.createAndRegisterRunnable(node, (BeanDefinitionRegistry) beanFactory); + } + + // add beans for each RunnableCallFlowDescriptor of the source to the application context + for (RunnableCallFlowDescriptor descriptor : source + .getRunnableCallFlowDescriptors()) { + createAndRegisterFlowFor(descriptor, (BeanDefinitionRegistry) beanFactory); + } + } + + /** + * Creates a RunnableCallFlow bean + * for a RunnableCallFlowDescriptor and registers + * it in the BeanDefinitionRegistry + * @param flowDescriptor + * @param registry + */ + private void createAndRegisterFlowFor(RunnableCallFlowDescriptor flowDescriptor, BeanDefinitionRegistry registry) { + // create the flow bean + GenericBeanDefinition flowBean = new GenericBeanDefinition(); + flowBean.setBeanClass(RunnableCallFlow.class); + + String beanName = flowBeanNamesPrefix + flowDescriptor.getBeanName(); + + MutablePropertyValues mpv = new MutablePropertyValues(); + mpv.addPropertyValue("runnableCalls", flowDescriptor.getRunnableCalls()); + mpv.addPropertyValue("sharedContextValuesMap", new RuntimeBeanReference(contextValuesBeanName)); + + mpv.addPropertyValue("name", beanName); + mpv.addPropertyValue("path", flowDescriptor.getPath()); + + mpv.addPropertyValue("executionContext", new RuntimeBeanReference(executionContextBeanName)); + + flowBean.setPropertyValues(mpv); + + // register it + if(log.isDebugEnabled()) { + log.debug("Registering bean definition for RunnableCallFlow " + beanName); + } + registry.registerBeanDefinition(beanName, flowBean); + } + + /** + * Creates the Context Values bean and register it in the + * BeanDefinitionRegistry + * @param registry + */ + private void createAndRegisterContextValuesBean(BeanDefinitionRegistry registry) { + GenericBeanDefinition contextValuesBean = new GenericBeanDefinition(); + contextValuesBean.setBeanClass(HashMap.class); + + BeanDefinitionHolder bdh = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(contextValuesBean, contextValuesBeanName), registry, true); + registry.registerBeanDefinition(contextValuesBeanName, bdh.getBeanDefinition()); + } + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + public void setSource(ExecutionFlowGeneratorSource source) { + this.source = source; + } + + public void setRunnableFactory(RunnableFactory runnableFactory) { + this.runnableFactory = runnableFactory; + } + + public void setExecutionContextBeanName(String executionContextBeanName) { + this.executionContextBeanName = executionContextBeanName; + } + + public void setContextValuesBeanName(String contextValuesBeanName) { + this.contextValuesBeanName = contextValuesBeanName; + } + + public void setFlowBeanNamesPrefix(String flowBeanNamesPrefix) { + this.flowBeanNamesPrefix = flowBeanNamesPrefix; + } +}