X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-data-codec-gson%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fdata%2Fcodec%2Fgson%2FJSONNormalizedNodeStreamWriter.java;h=dcbb94b3660a70cb291b871a2b2b53cfc72d9689;hb=c4517068c0183a892703b26baf098c97bfb2a854;hp=d32bd2c8c57fca68ee5921f1cf6503c123abe86b;hpb=b9d7b487da2eb037b1b17291819438fdbd4f1e16;p=yangtools.git 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 d32bd2c8c5..dcbb94b366 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 @@ -16,29 +16,31 @@ import com.google.common.collect.ClassToInstanceMap; import com.google.common.collect.ImmutableClassToInstanceMap; import com.google.gson.stream.JsonWriter; import java.io.IOException; -import java.net.URI; import java.util.regex.Pattern; import javax.xml.transform.dom.DOMSource; import org.checkerframework.checker.regex.qual.Regex; +import org.opendaylight.yangtools.rfc8528.data.api.MountPointContext; +import org.opendaylight.yangtools.rfc8528.data.api.MountPointIdentifier; +import org.opendaylight.yangtools.rfc8528.data.api.StreamWriterMountPointExtension; +import org.opendaylight.yangtools.yang.common.XMLNamespace; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue; -import org.opendaylight.yangtools.yang.data.api.schema.stream.AnydataExtension; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedAnydata; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriterExtension; -import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; import org.opendaylight.yangtools.yang.data.impl.codec.SchemaTracker; -import org.opendaylight.yangtools.yang.data.util.NormalizedAnydata; -import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; +import org.opendaylight.yangtools.yang.data.util.SingleChildDataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -50,7 +52,8 @@ import org.w3c.dom.Text; *

* Values of leaf and leaf-list are NOT translated according to codecs. */ -public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter, AnydataExtension { +public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter, + StreamWriterMountPointExtension { private static final class Exclusive extends JSONNormalizedNodeStreamWriter { Exclusive(final JSONCodecFactory codecFactory, final SchemaTracker tracker, final JsonWriter writer, final JSONStreamWriterRootContext rootContext) { @@ -126,9 +129,36 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt * @return A stream writer instance */ public static NormalizedNodeStreamWriter createExclusiveWriter(final JSONCodecFactory codecFactory, - final SchemaPath path, final URI initialNs, final JsonWriter jsonWriter) { - return new Exclusive(codecFactory, SchemaTracker.create(codecFactory.getSchemaContext(), path), jsonWriter, - new JSONStreamWriterExclusiveRootContext(initialNs)); + final SchemaPath path, final XMLNamespace initialNs, final JsonWriter jsonWriter) { + return new Exclusive(codecFactory, SchemaTracker.create(codecFactory.getEffectiveModelContext(), path), + jsonWriter, new JSONStreamWriterExclusiveRootContext(initialNs)); + } + + /** + * Create a new stream writer, which writes to the specified output stream. + * + *

+ * The codec factory can be reused between multiple writers. + * + *

+ * Returned writer is exclusive user of JsonWriter, which means it will start + * top-level JSON element and ends it. + * + *

+ * This instance of writer can be used only to emit one top level element, + * otherwise it will produce incorrect JSON. Closing this instance will close + * the writer too. + * + * @param codecFactory JSON codec factory + * @param path Schema Path + * @param initialNs Initial namespace + * @param jsonWriter JsonWriter + * @return A stream writer instance + */ + public static NormalizedNodeStreamWriter createExclusiveWriter(final JSONCodecFactory codecFactory, + final Absolute path, final XMLNamespace initialNs, final JsonWriter jsonWriter) { + return new Exclusive(codecFactory, SchemaTracker.create(codecFactory.getEffectiveModelContext(), path), + jsonWriter, new JSONStreamWriterExclusiveRootContext(initialNs)); } /** @@ -153,7 +183,7 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt * @return A stream writer instance */ public static NormalizedNodeStreamWriter createExclusiveWriter(final JSONCodecFactory codecFactory, - final DataNodeContainer rootNode, final URI initialNs, final JsonWriter jsonWriter) { + final DataNodeContainer rootNode, final XMLNamespace initialNs, final JsonWriter jsonWriter) { return new Exclusive(codecFactory, SchemaTracker.create(rootNode), jsonWriter, new JSONStreamWriterExclusiveRootContext(initialNs)); } @@ -178,8 +208,33 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt * @return A stream writer instance */ public static NormalizedNodeStreamWriter createNestedWriter(final JSONCodecFactory codecFactory, - final SchemaPath path, final URI initialNs, final JsonWriter jsonWriter) { - return new Nested(codecFactory, SchemaTracker.create(codecFactory.getSchemaContext(), path), jsonWriter, + final SchemaPath path, final XMLNamespace initialNs, final JsonWriter jsonWriter) { + return new Nested(codecFactory, SchemaTracker.create(codecFactory.getEffectiveModelContext(), path), jsonWriter, + new JSONStreamWriterSharedRootContext(initialNs)); + } + + /** + * Create a new stream writer, which writes to the specified output stream. + * + *

+ * The codec factory can be reused between multiple writers. + * + *

+ * Returned writer can be used emit multiple top level element, + * but does not start / close parent JSON object, which must be done + * by user providing {@code jsonWriter} instance in order for + * JSON to be valid. Closing this instance will not + * close the wrapped writer; the caller must take care of that. + * + * @param codecFactory JSON codec factory + * @param path Schema Path + * @param initialNs Initial namespace + * @param jsonWriter JsonWriter + * @return A stream writer instance + */ + public static NormalizedNodeStreamWriter createNestedWriter(final JSONCodecFactory codecFactory, + final Absolute path, final XMLNamespace initialNs, final JsonWriter jsonWriter) { + return new Nested(codecFactory, SchemaTracker.create(codecFactory.getEffectiveModelContext(), path), jsonWriter, new JSONStreamWriterSharedRootContext(initialNs)); } @@ -203,21 +258,21 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt * @return A stream writer instance */ public static NormalizedNodeStreamWriter createNestedWriter(final JSONCodecFactory codecFactory, - final DataNodeContainer rootNode, final URI initialNs, final JsonWriter jsonWriter) { + final DataNodeContainer rootNode, final XMLNamespace initialNs, final JsonWriter jsonWriter) { return new Nested(codecFactory, SchemaTracker.create(rootNode), jsonWriter, new JSONStreamWriterSharedRootContext(initialNs)); } @Override public ClassToInstanceMap getExtensions() { - return ImmutableClassToInstanceMap.of(AnydataExtension.class, this); + return ImmutableClassToInstanceMap.of(StreamWriterMountPointExtension.class, this); } @Override public void startLeafNode(final NodeIdentifier name) throws IOException { tracker.startLeafNode(name); - context.emittingChild(codecs.getSchemaContext(), writer); - context.writeChildJsonIdentifier(codecs.getSchemaContext(), writer, name.getNodeType()); + context.emittingChild(codecs.getEffectiveModelContext(), writer); + context.writeChildJsonIdentifier(codecs.getEffectiveModelContext(), writer, name.getNodeType()); } @Override @@ -229,7 +284,7 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt @Override public void startLeafSetEntryNode(final NodeWithValue name) throws IOException { tracker.startLeafSetEntryNode(name); - context.emittingChild(codecs.getSchemaContext(), writer); + context.emittingChild(codecs.getEffectiveModelContext(), writer); } @Override @@ -294,11 +349,11 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt } @Override - public boolean startAnydataNode(final NodeIdentifier name, final Class objectModel) throws IOException { + public final boolean startAnydataNode(final NodeIdentifier name, final Class objectModel) throws IOException { if (NormalizedAnydata.class.isAssignableFrom(objectModel)) { tracker.startAnydataNode(name); - context.emittingChild(codecs.getSchemaContext(), writer); - context.writeChildJsonIdentifier(codecs.getSchemaContext(), writer, name.getNodeType()); + context.emittingChild(codecs.getEffectiveModelContext(), writer); + context.writeChildJsonIdentifier(codecs.getEffectiveModelContext(), writer, name.getNodeType()); return true; } @@ -306,27 +361,28 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt } @Override - public final void startAnyxmlNode(final NodeIdentifier name) throws IOException { - tracker.startAnyxmlNode(name); - context.emittingChild(codecs.getSchemaContext(), writer); - context.writeChildJsonIdentifier(codecs.getSchemaContext(), writer, name.getNodeType()); + public final NormalizedNodeStreamWriter startMountPoint(final MountPointIdentifier mountId, + final MountPointContext mountCtx) throws IOException { + final EffectiveModelContext ctx = mountCtx.getEffectiveModelContext(); + return new Nested(codecs.rebaseTo(ctx), SchemaTracker.create(ctx), writer, + new JSONStreamWriterSharedRootContext(context.getNamespace())); } @Override - public final void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint) - throws IOException { - tracker.startYangModeledAnyXmlNode(name); - context = new JSONStreamWriterNamedObjectContext(context, name, true); + public final boolean startAnyxmlNode(final NodeIdentifier name, final Class objectModel) throws IOException { + if (DOMSource.class.isAssignableFrom(objectModel)) { + tracker.startAnyxmlNode(name); + context.emittingChild(codecs.getEffectiveModelContext(), writer); + context.writeChildJsonIdentifier(codecs.getEffectiveModelContext(), writer, name.getNodeType()); + return true; + } + return false; } @Override public final void endNode() throws IOException { tracker.endNode(); - context = context.endNode(codecs.getSchemaContext(), writer); - - if (context instanceof JSONStreamWriterRootContext) { - context.emitEnd(writer); - } + context = context.endNode(codecs.getEffectiveModelContext(), writer); } @Override @@ -335,6 +391,11 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt } final void closeWriter() throws IOException { + if (!(context instanceof JSONStreamWriterRootContext)) { + throw new IOException("Unexpected root context " + context); + } + + context.endNode(codecs.getEffectiveModelContext(), writer); writer.close(); } @@ -343,7 +404,7 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt final Object current = tracker.getParent(); if (current instanceof TypedDataSchemaNode) { writeValue(value, codecs.codecFor((TypedDataSchemaNode) current)); - } else if (current instanceof AnyDataSchemaNode) { + } else if (current instanceof AnydataSchemaNode) { writeAnydataValue(value); } else { throw new IllegalStateException(String.format("Cannot emit scalar %s for %s", value, current)); @@ -353,7 +414,7 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt @Override public void domSourceValue(final DOMSource value) throws IOException { final Object current = tracker.getParent(); - checkState(current instanceof AnyXmlSchemaNode, "Cannot emit DOMSource %s for %s", value, current); + checkState(current instanceof AnyxmlSchemaNode, "Cannot emit DOMSource %s for %s", value, current); // FIXME: should have a codec based on this :) writeAnyXmlValue(value); } @@ -372,20 +433,9 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt } private void writeNormalizedAnydata(final NormalizedAnydata anydata) throws IOException { - // TODO: this is rather ugly - final DataSchemaNode root = anydata.getContextTree().getRoot().getDataSchemaNode(); - if (!(root instanceof SchemaContext)) { - throw new IOException("Unexpected root context " + root); - } - - final DataSchemaNode node = anydata.getContextNode().getDataSchemaNode(); - if (!(node instanceof DataNodeContainer)) { - throw new IOException("Unexpected node context " + node); - } - - NormalizedNodeWriter.forStreamWriter(JSONNormalizedNodeStreamWriter.createNestedWriter( - codecs.rebaseTo((SchemaContext) root), (DataNodeContainer) node, context.getNamespace(), writer)).write( - anydata.getData()).flush(); + anydata.writeTo(JSONNormalizedNodeStreamWriter.createNestedWriter( + codecs.rebaseTo(anydata.getEffectiveModelContext()), + new SingleChildDataNodeContainer(anydata.getContextNode()), context.getNamespace(), writer)); } private void writeAnyXmlValue(final DOMSource anyXmlValue) throws IOException {