com.inspiresoftware.lib.dto.geda.config.AnnotationDrivenGeDABeanDefinitionParser.java Source code

Java tutorial

Introduction

Here is the source code for com.inspiresoftware.lib.dto.geda.config.AnnotationDrivenGeDABeanDefinitionParser.java

Source

/*
 * This code is distributed under The GNU Lesser General Public License (LGPLv3)
 * Please visit GNU site for LGPLv3 http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright Denis Pavlov 2009
 * Web: http://www.genericdtoassembler.org
 * SVN: https://svn.code.sf.net/p/geda-genericdto/code/trunk/
 * SVN (mirror): http://geda-genericdto.googlecode.com/svn/trunk/
 */

package com.inspiresoftware.lib.dto.geda.config;

import com.inspiresoftware.lib.dto.geda.impl.DTOSupportImpl;
import com.inspiresoftware.lib.dto.geda.interceptor.GeDAInterceptor;
import com.inspiresoftware.lib.dto.geda.interceptor.impl.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.config.AopNamespaceUtils;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

/**
 * .
 * <p/>
 * User: denispavlov
 * Date: Jan 25, 2012
 * Time: 4:12:57 PM
 */
public class AnnotationDrivenGeDABeanDefinitionParser implements BeanDefinitionParser {

    private static final Logger LOG = LoggerFactory.getLogger(AnnotationDrivenGeDABeanDefinitionParser.class);

    private static final String XSD_ATTR__DTO_SUPPORT = "dto-support";
    private static final String XSD_ATTR__DTO_FACTORY = "dto-factory";
    private static final String XSD_ATTR__DTO_ADAPTERS_REGISTRAR = "dto-adapters-registrar";
    private static final String XSD_ATTR__DTO_DSL_REGISTRAR = "dto-dsl-registrar";
    private static final String XSD_ATTR__ON_DTO_ASSEMBLY = "on-dto-assembly";
    private static final String XSD_ATTR__ON_DTO_ASSEMBLED = "on-dto-assembled";
    private static final String XSD_ATTR__ON_DTO_FAILED = "on-dto-failed";
    private static final String XSD_ATTR__ON_ENTITY_ASSEMBLY = "on-entity-assembly";
    private static final String XSD_ATTR__ON_ENTITY_ASSEMBLED = "on-entity-assembled";
    private static final String XSD_ATTR__ON_ENTITY_FAILED = "on-entity-failed";
    private static final String XSD_ATTR__USE_PREPROCESSOR = "use-bean-preprocessor";
    private static final String XSD_ATTR__POINTCUT_MATCH_REGEX = "pointcut-match-regex";
    private static final String XSD_ATTR__POINTCUT_NOMATCH_REGEX = "pointcut-nomatch-regex";

    public static final String ADVISOR_BEAN_NAME = AnnotationDrivenGeDABeanDefinitionParser.class.getPackage()
            .getName() + ".internalGeDAAdvisor";

    public BeanDefinition parse(final Element element, final ParserContext parserContext) {

        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
        if (!parserContext.getRegistry().containsBeanDefinition(ADVISOR_BEAN_NAME)) {

            final Boolean usePreprocessor = Boolean.valueOf(element.getAttribute(XSD_ATTR__USE_PREPROCESSOR));
            final String dtoSupportBeanName = element.getAttribute(XSD_ATTR__DTO_SUPPORT);

            final BeanDefinitionRegistry registry = parserContext.getRegistry();
            final Object elementSource = parserContext.extractSource(element);

            final RuntimeBeanReference dtoSupportDef;

            if (!registry.containsBeanDefinition(dtoSupportBeanName)) {

                final String dtoFactoryBeanName = element.getAttribute(XSD_ATTR__DTO_FACTORY);
                final RuntimeBeanReference dtoFactoryRef = new RuntimeBeanReference(dtoFactoryBeanName);

                final String dtoVcrBeanName = element.getAttribute(XSD_ATTR__DTO_ADAPTERS_REGISTRAR);
                final RuntimeBeanReference dtoVcrRef;
                if (StringUtils.hasLength(dtoVcrBeanName)) {
                    dtoVcrRef = new RuntimeBeanReference(dtoVcrBeanName);
                } else {
                    dtoVcrRef = null;
                }

                final String dtoDslBeanName = element.getAttribute(XSD_ATTR__DTO_DSL_REGISTRAR);
                final RuntimeBeanReference dtoDslRef;
                if (StringUtils.hasLength(dtoDslBeanName)) {
                    dtoDslRef = new RuntimeBeanReference(dtoDslBeanName);
                } else {
                    dtoDslRef = null;
                }

                dtoSupportDef = this.setupDtoSupport(element, dtoSupportBeanName, registry, elementSource,
                        dtoFactoryRef, dtoVcrRef, dtoDslRef);

            } else {

                dtoSupportDef = new RuntimeBeanReference(dtoSupportBeanName);

            }

            if (usePreprocessor) {
                // bean pre processor version of configuration
                this.setupBootstapBeanPostprocessor(element, parserContext, elementSource);

                final RuntimeBeanReference defaultCfgAdvice = this.setupTransferableAdviceConfigResolver(
                        parserContext, elementSource, BootstrapAdviceConfigResolverImpl.class);

                final String[] matchRegEx = this.getPointcutRegex(element, XSD_ATTR__POINTCUT_MATCH_REGEX);
                final String[] noMatchRegEx = this.getPointcutRegex(element, XSD_ATTR__POINTCUT_NOMATCH_REGEX);

                final RuntimeBeanReference pointcut = this.setupPointcut(parserContext, elementSource,
                        defaultCfgAdvice, matchRegEx, noMatchRegEx);

                final RuntimeBeanReference defaultInterceptor = this.setupGeDAInterceptor(parserContext,
                        elementSource, dtoSupportDef, defaultCfgAdvice);

                this.setupPointcutAdvisor(element, parserContext, elementSource, pointcut, defaultInterceptor);

            } else {
                // runtime advice discovery
                final RuntimeBeanReference defaultCfgAdvice = this.setupTransferableAdviceConfigResolver(
                        parserContext, elementSource, RuntimeAdviceConfigResolverImpl.class);

                final String[] matchRegEx = this.getPointcutRegex(element, XSD_ATTR__POINTCUT_MATCH_REGEX);
                final String[] noMatchRegEx = this.getPointcutRegex(element, XSD_ATTR__POINTCUT_NOMATCH_REGEX);

                final RuntimeBeanReference pointcut = this.setupPointcut(parserContext, elementSource,
                        defaultCfgAdvice, matchRegEx, noMatchRegEx);

                final RuntimeBeanReference defaultInterceptor = this.setupGeDAInterceptor(parserContext,
                        elementSource, dtoSupportDef, defaultCfgAdvice);

                this.setupPointcutAdvisor(element, parserContext, elementSource, pointcut, defaultInterceptor);
            }
        }
        return null;
    }

    protected RuntimeBeanReference setupDtoSupport(final Element element, final String dtoSupportBeanName,
            final BeanDefinitionRegistry registry, final Object elementSource,
            final RuntimeBeanReference dtoFactoryRef, final RuntimeBeanReference dtoVcrRef,
            final RuntimeBeanReference dtoDslRef) {

        final RootBeanDefinition dtoSupportDef = new RootBeanDefinition(DTOSupportImpl.class);
        dtoSupportDef.setSource(elementSource);
        dtoSupportDef.setRole(BeanDefinition.ROLE_APPLICATION);

        final MutablePropertyValues valuesArgs = dtoSupportDef.getPropertyValues();
        valuesArgs.addPropertyValue("beanFactory", dtoFactoryRef);
        if (dtoVcrRef != null) {
            valuesArgs.addPropertyValue("adaptersRegistrar", dtoVcrRef);
        }
        if (dtoDslRef != null) {
            valuesArgs.addPropertyValue("dslRegistrar", dtoDslRef);
        }
        setupListenerProperty(valuesArgs, "onDtoAssembly", element.getAttribute(XSD_ATTR__ON_DTO_ASSEMBLY));
        setupListenerProperty(valuesArgs, "onDtoAssembled", element.getAttribute(XSD_ATTR__ON_DTO_ASSEMBLED));
        setupListenerProperty(valuesArgs, "onDtoFailed", element.getAttribute(XSD_ATTR__ON_DTO_FAILED));
        setupListenerProperty(valuesArgs, "onEntityAssembly", element.getAttribute(XSD_ATTR__ON_ENTITY_ASSEMBLY));
        setupListenerProperty(valuesArgs, "onEntityAssembled", element.getAttribute(XSD_ATTR__ON_ENTITY_ASSEMBLED));
        setupListenerProperty(valuesArgs, "onEntityFailed", element.getAttribute(XSD_ATTR__ON_ENTITY_FAILED));

        registry.registerBeanDefinition(dtoSupportBeanName, dtoSupportDef);

        return new RuntimeBeanReference(dtoSupportBeanName);
    }

    protected void setupListenerProperty(final MutablePropertyValues valuesArgs, final String property,
            final String listenerName) {
        if (StringUtils.hasLength(listenerName)) {
            valuesArgs.addPropertyValue(property, new RuntimeBeanReference(listenerName));
        }

    }

    protected RuntimeBeanReference setupTransferableAdviceConfigResolver(final ParserContext parserContext,
            final Object elementSource, final Class impl) {

        final RootBeanDefinition defaultResolver = new RootBeanDefinition(impl);
        defaultResolver.setSource(elementSource);
        defaultResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

        final XmlReaderContext readerContext = parserContext.getReaderContext();

        final String beanName = readerContext.registerWithGeneratedName(defaultResolver);

        return new RuntimeBeanReference(beanName);
    }

    protected String[] getPointcutRegex(final Element element, final String attrName) {
        final String matchRegexAttr = element.getAttribute(attrName);
        final String[] matchRegex;
        if (StringUtils.hasText(matchRegexAttr)) {
            final String[] regex = matchRegexAttr.split(",");
            matchRegex = new String[regex.length];
            for (int i = 0; i < regex.length; i++) {
                matchRegex[i] = regex[i].trim();
            }
            return matchRegex;
        }
        return new String[0];
    }

    protected RuntimeBeanReference setupPointcut(final ParserContext parserContext, final Object elementSource,
            final RuntimeBeanReference resolver, final String[] pointcutMatchRegex,
            final String[] pointcutNoMatchRegex) {

        final RootBeanDefinition pointcut;

        if (pointcutMatchRegex.length == 0 && pointcutNoMatchRegex.length == 0) {
            pointcut = new RootBeanDefinition(GeDAMethodMatcherPointcut.class);
            final ConstructorArgumentValues constructorArgs = pointcut.getConstructorArgumentValues();
            constructorArgs.addGenericArgumentValue(resolver);
        } else {
            pointcut = new RootBeanDefinition(GeDAMethodRegExMatcherPointcut.class);
            final ConstructorArgumentValues constructorArgs = pointcut.getConstructorArgumentValues();
            constructorArgs.addGenericArgumentValue(resolver);
            final MutablePropertyValues propertyValues = pointcut.getPropertyValues();
            if (pointcutMatchRegex.length > 0) {
                propertyValues.addPropertyValue("patterns", pointcutMatchRegex);
            }
            if (pointcutNoMatchRegex.length > 0) {
                propertyValues.addPropertyValue("excludedPatterns", pointcutNoMatchRegex);
            }
        }

        pointcut.setSource(elementSource);
        pointcut.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

        final XmlReaderContext readerContext = parserContext.getReaderContext();
        final String pointcutBeanName = readerContext.registerWithGeneratedName(pointcut);

        return new RuntimeBeanReference(pointcutBeanName);
    }

    protected RuntimeBeanReference setupGeDAInterceptor(final ParserContext parserContext,
            final Object elementSource, final RuntimeBeanReference defaultSupport,
            final RuntimeBeanReference defaultResolver) {

        final RootBeanDefinition defaultInterceptor = new RootBeanDefinition(GeDAInterceptor.class);
        defaultInterceptor.setSource(elementSource);
        defaultInterceptor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

        final MutablePropertyValues propertyValues = defaultInterceptor.getPropertyValues();
        propertyValues.addPropertyValue("support", defaultSupport);
        propertyValues.addPropertyValue("resolver", defaultResolver);

        final XmlReaderContext readerContext = parserContext.getReaderContext();

        final String beanName = readerContext.registerWithGeneratedName(defaultInterceptor);

        return new RuntimeBeanReference(beanName);

    }

    protected RuntimeBeanReference setupPointcutAdvisor(final Element element, final ParserContext parserContext,
            final Object elementSource, final RuntimeBeanReference pointcutBeanReference,
            final RuntimeBeanReference interceptorBeanReference) {

        final RootBeanDefinition pointcutAdvisor = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
        pointcutAdvisor.setSource(elementSource);
        pointcutAdvisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

        final MutablePropertyValues propertyValues = pointcutAdvisor.getPropertyValues();
        propertyValues.addPropertyValue("adviceBeanName", interceptorBeanReference.getBeanName());
        propertyValues.addPropertyValue("pointcut", pointcutBeanReference);
        if (element.hasAttribute("order")) {
            propertyValues.addPropertyValue("order", element.getAttribute("order"));
        }

        final BeanDefinitionRegistry registry = parserContext.getRegistry();
        registry.registerBeanDefinition(ADVISOR_BEAN_NAME, pointcutAdvisor);
        return new RuntimeBeanReference(ADVISOR_BEAN_NAME);
    }

    protected RuntimeBeanReference setupBootstapBeanPostprocessor(final Element element,
            final ParserContext parserContext, final Object elementSource) {

        final RootBeanDefinition beanPostProcessor = new RootBeanDefinition(GeDABootstrapAdvicePostProcessor.class);
        beanPostProcessor.setSource(elementSource);
        beanPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

        final XmlReaderContext readerContext = parserContext.getReaderContext();

        final String beanName = readerContext.registerWithGeneratedName(beanPostProcessor);

        return new RuntimeBeanReference(beanName);
    }

}