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

com.github.peterbecker.configuration.storage.XmlStore Maven / Gradle / Ivy

package com.github.peterbecker.configuration.storage;

import com.github.peterbecker.configuration.ConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
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;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

/**
 * A Store implemented through an XML object.
 */
public class XmlStore implements Store {
    private final Document doc;

    public XmlStore(Path resource) throws IOException {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            this.doc = db.parse(Files.newInputStream(resource));
        } catch (ParserConfigurationException e) {
            throw new RuntimeException("Unexpected internal error.", e);
        } catch (SAXException e) {
            throw new IOException("Could not parse XML file.", e);
        }
    }

    @Override
    public Optional getValue(Key key) throws ConfigurationException {
        String contextPath = getContextPath(key.getContext());
        try {
            XPath xpath = XPathFactory.newInstance().newXPath();
            NodeList nodes = (NodeList) xpath.evaluate(contextPath + "/" + getLocalPath(key), doc, XPathConstants.NODESET);
            if (nodes.getLength() == 0) {
                if(key.isIndexed()) {
                    return Optional.empty();
                }
                nodes = (NodeList) xpath.evaluate(contextPath + "/@" + key.getOptionName(), doc, XPathConstants.NODESET);
                if (nodes.getLength() == 0) {
                    return Optional.empty();
                }
            }
            if (nodes.getLength() > 1) {
                throw new ConfigurationException("More than one node matches " + contextPath);
            }
            return Optional.of(nodes.item(0).getTextContent());
        } catch (XPathExpressionException e) {
            throw new ConfigurationException("Can not identify node at " + contextPath, e);
        }
    }

    private String getContextPath(Key key) {
        if (key == Key.ROOT) {
            return "/*";
        } else {

            return getContextPath(key.getContext()) + "/" + getLocalPath(key);
        }
    }

    private String getLocalPath(Key key) {
        return key.getOptionName() + (key.isIndexed() ? "[" + (key.getIndex() + 1) + "]" : "");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy