001/*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2011-2017 Oracle and/or its affiliates. All rights reserved.
005 *
006 * The contents of this file are subject to the terms of either the GNU
007 * General Public License Version 2 only ("GPL") or the Common Development
008 * and Distribution License("CDDL") (collectively, the "License").  You
009 * may not use this file except in compliance with the License.  You can
010 * obtain a copy of the License at
011 * https://oss.oracle.com/licenses/CDDL+GPL-1.1
012 * or LICENSE.txt.  See the License for the specific
013 * language governing permissions and limitations under the License.
014 *
015 * When distributing the software, include this License Header Notice in each
016 * file and include the License file at LICENSE.txt.
017 *
018 * GPL Classpath Exception:
019 * Oracle designates this particular file as subject to the "Classpath"
020 * exception as provided by Oracle in the GPL Version 2 section of the License
021 * file that accompanied this code.
022 *
023 * Modifications:
024 * If applicable, add the following below the License Header, with the fields
025 * enclosed by brackets [] replaced by your own identifying information:
026 * "Portions Copyright [year] [name of copyright owner]"
027 *
028 * Contributor(s):
029 * If you wish your version of this file to be governed by only the CDDL or
030 * only the GPL Version 2, indicate your decision by adding "[Contributor]
031 * elects to include this software in this distribution under the [CDDL or GPL
032 * Version 2] license."  If you don't indicate a single choice of license, a
033 * recipient has the option to distribute your version of this file under
034 * either the CDDL, the GPL Version 2 or to extend the choice of license to
035 * its licensees as provided above.  However, if you add GPL Version 2 code
036 * and therefore, elected the GPL Version 2 license, then the option applies
037 * only if the new code is made subject to such option by the copyright
038 * holder.
039 */
040
041package javax.json;
042
043import java.util.List;
044import java.util.function.Function;
045import java.util.stream.Collectors;
046import java.util.stream.Stream;
047
048/**
049 * {@code JsonArray} represents an immutable JSON array
050 * (an ordered sequence of zero or more values).
051 * It also provides an unmodifiable list view of the values in the array.
052 *
053 * <EMBED CLASS='external-html' DATA-FILE-ID=LICENSE DATA-CIETName=JsonArray>
054 * 
055 * <BR /><BR />A {@code JsonArray} object can be created by reading JSON data from
056 * an input source or it can be built from scratch using an array builder
057 * object.
058 *
059 * <BR /><BR />The following example demonstrates how to create a {@code JsonArray}
060 * object from an input source using the method {@link JsonReader#readArray()}:
061 * 
062 * <BR /><DIV CLASS=SNIP>{@code
063 * JsonReader   jsonReader  = Json.createReader(...);
064 * JsonArray    array       = jsonReader.readArray();
065 * 
066 * jsonReader.close();
067 * }</DIV>
068 *
069 * <BR /><BR />The following example demonstrates how to build an empty JSON array
070 * using the class {@link JsonArrayBuilder}:
071 * 
072 * <BR /><DIV CLASS=SNIP>{@code
073 * JsonArray array = Json.createArrayBuilder().build();
074 * }</DIV>
075 *
076 * <BR /><BR />The example code below demonstrates how to create the following JSON array:
077 * 
078 * <DIV CLASS=JSON>{@code
079 * [
080 *     { "type": "home", "number": "212 555-1234" },
081 *     { "type": "fax", "number": "646 555-4567" }
082 * ]
083 * }</DIV>
084 * 
085 * <DIV CLASS=EXAMPLE>{@code
086 * JsonArray value = Json
087 *      .createArrayBuilder()
088 *      .add(Json.createObjectBuilder()
089 *          .add("type", "home")
090 *          .add("number", "212 555-1234"))
091 *      .add(Json.createObjectBuilder()
092 *          .add("type", "fax")
093 *          .add("number", "646 555-4567"))
094 *      .build();
095 * }</DIV>
096 *
097 * <BR />The following example demonstrates how to write a {@code JsonArray} object 
098 * as JSON data:
099 * 
100 * <BR /><DIV CLASS=SNIP>{@code
101 * JsonArray    arr     = ...;
102 * JsonWriter   writer  = Json.createWriter(...)
103 * 
104 * writer.writeArray(arr);
105 * writer.close();
106 * }</DIV>
107 *
108 * <BR /><BR />The values in a {@code JsonArray} can be of the following types:
109 * {@link JsonObject}, {@link JsonArray},
110 * {@link JsonString}, {@link JsonNumber}, {@link JsonValue#TRUE},
111 * {@link JsonValue#FALSE}, and {@link JsonValue#NULL}. 
112 * {@code JsonArray} provides various accessor methods to access the values
113 * in an array.
114 * 
115 * <BR /><BR />The following example shows how to obtain the home phone number 
116 * "212 555-1234" from the array built in the previous example:
117 * 
118 * <BR /><DIV CLASS=SNIP>{@code
119 * JsonObject home = array.getJsonObject(0);
120 * String number = home.getString("number");
121 * }</DIV>
122 *
123 * <BR /><BR />{@code JsonArray} instances are list objects that provide read-only 
124 * access to the values in the JSON array. Any attempt to modify the list,
125 * whether directly or using its collection views, results in an 
126 * {@code UnsupportedOperationException}.
127 */
128public interface JsonArray extends JsonStructure, List<JsonValue> {
129
130    /**
131     * Returns the object value at the specified position in this array.
132     * This is a convenience method for {@code (JsonObject)get(index)}.
133     *
134     * @param index index of the value to be returned
135     * @return the value at the specified position in this array
136     * @throws IndexOutOfBoundsException if the index is out of range
137     * @throws ClassCastException if the value at the specified position is not
138     * assignable to the JsonObject type
139     */
140    JsonObject getJsonObject(int index);
141
142    /**
143     * Returns the array value at the specified position in this array.
144     * This is a convenience method for {@code (JsonArray)get(index)}.
145     *
146     * @param index index of the value to be returned
147     * @return the value at the specified position in this array
148     * @throws IndexOutOfBoundsException if the index is out of range
149     * @throws ClassCastException if the value at the specified position is not
150     * assignable to the JsonArray type
151     */
152    JsonArray getJsonArray(int index);
153
154    /**
155     * Returns the number value at the specified position in this array.
156     * This is a convenience method for {@code (JsonNumber)get(index)}.
157     *
158     * @param index index of the value to be returned
159     * @return the value at the specified position in this array
160     * @throws IndexOutOfBoundsException if the index is out of range
161     * @throws ClassCastException if the value at the specified position is not
162     * assignable to the JsonNumber type
163     */
164    JsonNumber getJsonNumber(int index);
165
166    /**
167     * Returns the string value at ths specified position in this array.
168     * This is a convenience method for {@code (JsonString)get(index)}.
169     *
170     * @param index index of the value to be returned
171     * @return the value at the specified position in this array
172     * @throws IndexOutOfBoundsException if the index is out of range
173     * @throws ClassCastException if the value at the specified position is not
174     * assignable to the JsonString type
175     */
176    JsonString getJsonString(int index);
177
178    /**
179     * Returns a list view of the specified type for the array. This method
180     * does not verify if there is a value of wrong type in the array. Providing
181     * this typesafe view dynamically may cause a program fail with a
182     * {@code ClassCastException}, if there is a value of wrong type in this
183     * array. Unfortunately, the exception can occur at any time after this
184     * method returns.
185     *
186     * @param <T> The type of the List for the array
187     * @param clazz a JsonValue type
188     * @return a list view of the specified type
189     */
190    <T extends JsonValue> List<T> getValuesAs(Class<T> clazz);
191
192    /**
193     * Returns a list view for the array. The value and the type of the elements
194     * in the list is specified by the {@code func} argument.
195     *
196     * <BR />This method can be used to obtain a list of the unwrapped types, such as
197     * 
198     * <BR /><DIV CLASS=SNIP>{@code
199     * List<String> strings = ary1.getValuesAs(JsonString::getString);
200     * List<Integer> ints = ary2.getValuesAs(JsonNumber::intValue);
201     * }</DIV>
202     * 
203     * <BR /><BR />or a list of simple projections, such as
204     * 
205     * <BR /><DIV CLASS=SNIP>{@code
206     * List<Integer> stringsizes = ary1.getValueAs((JsonString v)->v.getString().length();
207     * }</DIV>
208     * 
209     * @param <K> The element type (must be a subtype of JsonValue) of this JsonArray.
210     * @param <T> The element type of the returned List
211     * @param func The function that maps the elements of this JsonArray to the target elements.
212     * @return A List of the specified values and type.
213     * @throws ClassCastException if the {@code JsonArray} contains a value of wrong type
214     *
215     * @since 1.1
216     */
217    default <T, K extends JsonValue> List<T> getValuesAs(Function<K, T> func) {
218        @SuppressWarnings("unchecked")
219        Stream<K> stream = (Stream<K>) stream();
220        return stream.map(func).collect(Collectors.toList());
221    }
222
223    /**
224     * A convenience method for
225     * {@code getJsonString(index).getString()}.
226     *
227     * @param index index of the {@code JsonString} value
228     * @return the String value at the specified position
229     * @throws IndexOutOfBoundsException if the index is out of range
230     * @throws ClassCastException if the value at the specified position is not
231     * assignable to {@code JsonString}
232     */
233    String getString(int index);
234
235    /**
236     * Returns the {@code String} value of {@code JsonString} at the specified
237     * position in this JSON array values. If {@code JsonString} is found,
238     * its {@link javax.json.JsonString#getString()} is returned. Otherwise,
239     * the specified default value is returned.
240     *
241     * @param index index of the {@code JsonString} value
242     * @param defaultValue the String to return if the {@code JsonValue} at the
243     *    specified position is not a {@code JsonString}
244     * @return the String value at the specified position in this array,
245     * or the specified default value
246     */
247    String getString(int index, String defaultValue);
248
249    /**
250     * A convenience method for
251     * {@code getJsonNumber(index).intValue()}.
252     *
253     * @param index index of the {@code JsonNumber} value
254     * @return the int value at the specified position
255     * @throws IndexOutOfBoundsException if the index is out of range
256     * @throws ClassCastException if the value at the specified position is not
257     * assignable to {@code JsonNumber}
258     */
259    int getInt(int index);
260
261    /**
262     * Returns the int value of the {@code JsonNumber} at the specified position. 
263     * If the value at that position is a {@code JsonNumber},
264     * this method returns {@link javax.json.JsonNumber#intValue()}. Otherwise
265     * this method returns the specified default value.
266     *
267     * @param index index of the {@code JsonNumber} value
268     * @param defaultValue the int value to return if the {@code JsonValue} at
269     *     the specified position is not a {@code JsonNumber}
270     * @return the int value at the specified position in this array,
271     * or the specified default value
272     */
273    int getInt(int index, int defaultValue);
274
275    /**
276     * Returns the boolean value at the specified position.
277     * If the value at the specified position is {@code JsonValue.TRUE} 
278     * this method returns {@code true}. If the value at the specified position 
279     * is {@code JsonValue.FALSE} this method returns {@code false}.
280     *
281     * @param index index of the JSON boolean value
282     * @return the boolean value at the specified position
283     * @throws IndexOutOfBoundsException if the index is out of range
284     * @throws ClassCastException if the value at the specified position is not
285     * assignable to {@code JsonValue.TRUE} or {@code JsonValue.FALSE}
286     */
287    boolean getBoolean(int index);
288
289    /**
290     * Returns the boolean value at the specified position.
291     * If the value at the specified position is {@code JsonValue.TRUE}
292     * this method returns {@code true}. If the value at the specified position 
293     * is {@code JsonValue.FALSE} this method returns {@code false}. 
294     * Otherwise this method returns the specified default value.
295     *
296     * @param index index of the JSON boolean value
297     * @param defaultValue the boolean value to return if the {@code JsonValue}
298     *    at the specified position is neither TRUE nor FALSE
299     * @return the boolean value at the specified position,
300     * or the specified default value
301     */
302    boolean getBoolean(int index, boolean defaultValue);
303
304    /**
305     * Returns {@code true} if the value at the specified location in this
306     * array is {@code JsonValue.NULL}.
307     *
308     * @param index index of the JSON null value
309     * @return return true if the value at the specified location is
310     * {@code JsonValue.NULL}, otherwise false
311     * @throws IndexOutOfBoundsException if the index is out of range
312     */
313    boolean isNull(int index);
314}