From dcbf1f7b9b958a345204494514d568b59aca6096 Mon Sep 17 00:00:00 2001 From: Peter Kajsa Date: Thu, 11 Dec 2014 16:43:02 +0100 Subject: [PATCH] Updated Json Stream Writer to use gson JsonWriter. Custom implementation of JSON writing methods has been replaced with native com.google.gson.stream.JsonWriter methods. Among other things, this rework resolves issues (bugs) with escape characters in string values being written into Json (e.g. new lines in strings etc.). Important notice: com.google.gson.stream.JsonWriter enforces that output must start with '{' and end with '}', otherwise 'java.lang.IllegalStateException:Nesting problem' is thrown. So our original output looks for an example like: "my-module:top-container": { ... } Now, new output looks as following: { "my-module:top-container": { ... } } . Change-Id: I8073285d003015721d54887ddbff0484d7db89c8 Signed-off-by: Peter Kajsa --- .../data/codec/gson/AbstractJSONCodec.java | 21 ++-- .../data/codec/gson/BooleanJSONCodec.java | 39 +++++++ .../yang/data/codec/gson/JSONCodec.java | 12 ++ .../data/codec/gson/JSONCodecFactory.java | 11 +- .../data/codec/gson/JSONLeafrefCodec.java | 13 +++ .../gson/JSONNormalizedNodeStreamWriter.java | 110 +++++++++--------- .../codec/gson/JSONStreamWriterContext.java | 48 +++----- .../JSONStreamWriterInvisibleContext.java | 5 +- .../gson/JSONStreamWriterListContext.java | 10 +- .../JSONStreamWriterNamedObjectContext.java | 5 +- .../gson/JSONStreamWriterObjectContext.java | 12 +- .../gson/JSONStreamWriterRootContext.java | 14 ++- .../gson/JSONStreamWriterURIContext.java | 6 +- .../gson/JSONStringIdentityrefCodec.java | 15 ++- .../JSONStringInstanceIdentifierCodec.java | 15 ++- .../data/codec/gson/JsonWriterFactory.java | 47 ++++++++ ...tedJSONCodec.java => NumberJSONCodec.java} | 17 ++- .../yang/data/codec/gson/QuotedJSONCodec.java | 13 +++ .../gson/NormalizedNodeToJsonStreamTest.java | 4 +- 19 files changed, 287 insertions(+), 130 deletions(-) create mode 100644 yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/BooleanJSONCodec.java create mode 100644 yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonWriterFactory.java rename yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/{UnquotedJSONCodec.java => NumberJSONCodec.java} (58%) diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractJSONCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractJSONCodec.java index 94646531a8..9b3f3d2ac4 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractJSONCodec.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractJSONCodec.java @@ -8,7 +8,6 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import com.google.common.base.Preconditions; - import org.opendaylight.yangtools.concepts.Codec; import org.opendaylight.yangtools.yang.data.api.codec.BooleanCodec; import org.opendaylight.yangtools.yang.data.api.codec.DecimalCodec; @@ -39,16 +38,18 @@ abstract class AbstractJSONCodec implements JSONCodec { * @param codec underlying codec * @return A JSONCodec instance */ - public static JSONCodec create(final Codec codec) { - if (codec instanceof BooleanCodec || codec instanceof DecimalCodec || - codec instanceof Int8Codec || codec instanceof Int16Codec || - codec instanceof Int32Codec || codec instanceof Int64Codec || - codec instanceof Uint8Codec || codec instanceof Uint16Codec || - codec instanceof Uint32Codec || codec instanceof Uint64Codec) { - return new UnquotedJSONCodec<>(codec); + public static JSONCodec create(final Codec codec) { + if (codec instanceof BooleanCodec) { + return new BooleanJSONCodec((BooleanCodec) codec); + } else if (codec instanceof DecimalCodec || codec instanceof Int8Codec + || codec instanceof Int16Codec || codec instanceof Int32Codec + || codec instanceof Int64Codec || codec instanceof Uint8Codec + || codec instanceof Uint16Codec || codec instanceof Uint32Codec + || codec instanceof Uint64Codec) { + return new NumberJSONCodec(codec); + } else { + return new QuotedJSONCodec<>(codec); } - - return new QuotedJSONCodec<>(codec); } @Override diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/BooleanJSONCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/BooleanJSONCodec.java new file mode 100644 index 0000000000..0840cd43a9 --- /dev/null +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/BooleanJSONCodec.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.data.codec.gson; + +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import org.opendaylight.yangtools.concepts.Codec; + +/** + * A {@link JSONCodec} which does not need double quotes in output representation. + * + * @param Deserialized value type + */ +final class BooleanJSONCodec extends AbstractJSONCodec { + BooleanJSONCodec(final Codec codec) { + super(codec); + } + + @Override + public boolean needQuotes() { + return false; + } + + /** + * Serialize specified value with specified JsonWriter. + * + * @param writer JsonWriter + * @param value + */ + @Override + public void serializeToWriter(JsonWriter writer, Boolean value) throws IOException { + writer.value(value); + }; +} \ No newline at end of file diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java index aa52259c58..003684cbf6 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java @@ -7,8 +7,20 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import org.opendaylight.yangtools.concepts.Codec; interface JSONCodec extends Codec { + // FIXME: Unused, remove once we are sure we do not need this anymore. boolean needQuotes(); + + + /** + * Serialize specified value with specified JsonWriter. + * + * @param writer JsonWriter + * @param value + */ + void serializeToWriter(JsonWriter writer, T value) throws IOException; } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodecFactory.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodecFactory.java index 8ee9517ec2..c99d464048 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodecFactory.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodecFactory.java @@ -12,7 +12,8 @@ import com.google.common.base.Preconditions; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; - +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; @@ -45,6 +46,12 @@ public final class JSONCodecFactory { public boolean needQuotes() { return false; } + + @Override + public void serializeToWriter(JsonWriter writer, Object value) throws IOException { + // NOOP since codec is unkwown. + LOG.warn("Call of the serializeToWriter method on JSONCodecFactory.NULL_CODEC object. No operation performed."); + } }; private static TypeDefinition resolveBaseTypeFrom(final TypeDefinition type) { @@ -78,7 +85,7 @@ public final class JSONCodecFactory { return NULL_CODEC; } - return AbstractJSONCodec.create(codec); + return (JSONCodec) AbstractJSONCodec.create(codec); } }); diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java index 5613433bbe..51fc686513 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java @@ -7,6 +7,8 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec; final class JSONLeafrefCodec implements JSONCodec, LeafrefCodec { @@ -24,4 +26,15 @@ final class JSONLeafrefCodec implements JSONCodec, LeafrefCodec public boolean needQuotes() { return true; } + + /** + * Serialize specified value with specified JsonWriter. + * + * @param writer JsonWriter + * @param value + */ + @Override + public void serializeToWriter(JsonWriter writer, Object value) throws IOException { + writer.value(serialize(value)); + } } \ No newline at end of file diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java index 59ef1f1e50..079b8e324a 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java @@ -7,9 +7,7 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; -import com.google.common.base.CharMatcher; import com.google.common.base.Preconditions; -import com.google.common.base.Strings; import com.google.gson.stream.JsonWriter; import java.io.IOException; import java.io.Writer; @@ -31,7 +29,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaPath; * * Values of leaf and leaf-list are NOT translated according to codecs. * - * FIXME: rewrite this in terms of {@link JsonWriter}. */ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter { /** @@ -40,27 +37,13 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite */ private static final boolean DEFAULT_EMIT_EMPTY_CONTAINERS = true; - /** - * Matcher used to check if a string needs to be escaped. - */ - private static final CharMatcher JSON_ILLEGAL_STRING_CHARACTERS = CharMatcher.anyOf("\\\"\n\r"); - private final SchemaTracker tracker; private final JSONCodecFactory codecs; - private final Writer writer; - private final String indent; + private final JsonWriter writer; private JSONStreamWriterContext context; - private JSONNormalizedNodeStreamWriter(final JSONCodecFactory codecFactory, final SchemaPath path, - final Writer writer, final URI initialNs, final int indentSize) { - this.writer = Preconditions.checkNotNull(writer); - - Preconditions.checkArgument(indentSize >= 0, "Indent size must be non-negative"); - if (indentSize != 0) { - indent = Strings.repeat(" ", indentSize); - } else { - indent = null; - } + private JSONNormalizedNodeStreamWriter(final JSONCodecFactory codecFactory, final SchemaPath path, final URI initialNs, JsonWriter JsonWriter) { + this.writer = JsonWriter; this.codecs = Preconditions.checkNotNull(codecFactory); this.tracker = SchemaTracker.create(codecFactory.getSchemaContext(), path); this.context = new JSONStreamWriterRootContext(initialNs); @@ -74,7 +57,7 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite * @return A stream writer instance */ public static NormalizedNodeStreamWriter create(final SchemaContext schemaContext, final Writer writer) { - return new JSONNormalizedNodeStreamWriter(JSONCodecFactory.create(schemaContext), SchemaPath.ROOT, writer, null, 0); + return create(schemaContext, SchemaPath.ROOT, null, writer); } /** @@ -86,7 +69,7 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite * @return A stream writer instance */ public static NormalizedNodeStreamWriter create(final SchemaContext schemaContext, final SchemaPath path, final Writer writer) { - return new JSONNormalizedNodeStreamWriter(JSONCodecFactory.create(schemaContext), path, writer, null, 0); + return create(schemaContext, path, null, writer); } /** @@ -100,7 +83,7 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite */ public static NormalizedNodeStreamWriter create(final SchemaContext schemaContext, final SchemaPath path, final URI initialNs, final Writer writer) { - return new JSONNormalizedNodeStreamWriter(JSONCodecFactory.create(schemaContext), path, writer, initialNs, 0); + return create(JSONCodecFactory.create(schemaContext), path, initialNs, JsonWriterFactory.createJsonWriter(writer)); } /** @@ -112,7 +95,7 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite * @return A stream writer instance */ public static NormalizedNodeStreamWriter create(final SchemaContext schemaContext, final Writer writer, final int indentSize) { - return new JSONNormalizedNodeStreamWriter(JSONCodecFactory.create(schemaContext), SchemaPath.ROOT, writer, null, indentSize); + return create(JSONCodecFactory.create(schemaContext), SchemaPath.ROOT, null,JsonWriterFactory.createJsonWriter(writer, indentSize)); } /** @@ -125,7 +108,35 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite * @return A stream writer instance */ public static NormalizedNodeStreamWriter create(final JSONCodecFactory codecFactory, final Writer writer, final int indentSize) { - return new JSONNormalizedNodeStreamWriter(codecFactory, SchemaPath.ROOT, writer, null, indentSize); + return create(codecFactory, SchemaPath.ROOT, null, JsonWriterFactory.createJsonWriter(writer,indentSize)); + } + + /** + * Create a new stream writer, which writes to the specified output stream. + * + * @param schemaContext Schema context + * @param path Schema Path + * @param initialNs Initial namespace + * @param jsonWriter JsonWriter + * @return A stream writer instance + */ + public static NormalizedNodeStreamWriter create(SchemaContext schemaContext, SchemaPath path, URI initialNs, + JsonWriter jsonWriter) { + return create(JSONCodecFactory.create(schemaContext), path, initialNs, jsonWriter); + } + + /** + * Create a new stream writer, which writes to the specified output stream. The codec factory + * can be reused between multiple writers. + * + * @param codecFactory JSON codec factory + * @param path Schema Path + * @param initialNs Initial namespace + * @param jsonWriter JsonWriter + * @return A stream writer instance + */ + public static NormalizedNodeStreamWriter create(JSONCodecFactory codecFactory, SchemaPath path, URI initialNs, JsonWriter jsonWriter) { + return new JSONNormalizedNodeStreamWriter(codecFactory, path, initialNs, jsonWriter); } @Override @@ -133,9 +144,10 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite final LeafSchemaNode schema = tracker.leafNode(name); final JSONCodec codec = codecs.codecFor(schema.getType()); - context.emittingChild(codecs.getSchemaContext(), writer, indent); + context.emittingChild(codecs.getSchemaContext(), writer); context.writeChildJsonIdentifier(codecs.getSchemaContext(), writer, name.getNodeType()); - writeValue(codec.serialize(value), codec.needQuotes()); + + writeValue(value, codec); } @Override @@ -149,8 +161,9 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite final LeafListSchemaNode schema = tracker.leafSetEntryNode(); final JSONCodec codec = codecs.codecFor(schema.getType()); - context.emittingChild(codecs.getSchemaContext(), writer, indent); - writeValue(codec.serialize(value), codec.needQuotes()); + context.emittingChild(codecs.getSchemaContext(), writer); + + writeValue(value, codec); } /* @@ -216,42 +229,23 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite final AnyXmlSchemaNode schema = tracker.anyxmlNode(name); // FIXME: should have a codec based on this :) - context.emittingChild(codecs.getSchemaContext(), writer, indent); + context.emittingChild(codecs.getSchemaContext(), writer); context.writeChildJsonIdentifier(codecs.getSchemaContext(), writer, name.getNodeType()); - writeValue(String.valueOf(value), true); + writer.value(String.valueOf(value)); } @Override public void endNode() throws IOException { tracker.endNode(); - context = context.endNode(codecs.getSchemaContext(), writer, indent); + context = context.endNode(codecs.getSchemaContext(), writer); + if(context instanceof JSONStreamWriterRootContext) { + context.emitEnd(writer); + } } - private void writeValue(final String str, final boolean needQuotes) throws IOException { - if (needQuotes) { - writer.append('"'); - - final int needEscape = JSON_ILLEGAL_STRING_CHARACTERS.countIn(str); - if (needEscape != 0) { - final char[] escaped = new char[str.length() + needEscape]; - int offset = 0; - - for (int i = 0; i < str.length(); i++) { - final char c = str.charAt(i); - if (JSON_ILLEGAL_STRING_CHARACTERS.matches(c)) { - escaped[offset++] = '\\'; - } - escaped[offset++] = c; - } - writer.write(escaped); - } else { - writer.append(str); - } - - writer.append('"'); - } else { - writer.append(str); - } + private void writeValue(Object value, JSONCodec codec) + throws IOException { + codec.serializeToWriter(writer,value); } @Override @@ -265,4 +259,6 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite writer.close(); } + + } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterContext.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterContext.java index a3ad80dfb3..a29972aa93 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterContext.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterContext.java @@ -8,8 +8,9 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import com.google.common.base.Preconditions; +import com.google.gson.stream.JsonWriter; import java.io.IOException; -import java.io.Writer; +import java.io.StringWriter; import java.net.URI; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.QName; @@ -26,7 +27,6 @@ abstract class JSONStreamWriterContext { private final boolean mandatory; private final int depth; private boolean emittedMyself = false; - private boolean haveChild = false; /** * Construct a new context. @@ -55,21 +55,21 @@ abstract class JSONStreamWriterContext { * @param qname Namespace/name tuple * @throws IOException when the writer reports it */ - final void writeChildJsonIdentifier(final SchemaContext schema, final Writer writer, final QName qname) throws IOException { - writer.append('"'); + final void writeChildJsonIdentifier(final SchemaContext schema, final JsonWriter writer, final QName qname) throws IOException { + StringWriter strWriter = new StringWriter(); // Prepend module name if namespaces do not match final URI ns = qname.getNamespace(); if (!ns.equals(getNamespace())) { final Module module = schema.findModuleByNamespaceAndRevision(ns, null); Preconditions.checkArgument(module != null, "Could not find module for namespace {}", ns); - writer.append(module.getName()); - writer.append(':'); + strWriter.append(module.getName()); + strWriter.append(':'); } + strWriter.append(qname.getLocalName()); - writer.append(qname.getLocalName()); - writer.append("\":"); + writer.name(strWriter.toString()); } /** @@ -81,7 +81,7 @@ abstract class JSONStreamWriterContext { * @param qname Namespace/name tuple * @throws IOException when the writer reports it */ - protected final void writeMyJsonIdentifier(final SchemaContext schema, final Writer writer, final QName qname) throws IOException { + protected final void writeMyJsonIdentifier(final SchemaContext schema, final JsonWriter writer, final QName qname) throws IOException { parent.writeChildJsonIdentifier(schema, writer, qname); } @@ -99,7 +99,7 @@ abstract class JSONStreamWriterContext { * @param writer Output writer * @throws IOException */ - protected abstract void emitStart(final SchemaContext schema, final Writer writer) throws IOException; + protected abstract void emitStart(final SchemaContext schema, final JsonWriter writer) throws IOException; /** * Emit the end of an element. @@ -108,12 +108,12 @@ abstract class JSONStreamWriterContext { * @param writer Output writer * @throws IOException */ - protected abstract void emitEnd(final Writer writer) throws IOException; + protected abstract void emitEnd(final JsonWriter writer) throws IOException; - private final void emitMyself(final SchemaContext schema, final Writer writer, final String indent) throws IOException { + private final void emitMyself(final SchemaContext schema, final JsonWriter writer) throws IOException { if (!emittedMyself) { if (parent != null) { - parent.emittingChild(schema, writer, indent); + parent.emittingChild(schema, writer); } emitStart(schema, writer); @@ -128,23 +128,10 @@ abstract class JSONStreamWriterContext { * * @param schema Schema context * @param writer Output writer - * @param indent Indentation string * @throws IOException when writer reports it */ - final void emittingChild(final SchemaContext schema, final Writer writer, final String indent) throws IOException { - emitMyself(schema, writer, indent); - if (haveChild) { - writer.append(','); - } - - if (indent != null) { - writer.append('\n'); - - for (int i = 0; i < depth; i++) { - writer.append(indent); - } - } - haveChild = true; + final void emittingChild(final SchemaContext schema, final JsonWriter writer) throws IOException { + emitMyself(schema, writer); } /** @@ -153,14 +140,13 @@ abstract class JSONStreamWriterContext { * * @param schema Schema context * @param writer Output writer - * @param indent Indentation string * @return Parent node context * @throws IOException when writer reports it * @throws IllegalArgumentException if this node cannot be ended (e.g. root) */ - final JSONStreamWriterContext endNode(final SchemaContext schema, final Writer writer, final String indent) throws IOException { + final JSONStreamWriterContext endNode(final SchemaContext schema, final JsonWriter writer) throws IOException { if (!emittedMyself && mandatory) { - emitMyself(schema, writer, indent); + emitMyself(schema, writer); } if (emittedMyself) { diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterInvisibleContext.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterInvisibleContext.java index 7f22c19466..e43aead9f4 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterInvisibleContext.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterInvisibleContext.java @@ -8,8 +8,9 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import com.google.common.base.Preconditions; +import com.google.gson.stream.JsonWriter; + -import java.io.Writer; /** * A virtual recursion level in {@link JSONNormalizedNodeStreamWriter}, used for nodes @@ -21,7 +22,7 @@ final class JSONStreamWriterInvisibleContext extends JSONStreamWriterURIContext } @Override - protected void emitEnd(final Writer writer) { + protected void emitEnd(final JsonWriter writer) { // No-op } } \ No newline at end of file diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterListContext.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterListContext.java index 9c0be476b1..e1505c7b10 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterListContext.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterListContext.java @@ -8,8 +8,8 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import com.google.common.base.Preconditions; +import com.google.gson.stream.JsonWriter; import java.io.IOException; -import java.io.Writer; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.model.api.SchemaContext; @@ -23,13 +23,13 @@ final class JSONStreamWriterListContext extends JSONStreamWriterQNameContext { } @Override - protected void emitStart(final SchemaContext schema, final Writer writer) throws IOException { + protected void emitStart(final SchemaContext schema, final JsonWriter writer) throws IOException { writeMyJsonIdentifier(schema, writer, getQName()); - writer.append('['); + writer.beginArray(); } @Override - protected void emitEnd(final Writer writer) throws IOException { - writer.append(']'); + protected void emitEnd(final JsonWriter writer) throws IOException { + writer.endArray(); } } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterNamedObjectContext.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterNamedObjectContext.java index 91c6ca70ae..fe08410caf 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterNamedObjectContext.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterNamedObjectContext.java @@ -7,11 +7,12 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; +import com.google.gson.stream.JsonWriter; import java.io.IOException; -import java.io.Writer; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.model.api.SchemaContext; + /** * A recursion level of {@link JSONNormalizedNodeStreamWriter}, which represents * a JSON object which has to be prefixed with its identifier -- such as a @@ -23,7 +24,7 @@ final class JSONStreamWriterNamedObjectContext extends JSONStreamWriterObjectCon } @Override - protected void emitStart(final SchemaContext schema, final Writer writer) throws IOException { + protected void emitStart(final SchemaContext schema, final JsonWriter writer) throws IOException { writeMyJsonIdentifier(schema, writer, getQName()); super.emitStart(schema, writer); } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterObjectContext.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterObjectContext.java index d12f0449dd..fb4e48ed60 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterObjectContext.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterObjectContext.java @@ -8,10 +8,8 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import com.google.common.base.Preconditions; - +import com.google.gson.stream.JsonWriter; import java.io.IOException; -import java.io.Writer; - import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.model.api.SchemaContext; @@ -26,12 +24,12 @@ class JSONStreamWriterObjectContext extends JSONStreamWriterQNameContext { } @Override - protected void emitStart(final SchemaContext schema, final Writer writer) throws IOException { - writer.append('{'); + protected void emitStart(final SchemaContext schema, final JsonWriter writer) throws IOException { + writer.beginObject(); } @Override - protected void emitEnd(final Writer writer) throws IOException { - writer.append('}'); + protected void emitEnd(final JsonWriter writer) throws IOException { + writer.endObject(); } } \ No newline at end of file diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterRootContext.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterRootContext.java index 36c3ff38c3..bb0d49dc86 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterRootContext.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterRootContext.java @@ -7,8 +7,11 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; -import java.io.Writer; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.net.URI; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + /** * The root node of a particular {@link JSONNormalizedNodeStreamWriter} instance. @@ -20,7 +23,12 @@ final class JSONStreamWriterRootContext extends JSONStreamWriterURIContext { } @Override - protected void emitEnd(final Writer writer) { - throw new IllegalArgumentException("Top-level node reached"); + protected void emitStart(final SchemaContext schema, final JsonWriter writer) throws IOException { + writer.beginObject(); + } + + @Override + protected void emitEnd(final JsonWriter writer) throws IOException { + writer.endObject(); } } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterURIContext.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterURIContext.java index 06c32bf26d..f0d286a427 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterURIContext.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStreamWriterURIContext.java @@ -7,12 +7,12 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; +import com.google.gson.stream.JsonWriter; import java.io.IOException; -import java.io.Writer; import java.net.URI; - import org.opendaylight.yangtools.yang.model.api.SchemaContext; + /** * Abstract class tracking a virtual level of {@link JSONNormalizedNodeStreamWriter} * recursion. It only tracks the namespace associated with this node. @@ -31,7 +31,7 @@ abstract class JSONStreamWriterURIContext extends JSONStreamWriterContext { } @Override - protected final void emitStart(final SchemaContext schema, final Writer writer) throws IOException { + protected void emitStart(final SchemaContext schema, final JsonWriter writer) throws IOException { // No-op } } \ No newline at end of file diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringIdentityrefCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringIdentityrefCodec.java index fcbe473cca..7e099b4e2d 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringIdentityrefCodec.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringIdentityrefCodec.java @@ -8,9 +8,9 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import com.google.common.base.Preconditions; - +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.net.URI; - import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringIdentityrefCodec; import org.opendaylight.yangtools.yang.model.api.Module; @@ -38,4 +38,15 @@ final class JSONStringIdentityrefCodec extends AbstractModuleStringIdentityrefCo public boolean needQuotes() { return true; } + + /** + * Serialize QName with specified JsonWriter. + * + * @param writer JsonWriter + * @param value QName + */ + @Override + public void serializeToWriter(JsonWriter writer, QName value) throws IOException { + writer.value(serialize(value)); + } } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringInstanceIdentifierCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringInstanceIdentifierCodec.java index a1580dd5bb..77fa797efa 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringInstanceIdentifierCodec.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringInstanceIdentifierCodec.java @@ -8,9 +8,9 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import com.google.common.base.Preconditions; - +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.net.URI; - import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec; import org.opendaylight.yangtools.yang.model.api.Module; @@ -38,4 +38,15 @@ final class JSONStringInstanceIdentifierCodec extends AbstractModuleStringInstan public boolean needQuotes() { return true; } + + /** + * Serialize YangInstanceIdentifier with specified JsonWriter. + * + * @param writer JsonWriter + * @param value YangInstanceIdentifier + */ + @Override + public void serializeToWriter(JsonWriter writer, YangInstanceIdentifier value) throws IOException { + writer.value(serialize(value)); + } } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonWriterFactory.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonWriterFactory.java new file mode 100644 index 0000000000..3b3bf8d013 --- /dev/null +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonWriterFactory.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.data.codec.gson; + +import com.google.common.annotations.Beta; +import com.google.common.base.Strings; +import com.google.gson.stream.JsonWriter; +import java.io.Writer; + +/** + * Factory Method class for JsonWriter creation + */ +@Beta +public final class JsonWriterFactory { + + private JsonWriterFactory() { + } + /** + * Create a new JsonWriter, which writes to the specified output writer. + * + * @param writer Output writer + * @return A JsonWriter instance + */ + public static JsonWriter createJsonWriter(Writer writer) { + return new JsonWriter(writer); + } + + /** + * Create a new JsonWriter, which writes to the specified output writer. + * + * @param writer Output writer + * @param indentSize size of the indent + * @return A JsonWriter instance + */ + public static JsonWriter createJsonWriter(Writer writer, int indentSize) { + JsonWriter jsonWriter = new JsonWriter(writer); + final String indent = Strings.repeat(" ", indentSize); + jsonWriter.setIndent(indent); + return jsonWriter; + } + +} diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnquotedJSONCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/NumberJSONCodec.java similarity index 58% rename from yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnquotedJSONCodec.java rename to yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/NumberJSONCodec.java index f29db5d1ee..d262a440ce 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnquotedJSONCodec.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/NumberJSONCodec.java @@ -7,6 +7,8 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import org.opendaylight.yangtools.concepts.Codec; /** @@ -14,8 +16,8 @@ import org.opendaylight.yangtools.concepts.Codec; * * @param Deserialized value type */ -final class UnquotedJSONCodec extends AbstractJSONCodec { - UnquotedJSONCodec(final Codec codec) { +final class NumberJSONCodec extends AbstractJSONCodec { + NumberJSONCodec(final Codec codec) { super(codec); } @@ -23,4 +25,15 @@ final class UnquotedJSONCodec extends AbstractJSONCodec { public boolean needQuotes() { return false; } + + /** + * Serialize specified value with specified JsonWriter. + * + * @param writer JsonWriter + * @param value + */ + @Override + public void serializeToWriter(JsonWriter writer, T value) throws IOException { + writer.value(value); + } } \ No newline at end of file diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java index e8606f8d95..45782896cf 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java @@ -7,6 +7,8 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import org.opendaylight.yangtools.concepts.Codec; /** @@ -23,4 +25,15 @@ final class QuotedJSONCodec extends AbstractJSONCodec { public boolean needQuotes() { return true; } + + /** + * Serialize specified value with specified JsonWriter. + * + * @param writer JsonWriter + * @param value + */ + @Override + public void serializeToWriter(JsonWriter writer, T value) throws IOException { + writer.value(serialize(value)); + } } \ No newline at end of file diff --git a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/NormalizedNodeToJsonStreamTest.java b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/NormalizedNodeToJsonStreamTest.java index 39a1f1bc7b..484aa70029 100644 --- a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/NormalizedNodeToJsonStreamTest.java +++ b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/NormalizedNodeToJsonStreamTest.java @@ -382,11 +382,11 @@ public class NormalizedNodeToJsonStreamTest { private String normalizedNodeToJsonStreamTransformation(final Writer writer, final NormalizedNode inputStructure) throws IOException { - writer.write("{\n"); + final NormalizedNodeStreamWriter jsonStream = JSONNormalizedNodeStreamWriter.create(schemaContext, writer, 2); final NormalizedNodeWriter nodeWriter = NormalizedNodeWriter.forStreamWriter(jsonStream); nodeWriter.write(inputStructure); - writer.write("\n}"); + nodeWriter.close(); return writer.toString(); } -- 2.36.6