com.sqewd.os.maracache.core.Config.java Source code

Java tutorial

Introduction

Here is the source code for com.sqewd.os.maracache.core.Config.java

Source

/*
 * Copyright 2014 Subhabrata Ghosh
 *
 * 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 com.sqewd.os.maracache.core;

import org.apache.commons.lang.StringUtils;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;

/**
 * Container class for a XML parsed configuration object.
 * <p/>
 * Created by subghosh on 14/02/14.
 */
public class Config {
    private String filePath;
    private String configPath;
    private ConfigNode node;
    private EObjectState state = EObjectState.Unknown;

    /**
     * Construct the configuration handle with the configuration path specified.
     *
     * @param filePath   - XML file to load the configuration from.
     * @param configPath - XML path for loading the root configuration node.
     */
    public Config(String filePath, String configPath) {
        this.filePath = filePath;
        this.configPath = configPath;
    }

    /**
     * Get the file this configuration was loaded from.
     *
     * @return - Config file path.
     */
    public String getFilePath() {
        return filePath;
    }

    /**
     * Get the root configuration node.
     *
     * @return - Root configuration node.
     */
    public ConfigNode getNode() {
        return node;
    }

    /**
     * Search for a configuration element in the tree.
     *
     * @param path - Path to the configuration element. Paths are represented using the dot(.) notation. Example :
     *             name1.name2.name3
     * @return - Configuration node (path node or value). Null is returned if path not found.
     * @throws ConfigException
     */
    public ConfigNode search(String path) throws ConfigException {
        try {
            EObjectState.checkState(state, EObjectState.Available, this.getClass());
            if (node != null && (node instanceof ConfigPath)) {
                if (!StringUtils.isEmpty(path)) {
                    String[] parts = path.split("\\.");
                    if (parts != null && parts.length > 0) {
                        return ((ConfigPath) node).search(parts, 0);
                    }
                }
            }
        } catch (ObjectStateException ose) {
            throw new ConfigException(ose.getLocalizedMessage(), ose);
        }
        return null;
    }

    /**
     * Load the configuration from the path and file specified.
     *
     * @throws ConfigException
     */
    public void load() throws ConfigException {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(filePath);

            //optional, but recommended
            //read this - http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
            doc.getDocumentElement().normalize();

            XPath xp = XPathFactory.newInstance().newXPath();
            Element root = (Element) xp.compile(configPath).evaluate(doc, XPathConstants.NODE);
            if (root == null) {
                throw new ConfigException("Cannot find specified path in document. [path=" + configPath + "]");
            }

            node = new ConfigPath(root.getNodeName(), null);
            load(node, root);

            state = EObjectState.Available;
        } catch (ParserConfigurationException pse) {
            state = EObjectState.Exception;
            state.setException(pse);
            throw new ConfigException("Error building the configuration document.", pse);
        } catch (IOException ioe) {
            state = EObjectState.Exception;
            state.setException(ioe);
            throw new ConfigException("Error reading configuration file [path=" + filePath + "]", ioe);
        } catch (SAXException se) {
            state = EObjectState.Exception;
            state.setException(se);
            throw new ConfigException("Error parsing document [document=" + filePath + "]", se);
        } catch (XPathExpressionException xpe) {
            state = EObjectState.Exception;
            state.setException(xpe);
            throw new ConfigException("Error parsing specified XPath expression.", xpe);
        }
    }

    private ConfigPath load(ConfigNode parent, Element elm) throws ConfigException {
        if (parent instanceof ConfigPath) {
            // Check if there are any attributes.
            // Attributes are treated as Value nodes.
            if (elm.hasAttributes()) {
                NamedNodeMap map = elm.getAttributes();
                if (map.getLength() > 0) {
                    for (int ii = 0; ii < map.getLength(); ii++) {
                        Node n = map.item(ii);
                        ((ConfigPath) parent).addValueNode(n.getNodeName(), n.getNodeValue());
                    }
                }
            }
            if (elm.hasChildNodes()) {
                NodeList children = elm.getChildNodes();
                for (int ii = 0; ii < children.getLength(); ii++) {
                    Node cn = children.item(ii);
                    if (cn.getNodeType() == Node.ELEMENT_NODE) {
                        Element e = (Element) cn;
                        if (e.hasChildNodes()) {
                            int nc = 0;
                            for (int jj = 0; jj < e.getChildNodes().getLength(); jj++) {
                                Node ccn = e.getChildNodes().item(jj);
                                // Read the text node if there is any.
                                if (ccn.getNodeType() == Node.TEXT_NODE) {
                                    String n = e.getNodeName();
                                    String v = ccn.getNodeValue();
                                    if (!StringUtils.isEmpty(v.trim()))
                                        ((ConfigPath) parent).addValueNode(n, v);
                                    nc++;
                                }
                            }
                            // Make sure this in not a text only node.
                            if (e.getChildNodes().getLength() > nc) {
                                // Check if this is a parameter node. Parameters are treated differently.
                                if (e.getNodeName().compareToIgnoreCase(ConfigParams.NODE_NAME) == 0) {
                                    ConfigParams cp = ((ConfigPath) parent).addParamNode();
                                    setParams(cp, e);
                                } else {
                                    ConfigPath cp = ((ConfigPath) parent).addPathNode(e.getNodeName());
                                    load(cp, e);
                                }
                            }
                        }
                    }
                }
            }
        }
        return (ConfigPath) parent;
    }

    private void setParams(ConfigParams node, Element elm) {
        for (int ii = 0; ii < elm.getChildNodes().getLength(); ii++) {
            Node n = elm.getChildNodes().item(ii);
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                Element e = (Element) n;
                if (e.getNodeName().compareToIgnoreCase(ConfigParams.NODE_VALUE_NAME) == 0) {
                    String name = e.getAttribute(ConfigParams.NODE_ATTR_NAME);
                    String value = e.getAttribute(ConfigParams.NODE_ATTR_VALUE);
                    if (!StringUtils.isEmpty(name) && !StringUtils.isEmpty(value)) {
                        node.addParam(name, value);
                    }
                }
            }
        }
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("[FILE:").append(filePath).append("]\n");
        if (node != null) {
            sb.append(node.toString());
        }
        return sb.toString();
    }
}