001    package net.sourceforge.javajson;
002    
003    import java.io.InputStream;
004    import java.io.Reader;
005    import java.io.StringReader;
006    import java.util.ArrayList;
007    import java.util.Iterator;
008    import java.util.List;
009    
010    import net.sourceforge.javajson.parser.ASTparse;
011    import net.sourceforge.javajson.parser.JsonParser;
012    import net.sourceforge.javajson.parser.ParseException;
013    import net.sourceforge.javajson.parser.TokenMgrError;
014    
015    public class JsonArray implements Iterable<JsonValue> {
016            private List<JsonValue> list;
017    
018            /** Parses a string to a json object. */
019            public static JsonArray parse(String input) throws JsonException {
020                    return parse(new StringReader(input));
021            }
022    
023            /** Parses a string to a json object. */
024            public static JsonArray parse(Reader reader) throws JsonException {
025                    try {
026                            JsonParser parser = new JsonParser(reader);
027                            ASTparse root = (ASTparse) parser.parse();
028                            return root.getJsonArray();
029                    } catch (ParseException pe) {
030                            throw new JsonException(pe);
031                    } catch (TokenMgrError error) {
032                            throw new JsonException(error);
033                    }
034            }
035    
036            /** Parses a string to a json object. */
037            public static JsonArray parse(InputStream is) throws JsonException {
038                    try {
039                            JsonParser parser = new JsonParser(is);
040                            ASTparse root = (ASTparse) parser.parse();
041                            return root.getJsonArray();
042                    } catch (ParseException pe) {
043                            throw new JsonException(pe);
044                    } catch (TokenMgrError error) {
045                            throw new JsonException(error);
046                    }
047            }
048    
049            public JsonArray() {
050                    list = new ArrayList<JsonValue>();
051            }
052    
053            public JsonArray add(boolean value) {
054                    list.add(new JsonValue(value));
055                    return this;
056            }
057    
058            public JsonArray add(double value) {
059                    list.add(new JsonValue(value));
060                    return this;
061            }
062    
063            public JsonArray add(float value) {
064                    list.add(new JsonValue(value));
065                    return this;
066            }
067    
068            public JsonArray add(int value) {
069                    list.add(new JsonValue(value));
070                    return this;
071            }
072    
073            public JsonArray add(long value) {
074                    list.add(new JsonValue(value));
075                    return this;
076            }
077    
078            public JsonArray add(JsonArray value) {
079                    list.add(new JsonValue(value));
080                    return this;
081            }
082    
083            public JsonArray add(JsonObject value) {
084                    list.add(new JsonValue(value));
085                    return this;
086            }
087    
088            public JsonArray add(String value) {
089                    list.add(new JsonValue(value));
090                    return this;
091            }
092    
093            public JsonArray add(Object value) {
094                    if (value instanceof Boolean)
095                            add(((Boolean) value).booleanValue());
096                    else if (value instanceof Double)
097                            add(((Double) value).doubleValue());
098                    else if (value instanceof Float)
099                            add(((Float) value).floatValue());
100                    else if (value instanceof Integer)
101                            add(((Integer) value).intValue());
102                    else if (value instanceof Long)
103                            add(((Long) value).longValue());
104                    else if (value instanceof JsonArray)
105                            add((JsonArray) value);
106                    else if (value instanceof JsonObject)
107                            add((JsonObject) value);
108                    else if (value instanceof JsonValue)
109                            list.add((JsonValue) value);
110                    else if (value instanceof String)
111                            add((String) value);
112                    else if (value == null)
113                            add((String) null);
114                    else
115                            throw new ClassCastException("Unrecognized class");
116                    return this;
117            }
118    
119            /**
120             * @param index
121             * @throws ClassCastException
122             *             if the value cannot be converted to a boolean
123             * @throws IndexOutOfBoundsException
124             *             if its out of bounds
125             */
126            public boolean getBoolean(int index) {
127                    if (index >= 0 && index < list.size())
128                            return list.get(index).getBoolean();
129                    else
130                            throw new IndexOutOfBoundsException();
131            }
132    
133            /**
134             * @throws ClassCastException
135             *             if the value cannot be converted to a double
136             * @throws IndexOutOfBoundsException
137             *             if its out of bounds
138             */
139            public double getDouble(int index) {
140                    if (index >= 0 && index < list.size())
141                            return list.get(index).getDouble();
142                    else
143                            throw new IndexOutOfBoundsException();
144            }
145    
146            /**
147             * @throws ClassCastException
148             *             if the value cannot be converted to a double
149             * @throws IndexOutOfBoundsException
150             *             if its out of bounds
151             */
152            public float getFloat(int index) {
153                    if (index >= 0 && index < list.size())
154                            return list.get(index).getFloat();
155                    else
156                            throw new IndexOutOfBoundsException();
157            }
158    
159            /**
160             * @throws ClassCastException
161             *             if the value cannot be converted to a double
162             * @throws IndexOutOfBoundsException
163             *             if its out of bounds
164             */
165            public int getInt(int index) {
166                    if (index >= 0 && index < list.size())
167                            return list.get(index).getInt();
168                    else
169                            throw new IndexOutOfBoundsException();
170            }
171    
172            /**
173             * @throws ClassCastException
174             *             if the value cannot be converted to a double
175             * @throws IndexOutOfBoundsException
176             *             if its out of bounds
177             */
178            public JsonArray getJsonArray(int index) {
179                    if (index >= 0 && index < list.size())
180                            return list.get(index).getJsonArray();
181                    else
182                            throw new IndexOutOfBoundsException();
183            }
184    
185            /**
186             * @throws ClassCastException
187             *             if the value cannot be converted to a double
188             * @throws IndexOutOfBoundsException
189             *             if its out of bounds
190             */
191            public JsonObject getJsonObject(int index) {
192                    if (index >= 0 && index < list.size())
193                            return list.get(index).getJsonObject();
194                    else
195                            throw new IndexOutOfBoundsException();
196            }
197    
198            /**
199             * @throws ClassCastException
200             *             if the value cannot be converted to a double
201             * @throws IndexOutOfBoundsException
202             *             if its out of bounds
203             */
204            public long getLong(int index) {
205                    if (index >= 0 && index < list.size())
206                            return list.get(index).getLong();
207                    else
208                            throw new IndexOutOfBoundsException();
209            }
210    
211            /**
212             * @throws IndexOutOfBoundsException
213             *             if its out of bounds
214             */
215            public String getString(int index) {
216                    if (index >= 0 && index < list.size())
217                            return list.get(index).getString();
218                    else
219                            throw new IndexOutOfBoundsException();
220            }
221    
222            /**
223             * Checks if the item at an index is a boolean. See
224             * {@link JsonValue#isBoolean()} for more information
225             * 
226             * @param index
227             *            The index of the array to check
228             * @return True if the object contains the item and is a boolean
229             * @throws IndexOutOfBoundsException
230             */
231            public boolean isBoolean(int index) {
232                    if (index >= 0 && index < list.size())
233                            return list.get(index).isBoolean();
234                    else
235                            throw new IndexOutOfBoundsException();
236            }
237            
238            /**
239             * Checks if the item at an index is a double. See
240             * {@link JsonValue#isLong()} for more information
241             * 
242             * @param index
243             *            The index of the array to check
244             * @return True if the object contains the item and is a double
245             * @throws IndexOutOfBoundsException
246             */
247            public boolean isDouble(int index) {
248                    if (index >= 0 && index < list.size())
249                            return list.get(index).isDouble();
250                    else
251                            throw new IndexOutOfBoundsException();
252            }
253            
254            /**
255             * Checks if the item at an index is a float. See
256             * {@link JsonValue#isLong()} for more information
257             * 
258             * @param index
259             *            The index of the array to check
260             * @return True if the object contains the item and is a float
261             * @throws IndexOutOfBoundsException
262             */
263            public boolean isFloat(int index) {
264                    if (index >= 0 && index < list.size())
265                            return list.get(index).isFloat();
266                    else
267                            throw new IndexOutOfBoundsException();
268            }
269            
270            /**
271             * Checks if the item at an index is a int. See
272             * {@link JsonValue#isLong()} for more information
273             * 
274             * @param index
275             *            The index of the array to check
276             * @return True if the object contains the item and is a int
277             * @throws IndexOutOfBoundsException
278             */
279            public boolean isInt(int index) {
280                    if (index >= 0 && index < list.size())
281                            return list.get(index).isInt();
282                    else
283                            throw new IndexOutOfBoundsException();
284            }
285    
286            /**
287             * Checks if the item at an index is an array. See
288             * {@link JsonValue#isJsonArray()} for more information
289             * 
290             * @param index
291             *            The index of the array to check
292             * @return True if the object contains the item and is a json array
293             * @throws IndexOutOfBoundsException
294             */
295            public boolean isJsonArray(int index) {
296                    if (index >= 0 && index < list.size())
297                            return list.get(index).isJsonArray();
298                    else
299                            throw new IndexOutOfBoundsException();
300            }
301    
302            /**
303             * Checks if the item at an index is an object. See
304             * {@link JsonValue#isJsonObject()} for more information
305             * 
306             * @param index
307             *            The index of the array to check
308             * @return True if the object contains the item and is a json object
309             * @throws IndexOutOfBoundsException
310             */
311            public boolean isJsonObject(int index) {
312                    if (index >= 0 && index < list.size())
313                            return list.get(index).isJsonObject();
314                    else
315                            throw new IndexOutOfBoundsException();
316            }
317            
318            /**
319             * Checks if the item at an index is a long. See
320             * {@link JsonValue#isLong()} for more information
321             * 
322             * @param index
323             *            The index of the array to check
324             * @return True if the object contains the item and is a long
325             * @throws IndexOutOfBoundsException
326             */
327            public boolean isLong(int index) {
328                    if (index >= 0 && index < list.size())
329                            return list.get(index).isLong();
330                    else
331                            throw new IndexOutOfBoundsException();
332            }
333    
334            /**
335             * Checks if the item at an index is an string. See
336             * {@link JsonValue#isString()} for more information
337             * 
338             * @param index
339             *            The index of the array to check
340             * @return True if the object contains the item and is a json string
341             * @throws IndexOutOfBoundsException
342             */
343            public boolean isString(int index) {
344                    if (index >= 0 && index < list.size())
345                            return list.get(index).isString();
346                    else
347                            throw new IndexOutOfBoundsException();
348            }
349    
350            /**
351             * Checks if the structure of this json array is similar to that of another
352             * array. It simply checks that each item exists in both objects (same
353             * length of array) and that subobjects (json object or json array) are also
354             * similar.
355             * 
356             * @param obj
357             * @return
358             */
359            public boolean isSimilar(JsonArray obj) {
360                    if (obj == null)
361                            return false;
362    
363                    if (obj.size() != size())
364                            return false;
365    
366                    for (int i = 0; i < size(); i++) {
367                            if (!list.get(i).isSimilar(obj.list.get(i)))
368                                    return false;
369                    }
370    
371                    return true;
372            }
373    
374            public Iterator<JsonValue> iterator() {
375                    return list.iterator();
376            }
377    
378            public int size() {
379                    return list.size();
380            }
381    
382            @Override
383            public String toString() {
384                    StringBuffer sb = new StringBuffer();
385                    boolean hadSome = false;
386                    sb.append("[");
387                    for (JsonValue val : list) {
388                            if (hadSome)
389                                    sb.append(",");
390                            sb.append(val);
391                            hadSome = true;
392                    }
393                    sb.append("]");
394                    return sb.toString();
395            }
396    
397            /**
398             * Returns a nicely formatted string
399             * 
400             * @param spacing
401             * @return
402             */
403            public String toString(int spacing) {
404                    return toString(spacing, 0);
405            }
406    
407            /**
408             * Called by toString(int) to keep track of the spacing
409             * 
410             * @param spacing
411             * @param margin
412             * @return
413             */
414            protected String toString(int spacing, int margin) {
415                    if (list.isEmpty())
416                            return "[]";
417                    else {
418                            StringBuffer sb = new StringBuffer();
419                            boolean hadSome = false;
420                            sb.append("[\n");               
421                            for (JsonValue val : list) {
422                                    if (hadSome)
423                                            sb.append(",\n");
424                                    sb.append(getSpaces(margin + spacing));
425                                    sb.append(val.toString(spacing, margin + spacing));
426                                    hadSome = true;
427                            }
428                            sb.append("\n");
429                            sb.append(getSpaces(margin));
430                            sb.append("]");
431                            
432                            return sb.toString();
433                    }
434            }
435    
436            private String getSpaces(int spaces) {
437                    StringBuffer sb = new StringBuffer();
438                    for (int i = 0; i < spaces; i++)
439                            sb.append(" ");
440                    return sb.toString();
441            }
442    }