net.wastl.webmail.xml.XMLData.java Source code

Java tutorial

Introduction

Here is the source code for net.wastl.webmail.xml.XMLData.java

Source

/*
 * @(#)$Id: XMLData.java 111 2008-10-29 23:09:35Z unsaved $
 *
 * Copyright 2008 by the JWebMail Development Team and Sebastian Schaffert.
 *
 * 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 net.wastl.webmail.xml;

import javax.xml.transform.TransformerException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xpath.CachedXPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * A generic class for holding some XML data. This class provides means to
 * retrieve data based on XPath expressions.
 *
 * @author <a href="mailto:wastl@wastl.net">Sebastian Schaffert</a>
 */
public class XMLData {
    private static Log log = LogFactory.getLog(XMLData.class);
    protected Document root;
    protected Element data;
    protected CachedXPathAPI xpath_api;

    public XMLData() {
        xpath_api = new CachedXPathAPI();
    }

    public XMLData(Document d) {
        xpath_api = new CachedXPathAPI();
        this.root = d;
        this.data = d.getDocumentElement();
    }

    /**
     * Return a DOM representation of this Storable.
     */
    public Document getDocumentInstance() {
        return root;
    }

    public DocumentFragment getDocumentFragment() {
        DocumentFragment df = root.createDocumentFragment();
        df.appendChild(data);
        return df;
    }

    /**
     * Get the value of the node pointed to by xpath, beginning at the root
     * node.
     */
    public String getProperty(String xpath) {
        return getValueXPath(xpath);
    }

    /* -------------------------- Access Members ------------------------- */

    protected String getParentXPath(String str) {
        int last_slash = str.lastIndexOf("/");
        if (last_slash == -1) {
            return ".";
        } else {
            return str.substring(0, last_slash);
        }
    }

    /**
     * Return the node value of a single node selected by the given xpath
     * expression.
     */
    public String getValueXPath(String path) {
        data.normalize();
        Node n = null;
        try {
            n = xpath_api.selectSingleNode(data, path);
        } catch (Exception ex) {
            log.error("XPath failure for path '" + path + "'.  Continuing as if path not found.");
            // TODO:  throw
        }
        return (n == null) ? null : n.getNodeValue();
    }

    /**
     * Set the node value of the node selected by the given xpath expression.
     */
    public void setValueXPath(String path, String value) {
        data.normalize();
        try {
            Node n = xpath_api.selectSingleNode(data, path);
            if (n != null) {
                if (!n.getNodeValue().equals(value)) {
                    n.setNodeValue(value);
                    invalidateCache();
                }
            } else {
                addNodeXPath(getParentXPath(path), root.createTextNode(value));
            }
        } catch (TransformerException ex) {
            addNodeXPath(getParentXPath(path), root.createTextNode(value));
        } catch (Exception ex) {
            log.error("XML error when trying to set value '" + value + "' for path '" + path + "'");
            // TODO:  throw
        }
    }

    public Node getNodeXPath(String path) throws TransformerException {
        return xpath_api.selectSingleNode(data, path);
    }

    /**
     * Add a node as child to the node selected by the given xpath expression.
     */
    public void addNodeXPath(String path, Node child) {
        try {
            Node n = xpath_api.selectSingleNode(data, path);
            n.appendChild(child);
            invalidateCache();
        } catch (Exception ex) {
            // We get here SOMETIMES if there is no Sent folder to add
            // sent mail to.
            log.error("XPath threw for path '" + path + "', or adding to it.  " + "'" + path
                    + " is probably just missing though.  " + "Continuing without adding the child");
            // Log the Exception if there is more going on than missing Sent
            // folder.
            //XMLCommon.dumpXML(log, path, root);
            //TODO: throw
        }
    }

    public NodeList getNodeListXPath(String path) {
        try {
            NodeList n = xpath_api.selectNodeList(data, path);
            return n;
        } catch (Exception ex) {
            log.warn("'" + path + "' query threw, " + "but it's probably an XPath library bug.  "
                    + "Continuing as if no node found.");
        }
        return null;
    }

    /**
     * Invalidate the XPath cache as the source document has been modified and thus
     * it is necessary to update the tables.
     */
    protected void invalidateCache() {
        xpath_api = new CachedXPathAPI();
    }
}