/* vim: set ts=2 et sw=2 cindent fo=qroca: */
package com.globant.katari.core.spring;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.globant.katari.core.web.MenuBar;
/** This class parses the xml fragment for the menu beans.
*/
public class MenuBarBeanDefinitionParser extends AbstractBeanDefinitionParser {
/** The class logger.
*/
private static Logger log =
LoggerFactory.getLogger(MenuBarBeanDefinitionParser.class);
/** Parses the xml fragment.
*
* {@inheritDoc}
*/
@Override
protected AbstractBeanDefinition parseInternal(final Element element, final
ParserContext parserContext) {
if (log.isTraceEnabled()) {
log.trace("Entering parseInternal('" + element.getTagName() + "')");
}
BeanDefinitionBuilder factory;
factory = BeanDefinitionBuilder.rootBeanDefinition(MenuBarFactory.class);
BeanDefinitionBuilder menubar;
menubar = BeanDefinitionBuilder.rootBeanDefinition(MenuBar.class);
factory.addPropertyValue("menuBar", menubar.getBeanDefinition());
// Obtain all menuNode and menuItem children.
List<Element> childElements = getMenuNodesOrItems(element);
if (childElements != null && childElements.size() > 0) {
parseChildren(childElements, factory);
}
AbstractBeanDefinition result = factory.getBeanDefinition();
log.trace("Leaving parseInternal");
return result;
}
/** Returns the list of child menu nodes (menuNode or menuItem) of the
* specified dom element.
*
* @param element The dom element. It cannot be null.
*
* @return a list of dom elements. It never returns null.
*/
private static List<Element> getMenuNodesOrItems(final Element element) {
NodeList nodeList = element.getChildNodes();
List<Element> children = new ArrayList<Element>();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
boolean isMenuElement = node instanceof Element
&& (DomUtils.nodeNameEquals(node, "menuItem")
|| DomUtils.nodeNameEquals(node, "menuNode"));
if (isMenuElement) {
children.add((Element) node);
}
}
return children;
}
/** Parses the list of children of a node.
*
* @param childElements The list of children. It cannot be null.
*
* @param parent the bean definition factory for the parent menu node. It
* cannot be null.
*/
@SuppressWarnings("unchecked")
private static void parseChildren(final List<Element> childElements,
final BeanDefinitionBuilder parent) {
log.trace("Entering parseChildren");
Validate.notNull(childElements, "The child elements cannot be null.");
Validate.notNull(parent, "The parent cannot be null.");
ManagedList children = new ManagedList(childElements.size());
for (int i = 0; i < childElements.size(); ++i) {
Element element = childElements.get(i);
BeanDefinitionBuilder child;
if (DomUtils.nodeNameEquals(element, "menuItem")) {
child = parseMenuItem(element);
} else {
child = parseMenuNode(element);
List<Element> nodeChildren = getMenuNodesOrItems(element);
parseChildren(nodeChildren, child);
}
children.add(child.getBeanDefinition());
}
parent.addPropertyValue("children", children);
log.trace("Leaving parseChildren");
}
/** Parses a menu item, that is, a leaf menu node.
*
* @param element The xml element to parse. It cannot be null.
*
* @return BeanDefinitionBuilder a bean definition factory that builds a
* MenuNodeHolder. It never returns null.
*/
private static BeanDefinitionBuilder parseMenuItem(final Element element) {
log.trace("Entering parseMenuItem");
Validate.notNull(element, "The element cannot be null.");
BeanDefinitionBuilder node;
node = BeanDefinitionBuilder.rootBeanDefinition(MenuNodeHolder.class);
node.addConstructorArgValue(element.getAttribute("display"));
node.addConstructorArgValue(element.getAttribute("name"));
node.addConstructorArgValue(element.getAttribute("position"));
node.addConstructorArgValue(element.getAttribute("tooltip"));
node.addConstructorArgValue(element.getAttribute("link"));
log.trace("Leaving parseMenuItem");
return node;
}
/** Parses a menu node.
*
* @param element The xml element to parse. It cannot be null.
*
* @return BeanDefinitionBuilder a bean definition factory that builds a
* MenuNode. It never returns null.
*/
private static BeanDefinitionBuilder parseMenuNode(final Element element) {
log.trace("Entering parseMenuNode");
Validate.notNull(element, "The element cannot be null.");
BeanDefinitionBuilder node;
node = BeanDefinitionBuilder.rootBeanDefinition(MenuNodeHolder.class);
node.addConstructorArgValue(element.getAttribute("display"));
node.addConstructorArgValue(element.getAttribute("name"));
node.addConstructorArgValue(element.getAttribute("position"));
node.addConstructorArgValue(element.getAttribute("tooltip"));
log.trace("Leaving parseMenuNode");
return node;
}
}