Remove Augmentation{Identifier,Node}
[yangtools.git] / codec / yang-data-codec-gson / src / main / java / org / opendaylight / yangtools / yang / data / codec / gson / JSONNormalizedNodeStreamWriter.java
index a62b8029f5e7fef20cb8ea31411f625f0a5627f7..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) {
@@ -101,9 +99,9 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
     JSONNormalizedNodeStreamWriter(final JSONCodecFactory codecFactory, final NormalizedNodeStreamWriterStack tracker,
             final JsonWriter writer, final JSONStreamWriterRootContext rootContext) {
         this.writer = requireNonNull(writer);
-        this.codecs = requireNonNull(codecFactory);
+        codecs = requireNonNull(codecFactory);
         this.tracker = requireNonNull(tracker);
-        this.context = requireNonNull(rootContext);
+        context = requireNonNull(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
@@ -303,8 +343,8 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
     @Override
     public final void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
         final SchemaNode schema = tracker.startContainerNode(name);
-        final boolean isPresence = schema instanceof ContainerSchemaNode
-            ? ((ContainerSchemaNode) schema).isPresenceContainer() : DEFAULT_EMIT_EMPTY_CONTAINERS;
+        final boolean isPresence = schema instanceof ContainerSchemaNode container
+            ? container.isPresenceContainer() : DEFAULT_EMIT_EMPTY_CONTAINERS;
         context = new JSONStreamWriterNamedObjectContext(context, name, isPresence);
     }
 
@@ -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,
@@ -405,8 +439,8 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
     @Override
     public void scalarValue(final Object value) throws IOException {
         final Object current = tracker.getParent();
-        if (current instanceof TypedDataSchemaNode) {
-            writeValue(value, codecs.codecFor((TypedDataSchemaNode) current, tracker));
+        if (current instanceof TypedDataSchemaNode typed) {
+            writeValue(value, codecs.codecFor(typed, tracker));
         } else if (current instanceof AnydataSchemaNode) {
             writeAnydataValue(value);
         } else {
@@ -428,8 +462,8 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
     }
 
     private void writeAnydataValue(final Object value) throws IOException {
-        if (value instanceof NormalizedAnydata) {
-            writeNormalizedAnydata((NormalizedAnydata) value);
+        if (value instanceof NormalizedAnydata normalized) {
+            writeNormalizedAnydata(normalized);
         } else {
             throw new IllegalStateException("Unexpected anydata value " + value);
         }
@@ -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);
                 }
             }
@@ -533,17 +567,10 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt
             return;
         }
         switch (childNodeText) {
-            case "null":
-                writer.nullValue();
-                break;
-            case "false":
-                writer.value(false);
-                break;
-            case "true":
-                writer.value(true);
-                break;
-            default:
-                writer.value(childNodeText);
+            case "null" -> writer.nullValue();
+            case "false" -> writer.value(false);
+            case "true" -> writer.value(true);
+            default -> writer.value(childNodeText);
         }
     }