/*
* 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 org.solmix.commons.util.DOMUtils;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
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$ 2014年9月10日
*/
public class AbstractBeanDefinitionParser extends
AbstractSingleBeanDefinitionParser
{
public static final String WIRE_CONTAINER_ATTRIBUTE =
AbstractBeanDefinitionParser.class.getName()+ ".wireBus";
public static final String WIRE_CONTAINER_NAME =
AbstractBeanDefinitionParser.class.getName()+ ".wireBusName";
public static final String WIRE_CONTAINER_CREATE =
AbstractBeanDefinitionParser.class.getName()+ ".wireBusCreate";
public static final String WIRE_CONTAINER_HANDLER = ContainerPostProcessor.class.getName();
private Class<?> beanClass;
@Override
protected void doParse(Element element, ParserContext ctx,
BeanDefinitionBuilder bean) {
boolean setBus = parseAttributes(element, ctx, bean);
if (!setBus && hasBusProperty()) {
addBusWiringAttribute(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();
mapElement(ctx, bean, el, name);
el = DOMUtils.getNextElement(el);
}
}
protected void mapElement(ParserContext ctx, BeanDefinitionBuilder bean,
Element e, String name) {
}
protected boolean hasBusProperty() {
return false;
}
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)) {
processNameAttribute(element, ctx, bean, val);
} else if ("container".equals(name)) {
setBus = processBusAttribute(element, ctx, bean, val);
} else if (!"id".equals(name) && isAttribute(pre, name)) {
mapAttribute(bean, element, name, val);
}
}
return setBus;
}
protected void mapAttribute(BeanDefinitionBuilder bean, Element e,
String name, String val) {
mapAttribute(bean, name, val);
}
protected void mapAttribute(BeanDefinitionBuilder bean, String name,
String val) {
mapToProperty(bean, name, val);
}
protected void mapToProperty(BeanDefinitionBuilder bean,
String propertyName, String val) {
if (ID_ATTRIBUTE.equals(propertyName)) {
return;
}
if (val != null && val.trim().length() > 0) {
bean.addPropertyValue(propertyName, val);
}
}
protected boolean processBusAttribute(Element element, ParserContext ctx,
BeanDefinitionBuilder bean, String val) {
if (val != null && val.trim().length() > 0) {
if (ctx.getRegistry().containsBeanDefinition(val)) {
bean.addPropertyReference("container", val);
} else {
addBusWiringAttribute(bean, true, val, ctx);
}
return true;
}
return false;
}
protected void processNameAttribute(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 addBusWiringAttribute(BeanDefinitionBuilder bean,
boolean type) {
addBusWiringAttribute(bean, type, null, null);
}
protected void addBusWiringAttribute(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;
}
public void setBeanClass(Class<?> beanClass) {
this.beanClass = beanClass;
}
@Override
protected Class<?> getBeanClass(Element e) {
return beanClass;
}
}