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

br.com.digilabs.jqplot.support.JqPlotJsonMapHierarchicalWriter Maven / Gradle / Ivy

/*
 * Copyright (C) 2006 Joe Walnes.
 * Copyright (C) 2006, 2007, 2008 XStream Committers.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 * 
 * Created on 28. November 2008 by Joerg Schaible
 */
package br.com.digilabs.jqplot.support;

import br.com.digilabs.jqplot.JqPlotResources;

import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.core.util.FastStack;
import com.thoughtworks.xstream.core.util.Primitives;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriter;

import java.io.Writer;
import java.util.Collection;
import java.util.Map;

/**
 * 
 * @author Joe Walnes. / inaiat
 */
public class JqPlotJsonMapHierarchicalWriter implements ExtendedHierarchicalStreamWriter {

    /**
     * DROP_ROOT_MODE drops the JSON root node.
     * 

* The root node is the first level of the JSON object i.e. * *

     * { "person": {
     *     "name": "Joe"
     * }}
     * 
* * will be written without root simply as * *
     * {
     *     "name": "Joe"
     * }
     * 
* * Without a root node, the top level element might now also be an array. However, it is * possible to generate invalid JSON unless {@link #STRICT_MODE} is also set. *

* * @since 1.3.1 */ public static final int DROP_ROOT_MODE = 1; /** * STRICT_MODE prevents invalid JSON for single value objects when dropping the root. *

* The mode is only useful in combination with the {@link #DROP_ROOT_MODE}. An object with a * single value as first node i.e. * *

     * { "name": "Joe" }
     * 
* * is simply written as * *
     * "Joe"
     * 
* * However, this is no longer valid JSON. Therefore you can activate {@link #STRICT_MODE} * and a {@link ConversionException} is thrown instead. *

* * @since 1.3.1 */ public static final int STRICT_MODE = 2; private final QuickWriter writer; private final FastStack elementStack = new FastStack(16); private final char[] lineIndenter; private int depth; private boolean readyForNewLine; private boolean tagIsEmpty; private final String newLine; private int mode; /** * * @param writer * @param lineIndenter * @param newLine */ public JqPlotJsonMapHierarchicalWriter(Writer writer, char[] lineIndenter, String newLine) { this(writer, lineIndenter, newLine, 0); } /** * * @param writer * @param lineIndenter */ public JqPlotJsonMapHierarchicalWriter(Writer writer, char[] lineIndenter) { this(writer, lineIndenter, "\n"); } /** * * @param writer * @param lineIndenter * @param newLine */ public JqPlotJsonMapHierarchicalWriter(Writer writer, String lineIndenter, String newLine) { this(writer, lineIndenter.toCharArray(), newLine); } /** * * @param writer * @param lineIndenter */ public JqPlotJsonMapHierarchicalWriter(Writer writer, String lineIndenter) { this(writer, lineIndenter.toCharArray()); } /** * * @param writer */ public JqPlotJsonMapHierarchicalWriter(Writer writer) { this(writer, new char[]{' ', ' '}); } /** * @since 1.3.1 */ public JqPlotJsonMapHierarchicalWriter(Writer writer, char[] lineIndenter, String newLine, int mode) { this.writer = new QuickWriter(writer); this.lineIndenter = lineIndenter; this.newLine = newLine; this.mode = mode; } /** * Create a JsonWriter where the writer mode can be chosen. *

* Following constants can be used as bit mask: *

    *
  • {@link #DROP_ROOT_MODE}: drop the root node
  • *
  • {@link #STRICT_MODE}: do not throw {@link ConversionException}, if writer should * generate invalid JSON
  • *
*

* * @param writer the {@link Writer} where the JSON is written to * @param mode the JsonWriter mode * @since 1.3.1 */ public JqPlotJsonMapHierarchicalWriter(Writer writer, int mode) { this(writer, new char[]{' ', ' '}, "\n", mode); } /** * @deprecated since 1.2, use startNode(String name, Class clazz) instead. */ public void startNode(String name) { startNode(name, null); } /** * * @param name * @param clazz */ public void startNode(String name, Class clazz) { Node currNode = (Node)elementStack.peek(); if (currNode == null && ((mode & DROP_ROOT_MODE) == 0 || (depth > 0 && !isCollection(clazz)))) { writer.write("{"); } if (currNode != null && currNode.fieldAlready) { writer.write(","); readyForNewLine = true; } tagIsEmpty = false; finishTag(); if (currNode == null || currNode.clazz == null || (currNode.clazz != null && !currNode.isCollection)) { if (currNode != null && !currNode.fieldAlready) { writer.write("{"); readyForNewLine = true; finishTag(); } if ((mode & DROP_ROOT_MODE) == 0 || depth > 0) { writer.write("\""); writer.write(name); writer.write("\": "); } } if (isCollection(clazz)) { writer.write("["); readyForNewLine = true; } if (currNode != null) { currNode.fieldAlready = true; } elementStack.push(new Node(name, clazz)); depth++ ; tagIsEmpty = true; } /** * */ public class Node { public final String name; public final Class clazz; public boolean fieldAlready; public boolean isCollection; public Node(String name, Class clazz) { this.name = name; this.clazz = clazz; isCollection = isCollection(clazz); } } /** * * @param text */ public void setValue(String text) { Node currNode = (Node)elementStack.peek(); if (currNode != null && currNode.fieldAlready) { startNode("$", String.class); tagIsEmpty = false; writeText(text, String.class); endNode(); } else { if ((mode & (DROP_ROOT_MODE | STRICT_MODE)) == (DROP_ROOT_MODE | STRICT_MODE) && depth == 1) { throw new ConversionException("Single value cannot be JSON root element"); } readyForNewLine = false; tagIsEmpty = false; finishTag(); writeText(writer, text); } } /** * * @param key * @param value */ public void addAttribute(String key, String value) { Node currNode = (Node)elementStack.peek(); if (currNode == null || !currNode.isCollection) { startNode('@' + key, String.class); tagIsEmpty = false; writeText(value, String.class); endNode(); } } /** * * @param writer * @param text */ protected void writeAttributeValue(QuickWriter writer, String text) { writeText(text, null); } /** * * @param writer * @param text */ protected void writeText(QuickWriter writer, String text) { Node foo = (Node)elementStack.peek(); writeText(text, foo.clazz); } /** * * @param text * @param clazz */ private void writeText(String text, Class clazz) { boolean isJqPlotResource = clazz.isAssignableFrom(JqPlotResources.class); if (!isJqPlotResource && needsQuotes(clazz)) { writer.write("\""); } if ((clazz == Character.class || clazz == Character.TYPE) && "".equals(text)) { text = "\0"; } int length = text.length(); for (int i = 0; i < length; i++ ) { char c = text.charAt(i); switch (c) { case '"': this.writer.write("\\\""); break; case '\\': this.writer.write("\\\\"); break; default: if (c > 0x1f) { this.writer.write(c); } else { this.writer.write("\\u"); String hex = "000" + Integer.toHexString(c); this.writer.write(hex.substring(hex.length() - 4)); } } } if (!isJqPlotResource && needsQuotes(clazz)) { writer.write("\""); } } /** * * @param clazz * @return */ private boolean isCollection(Class clazz) { return clazz != null && (Collection.class.isAssignableFrom(clazz) || clazz.isArray() || Map.class.isAssignableFrom(clazz) || Map.Entry.class.isAssignableFrom(clazz)); } /** * * @param clazz * @return */ private boolean needsQuotes(Class clazz) { clazz = clazz != null && clazz.isPrimitive() ? clazz : Primitives.unbox(clazz); return clazz == null || clazz == Character.TYPE; } /** * */ public void endNode() { depth-- ; Node node = (Node)elementStack.pop(); if (node.clazz != null && node.isCollection) { if (node.fieldAlready) { readyForNewLine = true; } finishTag(); writer.write("]"); } else if (tagIsEmpty) { readyForNewLine = false; writer.write("{}"); finishTag(); } else { finishTag(); if (node.fieldAlready) { writer.write("}"); } } readyForNewLine = true; if (depth == 0 && ((mode & DROP_ROOT_MODE) == 0 || (depth > 0 && !node.isCollection))) { writer.write("}"); writer.flush(); } } /** * */ private void finishTag() { if (readyForNewLine) { endOfLine(); } readyForNewLine = false; tagIsEmpty = false; } /** * */ protected void endOfLine() { writer.write(newLine); for (int i = 0; i < depth; i++ ) { writer.write(lineIndenter); } } /** * */ public void flush() { writer.flush(); } /** * */ public void close() { writer.close(); } /** * * @return */ public HierarchicalStreamWriter underlyingWriter() { return this; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy