001/* ======================================================
002 * JFreeChart : a chart library for the Java(tm) platform
003 * ======================================================
004 *
005 * (C) Copyright 2000-present, by David Gilbert and Contributors.
006 *
007 * Project Info:  https://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 * --------------
028 * JSONUtils.java
029 * --------------
030 * (C) Copyright 2014-present, by David Gilbert.
031 *
032 * Original Author:  David Gilbert;
033 * Contributor(s):   -;
034 *
035 */
036
037package org.jfree.data.json;
038
039import java.io.IOException;
040import java.io.StringWriter;
041import java.io.Writer;
042import java.util.Iterator;
043import java.util.List;
044import org.jfree.chart.util.Args;
045import org.jfree.data.KeyedValues;
046import org.jfree.data.KeyedValues2D;
047import org.jfree.data.category.CategoryDataset;
048import org.jfree.data.general.PieDataset;
049import org.jfree.data.json.impl.JSONValue;
050
051/**
052 * A utility class that can read and write data in specific JSON formats.
053 */
054public class JSONUtils {
055
056    private JSONUtils() {
057        // no requirement for instantiation
058    }
059
060    /**
061     * Returns a string containing the data in JSON format.  The format is
062     * an array of arrays, where each sub-array represents one data value.
063     * The sub-array should contain two items, first the item key as a string
064     * and second the item value as a number.  For example:
065     * {@code [["Key A", 1.0], ["Key B", 2.0]]}
066     * <br><br>
067     * Note that this method can be used with instances of {@link PieDataset}.
068     * 
069     * @param data  the data ({@code null} not permitted).
070     * 
071     * @return A string in JSON format. 
072     */
073    public static String writeKeyedValues(KeyedValues data) {
074        Args.nullNotPermitted(data, "data");
075        StringWriter sw = new StringWriter();
076        try {
077            writeKeyedValues(data, sw);
078        } catch (IOException ex) {
079            throw new RuntimeException(ex);
080        }
081        return sw.toString();
082    }
083
084    /**
085     * Writes the data in JSON format to the supplied writer.
086     * <br><br>
087     * Note that this method can be used with instances of {@link PieDataset}.
088     * 
089     * @param data  the data ({@code null} not permitted).
090     * @param writer  the writer ({@code null} not permitted).
091     * 
092     * @throws IOException if there is an I/O problem.
093     */
094    public static void writeKeyedValues(KeyedValues data, Writer writer) 
095            throws IOException {
096        Args.nullNotPermitted(data, "data");
097        Args.nullNotPermitted(writer, "writer");
098        writer.write("[");
099        boolean first = true;
100        Iterator iterator = data.getKeys().iterator();
101        while (iterator.hasNext()) {
102            Comparable key = (Comparable) iterator.next();
103            if (!first) {
104                writer.write(", ");
105            } else {
106                first = false;
107            }
108            writer.write("[");
109            writer.write(JSONValue.toJSONString(key.toString()));
110            writer.write(", ");
111            writer.write(JSONValue.toJSONString(data.getValue(key)));
112            writer.write("]");
113        }
114        writer.write("]");
115    }
116    
117    /**
118     * Returns a string containing the data in JSON format.  The format is...
119     * <br><br>
120     * Note that this method can be used with instances of 
121     * {@link CategoryDataset}.
122     * 
123     * @param data  the data ({@code null} not permitted).
124     * 
125     * @return A string in JSON format. 
126     */
127    public static String writeKeyedValues2D(KeyedValues2D data) {
128        Args.nullNotPermitted(data, "data");
129        StringWriter sw = new StringWriter();
130        try {
131            writeKeyedValues2D(data, sw);
132        } catch (IOException ex) {
133            throw new RuntimeException(ex);
134        }
135        return sw.toString();
136    }
137
138    /**
139     * Writes the data in JSON format to the supplied writer.
140     * <br><br>
141     * Note that this method can be used with instances of 
142     * {@link CategoryDataset}.
143     * 
144     * @param data  the data ({@code null} not permitted).
145     * @param writer  the writer ({@code null} not permitted).
146     * 
147     * @throws IOException if there is an I/O problem.
148     */
149    public static void writeKeyedValues2D(KeyedValues2D data, Writer writer) 
150            throws IOException {
151        Args.nullNotPermitted(data, "data");
152        Args.nullNotPermitted(writer, "writer");
153        List<Comparable<?>> columnKeys = data.getColumnKeys();
154        List<Comparable<?>> rowKeys = data.getRowKeys();
155        writer.write("{");
156        if (!columnKeys.isEmpty()) {
157            writer.write("\"columnKeys\": [");
158            boolean first = true;
159            for (Comparable<?> columnKey : columnKeys) {
160                if (!first) {
161                    writer.write(", ");
162                } else {
163                    first = false;
164                }
165                writer.write(JSONValue.toJSONString(columnKey.toString()));
166            }
167            writer.write("]");
168        }
169        if (!rowKeys.isEmpty()) {
170            writer.write(", \"rows\": [");
171            boolean firstRow = true;
172            for (Comparable<?> rowKey : rowKeys) {   
173                if (!firstRow) {
174                    writer.write(", [");
175                } else {
176                    writer.write("[");
177                    firstRow = false;
178                }
179                // write the row data 
180                writer.write(JSONValue.toJSONString(rowKey.toString()));
181                writer.write(", [");
182                boolean first = true;
183                for (Comparable<?> columnKey : columnKeys) {
184                    if (!first) {
185                        writer.write(", ");
186                    } else {
187                        first = false;
188                    }
189                    writer.write(JSONValue.toJSONString(data.getValue(rowKey, 
190                            columnKey)));
191                }
192                writer.write("]]");
193            }
194            writer.write("]");
195        }
196        writer.write("}");    
197    }
198    
199}