source: tags/MetisMQIDemo/src/main/java/weka/core/json/JSONNode.java

Last change on this file was 29, checked in by gnappo, 15 years ago

Taggata versione per la demo e aggiunto branch.

File size: 14.1 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 * JSONObject.java
19 * Copyright (C) 2009 University of Waikato, Hamilton, New Zealand
20 */
21
22package weka.core.json;
23
24import java.awt.BorderLayout;
25import java.io.Reader;
26
27import java_cup.runtime.DefaultSymbolFactory;
28import java_cup.runtime.SymbolFactory;
29
30import javax.swing.JFrame;
31import javax.swing.JScrollPane;
32import javax.swing.JTree;
33import javax.swing.tree.DefaultMutableTreeNode;
34
35/**
36 * Container class for storing a <a href="http://www.json.org/" target="_blank">JSON</a>
37 * data structure.
38 *
39 * @author  FracPete (fracpete at waikato dot ac dot nz)
40 * @version $Revision: 5786 $
41 */
42public class JSONNode
43  extends DefaultMutableTreeNode {
44
45  /** for serialization. */
46  private static final long serialVersionUID = -3047440914507883491L;
47
48  /**
49   * The type of a node.
50   *
51   * @author  FracPete (fracpete at waikato dot ac dot nz)
52   * @version $Revision: 5786 $
53   */
54  public static enum NodeType {
55    /** a primitive. */
56    PRIMITIVE,
57    /** an object with nested key-value pairs. */
58    OBJECT,
59    /** an array. */
60    ARRAY
61  }
62 
63  /** the name of the node. */
64  protected String m_Name;
65 
66  /** the value of the node. */
67  protected Object m_Value;
68 
69  /** the type of the node. */
70  protected NodeType m_NodeType;
71 
72  /**
73   * Initializes the root container.
74   */
75  public JSONNode() {
76    this(null, NodeType.OBJECT);
77  }
78 
79  /**
80   * Initializes the primitive container.
81   *
82   * @param name        the name
83   * @param value       the primitive value
84   */
85  public JSONNode(String name, Boolean value) {
86    this(name, value, NodeType.PRIMITIVE);
87  }
88 
89  /**
90   * Initializes the primitive container.
91   *
92   * @param name        the name
93   * @param value       the primitive value
94   */
95  public JSONNode(String name, Integer value) {
96    this(name, value, NodeType.PRIMITIVE);
97  }
98 
99  /**
100   * Initializes the primitive container.
101   *
102   * @param name        the name
103   * @param value       the primitive value
104   */
105  public JSONNode(String name, Double value) {
106    this(name, value, NodeType.PRIMITIVE);
107  }
108 
109  /**
110   * Initializes the primitive container.
111   *
112   * @param name        the name
113   * @param value       the primitive value
114   */
115  public JSONNode(String name, String value) {
116    this(name, value, NodeType.PRIMITIVE);
117  }
118 
119  /**
120   * Initializes the object container with null value.
121   *
122   * @param name        the name
123   * @param type        the node type
124   */
125  protected JSONNode(String name, NodeType type) {
126    this(name, null, type);
127  }
128 
129  /**
130   * Initializes the container.
131   *
132   * @param name        the name
133   * @param value       the primitive value
134   * @param type        the type of the node, null for primitives
135   */
136  protected JSONNode(String name, Object value, NodeType type) {
137    super();
138   
139    m_Name     = name;
140    m_Value    = value;
141    m_NodeType = type;
142  }
143 
144  /**
145   * Checks whether the node is anonymous.
146   *
147   * @return            true if no name available
148   */
149  public boolean isAnonymous() {
150    return (m_Name == null);
151  }
152 
153  /**
154   * Returns the name of the node.
155   *
156   * @return            the name, null for anonymous nodes
157   */
158  public String getName() {
159    return m_Name;
160  }
161 
162  /**
163   * Returns the stored value.
164   *
165   * @return            the stored value, can be null
166   */
167  public Object getValue() {
168    return getValue(null);
169  }
170 
171  /**
172   * Returns the stored value.
173   *
174   * @param defValue    the default value, if value is null
175   * @return            the stored value, can be null
176   */
177  public Object getValue(Object defValue) {
178    if (m_Value == null)
179      return defValue;
180    else
181      return m_Value;
182  }
183 
184  /**
185   * Returns whether the node stores a primitive value or a an array/object.
186   *
187   * @return            true if a primitive, false in case of an array/object
188   */
189  public boolean isPrimitive() {
190    return (m_NodeType == NodeType.PRIMITIVE);
191  }
192 
193  /**
194   * Returns wether the node is an array.
195   *
196   * @return            true if the node is array container
197   */
198  public boolean isArray() {
199    return (m_NodeType == NodeType.ARRAY);
200  }
201 
202  /**
203   * Returns wether the node is an object.
204   *
205   * @return            true if the node is object container
206   */
207  public boolean isObject() {
208    return (m_NodeType == NodeType.OBJECT);
209  }
210 
211  /**
212   * Returns the type of the container.
213   *
214   * @return            the type
215   */
216  public NodeType getNodeType() {
217    return m_NodeType;
218  }
219 
220  /**
221   * Adds a "null" child to the object.
222   *
223   * @param name        the name of the null value
224   * @return            the new node, or null if none added
225   */
226  public JSONNode addNull(String name) {
227    return add(name, null, NodeType.PRIMITIVE);
228  }
229 
230  /**
231   * Adds a key-value child to the object.
232   *
233   * @param name        the name of the pair
234   * @param value       the value
235   * @return            the new node, or null if none added
236   */
237  public JSONNode addPrimitive(String name, Boolean value) {
238    return add(name, value, NodeType.PRIMITIVE);
239  }
240 
241  /**
242   * Adds a key-value child to the object.
243   *
244   * @param name        the name of the pair
245   * @param value       the value
246   * @return            the new node, or null if none added
247   */
248  public JSONNode addPrimitive(String name, Integer value) {
249    return add(name, value, NodeType.PRIMITIVE);
250  }
251 
252  /**
253   * Adds a key-value child to the object.
254   *
255   * @param name        the name of the pair
256   * @param value       the value
257   * @return            the new node, or null if none added
258   */
259  public JSONNode addPrimitive(String name, Double value) {
260    return add(name, value, NodeType.PRIMITIVE);
261  }
262 
263  /**
264   * Adds a key-value child to the object.
265   *
266   * @param name        the name of the pair
267   * @param value       the value
268   * @return            the new node, or null if none added
269   */
270  public JSONNode addPrimitive(String name, String value) {
271    return add(name, value, NodeType.PRIMITIVE);
272  }
273 
274  /**
275   * Adds an array child to the object.
276   *
277   * @param name        the name of the pair
278   * @return            the new node, or null if none added
279   */
280  public JSONNode addArray(String name) {
281    return add(name, null, NodeType.ARRAY);
282  }
283 
284  /**
285   * Adds an array element child to the array.
286   *
287   * @param value       the value of the element array
288   * @return            the new node, or null if none added
289   */
290  public JSONNode addArrayElement(Object value) {
291    NodeType    type;
292
293    if (getNodeType() != NodeType.ARRAY)
294      return null;
295   
296    type = null;
297   
298    if (value != null) {
299      if (value instanceof Boolean)
300        type = NodeType.PRIMITIVE;
301      else if (value instanceof Integer)
302        type = NodeType.PRIMITIVE;
303      else if (value instanceof Double)
304        type = NodeType.PRIMITIVE;
305      else if (value instanceof String)
306        type = NodeType.PRIMITIVE;
307      else if (value.getClass().isArray())
308        type = NodeType.ARRAY;
309      else
310        type = NodeType.OBJECT;
311    }
312     
313    return add(null, value, type);
314  }
315 
316  /**
317   * Adds an object child to the object.
318   *
319   * @param name        the name of the pair
320   * @return            the new node, or null if none added
321   */
322  public JSONNode addObject(String name) {
323    return add(name, null, NodeType.OBJECT);
324  }
325 
326  /**
327   * Adds a key-value child to the object.
328   *
329   * @param name        the name of the pair
330   * @param value       the value
331   * @param type        the node type, null for primitives
332   * @return            the new node, or null if none added
333   */
334  protected JSONNode add(String name, Object value, NodeType type) {
335    JSONNode    child;
336   
337    if (isPrimitive())
338      return null;
339   
340    child = new JSONNode(name, value, type);
341    add(child);
342   
343    return child;
344  }
345 
346  /**
347   * Checks whether the node has a child with the given name.
348   *
349   * @param name        the name of the child
350   * @return            true if child with that name is available
351   */
352  public boolean hasChild(String name) {
353    return (getChild(name) != null);
354  }
355 
356  /**
357   * Returns the child with the given name.
358   *
359   * @param name        the name of the child
360   * @return            the child if available, null otherwise
361   */
362  public JSONNode getChild(String name) {
363    JSONNode    result;
364    JSONNode    node;
365    int         i;
366   
367    result = null;
368   
369    for (i = 0; i < getChildCount(); i++) {
370      node = (JSONNode) getChildAt(i);
371      if (!node.isAnonymous() && node.getName().equals(name)) {
372        result = node;
373        break;
374      }
375    }
376   
377    return result;
378  }
379 
380  /**
381   * Generates the indentation string.
382   *
383   * @param level       the level
384   * @return            the indentation string (tabs)
385   */
386  protected String getIndentation(int level) {
387    StringBuffer        result;
388    int                 i;
389   
390    result = new StringBuffer();
391    for (i = 0; i < level; i++)
392      result.append("\t");
393   
394    return result.toString();
395  }
396 
397  /**
398   * Escapes ", \, /, \b, \f, \n, \r, \t in strings.
399   *
400   * @param o           the object to process (only strings get processed)
401   * @return            the processed object
402   */
403  protected Object escape(Object o) {
404    if (o instanceof String)
405      return escape((String) o);
406    else
407      return o;
408  }
409 
410  /**
411   * Escapes ", /, \b, \f, \n, \r, \t.
412   *
413   * @param s           the string to process
414   * @return            the processed
415   */
416  protected String escape(String s) {
417    StringBuffer        result;
418    int                 i;
419    char                c;
420   
421    if (    (s.indexOf('\"') > -1)
422         || (s.indexOf('\\') > -1) 
423         || (s.indexOf('\b') > -1) 
424         || (s.indexOf('\f') > -1) 
425         || (s.indexOf('\n') > -1) 
426         || (s.indexOf('\r') > -1) 
427         || (s.indexOf('\t') > -1) ) {
428      result = new StringBuffer();
429      for (i = 0; i < s.length(); i++) {
430        c = s.charAt(i);
431        if (c == '\"')
432          result.append("\\\"");
433        else if (c == '\\')
434          result.append("\\\\");
435        else if (c == '\b')
436          result.append("\\b");
437        else if (c == '\f')
438          result.append("\\f");
439        else if (c == '\n')
440          result.append("\\n");
441        else if (c == '\r')
442          result.append("\\r");
443        else if (c == '\t')
444          result.append("\\t");
445        else
446          result.append(c);
447      }
448    }
449    else {
450      result = new StringBuffer(s);
451    }
452   
453    return result.toString();
454  }
455 
456  /**
457   * Dumps the node structure into JSON format.
458   *
459   * @param buffer      the buffer to add the data to
460   */
461  public void toString(StringBuffer buffer) {
462    int         level;
463    boolean     isLast;
464    String      indent;
465    int         i;
466   
467    level  = getLevel();
468    isLast = (getNextSibling() == null);
469    indent = getIndentation(level);
470   
471    buffer.append(indent);
472    if (m_Name != null) {
473      buffer.append("\"");
474      buffer.append(escape(m_Name));
475      buffer.append("\" : ");
476    }
477   
478    if (isObject()) {
479      buffer.append("{\n");
480      for (i = 0; i < getChildCount(); i++)
481        ((JSONNode) getChildAt(i)).toString(buffer);
482      buffer.append(indent);
483      buffer.append("}");
484    }
485    else if (isArray()) {
486      buffer.append("[\n");
487      for (i = 0; i < getChildCount(); i++)
488        ((JSONNode) getChildAt(i)).toString(buffer);
489      buffer.append(indent);
490      buffer.append("]");
491    }
492    else {
493      if (m_Value == null) {
494        buffer.append("null");
495      }
496      else if (m_Value instanceof String) {
497        buffer.append("\"");
498        buffer.append(escape((String) m_Value));
499        buffer.append("\"");
500      }
501      else {
502        buffer.append(m_Value.toString());
503      }
504    }
505   
506    if (!isLast)
507      buffer.append(",");
508    buffer.append("\n");
509  }
510
511  /**
512   * Returns a string representation of the node.
513   *
514   * @return            the string representation
515   */
516  public String toString() {
517    String      result;
518   
519    result = null;
520   
521    if (isObject()) {
522      if (isRoot())
523        result = "JSON";
524      else if (m_Name == null)
525        result = "<object>";
526      else
527        result = escape(m_Name) + " (Object)";
528    }
529    else if (isArray()) {
530      if (m_Name == null)
531        result = "<array>";
532      else
533        result = escape(m_Name) + " (Array)";
534    }
535    else {
536      if (m_Name != null)
537        result = escape(m_Name) + ": " + escape(m_Value);
538      else
539        result = "" + m_Value;
540    }
541   
542    return result;
543  }
544 
545  /**
546   * Reads the JSON object from the given reader.
547   *
548   * @param reader      the reader to read the JSON object from
549   * @return            the generated JSON object
550   * @throws Exception  if parsing fails
551   */
552  public static JSONNode read(Reader reader) throws Exception {
553    SymbolFactory       sf;
554    Parser              parser;
555   
556    sf     = new DefaultSymbolFactory();
557    parser = new Parser(new Scanner(reader, sf), sf);
558    parser.parse();
559   
560    return parser.getResult();
561  }
562 
563  /**
564   * Only for testing. Generates a simple JSON object and displays it.
565   *
566   * @param args        ignored
567   * @throws Exception  if something goes wrong
568   */
569  public static void main(String[] args) throws Exception {
570    // generates the example listed here:
571    // http://en.wikipedia.org/wiki/JSON
572    JSONNode person = new JSONNode();
573    person.addPrimitive("firstName", "John");
574    person.addPrimitive("lastName", "Smith");
575    JSONNode address = person.addObject("address");
576    address.addPrimitive("streetAddress", "21 2nd Street");
577    address.addPrimitive("city", "New York");
578    address.addPrimitive("state", "NY");
579    address.addPrimitive("postalCode", 10021);
580    JSONNode phonenumbers = person.addArray("phoneNumbers");
581    phonenumbers.addArrayElement("212 555-1234");
582    phonenumbers.addArrayElement("646 555-4567");
583   
584    // output in console
585    StringBuffer buffer = new StringBuffer();
586    person.toString(buffer);
587    System.out.println(buffer.toString());
588   
589    // display GUI
590    JTree tree = new JTree(person);
591    JFrame frame = new JFrame("JSON");
592    frame.setSize(800, 600);
593    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
594    frame.getContentPane().setLayout(new BorderLayout());
595    frame.getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
596    frame.setLocationRelativeTo(null);
597    frame.setVisible(true);
598  }
599}
Note: See TracBrowser for help on using the repository browser.