blob: 1f2e33eb8c107a26ad6bcefa3d57a77f952d11bf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.johnzon.core;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.stream.Stream;
import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonString;
import javax.json.JsonValue;
import javax.json.JsonValue.ValueType;
import javax.json.stream.JsonLocation;
class JsonInMemoryParser implements JohnzonJsonParser {
private final SimpleStack<Iterator<Event>> stack = new SimpleStack<Iterator<Event>>();
private Event currentEvent;
private JsonValue currentValue;
private class ArrayIterator implements Iterator<Event> {
private final Iterator<JsonValue> aentries;
private Boolean end = null;
public ArrayIterator(final JsonArray ja) {
aentries = ja.iterator();
}
@Override
public boolean hasNext() {
return !Boolean.TRUE.equals(end);
}
@Override
public Event next() {
if (end == null) {
end = Boolean.FALSE;
return Event.START_ARRAY;
} else if (!aentries.hasNext()) {
if (!stack.isEmpty()) {
stack.pop();
}
end = Boolean.TRUE;
return Event.END_ARRAY;
} else {
final JsonValue val = aentries.next();
final ValueType vt = val.getValueType();
if (vt == ValueType.OBJECT) {
stack.push(new ObjectIterator((JsonObject) val));
return stack.peek().next();
} else if (vt == ValueType.ARRAY) {
stack.push(new ArrayIterator((JsonArray) val));
return stack.peek().next();
} else {
currentValue = val;
return getEvent(vt);
}
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
private class ObjectIterator implements Iterator<Event> {
private final Iterator<Map.Entry<String, JsonValue>> oentries;
private JsonValue jsonValue;
private Boolean end = null;
public ObjectIterator(final JsonObject jo) {
oentries = jo.entrySet().iterator();
}
@Override
public boolean hasNext() {
return !Boolean.TRUE.equals(end);
}
@Override
public Event next() {
if (end == null) {
end = Boolean.FALSE;
return Event.START_OBJECT;
} else if (jsonValue == null && !oentries.hasNext()) {
if (!stack.isEmpty()) {
stack.pop();
}
end = Boolean.TRUE;
return Event.END_OBJECT;
} else if (jsonValue == null) {
final Map.Entry<String, JsonValue> tmp = oentries.next();
jsonValue = tmp.getValue();
currentValue = new JsonStringImpl(tmp.getKey());
return Event.KEY_NAME;
} else {
final ValueType vt = jsonValue.getValueType();
if (vt == ValueType.OBJECT) {
stack.push(new ObjectIterator((JsonObject) jsonValue));
jsonValue = null;
return stack.peek().next();
} else if (vt == ValueType.ARRAY) {
stack.push(new ArrayIterator((JsonArray) jsonValue));
jsonValue = null;
return stack.peek().next();
} else {
final Event ret = getEvent(vt);
currentValue = jsonValue;
jsonValue = null;
return ret;
}
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
private static Event getEvent(final ValueType value) {
switch (value) {
case NUMBER:
return Event.VALUE_NUMBER;
case STRING:
return Event.VALUE_STRING;
case FALSE:
return Event.VALUE_FALSE;
case NULL:
return Event.VALUE_NULL;
case TRUE:
return Event.VALUE_TRUE;
default:
throw new IllegalArgumentException(value + " not supported");
}
}
JsonInMemoryParser(final JsonObject object) {
stack.push(new ObjectIterator(object));
}
JsonInMemoryParser(final JsonArray array) {
stack.push(new ArrayIterator(array));
}
@Override
public boolean hasNext() {
return !stack.isEmpty();
}
@Override
public Event next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
currentEvent = stack.peek().next();
return currentEvent;
}
@Override
public String getString() {
if (currentEvent != Event.KEY_NAME && currentEvent != Event.VALUE_STRING) {
throw new IllegalStateException("String is for numbers and strings");
}
return JsonString.class.cast(currentValue).getString();
}
@Override
public boolean isIntegralNumber() {
if (currentEvent != Event.VALUE_NUMBER) {
throw new IllegalStateException("isIntegralNumber is for numbers");
}
return JsonNumber.class.cast(currentValue).isIntegral();
}
@Override
public boolean isNotTooLong() {
return true;
}
@Override
public int getInt() {
if (currentEvent != Event.VALUE_NUMBER) {
throw new IllegalStateException("getInt is for numbers");
}
return JsonNumber.class.cast(currentValue).intValue();
}
@Override
public long getLong() {
if (currentEvent != Event.VALUE_NUMBER) {
throw new IllegalStateException("getLong is for numbers");
}
return JsonNumber.class.cast(currentValue).longValue();
}
@Override
public BigDecimal getBigDecimal() {
if (currentEvent != Event.VALUE_NUMBER) {
throw new IllegalStateException("getBigDecimal is for numbers");
}
return JsonNumber.class.cast(currentValue).bigDecimalValue();
}
@Override
public JsonLocation getLocation() { // no location for in memory parsers
return JsonLocationImpl.UNKNOWN_LOCATION;
}
@Override
public void close() {
// no-op
}
@Override
public JsonObject getObject() {
throw new UnsupportedOperationException();
}
@Override
public JsonValue getValue() {
throw new UnsupportedOperationException();
}
@Override
public JsonArray getArray() {
throw new UnsupportedOperationException();
}
@Override
public Stream<JsonValue> getArrayStream() {
throw new UnsupportedOperationException();
}
@Override
public Stream<Map.Entry<String, JsonValue>> getObjectStream() {
throw new UnsupportedOperationException();
}
@Override
public Stream<JsonValue> getValueStream() {
throw new UnsupportedOperationException();
}
@Override
public void skipArray() {
throw new UnsupportedOperationException();
}
@Override
public void skipObject() {
throw new UnsupportedOperationException();
}
}