/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.config.spring.parsers.processors;
import org.mule.runtime.config.spring.MuleHierarchicalBeanDefinitionParserDelegate;
import org.mule.runtime.config.spring.parsers.PostProcessor;
import org.mule.runtime.config.spring.parsers.assembly.BeanAssembler;
import org.mule.runtime.config.spring.parsers.assembly.BeanAssemblerFactory;
import org.mule.runtime.config.spring.parsers.assembly.configuration.PropertyConfiguration;
import org.mule.runtime.config.spring.util.SpringXMLUtils;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* <p>
* This iterates over child elements, parsing them and calling {@link #insertBean(BeanAssembler, Object, Element, Element)}.
* </p>
* <p>
* There are two ways we can parse a tree of elements - have an external loop or let each parser iterate over its own children.
* Mule uses the first strategy, but some (most? all?) third party BDPs use the second. This processor lets us use third party
* beans inside the Mule framework.
* </p>
* <p>
* So this is a very specialised parser that should only be used when trying to inter-operate with beans from third party packages
* which themselves control how their children are parsed.
* </p>
* <p>
* Since for Mule beans the iteration over child elements (at least currently) is done via
* {@link MuleHierarchicalBeanDefinitionParserDelegate} the calling parser needs to set the flag
* {@link MuleHierarchicalBeanDefinitionParserDelegate#MULE_NO_RECURSE} - this stops the Mule recursion from working.
* </p>
* <p>
* NOTE - IMHO (ac) the Mule approach was probably a mistake; this processor could be used as a way to slowly migrate the Mule
* code to the more common approach.
* </p>
*/
public abstract class AbstractChildElementIterator implements PostProcessor {
private BeanAssemblerFactory beanAssemblerFactory;
private PropertyConfiguration configuration;
public AbstractChildElementIterator(BeanAssemblerFactory beanAssemblerFactory, PropertyConfiguration configuration) {
this.beanAssemblerFactory = beanAssemblerFactory;
this.configuration = configuration;
}
public void postProcess(ParserContext context, BeanAssembler assembler, Element element) {
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); ++i) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
processChildElement(context, assembler, element, (Element) child);
}
}
}
protected void processChildElement(ParserContext context, BeanAssembler assembler, Element parent, Element child) {
Object childBean = null;
if (SpringXMLUtils.isBeansNamespace(child) || SpringXMLUtils.isLocalName(child, BeanDefinitionParserDelegate.REF_ELEMENT)) {
childBean = context.getDelegate().parsePropertySubElement(child, null);
} else {
childBean = context.getDelegate().parseCustomElement(child, assembler.getBean().getBeanDefinition());
}
BeanAssembler targetAssembler =
beanAssemblerFactory.newBeanAssembler(null, null, configuration, assembler.getBean().getRawBeanDefinition());
insertBean(targetAssembler, childBean, parent, child);
}
protected abstract void insertBean(BeanAssembler targetAssembler, Object childBean, Element parent, Element child);
}