All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.freeutils.util.config.XMLConfiguration Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright © 2003-2024 Amichai Rothman
 *
 *  This file is part of JElementary - the Java Elementary Utilities package.
 *
 *  JElementary is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  JElementary 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with JElementary.  If not, see .
 *
 *  For additional info see https://www.freeutils.net/source/jelementary/
 */

package net.freeutils.util.config;

import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;

/**
 * The {@code XMLConfiguration} class encapsulates a configuration section
 * with an XML file as the underlying implementation.
 */
public class XMLConfiguration extends Configuration {

    /**
     * Constructs an XMLConfiguration by parsing an XML stream.
     * The encoding used is the one found in the XML header, or UTF-8 if no header exists.
     *
     * @param in the XML stream containing the configuration data
     * @throws IOException if an error occurs
     */
    public XMLConfiguration(InputStream in) throws IOException {
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(in);
            Element root = doc.getDocumentElement();
            name = root.getTagName();
            read(root, this);
        } catch (Exception e) {
            throw new IOException("error reading XML data", e);
        } finally {
            in.close();
        }
    }

    /**
     * Constructs an XMLConfiguration by parsing an XML file.
     * The encoding used is the one found in the XML header, or UTF-8 if no header exists.
     *
     * @param filename the XML file containing the configuration data
     * @throws IOException if an error occurs
     */
    public XMLConfiguration(String filename) throws IOException {
        this(new FileInputStream(filename));
    }

    /**
     * Reads the given element data into the given configuration section.
     *
     * @param el the element to read
     * @param conf the configuration section into which the data is read
     * @throws IOException if an error occurs
     * @throws ConfigurationException if a configuration error occurs
     */
    protected static void read(Element el, Configuration conf) throws IOException, ConfigurationException {
        addAttributes(el, conf);
        addChildren(el, conf);
    }

    /**
     * Adds all attributes of the given element into the given configuration section.
     *
     * @param el the element whose attributes are to be read
     * @param conf the configuration section into which the data is read
     */
    private static void addAttributes(Element el, Configuration conf) {
        NamedNodeMap attributes = el.getAttributes();
        if (attributes != null) {
            for (int i = 0; i < attributes.getLength(); i++)
                addTextNode(attributes.item(i), conf);
        }
    }

    /**
     * Adds all children of the given element into the given configuration section, recursively.
     *
     * @param el the element whose children are to be read
     * @param conf the configuration section into which the data is read
     * @throws IOException if an error occurs
     */
    private static void addChildren(Element el, Configuration conf) throws IOException {
        NodeList children = el.getChildNodes();
        if (children == null)
            return;
        for (int i = 0; i < children.getLength(); i++)
            addNode(children.item(i), conf);
        // a text child always exists, so we remove it unless it's the
        // only child, in which case it becomes the actual value
        if (conf.items.size() > 1)
            conf.items.remove("#text");
    }

    /**
     * Adds the data in the given node into the given configuration section, recursively.
     *
     * @param n the node containing the data
     * @param conf the configuration section into which the data is read
     * @throws IOException if an error occurs
     */
    private static void addNode(Node n, Configuration conf) throws IOException {
        switch (n.getNodeType()) {
            case Node.ELEMENT_NODE:
                addElementNode((Element)n, conf);
                break;
            case Node.TEXT_NODE:
                addTextNode(n, conf);
                break;
            // ignore comments and other types of nodes
        }
    }

    /**
     * Adds the data in the given element into the given configuration section, recursively.
     *
     * @param el the element containing the data
     * @param conf the configuration section into which the data is read
     * @throws IOException if an error occurs
     */
    private static void addElementNode(Element el, Configuration conf) throws IOException {
        String nodeName = el.getNodeName();
        Configuration c = new Configuration(nodeName);
        read(el, c);
        if (c.items.size() == 1 && c.items.containsKey("#text"))
            conf.add(nodeName, c.get("#text")); // only text
        else
            conf.add(nodeName, c); // a nested section
    }

    /**
     * Adds the text in the given node into the given configuration section.
     *
     * @param n the node containing the text
     * @param conf the configuration section into which the data is read
     */
    private static void addTextNode(Node n, Configuration conf) {
        conf.add(n.getNodeName(), n.getNodeValue());
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy