/* Copyright (c) 2011 Danish Maritime Authority. * * Licensed 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 net.maritimecloud.internal.message.text.json; import static java.util.Objects.requireNonNull; import java.io.IOException; import java.io.StringReader; import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import net.maritimecloud.internal.core.javax.json.JsonObject; import net.maritimecloud.internal.core.javax.json.JsonReader; import net.maritimecloud.internal.core.javax.json.JsonString; import net.maritimecloud.internal.core.javax.json.JsonValue; import net.maritimecloud.internal.core.javax.json.spi.JsonProvider; import net.maritimecloud.internal.message.AbstractMessageReader; import net.maritimecloud.message.Message; import net.maritimecloud.message.MessageEnum; import net.maritimecloud.message.MessageEnumSerializer; import net.maritimecloud.message.MessageFormatType; import net.maritimecloud.message.MessageSerializer; import net.maritimecloud.message.SerializationException; import net.maritimecloud.message.ValueReader; import net.maritimecloud.message.ValueSerializer; /** * * @author Kasper Nielsen */ public class JsonMessageReader extends AbstractMessageReader { final JsonIterator iter; final JsonReader r; public JsonMessageReader(CharSequence s) { this(JsonProvider.provider().createReader(new StringReader(s.toString()))); } /** {@inheritDoc} */ @Override public final MessageFormatType getFormatType() { return MessageFormatType.HUMAN_READABLE; } public JsonMessageReader(JsonObject o) { this.r = null; this.iter = new JsonIterator(o); } public JsonMessageReader(JsonReader r) { this.r = requireNonNull(r); iter = new JsonIterator(r.readObject()); } /** {@inheritDoc} */ @Override public void close() throws IOException {} protected ValueReader find(int tag, String name) throws SerializationException { if (isNext(-1, name)) { return new JsonValueReader(iter.next().getValue()); } throw new SerializationException("Could not find tag '" + name + "'"); } protected ValueReader findOptional(int tag, String name) { if (isNext(-1, name)) { return new JsonValueReader(iter.next().getValue()); } return null; } /** {@inheritDoc} */ @Override public boolean isNext(int tag, String name) { requireNonNull(name, "name is null"); if (iter.hasNext()) { return name.equals(iter.peek().getKey()); } return false; } /** {@inheritDoc} */ @Override public <T extends MessageEnum> T readEnum(int tag, String name, MessageEnumSerializer<T> factory) throws IOException { ValueReader r = find(tag, name); return factory.from(r.readText()); } /** {@inheritDoc} */ @Override public <K, V> Map<K, V> readMap(int tag, String name, ValueSerializer<K> keyParser, ValueSerializer<V> valueParser) throws IOException { if (isNext(-1, name)) { Entry<String, JsonValue> next = iter.next(); return new JsonValueReader(next.getValue()).readMap(keyParser, valueParser); } return Collections.emptyMap(); } /** {@inheritDoc} */ @Override public <T extends Message> T readMessage(int tag, String name, MessageSerializer<T> parser) throws IOException { if (isNext(-1, name)) { Entry<String, JsonValue> next = iter.next(); return new JsonValueReader(next.getValue()).readMessage(parser); // // JsonIterator existing = iter; // Entry<String, JsonValue> next = iter.next(); // JsonObject a = (JsonObject) next.getValue(); // iter = new JsonIterator(a); // T result = parser.parse(this); // iter = existing; // return result; } return null; // parser.parse(null) // stack.push(o); // o = (JSONObject) o.get(name); // T result = parser.parse(this); // o = stack.pop(); // return result; } // A Quick hack public static <T> T readFromString(String value, ValueSerializer<T> parser) throws IOException { String ss = " { \"x\": " + value + "}"; JsonReader reader = JsonProvider.provider().createReader(new StringReader(ss)); JsonObject o = reader.readObject(); JsonValue val = o.get("x"); ValueReader r = new JsonValueReader(val); return parser.read(r); } static class JsonIterator { Iterator<Entry<String, net.maritimecloud.internal.core.javax.json.JsonValue>> iter; private Entry<String, net.maritimecloud.internal.core.javax.json.JsonValue> next; final JsonObject o; JsonIterator(JsonObject o) { this.o = o; iter = o.entrySet().iterator(); if (iter.hasNext()) { next = iter.next(); } } boolean hasNext() { return next != null; } Entry<String, net.maritimecloud.internal.core.javax.json.JsonValue> next() { Entry<String, net.maritimecloud.internal.core.javax.json.JsonValue> n = next; if (iter.hasNext()) { next = iter.next(); } else { next = null; } return n; } Entry<String, net.maritimecloud.internal.core.javax.json.JsonValue> peek() { return next; } } } final class JsonStringImpl implements JsonString { private final String value; JsonStringImpl(String value) { this.value = value; } public boolean equals(Object obj) { if (!(obj instanceof JsonString)) { return false; } JsonString other = (JsonString) obj; return getString().equals(other.getString()); } public CharSequence getChars() { return this.value; } public String getString() { return this.value; } public JsonValue.ValueType getValueType() { return JsonValue.ValueType.STRING; } public int hashCode() { return getString().hashCode(); } public String toString() { StringBuilder sb = new StringBuilder(); sb.append('"'); for (int i = 0; i < this.value.length(); ++i) { char c = this.value.charAt(i); if (c >= ' ' && c <= 1114111 && c != '"' && c != '\\') { sb.append(c); } else { switch (c) { case '"': case '\\': sb.append('\\'); sb.append(c); break; case '\b': sb.append('\\'); sb.append('b'); break; case '\f': sb.append('\\'); sb.append('f'); break; case '\n': sb.append('\\'); sb.append('n'); break; case '\r': sb.append('\\'); sb.append('r'); break; case '\t': sb.append('\\'); sb.append('t'); break; default: String hex = new StringBuilder().append("000").append(Integer.toHexString(c)).toString(); sb.append("\\u").append(hex.substring(hex.length() - 4)); } } } sb.append('"'); return sb.toString(); } } // public static ValueReader readFromString(String value) { // String ss = " { \"x\": " + value + "}"; // JsonReader reader = JsonProvider.provider().createReader(new StringReader(ss)); // JsonObject o = reader.readObject(); // JsonValue val = o.get("x"); // return new JsonValueReader(val); // }