com.xmlcalabash.util.JSONtoXML.java Source code

Java tutorial

Introduction

Here is the source code for com.xmlcalabash.util.JSONtoXML.java

Source

/*
QuiXProc: efficient evaluation of XProc Pipelines.
Copyright (C) 2011-2012 Innovimax
2008-2012 Mark Logic Corporation.
Portions Copyright 2007 Sun Microsystems, Inc.
All rights reserved.
    
This program 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 3
of the License, or (at your option) 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
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package com.xmlcalabash.util;

import java.util.Iterator;

import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.serialize.charcode.XMLCharacterData;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import com.xmlcalabash.core.XProcConstants;
import com.xmlcalabash.core.XProcException;

/**
 * Created by IntelliJ IDEA.
 * User: ndw
 * Date: 12/18/10
 * Time: 4:24 PM
 * To change this template use File | Settings | File Templates.
 */
public class JSONtoXML {
    public static final String CALABASH_DEPRECATED = "calabash-deprecated";
    public static final String CALABASH = "calabash";
    public static final String JSONX = "jsonx";
    public static final String JXML = "jxml";
    public static final String MARKLOGIC = "marklogic";

    public static final String JSONX_NS = "http://www.ibm.com/xmlns/prod/2009/jsonx";
    public static final String MLJS_NS = "http://marklogic.com/json";
    public static final String JXML_NS = "http://www.xmlsh.org/jxml";

    private static final QName _type = new QName("", "type");
    private static final QName _name = new QName("", "name");

    private static final QName c_json = new QName("c", XProcConstants.NS_XPROC_STEP, "json");
    private static final QName c_pair = new QName("c", XProcConstants.NS_XPROC_STEP, "pair");
    private static final QName c_item = new QName("c", XProcConstants.NS_XPROC_STEP, "item");

    private static final QName _json = new QName("json");
    private static final QName _pair = new QName("pair");
    private static final QName _item = new QName("item");

    private static final QName j_object = new QName("j", JSONX_NS, "object");
    private static final QName j_array = new QName("j", JSONX_NS, "array");
    private static final QName j_string = new QName("j", JSONX_NS, "string");
    private static final QName j_number = new QName("j", JSONX_NS, "number");
    private static final QName j_boolean = new QName("j", JSONX_NS, "boolean");
    private static final QName j_null = new QName("j", JSONX_NS, "null");

    private static final QName mj_json = new QName("j", MLJS_NS, "json");

    private static final QName jx_object = new QName("j", JXML_NS, "object");
    private static final QName jx_member = new QName("j", JXML_NS, "member");
    private static final QName jx_boolean = new QName("j", JXML_NS, "boolean");
    private static final QName jx_array = new QName("j", JXML_NS, "array");
    private static final QName jx_string = new QName("j", JXML_NS, "string");
    private static final QName jx_number = new QName("j", JXML_NS, "number");
    private static final QName jx_null = new QName("j", JXML_NS, "null");

    public static boolean knownFlavor(String jsonFlavor) {
        return (JSONtoXML.CALABASH_DEPRECATED.equals(jsonFlavor) || JSONtoXML.CALABASH.equals(jsonFlavor)
                || JSONtoXML.JSONX.equals(jsonFlavor) || JSONtoXML.JXML.equals(jsonFlavor)
                || JSONtoXML.MARKLOGIC.equals(jsonFlavor));
    }

    public static XdmNode convert(Processor processor, JSONTokener jt, String flavor) {
        TreeWriter tree = new TreeWriter(processor);
        tree.startDocument(null);

        if (JSONX.equals(flavor)) {
            buildJsonX(tree, jt);
        } else if (MARKLOGIC.equals(flavor)) {
            buildMarkLogic(tree, jt);
        } else if (JXML.equals(flavor)) {
            buildJxml(tree, jt);
        } else if (CALABASH.equals(flavor)) {
            buildMine(tree, jt, true);
        } else {
            buildMine(tree, jt, false);
        }

        tree.endDocument();
        return tree.getResult();
    }

    private static void buildJsonX(TreeWriter tree, JSONTokener jt) {
        try {
            char ch = jt.next();
            jt.back();

            if (ch == '{') {
                tree.addStartElement(j_object);
                tree.startContent();
                buildJsonXPairs(tree, new JSONObject(jt));
            } else {
                tree.addStartElement(j_array);
                buildJsonXArray(tree, new JSONArray(jt));
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }

        tree.addEndElement();
    }

    private static void buildJsonXPairs(TreeWriter tree, JSONObject jo) {
        try {
            Iterator keys = jo.keys();
            while (keys.hasNext()) {
                String name = (String) keys.next();
                Object json = jo.get(name);
                serializeJsonX(tree, json, name);
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }
    }

    private static void buildJsonXArray(TreeWriter tree, JSONArray arr) {
        try {
            for (int pos = 0; pos < arr.length(); pos++) {
                Object json = arr.get(pos);
                serializeJsonX(tree, json, null);
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }
    }

    private static void serializeJsonX(TreeWriter tree, Object json, String name) {
        if (json instanceof JSONObject) {
            tree.addStartElement(j_object);
            if (name != null) {
                tree.addAttribute(_name, name);
            }
            tree.startContent();
            buildJsonXPairs(tree, (JSONObject) json);
            tree.addEndElement();
        } else if (json instanceof JSONArray) {
            tree.addStartElement(j_array);
            if (name != null) {
                tree.addAttribute(_name, name);
            }
            tree.startContent();
            buildJsonXArray(tree, (JSONArray) json);
            tree.addEndElement();
        } else if (json instanceof Integer || json instanceof Double || json instanceof Long) {
            tree.addStartElement(j_number);
            if (name != null) {
                tree.addAttribute(_name, name);
            }
            tree.startContent();
            tree.addText(json.toString());
            tree.addEndElement();
        } else if (json instanceof String) {
            tree.addStartElement(j_string);
            if (name != null) {
                tree.addAttribute(_name, name);
            }
            tree.startContent();
            tree.addText(json.toString());
            tree.addEndElement();
        } else if (json instanceof Boolean) {
            tree.addStartElement(j_boolean);
            if (name != null) {
                tree.addAttribute(_name, name);
            }
            tree.startContent();
            tree.addText(json.toString());
            tree.addEndElement();
        } else if (json == JSONObject.NULL) {
            tree.addStartElement(j_null);
            if (name != null) {
                tree.addAttribute(_name, name);
            }
            tree.startContent();
            tree.addEndElement();
        } else {
            throw new XProcException("Unexpected type in JSON conversion.");
        }
    }

    private static void buildMarkLogic(TreeWriter tree, JSONTokener jt) {
        tree.addStartElement(mj_json);

        try {
            char ch = jt.next();
            jt.back();

            if (ch == '{') {
                tree.addAttribute(_type, "object");
                tree.startContent();
                buildMarkLogicPairs(tree, new JSONObject(jt));
            } else {
                tree.addAttribute(_type, "object");
                buildMarkLogicArray(tree, new JSONArray(jt));
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }

        tree.addEndElement();
    }

    private static void buildMarkLogicPairs(TreeWriter tree, JSONObject jo) {
        try {
            Iterator keys = jo.keys();
            while (keys.hasNext()) {
                String name = (String) keys.next();
                Object json = jo.get(name);
                serializeMarkLogic(tree, json, name);
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }
    }

    private static void buildMarkLogicArray(TreeWriter tree, JSONArray arr) {
        try {
            for (int pos = 0; pos < arr.length(); pos++) {
                Object json = arr.get(pos);
                serializeMarkLogic(tree, json, null);
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }
    }

    private static void serializeMarkLogic(TreeWriter tree, Object json, String name) {
        String localName = "item";
        if (name != null) {
            if ("".equals(name)) {
                localName = "_";
            } else {
                localName = "";
                for (int pos = 0; pos < name.length(); pos++) {
                    int ch = name.charAt(pos);
                    if ('_' != ch && ((pos == 0 && XMLCharacterData.isNCNameStart10(ch))
                            || (pos > 0 && XMLCharacterData.isNCName10(ch)))) {
                        localName += Character.toString((char) ch);
                    } else {
                        localName += String.format("_%04x", ch);
                    }
                }
            }
        }

        QName elemName = new QName("j", MLJS_NS, localName);
        tree.addStartElement(elemName);

        if (json instanceof JSONObject) {
            tree.addAttribute(_type, "object");
            tree.startContent();
            buildMarkLogicPairs(tree, (JSONObject) json);
        } else if (json instanceof JSONArray) {
            tree.addAttribute(_type, "array");
            tree.startContent();
            buildMarkLogicArray(tree, (JSONArray) json);
        } else if (json instanceof Integer || json instanceof Double || json instanceof Long) {
            tree.addAttribute(_type, "number");
            tree.startContent();
            tree.addText(json.toString());
        } else if (json instanceof String) {
            tree.addAttribute(_type, "string");
            tree.startContent();
            tree.addText(json.toString());
        } else if (json instanceof Boolean) {
            tree.addAttribute(_type, "boolean");
            tree.startContent();
            tree.addText(json.toString());
        } else if (json == JSONObject.NULL) {
            tree.addAttribute(_type, "null");
            tree.startContent();
        } else {
            throw new XProcException("Unexpected type in JSON conversion.");
        }

        tree.addEndElement();
    }

    private static void buildJxml(TreeWriter tree, JSONTokener jt) {
        try {
            char ch = jt.next();
            jt.back();

            if (ch == '{') {
                tree.addStartElement(jx_object);
                tree.startContent();
                buildJxmlPairs(tree, new JSONObject(jt));
            } else {
                tree.addStartElement(jx_array);
                buildJxmlArray(tree, new JSONArray(jt));
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }

        tree.addEndElement();
    }

    private static void buildJxmlPairs(TreeWriter tree, JSONObject jo) {
        try {
            Iterator keys = jo.keys();
            while (keys.hasNext()) {
                String name = (String) keys.next();
                Object json = jo.get(name);
                serializeJxml(tree, json, name);
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }
    }

    private static void buildJxmlArray(TreeWriter tree, JSONArray arr) {
        try {
            for (int pos = 0; pos < arr.length(); pos++) {
                Object json = arr.get(pos);
                serializeJxml(tree, json, null);
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }
    }

    private static void serializeJxml(TreeWriter tree, Object json, String name) {
        if (name != null) {
            tree.addStartElement(jx_member);
            tree.addAttribute(_name, name);
            tree.startContent();
        }

        if (json instanceof JSONObject) {
            tree.addStartElement(jx_object);
            tree.startContent();
            buildJxmlPairs(tree, (JSONObject) json);
            tree.addEndElement();
        } else if (json instanceof JSONArray) {
            tree.addStartElement(jx_array);
            tree.startContent();
            buildJxmlArray(tree, (JSONArray) json);
            tree.addEndElement();
        } else if (json instanceof Integer || json instanceof Double || json instanceof Long) {
            tree.addStartElement(jx_number);
            tree.startContent();
            tree.addText(json.toString());
            tree.addEndElement();
        } else if (json instanceof String) {
            tree.addStartElement(jx_string);
            tree.startContent();
            tree.addText(json.toString());
            tree.addEndElement();
        } else if (json instanceof Boolean) {
            tree.addStartElement(jx_boolean);
            tree.startContent();
            tree.addText(json.toString());
            tree.addEndElement();
        } else if (json == JSONObject.NULL) {
            tree.addStartElement(jx_null);
            tree.startContent();
            tree.addEndElement();
        } else {
            throw new XProcException("Unexpected type in JSON conversion.");
        }

        if (name != null) {
            tree.addEndElement();
        }
    }

    private static void buildMine(TreeWriter tree, JSONTokener jt, boolean usens) {
        tree.addStartElement(usens ? c_json : _json);

        try {
            char ch = jt.next();
            jt.back();

            if (ch == '{') {
                tree.addAttribute(_type, "object");
                tree.startContent();
                buildMyPairs(tree, new JSONObject(jt), usens);
            } else {
                tree.addAttribute(_type, "array");
                tree.startContent();
                buildMyArray(tree, new JSONArray(jt), usens);
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }

        tree.addEndElement();
    }

    private static void buildMyPairs(TreeWriter tree, JSONObject jo, boolean usens) {
        try {
            Iterator keys = jo.keys();
            while (keys.hasNext()) {
                String name = (String) keys.next();
                Object json = jo.get(name);
                tree.addStartElement(usens ? c_pair : _pair);
                tree.addAttribute(_name, name);

                if (json instanceof JSONObject) {
                    tree.addAttribute(_type, "object");
                    tree.startContent();
                    buildMyPairs(tree, (JSONObject) json, usens);
                } else if (json instanceof JSONArray) {
                    tree.addAttribute(_type, "array");
                    tree.startContent();
                    buildMyArray(tree, (JSONArray) json, usens);
                } else if (json instanceof Integer) {
                    tree.addAttribute(_type, "number");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json instanceof Double) {
                    tree.addAttribute(_type, "number");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json instanceof Long) {
                    tree.addAttribute(_type, "number");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json instanceof String) {
                    tree.addAttribute(_type, "string");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json instanceof Boolean) {
                    tree.addAttribute(_type, "boolean");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json == JSONObject.NULL) {
                    tree.addAttribute(_type, "null");
                    tree.startContent();
                } else {
                    throw new XProcException("Unexpected type in JSON conversion.");
                }

                tree.addEndElement();
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }
    }

    private static void buildMyArray(TreeWriter tree, JSONArray arr, boolean usens) {
        try {
            for (int pos = 0; pos < arr.length(); pos++) {
                Object json = arr.get(pos);

                tree.addStartElement(usens ? c_item : _item);

                if (json instanceof JSONObject) {
                    tree.addAttribute(_type, "object");
                    tree.startContent();
                    buildMyPairs(tree, (JSONObject) json, usens);
                } else if (json instanceof JSONArray) {
                    tree.addAttribute(_type, "array");
                    tree.startContent();
                    buildMyArray(tree, (JSONArray) json, usens);
                } else if (json instanceof Integer) {
                    tree.addAttribute(_type, "number");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json instanceof Double) {
                    tree.addAttribute(_type, "number");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json instanceof Long) {
                    tree.addAttribute(_type, "number");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json instanceof String) {
                    tree.addAttribute(_type, "string");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json instanceof Boolean) {
                    tree.addAttribute(_type, "boolean");
                    tree.startContent();
                    tree.addText(json.toString());
                } else if (json == JSONObject.NULL) {
                    tree.addAttribute(_type, "null");
                    tree.startContent();
                } else {
                    throw new XProcException("Unexpected type in JSON conversion.");
                }

                tree.addEndElement();
            }
        } catch (JSONException je) {
            throw new XProcException(je);
        }
    }

}