org.staticioc.parser.ParserHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.staticioc.parser.ParserHelper.java

Source

/**
 *  Copyright (C) 2013 Charles Gibault
 *
 *  Static IoC - Compile XML based inversion of control configuration file into a single init class, for many languages.
 *  Project Home : http://code.google.com/p/static-ioc/
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.staticioc.parser;

import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.staticioc.model.Property;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Commonly used methods for configuration parsing
 * @author charles
 *
 */
public class ParserHelper implements ParserConstants {
    protected static final Logger logger = LoggerFactory.getLogger(ParserHelper.class);

    /**
     * Builds a value property
     * @param propertyName name of the Property to build
     * @param value of the Property to build
     * @return the built Property if value is not null, null otherwise
     */
    public static Property getVal(String propertyName, String value) {
        if (value == null) {
            return null;
        }
        return new Property(propertyName, value, null);
    }

    /**
     * Builds a ref property
     * @param propertyName name of the Property to build
     * @param ref of the Property to build
     * @return the built Property if ref is not null, null otherwise
     */
    public static Property getRef(String propertyName, String ref) {
        if (ref == null) {
            return null;
        }
        return new Property(propertyName, null, ref);
    }

    /**
     * Handle value, ref and idref attribute of an XML node and builds the corresponding property
     * @param propName name of the Property to build
     * @param node to analyze
     * @return the built Property, if value, ref or idref is found, null otherwise
     */
    public static Property handleValueRefAttributes(final String propName, final Node node) {
        Property prop = null;
        final NamedNodeMap propAttributes = node.getAttributes();

        final Node valueNode = propAttributes.getNamedItem(VALUE);
        final String value = (valueNode != null) ? valueNode.getNodeValue() : null;

        final Node refNode = propAttributes.getNamedItem(REF);
        final Node idRefNode = propAttributes.getNamedItem(IDREF);
        final String ref = refNode != null ? refNode.getNodeValue()
                : (idRefNode != null ? idRefNode.getNodeValue() : null);

        if (value != null || ref != null) // Simple property : value or reference
        {
            prop = new Property(propName, value, ref);

            // Handle type specified as an attribute
            if (value != null) {
                final Node typeNode = propAttributes.getNamedItem(TYPE);
                if (typeNode != null) {
                    prop.setType(typeNode.getNodeValue());
                }
            }
        }
        return prop;
    }

    /**
     * 
     * @param index of the constructor argument
     * @param value of the argument
     * @param ref (for ref argument)
     * @return a Property representing the 
     */
    public static Property buildContructorArgument(int index, String value, String ref) {
        return new Property(CONSTRUCTOR_ARGS + index, value, ref);
    }

    /**
     * Extract the name and id attributes of a node a resolve it as an <id,alias> Pair 
     * @param beanNode to parse
     * @return an <id,alias> Pair
     */
    public static Pair<String, String> extractBeanId(final Node beanNode) {
        final NamedNodeMap beanAttributes = beanNode.getAttributes();

        // use Id if defined, name otherwise (if defined), auto-generated bean name otherwise.
        final Node idNode = beanAttributes.getNamedItem(ID);
        final Node bNameNode = beanAttributes.getNamedItem(NAME);

        String id = (idNode != null) ? idNode.getNodeValue()
                : (bNameNode != null) ? bNameNode.getNodeValue() : null;
        final String alias = (idNode != null && bNameNode != null) ? bNameNode.getNodeValue() : null;

        return ImmutablePair.of(id, alias);
    }

    /**
     * Extract an attribute value as text
     * @param attributeName name of the attribute to extract
     * @param attributes Map of the node
     * @return the String value of the attribute, if it exists, or null otherwise
     */
    public static String extractAttributeValueAsString(final String attributeName, final NamedNodeMap attributes,
            String defaultValue) {
        final Node valueNode = attributes.getNamedItem(attributeName);
        if (valueNode != null) {
            return valueNode.getNodeValue();
        }
        return defaultValue;
    }

    /**
     * Extract an attribute value as Boolean
     * @param attributeName name of the attribute to extract
     * @param attributes Map of the node
     * @return the Boolean value of the attribute, if it exists, or null otherwise
     */
    public static Boolean extractAttributeValueAsBoolean(final String attributeName, final NamedNodeMap attributes,
            Boolean defaultValue) {
        final String valueAsText = extractAttributeValueAsString(attributeName, attributes, null);
        if (valueAsText == null) {
            return defaultValue;
        }
        return Boolean.valueOf(valueAsText);
    }

    /**
     * Extract text value for nodes like <value>text</value>
     * @param node
     * @return the content of the first subnode of a node, expressed as a String, or null otherwise
     */
    public static String extractFirstChildValue(final Node node) {
        final Node valueSubNode = node.getFirstChild();

        if (valueSubNode == null) {
            return null;
        }
        return valueSubNode.getNodeValue();
    }

    /**
     * Go through a node list a extract the first matching node given its name
     * @param nodes
     * @param name
     * @return the first matching node given in the NodeList, or null if not matching Node is found
     */
    public static Node extractFirstNodeByName(final NodeList nodes, final String name,
            final String namespacePrefix) {
        if (nodes != null && name != null) {
            for (int n = 0; n < nodes.getLength(); ++n) {
                final Node node = nodes.item(n);

                if (match(name, node.getNodeName(), namespacePrefix)) {
                    return node;
                }
            }
        }

        return null;
    }

    /**
     * Go through a node list a extract the first matching node given its name
     * @param nodes
     * @param name
     * @return the first matching node given in the NodeList, or null if not matching Node is found
     */
    public static Collection<Node> extractNodesByName(final NodeList nodes, final String name,
            final String namespacePrefix) {
        Collection<Node> result = new LinkedList<Node>();

        if (nodes != null && name != null) {
            for (int n = 0; n < nodes.getLength(); ++n) {
                final Node node = nodes.item(n);

                if (match(name, node.getNodeName(), namespacePrefix)) {
                    result.add(node);
                }
            }
        }

        return result;
    }

    /**
     * Parse a NodeList for XML namespace declaration attributes and build a mapping associating each namespace with its prefix
     * 
     * @param nodes to analyze
     * @return a Map<namespace URL, namespace prefix> for each namespace definition attached to any nodes in the passed NodeList
     */
    public static Map<String, String> extractNamespacePrefix(final NodeList nodes) {
        final Map<String, String> namespacePrefix = new ConcurrentHashMap<String, String>();

        for (int i = 0; i < nodes.getLength(); ++i) {
            Node node = nodes.item(i);
            NamedNodeMap attributes = node.getAttributes();

            for (int a = 0; a < attributes.getLength(); ++a) {
                final Node attribute = attributes.item(a);
                final String attributeValue = attribute.getNodeName();

                if (attributeValue != null && attributeValue.startsWith(XML_NAMESPACE_DEF)) // its a namespace declaration
                {
                    final String schemaUrl = attribute.getNodeValue();
                    String prefix = "";

                    if (attributeValue.contains(":")) // prefix
                    {
                        prefix = attributeValue.split(":")[1];
                    }

                    namespacePrefix.put(schemaUrl, prefix);
                }
            }
        }

        return namespacePrefix;
    }

    /**
     * Build full name of an element given the prefix of its namespace
     * @param prefix of the namespace the element belongs to
     * @param name of the element
     * @return exact name of the element as it is expected in present document
    */
    public static String prefixedName(String prefix, String name) {
        if (StringUtils.isEmpty(prefix)) {
            return name;
        }

        StringBuilder sb = new StringBuilder(prefix);
        sb.append(XML_NAMESPACE_DELIMITER);
        sb.append(name);
        return sb.toString();
    }

    /**
     * Check whether a node has the expected name after prefix resolution
     * 
     * @param expectedName unprefixed expected name 
     * @param nodeName full name of the element to compare
     * @param prefix of the namespace the expected element belongs to
     * @return true if nodeName is equals to expectedName after prefix resolution
     */
    public static boolean match(String expectedName, String nodeName, String prefix) {
        if (expectedName == null) {
            return StringUtils.isEmpty(prefix) && nodeName == null;
        }

        if (StringUtils.isEmpty(prefix)) {
            return expectedName.equals(nodeName);
        }

        if (nodeName == null || nodeName.length() != expectedName.length() + prefix.length() + 1) {
            return false;
        }

        return nodeName.startsWith(prefix) && nodeName.endsWith(expectedName)
                && nodeName.charAt(prefix.length()) == XML_NAMESPACE_DELIMITER;
    }
}