Update NormalizedMetadata(StreamWriter) design 89/80689/2
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 5 Mar 2019 15:13:38 +0000 (16:13 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 5 Mar 2019 15:27:56 +0000 (16:27 +0100)
While having a complete decomposition of metadata blocks would be
a nice design, it is not efficient for our current use:

- NormalizedMetadata has the block readily-available
- Both JSON and XML parsers fully assemble attributes before
  emitting them. Even if the implementation changes, both parsers
  can very easily assemble the full block, as XML encodes it just
  after the element and JSON uses dedicated objects.
- NETCONF edit-config processing requires metadata to be visible
  before it can decide how to process the node

This patch changes NormalizedMetadataStreamWriter have a single
metadata() event, which takes an ImmutableMap. This communicates
the intent quite clearly and allows for optimizations on both ends.

JIRA: YANGTOOLS-961
Change-Id: I638c78d5ab1d3a8b544ab53a84b872420b49d637
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/rfc7952-data-api/src/main/java/org/opendaylight/yangtools/rfc7952/data/api/NormalizedMetadata.java
yang/rfc7952-data-api/src/main/java/org/opendaylight/yangtools/rfc7952/data/api/NormalizedMetadataStreamWriter.java
yang/rfc7952-data-util/src/main/java/org/opendaylight/yangtools/rfc7952/data/util/NormalizedNodeStreamWriterMetadataDecorator.java

index 813d7ffc02ffdfb59f99cba30b9dd085c14e3c73..ad642d80bcd31499d4cfcece7f323802246df269 100644 (file)
@@ -35,7 +35,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 public interface NormalizedMetadata extends Identifiable<PathArgument>, Immutable {
     /**
      * Return the set of annotations defined in this metadata node. Values are expected to be effectively-immutable
-     * scalar types, like {@link String}s, {@link Number}s and similar.
+     * scalar types, like {@link String}s, {@link Number}s and similar. The map must also be effectively-immutable.
      *
      * @return The set of annotations attached to the corresponding data node.
      */
index f4b9e3477b9cc8ac824cac6afa823cb36330748d..32dad3b51152d9f2780b93c59627b7392361dea2 100644 (file)
@@ -8,27 +8,16 @@
 package org.opendaylight.yangtools.rfc7952.data.api;
 
 import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableMap;
 import java.io.IOException;
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.yangtools.rfc7952.model.api.AnnotationSchemaNode;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriterExtension;
 
 /**
  * Extension to the NormalizedNodeStreamWriter with metadata support. Semantically this extends the event model of
- * {@link NormalizedNodeStreamWriter} with two new events:
- * <ul>
- * <li>{@link #startMetadata(int)} is within the scope of any open node and starts a block of metadata entries. It
- * is recommended to emit this block before any other events. Only
- * {@link #startMetadataEntry(QName, AnnotationSchemaNode)} and {@link NormalizedNodeStreamWriter#endNode()} are valid
- * in this node. This event may be emitted at most once for any open node.
- * </li>
- * <li>{@link #startMetadataEntry(QName, AnnotationSchemaNode)} to start a metadata entry. Its value is must be emitted
- * via {@link NormalizedNodeStreamWriter#nodeValue(Object)} before the entry is closed via
- * {@link NormalizedNodeStreamWriter#endNode()}.
- * </ul>
+ * {@link NormalizedNodeStreamWriter} with a new event, {@link #metadata(ImmutableMap)}. This event is valid on any
+ * open node. This event may be emitted only once.
  *
  * <p>
  * Note that some implementations of this interface, notably those targeting streaming XML, may require metadata to
@@ -42,29 +31,17 @@ import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStre
 @Beta
 public interface NormalizedMetadataStreamWriter extends NormalizedNodeStreamWriterExtension {
     /**
-     * Start the metadata block for the currently-open node. Allowed events are
-     * {@link #startMetadataEntry(QName, AnnotationSchemaNode)} and {@link NormalizedNodeStreamWriter#endNode()}.
+     * Emit a block of metadata associated with the currently-open node. The argument is a map of annotation names,
+     * as defined {@code md:annotation} extension. Values are normalized objects, which are required to be
+     * effectively-immutable.
      *
-     * @param childSizeHint Non-negative count of expected direct child nodes or
-     *                      {@link NormalizedNodeStreamWriter#UNKNOWN_SIZE} if count is unknown. This is only hint and
-     *                      should not fail writing of child events, if there are more events than count.
-     * @throws IllegalStateException if current node already has a metadata block or cannot receive metadata -- for
-     *                               example because {@link #requireMetadataFirst()} was not honored.
+     * @param metadata Metadata block
+     * @throws NullPointerException if {@code metadata} is null
+     * @throws IllegalStateException when this method is invoked outside of an open node or metadata has already been
+     *                               emitted.
      * @throws IOException if an underlying IO error occurs
      */
-    void startMetadata(int childSizeHint) throws IOException;
-
-    /**
-     * Start a new metadata entry. The value of the metadata entry should be emitted through
-     * {@link NormalizedNodeStreamWriter#nodeValue(Object)}.
-     *
-     * @param name Metadata name, as defined through {@code md:annotation}
-     * @param schema Effective {@code md:annotation} schema, or null if unknown to the caller
-     * @throws NullPointerException if {@code name} is null
-     * @throws IllegalStateException when this method is invoked outside of a metadata block
-     * @throws IOException if an underlying IO error occurs
-     */
-    void startMetadataEntry(@NonNull QName name, @Nullable AnnotationSchemaNode schema) throws IOException;
+    void metadata(ImmutableMap<QName, Object> metadata) throws IOException;
 
     /**
      * Indicate whether metadata is required to be emitted just after an entry is open. The default implementation
index 9f8bfbe05b0615690a2cc286560a50401206fd96..abba3489a3955a649dce023d0dbcbd63148fb1ec 100644 (file)
@@ -9,11 +9,11 @@ package org.opendaylight.yangtools.rfc7952.data.util;
 
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.collect.ImmutableMap;
 import java.io.IOException;
 import java.util.ArrayDeque;
 import java.util.Deque;
 import java.util.Map;
-import java.util.Map.Entry;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.rfc7952.data.api.NormalizedMetadata;
 import org.opendaylight.yangtools.rfc7952.data.api.NormalizedMetadataContainer;
@@ -160,13 +160,7 @@ final class NormalizedNodeStreamWriterMetadataDecorator extends ForwardingNormal
 
     private void emitAnnotations(final Map<QName, Object> annotations) throws IOException {
         if (!annotations.isEmpty()) {
-            metaWriter.startMetadata(annotations.size());
-            for (Entry<QName, Object> entry : annotations.entrySet()) {
-                metaWriter.startMetadataEntry(entry.getKey(), null);
-                writer.nodeValue(entry.getValue());
-                writer.endNode();
-            }
-            writer.endNode();
+            metaWriter.metadata(ImmutableMap.copyOf(annotations));
         }
     }
 }