Ignore empty augmentations at runtime
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / BindingToNormalizedStreamWriter.java
index fc982428b8427d02e061d3aab26250daeb2cfaf9..5e88eabade3149c24a829091d1622af0825a3856 100644 (file)
@@ -7,39 +7,44 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
 import java.io.IOException;
 import java.util.AbstractMap;
 import java.util.ArrayDeque;
 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.BindingStreamEventWriter;
 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.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.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
-final class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Delegator<NormalizedNodeStreamWriter> {
-    private final Deque<NodeCodecContext<?>> schema = new ArrayDeque<>();
+final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWriter,
+        Delegator<NormalizedNodeStreamWriter> {
+    private final Deque<NodeCodecContext> schema = new ArrayDeque<>();
     private final NormalizedNodeStreamWriter delegate;
-    private final NodeCodecContext<?> rootNodeSchema;
+    private final NodeCodecContext rootNodeSchema;
 
-    BindingToNormalizedStreamWriter(final NodeCodecContext<?> rootNodeSchema,
-            final NormalizedNodeStreamWriter delegate) {
-        this.rootNodeSchema = Preconditions.checkNotNull(rootNodeSchema);
-        this.delegate = Preconditions.checkNotNull(delegate);
+    BindingToNormalizedStreamWriter(final NodeCodecContext rootNodeSchema, final NormalizedNodeStreamWriter delegate) {
+        this.rootNodeSchema = requireNonNull(rootNodeSchema);
+        this.delegate = requireNonNull(delegate);
     }
 
-    static BindingToNormalizedStreamWriter create(final NodeCodecContext<?> schema,
+    static @NonNull BindingToNormalizedStreamWriter create(final NodeCodecContext schema,
             final NormalizedNodeStreamWriter delegate) {
         return new BindingToNormalizedStreamWriter(schema, delegate);
     }
@@ -48,12 +53,12 @@ final class BindingToNormalizedStreamWriter implements BindingStreamEventWriter,
         delegate.nextDataSchemaNode((DataSchemaNode) schemaNode);
     }
 
-    NodeCodecContext<?> current() {
+    NodeCodecContext current() {
         return schema.peek();
     }
 
     private NodeIdentifier duplicateSchemaEnter() {
-        final NodeCodecContext<?> next;
+        final NodeCodecContext next;
         if (current() == null) {
             // Entry of first node
             next = rootNodeSchema;
@@ -66,13 +71,12 @@ final class BindingToNormalizedStreamWriter implements BindingStreamEventWriter,
 
     @SuppressWarnings({"unchecked", "rawtypes"})
     private <T extends YangInstanceIdentifier.PathArgument> T enter(final Class<?> name, final Class<T> identifier) {
-        final NodeCodecContext<?> next;
+        final NodeCodecContext next;
         if (current() == null) {
             // Entry of first node
             next = rootNodeSchema;
         } else {
-            Preconditions.checkArgument(current() instanceof DataContainerCodecContext, "Could not start node %s",
-                    name);
+            checkArgument(current() instanceof DataContainerCodecContext, "Could not start node %s", name);
             next = ((DataContainerCodecContext<?,?>) current()).streamChild((Class) name);
         }
         this.schema.push(next);
@@ -81,8 +85,8 @@ final class BindingToNormalizedStreamWriter implements BindingStreamEventWriter,
     }
 
     private <T extends YangInstanceIdentifier.PathArgument> T enter(final String localName, final Class<T> identifier) {
-        NodeCodecContext<?> current = current();
-        NodeCodecContext<?> next = ((DataObjectCodecContext<?,?>) current).getLeafChild(localName);
+        NodeCodecContext current = current();
+        NodeCodecContext next = ((DataObjectCodecContext<?, ?>) current).getLeafChild(localName);
         this.schema.push(next);
         @SuppressWarnings("unchecked")
         T arg = (T) next.getDomPathArgument();
@@ -96,21 +100,21 @@ final class BindingToNormalizedStreamWriter implements BindingStreamEventWriter,
 
     @Override
     public void endNode() throws IOException {
-        NodeCodecContext<?> left = schema.pop();
+        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)) {
-            getDelegate().endNode();
+            delegate.endNode();
         }
     }
 
     private Map.Entry<NodeIdentifier, Object> serializeLeaf(final String localName, final Object value) {
-        Preconditions.checkArgument(current() instanceof DataObjectCodecContext);
+        checkArgument(current() instanceof DataObjectCodecContext);
 
         DataObjectCodecContext<?,?> currentCasted = (DataObjectCodecContext<?,?>) current();
-        LeafNodeCodecContext<?> leafContext = currentCasted.getLeafChild(localName);
+        ValueNodeCodecContext leafContext = currentCasted.getLeafChild(localName);
 
-        NodeIdentifier domArg = (NodeIdentifier) leafContext.getDomPathArgument();
+        NodeIdentifier domArg = leafContext.getDomPathArgument();
         Object domValue = leafContext.getValueCodec().serialize(value);
         emitSchema(leafContext.getSchema());
         return new AbstractMap.SimpleEntry<>(domArg, domValue);
@@ -118,27 +122,44 @@ final class BindingToNormalizedStreamWriter implements BindingStreamEventWriter,
 
     @Override
     public void leafNode(final String localName, final Object value) throws IOException {
-        Entry<NodeIdentifier, Object> dom = serializeLeaf(localName, value);
-        getDelegate().leafNode(dom.getKey(), dom.getValue());
+        final Entry<NodeIdentifier, Object> dom = serializeLeaf(localName, value);
+        delegate.startLeafNode(dom.getKey());
+        delegate.scalarValue(dom.getValue());
+        delegate.endNode();
+    }
+
+    @Override
+    public void anydataNode(final String name, final OpaqueObject<?> value) throws IOException {
+        final Entry<NodeIdentifier, Object> dom = serializeLeaf(name, value);
+        if (delegate.startAnydataNode(dom.getKey(), value.getValue().getObjectModel())) {
+            delegate.scalarValue(dom.getValue());
+            delegate.endNode();
+        }
     }
 
     @Override
     public void anyxmlNode(final String name, final Object value) throws IOException {
-        Entry<NodeIdentifier, Object> dom = serializeLeaf(name, value);
-        getDelegate().anyxmlNode(dom.getKey(), dom.getValue());
+        final Entry<NodeIdentifier, Object> dom = serializeLeaf(name, value);
+        // FIXME: this is not quite right -- we should be handling other object models, too
+        if (delegate.startAnyxmlNode(dom.getKey(), DOMSource.class)) {
+            delegate.domSourceValue((DOMSource) dom.getValue());
+            delegate.endNode();
+        }
     }
 
     @Override
     public void leafSetEntryNode(final Object value) throws IOException {
-        LeafNodeCodecContext<?> ctx = (LeafNodeCodecContext<?>) current();
-        getDelegate().leafSetEntryNode(ctx.getSchema().getQName(),
-            ctx.getValueCodec().serialize(value));
+        final LeafSetNodeCodecContext ctx = (LeafSetNodeCodecContext) current();
+        final Object domValue = ctx.getValueCodec().serialize(value);
+        delegate.startLeafSetEntryNode(new NodeWithValue<>(ctx.getSchema().getQName(), domValue));
+        delegate.scalarValue(domValue);
+        delegate.endNode();
     }
 
     @Override
     public void startAugmentationNode(final Class<? extends Augmentation<?>> augmentationType)
             throws IOException {
-        getDelegate().startAugmentationNode(enter(augmentationType, AugmentationIdentifier.class));
+        delegate.startAugmentationNode(enter(augmentationType, AugmentationIdentifier.class));
     }
 
     @Override
@@ -149,63 +170,63 @@ final class BindingToNormalizedStreamWriter implements BindingStreamEventWriter,
     @Override
     public void startChoiceNode(final Class<? extends DataContainer> type, final int childSizeHint)
             throws IOException {
-        getDelegate().startChoiceNode(enter(type, NodeIdentifier.class), childSizeHint);
+        delegate.startChoiceNode(enter(type, NodeIdentifier.class), childSizeHint);
     }
 
     @Override
     public void startContainerNode(final Class<? extends DataObject> object, final int childSizeHint)
             throws IOException {
-        getDelegate().startContainerNode(enter(object, NodeIdentifier.class), childSizeHint);
+        delegate.startContainerNode(enter(object, NodeIdentifier.class), childSizeHint);
     }
 
     @Override
     public void startLeafSet(final String localName, final int childSizeHint) throws IOException {
         final NodeIdentifier id = enter(localName, NodeIdentifier.class);
         emitSchema(current().getSchema());
-        getDelegate().startLeafSet(id, childSizeHint);
+        delegate.startLeafSet(id, childSizeHint);
     }
 
     @Override
     public void startOrderedLeafSet(final String localName, final int childSizeHint) throws IOException {
-        getDelegate().startOrderedLeafSet(enter(localName, NodeIdentifier.class), childSizeHint);
+        delegate.startOrderedLeafSet(enter(localName, NodeIdentifier.class), childSizeHint);
     }
 
     @Override
     public void startMapEntryNode(final Identifier<?> key, final int childSizeHint) throws IOException {
         duplicateSchemaEnter();
-        NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext<?>) current()).serialize(key);
-        getDelegate().startMapEntryNode(identifier, childSizeHint);
+        NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext<?, ?>) current()).serialize(key);
+        delegate.startMapEntryNode(identifier, childSizeHint);
     }
 
     @Override
     public <T extends DataObject & Identifiable<?>> void startMapNode(final Class<T> mapEntryType,
             final int childSizeHint) throws IOException {
-        getDelegate().startMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
+        delegate.startMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
     }
 
     @Override
     public <T extends DataObject & Identifiable<?>> void startOrderedMapNode(final Class<T> mapEntryType,
             final int childSizeHint) throws IOException {
-        getDelegate().startOrderedMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
+        delegate.startOrderedMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
     }
 
     @Override
     public void startUnkeyedList(final Class<? extends DataObject> obj, final int childSizeHint) throws IOException {
-        getDelegate().startUnkeyedList(enter(obj, NodeIdentifier.class), childSizeHint);
+        delegate.startUnkeyedList(enter(obj, NodeIdentifier.class), childSizeHint);
     }
 
     @Override
     public void startUnkeyedListItem(final int childSizeHint) throws IOException {
-        getDelegate().startUnkeyedListItem(duplicateSchemaEnter(), childSizeHint);
+        delegate.startUnkeyedListItem(duplicateSchemaEnter(), childSizeHint);
     }
 
     @Override
     public void flush() throws IOException {
-        getDelegate().flush();
+        delegate.flush();
     }
 
     @Override
     public void close() throws IOException {
-        getDelegate().close();
+        delegate.close();
     }
 }