Refactor PathArgument to DataObjectStep
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / BindingToNormalizedStreamWriter.java
index a3513f74faaf57ba719d57d96820643c4acf79d1..2bf031865aa797280b751faf408213c6175b1f9f 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
 
 import java.io.IOException;
@@ -17,79 +16,75 @@ import java.util.Deque;
 import java.util.Map;
 import java.util.Map.Entry;
 import javax.xml.transform.dom.DOMSource;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.Identifiable;
-import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.Key;
+import org.opendaylight.yangtools.yang.binding.KeyAware;
 import org.opendaylight.yangtools.yang.binding.OpaqueObject;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-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.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
 final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWriter,
         Delegator<NormalizedNodeStreamWriter> {
-    private final Deque<NodeCodecContext> schema = new ArrayDeque<>();
-    private final NormalizedNodeStreamWriter delegate;
-    private final NodeCodecContext rootNodeSchema;
+    private final Deque<CodecContext> schema = new ArrayDeque<>();
+    private final @NonNull NormalizedNodeStreamWriter delegate;
+    private final CodecContext rootContext;
 
-    BindingToNormalizedStreamWriter(final NodeCodecContext rootNodeSchema, final NormalizedNodeStreamWriter delegate) {
-        this.rootNodeSchema = requireNonNull(rootNodeSchema);
-        this.delegate = requireNonNull(delegate);
-    }
-
-    static BindingToNormalizedStreamWriter create(final NodeCodecContext schema,
+    BindingToNormalizedStreamWriter(final DataContainerCodecContext<?, ?, ?> rootContext,
             final NormalizedNodeStreamWriter delegate) {
-        return new BindingToNormalizedStreamWriter(schema, delegate);
+        this.rootContext = requireNonNull(rootContext);
+        this.delegate = requireNonNull(delegate);
     }
 
     private void emitSchema(final Object schemaNode) {
         delegate.nextDataSchemaNode((DataSchemaNode) schemaNode);
     }
 
-    NodeCodecContext current() {
+    CodecContext current() {
         return schema.peek();
     }
 
     private NodeIdentifier duplicateSchemaEnter() {
-        final NodeCodecContext next;
-        if (current() == null) {
+        final var current = current();
+        final CodecContext next;
+        if (current == null) {
             // Entry of first node
-            next = rootNodeSchema;
+            next = rootContext;
         } else {
-            next = current();
+            next = current;
         }
-        this.schema.push(next);
-        return (NodeIdentifier) current().getDomPathArgument();
+        schema.push(next);
+        return next.getDomPathArgument();
     }
 
     @SuppressWarnings({"unchecked", "rawtypes"})
-    private <T extends YangInstanceIdentifier.PathArgument> T enter(final Class<?> name, final Class<T> identifier) {
-        final NodeCodecContext next;
-        if (current() == null) {
+    private <T extends PathArgument> T enter(final Class<?> name, final Class<T> identifier) {
+        final var current = current();
+        final CodecContext next;
+        if (current == null) {
             // Entry of first node
-            next = rootNodeSchema;
+            next = rootContext;
+        } else if (current instanceof DataContainerCodecContext<?, ?, ?> currentContainer) {
+            next = currentContainer.getStreamChild((Class) name);
         } else {
-            checkArgument(current() instanceof DataContainerCodecContext, "Could not start node %s", name);
-            next = ((DataContainerCodecContext<?,?>) current()).streamChild((Class) name);
+            throw new IllegalArgumentException("Could not start node " + name + " in non-container " + current);
         }
-        this.schema.push(next);
-        T arg = (T) next.getDomPathArgument();
-        return arg;
+        schema.push(next);
+        return identifier.cast(next.getDomPathArgument());
     }
 
-    private <T extends YangInstanceIdentifier.PathArgument> T enter(final String localName, final Class<T> identifier) {
-        NodeCodecContext current = current();
-        NodeCodecContext next = ((DataObjectCodecContext<?, ?>) current).getLeafChild(localName);
-        this.schema.push(next);
-        @SuppressWarnings("unchecked")
-        T arg = (T) next.getDomPathArgument();
-        return arg;
+    private <T extends PathArgument> T enter(final String localName, final Class<T> identifier) {
+        final var current = current();
+        final var next = ((AbstractDataObjectCodecContext<?, ?>) current).getLeafChild(localName);
+        schema.push(next);
+        return identifier.cast(next.getDomPathArgument());
     }
 
     @Override
@@ -99,20 +94,21 @@ final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWrite
 
     @Override
     public void endNode() throws IOException {
-        NodeCodecContext left = schema.pop();
-        // NormalizedNode writer does not have entry into case, but into choice
-        // so for leaving case, we do not emit endNode.
-        if (!(left instanceof CaseNodeCodecContext)) {
+        CodecContext left = schema.pop();
+        // Due to writer does not start a new node on startCase() and on startAugmentationNode()
+        // node ending should not be triggered when associated endNode() is invoked.
+        if (!(left instanceof CaseCodecContext) && !(left instanceof AugmentationCodecContext)) {
             delegate.endNode();
         }
     }
 
     private Map.Entry<NodeIdentifier, Object> serializeLeaf(final String localName, final Object value) {
-        checkArgument(current() instanceof DataObjectCodecContext);
+        final var current = current();
+        if (!(current instanceof AbstractDataObjectCodecContext<?, ?> currentCasted)) {
+            throw new IllegalArgumentException("Unexpected current context " + current);
+        }
 
-        DataObjectCodecContext<?,?> currentCasted = (DataObjectCodecContext<?,?>) current();
         ValueNodeCodecContext leafContext = currentCasted.getLeafChild(localName);
-
         NodeIdentifier domArg = leafContext.getDomPathArgument();
         Object domValue = leafContext.getValueCodec().serialize(value);
         emitSchema(leafContext.getSchema());
@@ -156,9 +152,8 @@ final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWrite
     }
 
     @Override
-    public void startAugmentationNode(final Class<? extends Augmentation<?>> augmentationType)
-            throws IOException {
-        delegate.startAugmentationNode(enter(augmentationType, AugmentationIdentifier.class));
+    public void startAugmentationNode(final Class<? extends Augmentation<?>> augmentationType) throws IOException {
+        enter(augmentationType, NodeIdentifier.class);
     }
 
     @Override
@@ -191,20 +186,20 @@ final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWrite
     }
 
     @Override
-    public void startMapEntryNode(final Identifier<?> key, final int childSizeHint) throws IOException {
+    public void startMapEntryNode(final Key<?> key, final int childSizeHint) throws IOException {
         duplicateSchemaEnter();
-        NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext<?>) current()).serialize(key);
+        NodeIdentifierWithPredicates identifier = ((MapCodecContext<?, ?>) current()).serialize(key);
         delegate.startMapEntryNode(identifier, childSizeHint);
     }
 
     @Override
-    public <T extends DataObject & Identifiable<?>> void startMapNode(final Class<T> mapEntryType,
-            final int childSizeHint) throws IOException {
+    public <T extends DataObject & KeyAware<?>> void startMapNode(final Class<T> mapEntryType, final int childSizeHint)
+            throws IOException {
         delegate.startMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
     }
 
     @Override
-    public <T extends DataObject & Identifiable<?>> void startOrderedMapNode(final Class<T> mapEntryType,
+    public <T extends DataObject & KeyAware<?>> void startOrderedMapNode(final Class<T> mapEntryType,
             final int childSizeHint) throws IOException {
         delegate.startOrderedMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
     }