source: josm/trunk/src/org/glassfish/json/NodeReference.java@ 13689

Last change on this file since 13689 was 13231, checked in by Don-vip, 6 years ago

see #15682 - upgrade to JSR 374 (JSON Processing) API 1.1.2

File size: 10.6 KB
Line 
1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright (c) 2015-2017 Oracle and/or its affiliates. All rights reserved.
5 *
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common Development
8 * and Distribution License("CDDL") (collectively, the "License"). You
9 * may not use this file except in compliance with the License. You can
10 * obtain a copy of the License at
11 * https://oss.oracle.com/licenses/CDDL+GPL-1.1
12 * or LICENSE.txt. See the License for the specific
13 * language governing permissions and limitations under the License.
14 *
15 * When distributing the software, include this License Header Notice in each
16 * file and include the License file at LICENSE.txt.
17 *
18 * GPL Classpath Exception:
19 * Oracle designates this particular file as subject to the "Classpath"
20 * exception as provided by Oracle in the GPL Version 2 section of the License
21 * file that accompanied this code.
22 *
23 * Modifications:
24 * If applicable, add the following below the License Header, with the fields
25 * enclosed by brackets [] replaced by your own identifying information:
26 * "Portions Copyright [year] [name of copyright owner]"
27 *
28 * Contributor(s):
29 * If you wish your version of this file to be governed by only the CDDL or
30 * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 * elects to include this software in this distribution under the [CDDL or GPL
32 * Version 2] license." If you don't indicate a single choice of license, a
33 * recipient has the option to distribute your version of this file under
34 * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 * its licensees as provided above. However, if you add GPL Version 2 code
36 * and therefore, elected the GPL Version 2 license, then the option applies
37 * only if the new code is made subject to such option by the copyright
38 * holder.
39 */
40
41package org.glassfish.json;
42
43import javax.json.Json;
44import javax.json.JsonArray;
45import javax.json.JsonArrayBuilder;
46import javax.json.JsonException;
47import javax.json.JsonObject;
48import javax.json.JsonStructure;
49import javax.json.JsonValue;
50
51/**
52 * This class is a helper class for JsonPointer implementation,
53 * and is not part of the API.
54 *
55 * This class encapsulates a reference to a JSON node.
56 * There are three types of references.
57 * <ol><li>a reference to the root of a JSON tree.</li>
58 * <li>a reference to a name/value (possibly non-existing) pair of a JSON object, identified by a name.</li>
59 * <li>a reference to a member value of a JSON array, identified by an index.</li>
60 * </ol>
61 * Static factory methods are provided for creating these references.
62 *
63 * <p>A referenced value can be retrieved or replaced.
64 * The value of a JSON object or JSON array can be
65 * removed. A new value can be added to a JSON object or
66 * inserted into a JSON array</p>
67 *
68 * <p>Since a {@code JsonObject} or {@code JsonArray} is immutable, these operations
69 * must not modify the referenced JSON object or array. The methods {@link #add},
70 * {@link #replace}, and {@link #remove} returns a new
71 * JSON object or array after the execution of the operation.</p>
72 */
73abstract class NodeReference {
74
75 /**
76 * Return {@code true} if a reference points to a valid value, {@code false} otherwise.
77 *
78 * @return {@code true} if a reference points to a value
79 */
80 abstract public boolean contains();
81
82 /**
83 * Get the value at the referenced location.
84 *
85 * @return the JSON value referenced
86 * @throws JsonException if the referenced value does not exist
87 */
88 abstract public JsonValue get();
89
90 /**
91 * Add or replace a value at the referenced location.
92 * If the reference is the root of a JSON tree, the added value must be
93 * a JSON object or array, which becomes the referenced JSON value.
94 * If the reference is an index of a JSON array, the value is inserted
95 * into the array at the index. If the index is -1, the value is
96 * appended to the array.
97 * If the reference is a name of a JSON object, the name/value pair is added
98 * to the object, replacing any pair with the same name.
99 *
100 * @param value the value to be added
101 * @return the JsonStructure after the operation
102 * @throws JsonException if the index to the array is not -1 or is out of range
103 */
104 abstract public JsonStructure add(JsonValue value);
105
106 /**
107 * Remove the name/value pair from the JSON object, or the value in a JSON array, as specified by the reference
108 *
109 * @return the JsonStructure after the operation
110 * @throws JsonException if the name/value pair of the referenced JSON object
111 * does not exist, or if the index of the referenced JSON array is
112 * out of range, or if the reference is a root reference
113 */
114 abstract public JsonStructure remove();
115
116 /**
117 * Replace the referenced value with the specified value.
118 *
119 * @param value the JSON value to be stored at the referenced location
120 * @return the JsonStructure after the operation
121 * @throws JsonException if the name/value pair of the referenced JSON object
122 * does not exist, or if the index of the referenced JSON array is
123 * out of range, or if the reference is a root reference
124 */
125 abstract public JsonStructure replace(JsonValue value);
126
127 /**
128 * Returns a {@code NodeReference} for a {@code JsonStructure}.
129 *
130 * @param structure the {@code JsonStructure} referenced
131 * @return the {@code NodeReference}
132 */
133 public static NodeReference of(JsonStructure structure) {
134 return new RootReference(structure);
135 }
136
137 /**
138 * Returns a {@code NodeReference} for a name/value pair in a
139 * JSON object.
140 *
141 * @param object the referenced JSON object
142 * @param name the name of the name/pair
143 * @return the {@code NodeReference}
144 */
145 public static NodeReference of(JsonObject object, String name) {
146 return new ObjectReference(object, name);
147 }
148
149 /**
150 * Returns a {@code NodeReference} for a member value in a
151 * JSON array.
152 *
153 * @param array the referenced JSON array
154 * @param index the index of the member value in the JSON array
155 * @return the {@code NodeReference}
156 */
157 public static NodeReference of(JsonArray array, int index) {
158 return new ArrayReference(array, index);
159 }
160
161 static class RootReference extends NodeReference {
162
163 private JsonStructure root;
164
165 RootReference(JsonStructure root) {
166 this.root = root;
167 }
168
169 @Override
170 public boolean contains() {
171 return root != null;
172 }
173
174 @Override
175 public JsonValue get() {
176 return root;
177 }
178
179 @Override
180 public JsonStructure add(JsonValue value) {
181 switch (value.getValueType() ) {
182 case OBJECT:
183 case ARRAY:
184 this.root = (JsonStructure) value;
185 break;
186 default:
187 throw new JsonException(JsonMessages.NODEREF_VALUE_ADD_ERR());
188 }
189 return root;
190 }
191
192 @Override
193 public JsonStructure remove() {
194 throw new JsonException(JsonMessages.NODEREF_VALUE_CANNOT_REMOVE());
195 }
196
197 @Override
198 public JsonStructure replace(JsonValue value) {
199 return add(value);
200 }
201 }
202
203 static class ObjectReference extends NodeReference {
204
205 private final JsonObject object;
206 private final String key;
207
208 ObjectReference(JsonObject object, String key) {
209 this.object = object;
210 this.key = key;
211 }
212
213 @Override
214 public boolean contains() {
215 return object != null && object.containsKey(key);
216 }
217
218 @Override
219 public JsonValue get() {
220 if (!contains()) {
221 throw new JsonException(JsonMessages.NODEREF_OBJECT_MISSING(key));
222 }
223 return object.get(key);
224 }
225
226 @Override
227 public JsonObject add(JsonValue value) {
228 return Json.createObjectBuilder(object).add(key, value).build();
229 }
230
231 @Override
232 public JsonObject remove() {
233 if (!contains()) {
234 throw new JsonException(JsonMessages.NODEREF_OBJECT_MISSING(key));
235 }
236 return Json.createObjectBuilder(object).remove(key).build();
237 }
238
239 @Override
240 public JsonObject replace(JsonValue value) {
241 if (!contains()) {
242 throw new JsonException(JsonMessages.NODEREF_OBJECT_MISSING(key));
243 }
244 return add(value);
245 }
246 }
247
248 static class ArrayReference extends NodeReference {
249
250 private final JsonArray array;
251 private final int index; // -1 means "-" in JSON Pointer
252
253 ArrayReference(JsonArray array, int index) {
254 this.array = array;
255 this.index = index;
256 }
257
258 @Override
259 public boolean contains() {
260 return array != null && index > -1 && index < array.size();
261 }
262
263 @Override
264 public JsonValue get() {
265 if (!contains()) {
266 throw new JsonException(JsonMessages.NODEREF_ARRAY_INDEX_ERR(index, array.size()));
267 }
268 return array.get(index);
269 }
270
271 @Override
272 public JsonArray add(JsonValue value) {
273 //TODO should we check for arrayoutofbounds?
274 // The spec seems to say index = array.size() is allowed. This is handled as append
275 JsonArrayBuilder builder = Json.createArrayBuilder(this.array);
276 if (index == -1 || index == array.size()) {
277 builder.add(value);
278 } else {
279 if(index < array.size()) {
280 builder.add(index, value);
281 } else {
282 throw new JsonException(JsonMessages.NODEREF_ARRAY_INDEX_ERR(index, array.size()));
283 }
284 }
285 return builder.build();
286 }
287
288 @Override
289 public JsonArray remove() {
290 if (!contains()) {
291 throw new JsonException(JsonMessages.NODEREF_ARRAY_INDEX_ERR(index, array.size()));
292 }
293 JsonArrayBuilder builder = Json.createArrayBuilder(this.array);
294 return builder.remove(index).build();
295 }
296
297 @Override
298 public JsonArray replace(JsonValue value) {
299 if (!contains()) {
300 throw new JsonException(JsonMessages.NODEREF_ARRAY_INDEX_ERR(index, array.size()));
301 }
302 JsonArrayBuilder builder = Json.createArrayBuilder(this.array);
303 return builder.set(index, value).build();
304 }
305 }
306}
307
Note: See TracBrowser for help on using the repository browser.