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

org.integratedmodelling.utils.xml.XML Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *  Copyright (C) 2007, 2014:
 *  
 *    - Ferdinando Villa 
 *    - integratedmodelling.org
 *    - any other authors listed in @author annotations
 *
 *    All rights reserved. This file is part of the k.LAB software suite,
 *    meant to enable modular, collaborative, integrated 
 *    development of interoperable data and model components. For
 *    details, see http://integratedmodelling.org.
 *    
 *    This program is free software; you can redistribute it and/or
 *    modify it under the terms of the Affero General Public License 
 *    Version 3 or any later version.
 *
 *    This program 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
 *    Affero General Public License for more details.
 *  
 *     You should have received a copy of the Affero General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *     The license is also available at: https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.utils.xml;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.swing.tree.DefaultMutableTreeNode;

import org.integratedmodelling.collections.Pair;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabValidationException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Make XML encoding as fun as possible using a functional style. Also automatically
 * converts (suitable) polylists to XML nodes.
 * 
 * Example:
 * 
 * XML.document("myns=http://my.namespace.org/ns"
 * 		XML.node("root",
 * 			XML.node("myns:content1", "Hi!")
 * 			XML.node("myns:content2", "Hi!")
 * 			XML.node("myns:content3", "Hi!")
 *      )).write("file.xml");
 * 
 * @author Ferdinando Villa
 * @see HTML for an HTML-specialized version.
 */
public class XML {

    public static class XmlNode extends DefaultMutableTreeNode {

        boolean isCdata = false;
        private static final long serialVersionUID = -3750169814447901831L;
        String tag = null;
        ArrayList> attrs = null;
        ArrayList contents = new ArrayList();

        protected XmlNode() {
        }

        public XmlNode attr(String s, String v) {
            if (attrs == null)
                attrs = new ArrayList>();
            attrs.add(new Pair(s, v));
            return this;
        }

        public void text(String text) {
            contents.add(text);
        }

        public XmlNode(String tag) {
            this.tag = tag;
        }

        Node create(Node parent, Document doc) throws KlabException {

            Node ret = doc.createElement(tag);

            if (attrs != null)
                for (Pair a : attrs) {
                    Attr attr = doc.createAttribute(a.getFirst());
                    attr.setValue(a.getSecond());
                    ((Element) ret).setAttributeNode(attr);
                }

            for (Object o : contents) {

                if (o instanceof String) {
                    String text = (String) o;
                    ret.setTextContent(text);
                } else if (o instanceof Collection) {
                    for (Iterator it = ((Collection) o).iterator(); it.hasNext();) {
                        Object no = it.next();
                        if (!(no instanceof XmlNode)) {
                            throw new KlabValidationException("XML.node: collections must be of XmlNode");
                        }
                        ret.appendChild(((XmlNode) no).create(ret, doc));
                    }
                } else if (o instanceof XmlNode) {
                    ret.appendChild(((XmlNode) o).create(ret, doc));
                }
            }

            return ret;
        }

        void define(Node self, Document doc) throws KlabException {

            if (attrs != null)
                for (Pair a : attrs) {
                    Attr attr = doc.createAttribute(a.getFirst());
                    attr.setValue(a.getSecond());
                    ((Element) self).setAttributeNode(attr);
                }

            for (Object o : contents) {

                if (o instanceof String) {
                    String text = (String) o;
                    self.setTextContent(text);
                } else if (o instanceof Collection) {
                    for (Iterator it = ((Collection) o).iterator(); it.hasNext();) {
                        Object no = it.next();
                        if (no instanceof XmlNode) {
                            self.appendChild(((XmlNode) no).create(self, doc));
                        } /* else if (no instanceof IList) {
                          self.appendChild(((IList)no).createXmlNode().create(self, doc));
                          } */else {
                            throw new KlabValidationException(
                                    "XML.node: collections must be of XmlNode or Polylist");
                        }
                    }
                } else if (o instanceof XmlNode) {
                    self.appendChild(((XmlNode) o).create(self, doc));
                } /* else if (o instanceof IList) {
                  self.appendChild(((IList)o).createXmlNode().create(self, doc));					
                  }  */
            }
        }
    }

    public static XMLDocument document(Object... objects) throws KlabException {

        XmlNode root = null;
        ArrayList namespaces = null;

        for (Object o : objects) {
            if (o instanceof String) {

                /*
                 * namespace
                 */
                if (namespaces == null)
                    namespaces = new ArrayList();

                //namespaces.add((String)o);

            } else if (o instanceof XmlNode) {

                /*
                 * must be only root node
                 */
                if (root != null)
                    throw new KlabValidationException("XML document: non-unique root node");
                root = (XmlNode) o;

            }
        }

        if (root == null)
            throw new KlabValidationException("XML.document: no root node specified");

        XMLDocument doc = new XMLDocument(root.tag);

        if (namespaces != null) {
            for (String ns : namespaces) {
                String[] nss = ns.split("=");
                if (nss.length != 2)
                    throw new KlabValidationException(
                            "XML.document: bad namespace specification: must be name=uri: " + ns);
                doc.addNamespace(nss[0], nss[1]);
            }
        }

        root.define(doc.root(), doc.dom);

        return doc;
    }

    public static XmlNode node(String tag, Object... objects) throws KlabException {

        XmlNode ret = new XmlNode(tag);

        if (objects == null)
            return ret;

        for (Object o : objects) {
            ret.contents.add(o);
        }

        return ret;
    }

    /*
     * used only to implement derived classes such as HTML or GeoRSS
     */
    protected static XmlNode node(XmlNode ret, String tag, Object... objects) throws KlabException {

        ret.tag = tag;

        if (objects == null)
            return ret;

        for (Object o : objects) {
            ret.contents.add(o);
        }

        return ret;
    }

    public static String cdata(String text) {
        // TODO make this a proxy for a proper node - this will convert the <> to entities
        return "";
    }

}