
org.eclipse.yasson.internal.JsonbRiParser Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Roman Grigoriadi
******************************************************************************/
package org.eclipse.yasson.internal;
import org.eclipse.yasson.internal.properties.MessageKeys;
import org.eclipse.yasson.internal.properties.Messages;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonValue;
import javax.json.bind.JsonbException;
import javax.json.stream.JsonLocation;
import javax.json.stream.JsonParser;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Map;
import java.util.Stack;
import java.util.stream.Stream;
/**
* Decorator for JSONP parser used by JSONB.
*
* @author Roman Grigoriadi
*/
public class JsonbRiParser implements JsonParser, JsonbParser {
/**
* State holder for current json structure level.
*/
public static class LevelContext {
private final LevelContext parent;
private JsonParser.Event lastEvent;
private String lastKeyName;
private boolean parsed;
/**
* Creates an instance.
*
* @param parent Parent context.
*/
public LevelContext(LevelContext parent) {
this.parent = parent;
}
/**
* Gets last event.
*
* @return Last event.
*/
public JsonParser.Event getLastEvent() {
return lastEvent;
}
private void setLastEvent(JsonParser.Event lastEvent) {
this.lastEvent = lastEvent;
}
/**
* Gets last key name.
*
* @return Last key name.
*/
public String getLastKeyName() {
return lastKeyName;
}
private void setLastKeyName(String lastKeyName) {
this.lastKeyName = lastKeyName;
}
/**
* Get parent.
*
* @return Parent.
*/
public LevelContext getParent() {
return parent;
}
/**
* Getter for parsed property.
*
* @return True or false.
*/
public boolean isParsed() {
return parsed;
}
private void finish() {
if (parsed) {
throw new IllegalStateException("Level already parsed");
}
parsed = true;
}
}
private final JsonParser jsonParser;
private final Stack level = new Stack<>();
private final LevelContext root = new LevelContext(null);
/**
* Creates a parser.
*
* @param jsonParser JSON-P parser to decorate.
*/
public JsonbRiParser(JsonParser jsonParser) {
this.jsonParser = jsonParser;
}
@Override
public boolean hasNext() {
return jsonParser.hasNext();
}
@Override
public long getLong() {
return jsonParser.getLong();
}
@Override
public int getInt() {
return jsonParser.getInt();
}
@Override
public JsonParser.Event next() {
final JsonParser.Event next = jsonParser.next();
final boolean rootLevel = level.empty();
if (rootLevel) {
root.setLastEvent(next);
} else {
level.peek().setLastEvent(next);
}
switch (next) {
case START_ARRAY:
case START_OBJECT:
final LevelContext newLevel = new LevelContext(rootLevel ? root : level.peek());
newLevel.setLastEvent(next);
level.push(newLevel);
break;
case END_ARRAY:
case END_OBJECT:
level.pop().finish();
break;
case KEY_NAME:
getCurrentLevel().setLastKeyName(jsonParser.getString());
break;
default:
break;
}
return next;
}
@Override
public boolean isIntegralNumber() {
return jsonParser.isIntegralNumber();
}
@Override
public BigDecimal getBigDecimal() {
return jsonParser.getBigDecimal();
}
@Override
public JsonLocation getLocation() {
return jsonParser.getLocation();
}
@Override
public void close() {
jsonParser.close();
}
@Override
public String getString() {
return jsonParser.getString();
}
@Override
public void moveTo(JsonParser.Event required) {
if (!level.empty() && level.peek().getLastEvent() == required) {
return;
}
final Event next = next();
if (next == required) {
return;
}
throw new JsonbException(Messages.getMessage(MessageKeys.INTERNAL_ERROR, "Event " + required + " not found." + getLastDataMsg()));
}
@Override
public Event moveToValue() {
return moveTo(Event.VALUE_STRING, Event.VALUE_NUMBER, Event.VALUE_FALSE, Event.VALUE_TRUE, Event.VALUE_NULL);
}
@Override
public Event moveToStartStructure() {
return moveTo(Event.START_OBJECT, Event.START_ARRAY);
}
private Event moveTo(Event... events) {
if (!level.empty() && contains(events, level.peek().getLastEvent())) {
return level.peek().getLastEvent();
}
final Event next = next();
if (contains(events, next)) {
return next;
}
throw new JsonbException(Messages.getMessage(MessageKeys.INTERNAL_ERROR, "Parser event ["+Arrays.toString(events)+"] not found." + getLastDataMsg()));
}
private boolean contains(Event[] events, Event candidate) {
for (Event event : events) {
if (event == candidate) {
return true;
}
}
return false;
}
private String getLastDataMsg() {
StringBuilder builder = new StringBuilder();
final LevelContext currentLevel = getCurrentLevel();
builder.append(" Last data: [").append("EVENT: ").append(currentLevel.getLastEvent()).append(" KEY_NAME: ")
.append(currentLevel.getLastKeyName()).append("]");
return builder.toString();
}
@Override
public LevelContext getCurrentLevel() {
if (level.empty()) {
return root;
}
return level.peek();
}
@Override
public void skipJsonStructure() {
final LevelContext currentLevel = level.peek();
switch (currentLevel.getLastEvent()) {
case START_ARRAY:
case START_OBJECT:
while (!currentLevel.isParsed()) {
next();
}
return;
default:
return;
}
}
@Override
public JsonObject getObject() {
JsonObject object = jsonParser.getObject();
level.pop();
return object;
}
@Override
public JsonValue getValue() {
return jsonParser.getValue();
}
@Override
public JsonArray getArray() {
JsonArray result = jsonParser.getArray();
level.pop();
return result;
}
@Override
public Stream getArrayStream() {
return jsonParser.getArrayStream();
}
@Override
public Stream> getObjectStream() {
return jsonParser.getObjectStream();
}
@Override
public Stream getValueStream() {
return jsonParser.getValueStream();
}
@Override
public void skipArray() {
jsonParser.skipArray();
level.pop();
}
@Override
public void skipObject() {
jsonParser.skipObject();
level.pop();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy