Remove Augmentation{Identifier,Node}
[yangtools.git] / codec / yang-data-codec-gson / src / main / java / org / opendaylight / yangtools / yang / data / codec / gson / JSONNormalizedNodeStreamWriter.java
index a4c9fe10f7278aa11d4858d29240b452e12e02bb..0655c6c78fc51d15a34238a75f3f76ef717a60bf 100644 (file)
@@ -10,25 +10,25 @@ package org.opendaylight.yangtools.yang.data.codec.gson;
 import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
 import com.google.gson.stream.JsonWriter;
 import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
 import java.util.NoSuchElementException;
 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.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.rfc8528.model.api.MountPointLabel;
 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.MountPointContext;
 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.NormalizedNodeStreamWriter.MountPointExtension;
 import org.opendaylight.yangtools.yang.data.util.NormalizedNodeStreamWriterStack;
 import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
@@ -36,7 +36,6 @@ import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.EffectiveStatementInference;
 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.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
@@ -51,8 +50,7 @@ import org.w3c.dom.Text;
  * <p>
  * Values of leaf and leaf-list are NOT translated according to codecs.
  */
-public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter,
-        StreamWriterMountPointExtension {
+public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter, MountPointExtension {
     private static final class Exclusive extends JSONNormalizedNodeStreamWriter {
         Exclusive(final JSONCodecFactory codecFactory, final NormalizedNodeStreamWriterStack tracker,
                 final JsonWriter writer, final JSONStreamWriterRootContext rootContext) {
@@ -122,16 +120,38 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
      * 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 SchemaPath path, final XMLNamespace initialNs, final JsonWriter jsonWriter) {
-        return new Exclusive(codecFactory,
-            NormalizedNodeStreamWriterStack.of(codecFactory.getEffectiveModelContext(), path), jsonWriter,
-            new JSONStreamWriterExclusiveRootContext(initialNs));
+            final JsonWriter jsonWriter) {
+        return createExclusiveWriter(codecFactory, jsonWriter, null);
+    }
+
+    /**
+     * Create a new stream writer, which writes to the specified output stream.
+     *
+     * <p>
+     * The codec factory can be reused between multiple writers.
+     *
+     * <p>
+     * Returned writer is exclusive user of JsonWriter, which means it will start
+     * top-level JSON element and ends it.
+     *
+     * <p>
+     * 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 jsonWriter JsonWriter
+     * @param initialNs Initial namespace, can be null
+     * @return A stream writer instance
+     */
+    public static NormalizedNodeStreamWriter createExclusiveWriter(final JSONCodecFactory codecFactory,
+            final JsonWriter jsonWriter, final @Nullable XMLNamespace initialNs) {
+        return new Exclusive(codecFactory, NormalizedNodeStreamWriterStack.of(codecFactory.getEffectiveModelContext()),
+            jsonWriter, new JSONStreamWriterExclusiveRootContext(initialNs));
     }
 
     /**
@@ -203,16 +223,36 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
      * close the wrapped writer; the caller must take care of that.
      *
      * @param codecFactory JSON codec factory
-     * @param path Schema Path
+     * @param jsonWriter JsonWriter
+     * @return A stream writer instance
+     */
+    public static NormalizedNodeStreamWriter createNestedWriter(final JSONCodecFactory codecFactory,
+            final JsonWriter jsonWriter) {
+        return createNestedWriter(codecFactory, jsonWriter, null);
+    }
+
+    /**
+     * Create a new stream writer, which writes to the specified output stream.
+     *
+     * <p>
+     * The codec factory can be reused between multiple writers.
+     *
+     * <p>
+     * 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 <strong>will not</strong>
+     * close the wrapped writer; the caller must take care of that.
+     *
+     * @param codecFactory JSON codec factory
      * @param initialNs Initial namespace
      * @param jsonWriter JsonWriter
      * @return A stream writer instance
      */
     public static NormalizedNodeStreamWriter createNestedWriter(final JSONCodecFactory codecFactory,
-            final SchemaPath path, final XMLNamespace initialNs, final JsonWriter jsonWriter) {
-        return new Nested(codecFactory,
-            NormalizedNodeStreamWriterStack.of(codecFactory.getEffectiveModelContext(), path), jsonWriter,
-            new JSONStreamWriterSharedRootContext(initialNs));
+            final JsonWriter jsonWriter, final @Nullable XMLNamespace initialNs) {
+        return new Nested(codecFactory, NormalizedNodeStreamWriterStack.of(codecFactory.getEffectiveModelContext()),
+            jsonWriter, new JSONStreamWriterSharedRootContext(initialNs));
     }
 
     /**
@@ -267,8 +307,8 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
     }
 
     @Override
-    public ClassToInstanceMap<NormalizedNodeStreamWriterExtension> getExtensions() {
-        return ImmutableClassToInstanceMap.of(StreamWriterMountPointExtension.class, this);
+    public Collection<? extends Extension> supportedExtensions() {
+        return List.of(this);
     }
 
     @Override
@@ -345,12 +385,6 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
         context = new JSONStreamWriterInvisibleContext(context);
     }
 
-    @Override
-    public final void startAugmentationNode(final AugmentationIdentifier identifier) {
-        tracker.startAugmentationNode(identifier);
-        context = new JSONStreamWriterInvisibleContext(context);
-    }
-
     @Override
     public final boolean startAnydataNode(final NodeIdentifier name, final Class<?> objectModel) throws IOException {
         if (NormalizedAnydata.class.isAssignableFrom(objectModel)) {
@@ -364,7 +398,7 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
     }
 
     @Override
-    public final NormalizedNodeStreamWriter startMountPoint(final MountPointIdentifier mountId,
+    public final NormalizedNodeStreamWriter startMountPoint(final MountPointLabel label,
             final MountPointContext mountCtx) throws IOException {
         final EffectiveModelContext ctx = mountCtx.getEffectiveModelContext();
         return new Nested(codecs.rebaseTo(ctx), NormalizedNodeStreamWriterStack.of(ctx), writer,
@@ -510,12 +544,12 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
     }
 
     private void writeObject(Node node) throws IOException {
-        String previousNodeName = "";
+        final var previousNodeNames = new HashSet<String>();
         while (node != null) {
             if (Node.ELEMENT_NODE == node.getNodeType()) {
-                if (!node.getNodeName().equals(previousNodeName)) {
-                    previousNodeName = node.getNodeName();
-                    writer.name(node.getNodeName());
+                final var nodeName = node.getNodeName();
+                if (previousNodeNames.add(nodeName)) {
+                    writer.name(nodeName);
                     writeXmlNode(node);
                 }
             }