001package org.dllearner.configuration.spring;
002
003import java.util.Collection;
004
005import org.dllearner.configuration.IConfiguration;
006import org.dllearner.configuration.IConfigurationProperty;
007import org.springframework.beans.BeansException;
008import org.springframework.beans.factory.config.BeanDefinition;
009import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
010import org.springframework.beans.factory.config.RuntimeBeanReference;
011import org.springframework.beans.factory.support.BeanDefinitionBuilder;
012import org.springframework.beans.factory.support.BeanDefinitionRegistry;
013import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
014import org.springframework.beans.factory.support.ManagedSet;
015
016/**
017 * Created by IntelliJ IDEA.
018 * User: Chris
019 * Date: 8/22/11
020 * Time: 6:38 AM
021 * <p/>
022 * This class is used to insert BeanDefinitions that are declared in the configuration file that
023 * do not exist in the existing registry (ie. they aren't declared in the spring XML file).
024 */
025public class ConfigurationBasedBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
026
027    private final IConfiguration configuration;
028
029    public ConfigurationBasedBeanDefinitionRegistryPostProcessor(IConfiguration configuration) {
030        this.configuration = configuration;
031    }
032
033    /**
034     * Ensure that BeanDefinitions exist for all referenced beans in the configuration.
035     *
036     * @param registry The Bean registry to use.
037     * @throws BeansException
038     */
039    @Override
040    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
041        final Collection<String> beanNames = configuration.getBeanNames();
042
043        for (String beanName : beanNames) {
044            if (!registry.containsBeanDefinition(beanName)) {
045                Class beanClass = configuration.getClass(beanName);
046                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
047
048                BeanDefinition definition = builder.getBeanDefinition();
049
050                registry.registerBeanDefinition(beanName, definition);
051            }
052        }
053
054    }
055
056    @Override
057    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
058
059        final Collection<String> beanNames = configuration.getBeanNames();
060
061
062        for (String beanName : beanNames) {
063
064            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
065
066            Collection<IConfigurationProperty> properties = configuration.getConfigurationProperties(beanName);
067
068            for (IConfigurationProperty property : properties) {
069
070                Object value = property.getValue();
071                //Process Single Bean References
072                if (property.isBeanReference()) {
073                    value = new RuntimeBeanReference((String)property.getValue());
074                }
075
076                //Process collections of bean references
077                if(property.isBeanReferenceCollection()){
078                    Collection<RuntimeBeanReference> beanReferences = new ManagedSet<>();
079                    Collection<String> referencedBeanNames = (Collection<String>)property.getValue();
080                    for (String referencedBeanName : referencedBeanNames) {
081                         beanReferences.add(new RuntimeBeanReference(referencedBeanName));
082                    }
083                    value = beanReferences;
084                }
085
086                addBaseDirectoryIfNeeded(beanDefinition);
087
088                beanDefinition.getPropertyValues().add(property.getName(), value);
089            }
090        }
091    }
092
093    /**
094     * Add Base Directory Value to Beans which need it.
095     *
096     * @param beanDefinition The current Bean Definition
097     */
098    private void addBaseDirectoryIfNeeded(BeanDefinition beanDefinition) {
099        Class beanClass = null;
100        try {
101            beanClass = Class.forName(beanDefinition.getBeanClassName());
102        } catch (ClassNotFoundException e) {
103            throw new RuntimeException("Can't find class " + beanDefinition.getBeanClassName());
104        }
105        /** Add Base Directory */
106        try {
107                        beanClass.getMethod("setBaseDir", String.class);
108                        beanDefinition.getPropertyValues().add("baseDir", configuration.getBaseDir());
109                } catch (NoSuchMethodException e) {
110                        // ignore
111                } catch (SecurityException e) {
112                        // TODO Auto-generated catch block
113                        e.printStackTrace();
114                }
115    }
116
117}