org.solmix.runtime.support.spring.AbstractBeanDefinitionParser.java Source code

Java tutorial

Introduction

Here is the source code for org.solmix.runtime.support.spring.AbstractBeanDefinitionParser.java

Source

/**
 * Copyright 2014 The Solmix Project
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.gnu.org/licenses/ 
 * or see the FSF site: http://www.fsf.org. 
 */

package org.solmix.runtime.support.spring;

import java.util.StringTokenizer;

import org.solmix.commons.util.DOMUtils;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;

/**
 * 
 * @author solmix.f@gmail.com
 * @version $Id$ 2014910
 */

public class AbstractBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    /** springContextcontainer,??Container,
     * springcontainer(wire),
     * container? */
    public static final String WIRE_CONTAINER_ATTRIBUTE = AbstractBeanDefinitionParser.class.getName() + ".wireCT";

    public static final String WIRE_CONTAINER_NAME = AbstractBeanDefinitionParser.class.getName() + ".wireCTName";

    /** container??   */
    public static final String WIRE_CONTAINER_CREATE = AbstractBeanDefinitionParser.class.getName()
            + ".wireCTCreate";

    public static final String WIRE_CONTAINER_HANDLER = ContainerPostProcessor.class.getName();

    private Class<?> beanClass;

    @Override
    protected void doParse(Element element, ParserContext ctx, BeanDefinitionBuilder bean) {
        //?container,?spring-true,?false.
        boolean setContainer = parseAttributes(element, ctx, bean);
        if (!setContainer && hasContainerProperty()) {
            addContainerWiringAttribute(bean, true);
        }
        parseChildElements(element, ctx, bean);
    }

    /**??*/
    protected void parseChildElements(Element element, ParserContext ctx, BeanDefinitionBuilder bean) {
        Element el = DOMUtils.getFirstElement(element);
        while (el != null) {
            String name = el.getLocalName();
            parseElement(ctx, bean, el, name);
            el = DOMUtils.getNextElement(el);
        }
    }

    protected void parseElement(ParserContext ctx, BeanDefinitionBuilder bean, Element e, String name) {
    }

    /** ??container*/
    protected boolean hasContainerProperty() {
        return false;
    }

    /**?Element,?Container*/
    protected boolean parseAttributes(Element element, ParserContext ctx, BeanDefinitionBuilder bean) {
        NamedNodeMap atts = element.getAttributes();
        boolean setBus = false;
        for (int i = 0; i < atts.getLength(); i++) {
            Attr node = (Attr) atts.item(i);
            String val = node.getValue();
            String pre = node.getPrefix();
            String name = node.getLocalName();
            String prefix = node.getPrefix();

            // Don't process namespaces
            if (isNamespace(name, prefix)) {
                continue;
            }
            if ("createdFromAPI".equals(name)) {
                bean.setAbstract(true);
            } else if ("abstract".equals(name)) {
                bean.setAbstract(true);
            } else if ("depends-on".equals(name)) {
                bean.addDependsOn(val);
            } else if ("name".equals(name)) {
                parseNameAttribute(element, ctx, bean, val);
            } else if ("container".equals(name)) {
                setBus = parseContainerAttribute(element, ctx, bean, val);
            } else if ("id".equals(name)) {
                parseIdAttribute(bean, element, name, val, ctx);
            } else if (isAttribute(pre, name)) {
                parseAttribute(bean, element, name, val, ctx);
            }
        }
        return setBus;
    }

    protected void parseIdAttribute(BeanDefinitionBuilder bean, Element element, String name, String val,
            ParserContext ctx) {

    }

    protected void parseAttribute(BeanDefinitionBuilder bean, Element e, String name, String val,
            ParserContext ctx) {
        parseAttribute(bean, name, val, ctx);
    }

    protected void parseAttribute(BeanDefinitionBuilder bean, String name, String val, ParserContext ctx) {
        attributeToProperty(bean, name, val, ctx);
    }

    protected void attributeToProperty(BeanDefinitionBuilder bean, String propertyName, String val,
            ParserContext ctx) {
        if (ID_ATTRIBUTE.equals(propertyName)) {
            return;
        }

        if (val != null && val.trim().length() > 0) {
            bean.addPropertyValue(propertyName, val);
        }
    }

    /**Container?*/
    protected boolean parseContainerAttribute(Element element, ParserContext ctx, BeanDefinitionBuilder bean,
            String val) {
        if (val != null && val.trim().length() > 0) {
            //?Container,Spring?validContainer.
            if (ctx.getRegistry().containsBeanDefinition(val)) {
                bean.addPropertyReference("container", val);
            } else {
                //spring,?Container.
                addContainerWiringAttribute(bean, true, val, ctx);
            }
            return true;
        }
        return false;
    }

    protected void parseNameAttribute(Element element, ParserContext ctx, BeanDefinitionBuilder bean, String val) {
        // nothing
    }

    protected boolean isAttribute(String pre, String name) {
        return !"xmlns".equals(name) && (pre == null || !pre.equals("xmlns")) && !"abstract".equals(name)
                && !"lazy-init".equals(name) && !"id".equals(name);
    }

    private boolean isNamespace(String name, String prefix) {
        return "xmlns".equals(prefix) || prefix == null && "xmlns".equals(name);
    }

    protected void addContainerWiringAttribute(BeanDefinitionBuilder bean, boolean type) {
        addContainerWiringAttribute(bean, type, null, null);
    }

    protected void addContainerWiringAttribute(BeanDefinitionBuilder bean, boolean type, String containerName,
            ParserContext ctx) {
        bean.getRawBeanDefinition().setAttribute(WIRE_CONTAINER_ATTRIBUTE, type);
        if (containerName != null && containerName.trim().length() > 0) {
            bean.getRawBeanDefinition().setAttribute(WIRE_CONTAINER_NAME, containerName);
        }

        if (ctx != null && !ctx.getRegistry().containsBeanDefinition(WIRE_CONTAINER_HANDLER)) {
            //??,
            BeanDefinitionBuilder b = BeanDefinitionBuilder.rootBeanDefinition(WIRE_CONTAINER_HANDLER);
            ctx.getRegistry().registerBeanDefinition(WIRE_CONTAINER_HANDLER, b.getBeanDefinition());
        }
    }

    public Class<?> getBeanClass() {
        return beanClass;
    }

    /**spring beanclass*/
    public void setBeanClass(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    @Override
    protected Class<?> getBeanClass(Element e) {
        return beanClass;
    }

    /**?,?id,spring*/
    @Override
    protected String resolveId(Element elem, AbstractBeanDefinition definition, ParserContext ctx)
            throws BeanDefinitionStoreException {
        //id
        String id = getIdOrName(elem);

        if (null == id || "".equals(id)) {
            return super.resolveId(elem, definition, ctx);
        }
        return id;
    }

    /**id ?*/
    protected String getIdOrName(Element elem) {
        String id = elem.getAttribute(BeanDefinitionParserDelegate.ID_ATTRIBUTE);
        //ID,name
        if (null == id || "".equals(id)) {
            String names = elem.getAttribute(BeanDefinitionParserDelegate.NAME_ATTRIBUTE);
            if (null != names) {
                StringTokenizer st = new StringTokenizer(names,
                        BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                //?
                if (st.countTokens() > 0) {
                    id = st.nextToken();
                }
            }
        }
        return id;
    }

    protected Element getFirstChild(Element element) {
        return DOMUtils.getFirstElement(element);
    }

    protected void firstChildAsProperty(Element element, ParserContext ctx, BeanDefinitionBuilder bean,
            String propertyName) {
        Element first = getFirstChild(element);
        if (first == null) {
            throw new IllegalStateException(propertyName + " property must have child elements!");
        }
        String id;
        BeanDefinition child;
        if (first.getNamespaceURI().equals(BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI)) {
            String name = first.getLocalName();
            if ("ref".equals(name)) {
                id = first.getAttribute("bean");
                if (id == null) {
                    throw new IllegalStateException("<ref> elements must have a \"bean\" attribute!");
                }
                bean.addPropertyReference(propertyName, id);
                return;
            } else if ("bean".equals(name)) {
                BeanDefinitionHolder bdh = ctx.getDelegate().parseBeanDefinitionElement(first);
                child = bdh.getBeanDefinition();
                bean.addPropertyValue(propertyName, child);
                return;
            } else {
                throw new UnsupportedOperationException("Elements with the name " + name + " are not currently "
                        + "supported as sub elements of " + element.getLocalName());
            }
        }
        child = ctx.getDelegate().parseCustomElement(first, bean.getBeanDefinition());
        bean.addPropertyValue(propertyName, child);
    }

    /***/
    protected void parseMultiRef(String property, String value, BeanDefinitionBuilder bean,
            ParserContext parserContext) {
        String[] values = value.split("\\s*[,]+\\s*");
        ManagedList<Object> list = null;
        for (int i = 0; i < values.length; i++) {
            String v = values[i];
            if (v != null && v.length() > 0) {
                if (list == null) {
                    list = new ManagedList<Object>();
                }
                list.add(new RuntimeBeanReference(v));
            }
        }
        bean.getBeanDefinition().getPropertyValues().addPropertyValue(property, list);
    }
}