org.rapidcontext.core.data.XmlSerializer.java Source code

Java tutorial

Introduction

Here is the source code for org.rapidcontext.core.data.XmlSerializer.java

Source

/*
 * RapidContext <http://www.rapidcontext.com/>
 * Copyright (c) 2007-2013 Per Cederberg. All rights reserved.
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the BSD license.
 *
 * 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 RapidContext LICENSE for more details.
 */

package org.rapidcontext.core.data;

import java.util.Date;

import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;
import org.rapidcontext.core.storage.StorableObject;
import org.rapidcontext.util.StringUtil;

/**
 * A data serializer for XML. This class currently only attempts to
 * render a machine-readable version of a data object, without any
 * efforts of parsing input data. The following basic requirements
 * must be met in order to serialize an object:
 *
 * <ul>
 *   <li>No circular references are permitted.
 *   <li>String, Integer, Boolean, Array and Dict objects are supported.
 *   <li>Key names must only consist of valid XML tag characters.
 * </ul>
 *
 * @author   Per Cederberg
 * @version  1.0
 */
public class XmlSerializer {

    /**
     * Serializes an object into an XML representation. The string
     * returned is a stand-alone XML document marked as being in the
     * UTF-8 charset.
     *
     * @param id             the data identifier
     * @param obj            the object to convert, or null
     *
     * @return an XML representation
     */
    public static String serialize(String id, Object obj) {
        StringBuilder buffer = new StringBuilder();
        buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        serialize(id, obj, 0, buffer);
        buffer.append("\n");
        return buffer.toString();
    }

    /**
     * Serializes an object into an XML representation.
     *
     * @param id             the data identifier
     * @param obj            the object to convert
     * @param indent         the current indentation level
     * @param buffer         the string buffer to append into
     */
    private static void serialize(String id, Object obj, int indent, StringBuilder buffer) {
        if (obj == null) {
            buffer.append("<");
            tagName(id, buffer);
            buffer.append(" type=\"null\"/>");
        } else if (obj instanceof Dict) {
            serialize(id, (Dict) obj, indent, buffer);
        } else if (obj instanceof Array) {
            serialize(id, (Array) obj, indent, buffer);
        } else if (obj instanceof Date) {
            tagStart(id, "date", buffer);
            buffer.append("@" + ((Date) obj).getTime());
            tagEnd(id, buffer);
        } else if (obj instanceof Class) {
            tagStart(id, "class", buffer);
            buffer.append(StringUtil.escapeXml(((Class) obj).getName()));
            tagEnd(id, buffer);
        } else if (obj instanceof StorableObject) {
            serialize(id, ((StorableObject) obj).serialize(), indent, buffer);
        } else {
            tagStart(id, null, buffer);
            buffer.append(StringUtil.escapeXml(obj.toString()));
            tagEnd(id, buffer);
        }
    }

    /**
     * Serializes a dictionary into an XML representation.
     *
     * @param id             the data identifier
     * @param dict           the dictionary to convert
     * @param indent         the current indentation level
     * @param buffer         the string buffer to append into
     */
    private static void serialize(String id, Dict dict, int indent, StringBuilder buffer) {
        String[] keys = dict.keys();
        tagStart(id, "object", buffer);
        for (int i = 0; i < keys.length; i++) {
            buffer.append("\n");
            buffer.append(StringUtils.repeat("  ", indent + 1));
            serialize(keys[i], dict.get(keys[i]), indent + 1, buffer);
        }
        buffer.append("\n");
        buffer.append(StringUtils.repeat("  ", indent));
        tagEnd(id, buffer);
    }

    /**
     * Serializes an array into an XML representation.
     *
     * @param id             the data identifier
     * @param arr            the array to convert
     * @param indent         the current indentation level
     * @param buffer         the string buffer to append into
     */
    private static void serialize(String id, Array arr, int indent, StringBuilder buffer) {
        tagStart(id, "array", buffer);
        for (int i = 0; i < arr.size(); i++) {
            buffer.append("\n");
            buffer.append(StringUtils.repeat("  ", indent + 1));
            serialize("item", arr.get(i), indent + 1, buffer);
        }
        buffer.append("\n");
        buffer.append(StringUtils.repeat("  ", indent));
        tagEnd(id, buffer);
    }

    /**
     * Writes an XML start tag.
     *
     * @param id             the tag name (identifier)
     * @param type           the data type, or null for none
     * @param buffer         the string buffer to append into
     */
    private static void tagStart(String id, String type, StringBuilder buffer) {
        buffer.append("<");
        tagName(id, buffer);
        if (type != null) {
            buffer.append(" type=\"");
            buffer.append(type);
            buffer.append("\"");
        }
        buffer.append(">");
    }

    /**
     * Writes an XML end tag.
     *
     * @param id             the tag name (identifier)
     * @param buffer         the string buffer to append into
     */
    private static void tagEnd(String id, StringBuilder buffer) {
        buffer.append("</");
        tagName(id, buffer);
        buffer.append(">");
    }

    /**
     * Writes an XML tag name.
     *
     * @param id             the tag name (identifier)
     * @param buffer         the string buffer to append into
     */
    private static void tagName(String id, StringBuilder buffer) {
        for (int i = 0; i < id.length(); i++) {
            char c = id.charAt(i);
            if (i == 0 && !CharUtils.isAsciiAlpha(c)) {
                c = '_';
            } else if (!CharUtils.isAsciiAlphanumeric(c)) {
                c = '_';
            }
            buffer.append(c);
        }
    }
}