source: josm/trunk/src/org/glassfish/json/JsonStructureParser.java@ 13661

Last change on this file since 13661 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.5 KB
Line 
1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright (c) 2012-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.*;
44import javax.json.stream.JsonLocation;
45import javax.json.stream.JsonParser;
46import java.math.BigDecimal;
47import java.util.ArrayDeque;
48import java.util.Deque;
49import java.util.Iterator;
50import java.util.Map;
51import java.util.NoSuchElementException;
52
53/**
54 * {@link JsonParser} implementation on top of JsonArray/JsonObject
55 *
56 * @author Jitendra Kotamraju
57 */
58class JsonStructureParser implements JsonParser {
59
60 private Scope current;
61 private Event state;
62 private final Deque<Scope> scopeStack = new ArrayDeque<>();
63
64 JsonStructureParser(JsonArray array) {
65 current = new ArrayScope(array);
66 }
67
68 JsonStructureParser(JsonObject object) {
69 current = new ObjectScope(object);
70 }
71
72 @Override
73 public String getString() {
74 switch (state) {
75 case KEY_NAME:
76 return ((ObjectScope)current).key;
77 case VALUE_STRING:
78 return ((JsonString)current.getJsonValue()).getString();
79 case VALUE_NUMBER:
80 return ((JsonNumber)current.getJsonValue()).toString();
81 default:
82 throw new IllegalStateException(JsonMessages.PARSER_GETSTRING_ERR(state));
83 }
84 }
85
86 @Override
87 public boolean isIntegralNumber() {
88 if (state == Event.VALUE_NUMBER) {
89 return ((JsonNumber)current.getJsonValue()).isIntegral();
90 }
91 throw new IllegalStateException(JsonMessages.PARSER_ISINTEGRALNUMBER_ERR(state));
92 }
93
94 @Override
95 public int getInt() {
96 if (state == Event.VALUE_NUMBER) {
97 return ((JsonNumber)current.getJsonValue()).intValue();
98 }
99 throw new IllegalStateException(JsonMessages.PARSER_GETINT_ERR(state));
100 }
101
102 @Override
103 public long getLong() {
104 if (state == Event.VALUE_NUMBER) {
105 return ((JsonNumber)current.getJsonValue()).longValue();
106 }
107 throw new IllegalStateException(JsonMessages.PARSER_GETLONG_ERR(state));
108 }
109
110 @Override
111 public BigDecimal getBigDecimal() {
112 if (state == Event.VALUE_NUMBER) {
113 return ((JsonNumber)current.getJsonValue()).bigDecimalValue();
114 }
115 throw new IllegalStateException(JsonMessages.PARSER_GETBIGDECIMAL_ERR(state));
116 }
117
118 @Override
119 public JsonLocation getLocation() {
120 return JsonLocationImpl.UNKNOWN;
121 }
122
123 @Override
124 public boolean hasNext() {
125 return !((state == Event.END_OBJECT || state == Event.END_ARRAY) && scopeStack.isEmpty());
126 }
127
128 @Override
129 public Event next() {
130 if (!hasNext()) {
131 throw new NoSuchElementException();
132 }
133 transition();
134 return state;
135 }
136
137 private void transition() {
138 if (state == null) {
139 state = current instanceof ArrayScope ? Event.START_ARRAY : Event.START_OBJECT;
140 } else {
141 if (state == Event.END_OBJECT || state == Event.END_ARRAY) {
142 current = scopeStack.pop();
143 }
144 if (current instanceof ArrayScope) {
145 if (current.hasNext()) {
146 current.next();
147 state = getState(current.getJsonValue());
148 if (state == Event.START_ARRAY || state == Event.START_OBJECT) {
149 scopeStack.push(current);
150 current = Scope.createScope(current.getJsonValue());
151 }
152 } else {
153 state = Event.END_ARRAY;
154 }
155 } else {
156 // ObjectScope
157 if (state == Event.KEY_NAME) {
158 state = getState(current.getJsonValue());
159 if (state == Event.START_ARRAY || state == Event.START_OBJECT) {
160 scopeStack.push(current);
161 current = Scope.createScope(current.getJsonValue());
162 }
163 } else {
164 if (current.hasNext()) {
165 current.next();
166 state = Event.KEY_NAME;
167 } else {
168 state = Event.END_OBJECT;
169 }
170 }
171 }
172 }
173 }
174
175 @Override
176 public void close() {
177 // no-op
178 }
179
180 @Override
181 public void skipObject() {
182 if (current instanceof ObjectScope) {
183 int depth = 1;
184 do {
185 if (state == Event.KEY_NAME) {
186 state = getState(current.getJsonValue());
187 switch (state) {
188 case START_OBJECT:
189 depth++;
190 break;
191 case END_OBJECT:
192 depth--;
193 break;
194 default:
195 //no-op
196 }
197 } else {
198 if (current.hasNext()) {
199 current.next();
200 state = Event.KEY_NAME;
201 } else {
202 state = Event.END_OBJECT;
203 depth--;
204 }
205 }
206 } while (state != Event.END_OBJECT && depth > 0);
207 }
208 }
209
210 @Override
211 public void skipArray() {
212 if (current instanceof ArrayScope) {
213 int depth = 1;
214 do {
215 if (current.hasNext()) {
216 current.next();
217 state = getState(current.getJsonValue());
218 switch (state) {
219 case START_ARRAY:
220 depth++;
221 break;
222 case END_ARRAY:
223 depth--;
224 break;
225 default:
226 //no-op
227 }
228 } else {
229 state = Event.END_ARRAY;
230 depth--;
231 }
232 } while (!(state == Event.END_ARRAY && depth == 0));
233 }
234 }
235
236 private static Event getState(JsonValue value) {
237 switch (value.getValueType()) {
238 case ARRAY:
239 return Event.START_ARRAY;
240 case OBJECT:
241 return Event.START_OBJECT;
242 case STRING:
243 return Event.VALUE_STRING;
244 case NUMBER:
245 return Event.VALUE_NUMBER;
246 case TRUE:
247 return Event.VALUE_TRUE;
248 case FALSE:
249 return Event.VALUE_FALSE;
250 case NULL:
251 return Event.VALUE_NULL;
252 default:
253 throw new JsonException(JsonMessages.PARSER_STATE_ERR(value.getValueType()));
254 }
255 }
256
257 private static abstract class Scope implements Iterator {
258 abstract JsonValue getJsonValue();
259
260 static Scope createScope(JsonValue value) {
261 if (value instanceof JsonArray) {
262 return new ArrayScope((JsonArray)value);
263 } else if (value instanceof JsonObject) {
264 return new ObjectScope((JsonObject)value);
265 }
266 throw new JsonException(JsonMessages.PARSER_SCOPE_ERR(value));
267 }
268 }
269
270 private static class ArrayScope extends Scope {
271 private final Iterator<JsonValue> it;
272 private JsonValue value;
273
274 ArrayScope(JsonArray array) {
275 this.it = array.iterator();
276 }
277
278 @Override
279 public boolean hasNext() {
280 return it.hasNext();
281 }
282
283 @Override
284 public JsonValue next() {
285 value = it.next();
286 return value;
287 }
288
289 @Override
290 public void remove() {
291 throw new UnsupportedOperationException();
292 }
293
294 @Override
295 JsonValue getJsonValue() {
296 return value;
297 }
298
299 }
300
301 private static class ObjectScope extends Scope {
302 private final Iterator<Map.Entry<String, JsonValue>> it;
303 private JsonValue value;
304 private String key;
305
306 ObjectScope(JsonObject object) {
307 this.it = object.entrySet().iterator();
308 }
309
310 @Override
311 public boolean hasNext() {
312 return it.hasNext();
313 }
314
315 @Override
316 public Map.Entry<String, JsonValue> next() {
317 Map.Entry<String, JsonValue> next = it.next();
318 this.key = next.getKey();
319 this.value = next.getValue();
320 return next;
321 }
322
323 @Override
324 public void remove() {
325 throw new UnsupportedOperationException();
326 }
327
328 @Override
329 JsonValue getJsonValue() {
330 return value;
331 }
332
333 }
334
335}
Note: See TracBrowser for help on using the repository browser.