Hide DataContainerCodecContext.getType()
[yangtools.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / DataContainerCodecContext.java
index 27a565652faa37a92cf39f137777c89a9fc98f21..2c37161b9a6aaba157418b57ea39206214978517 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 com.google.common.collect.ImmutableCollection;
@@ -27,9 +26,10 @@ import java.util.Optional;
 import java.util.Set;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeCodec;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingStreamEventWriter;
+import org.opendaylight.mdsal.binding.dom.codec.api.CommonDataObjectCodecTreeNode;
 import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException;
 import org.opendaylight.mdsal.binding.dom.codec.api.MissingClassInLoadingStrategyException;
 import org.opendaylight.mdsal.binding.dom.codec.api.MissingSchemaException;
@@ -48,16 +48,16 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 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.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-abstract class DataContainerCodecContext<D extends DataObject, T extends RuntimeTypeContainer> extends NodeCodecContext
-        implements BindingDataObjectCodecTreeNode<D>  {
+abstract sealed class DataContainerCodecContext<D extends DataObject, T extends RuntimeTypeContainer>
+        extends CodecContext implements CommonDataObjectCodecTreeNode<D>
+        permits AbstractDataObjectCodecContext, ChoiceCodecContext, RootCodecContext {
     private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecContext.class);
     private static final VarHandle EVENT_STREAM_SERIALIZER;
 
@@ -70,7 +70,7 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
         }
     }
 
-    private final @NonNull DataContainerCodecPrototype<T> prototype;
+    final @NonNull DataContainerCodecPrototype<T> prototype;
 
     // Accessed via a VarHandle
     @SuppressWarnings("unused")
@@ -80,10 +80,6 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
         this.prototype = requireNonNull(prototype);
     }
 
-    public final @NonNull T getType() {
-        return prototype.getType();
-    }
-
     @Override
     public final ChildAddressabilitySummary getChildAddressabilitySummary() {
         return prototype.getChildAddressabilitySummary();
@@ -97,8 +93,12 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
         return prototype.getFactory();
     }
 
+    protected final @NonNull T type() {
+        return prototype.getType();
+    }
+
     @Override
-    protected final YangInstanceIdentifier.PathArgument getDomPathArgument() {
+    protected NodeIdentifier getDomPathArgument() {
         return prototype.getYangArg();
     }
 
@@ -110,7 +110,7 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
      * @throws IllegalArgumentException If supplied argument does not represent valid child.
      */
     @Override
-    public abstract NodeCodecContext yangPathArgumentChild(YangInstanceIdentifier.PathArgument arg);
+    public abstract CodecContext yangPathArgumentChild(YangInstanceIdentifier.PathArgument arg);
 
     /**
      * Returns nested node context using supplied Binding Instance Identifier
@@ -123,10 +123,8 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
     @Override
     public DataContainerCodecContext<?, ?> bindingPathArgumentChild(final PathArgument arg,
             final List<YangInstanceIdentifier.PathArgument> builder) {
-        final DataContainerCodecContext<?, ?> child = streamChild(arg.getType());
-        if (builder != null) {
-            child.addYangPathArgument(arg, builder);
-        }
+        final var child = getStreamChild(arg.getType());
+        child.addYangPathArgument(arg, builder);
         return child;
     }
 
@@ -136,9 +134,16 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
      * @param arg Binding Path Argument
      * @param builder DOM Path argument.
      */
-    void addYangPathArgument(final PathArgument arg, final List<YangInstanceIdentifier.PathArgument> builder) {
+    final void addYangPathArgument(final PathArgument arg, final List<YangInstanceIdentifier.PathArgument> builder) {
         if (builder != null) {
-            builder.add(getDomPathArgument());
+            addYangPathArgument(builder, arg);
+        }
+    }
+
+    void addYangPathArgument(final @NonNull List<YangInstanceIdentifier.PathArgument> builder, final PathArgument arg) {
+        final var yangArg = getDomPathArgument();
+        if (yangArg != null) {
+            builder.add(yangArg);
         }
     }
 
@@ -160,7 +165,7 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
     }
 
     @Override
-    public abstract <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(Class<C> childClass);
+    public abstract <C extends DataObject> DataContainerCodecContext<C, ?> getStreamChild(Class<C> childClass);
 
     /**
      * Returns child context as if it was walked by {@link BindingStreamEventWriter}. This means that to enter case, one
@@ -170,27 +175,24 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
      * @return Context of child or Optional.empty is supplied class is not applicable in context.
      */
     @Override
-    public abstract <C extends DataObject> Optional<DataContainerCodecContext<C,?>> possibleStreamChild(
-            Class<C> childClass);
+    public abstract <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(Class<C> childClass);
 
     @Override
     public String toString() {
         return getClass().getSimpleName() + " [" + prototype.getBindingClass() + "]";
     }
 
-    @Override
-    public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
-            final ImmutableCollection<Class<? extends BindingObject>> cacheSpecifier) {
-        if (cacheSpecifier.isEmpty()) {
-            return new NonCachingCodec<>(this);
-        }
-        return new CachingNormalizedNodeCodec<>(this, ImmutableSet.copyOf(cacheSpecifier));
+    static final <T extends DataObject, C extends DataContainerCodecContext<T, ?> & BindingNormalizedNodeCodec<T>>
+            @NonNull BindingNormalizedNodeCachingCodec<T> createCachingCodec(final C context,
+                final ImmutableCollection<Class<? extends BindingObject>> cacheSpecifier) {
+        return cacheSpecifier.isEmpty() ? new NonCachingCodec<>(context)
+            : new CachingNormalizedNodeCodec<>(context, ImmutableSet.copyOf(cacheSpecifier));
     }
 
     protected final <V> @NonNull V childNonNull(final @Nullable V nullable,
             final YangInstanceIdentifier.PathArgument child, final String message, final Object... args) {
         if (nullable == null) {
-            throw childNullException(extractName(child), message, args);
+            throw childNullException(child.getNodeType(), message, args);
         }
         return nullable;
     }
@@ -249,15 +251,6 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
         return new IncorrectNestingException(message, args);
     }
 
-    private static QName extractName(final YangInstanceIdentifier.PathArgument child) {
-        if (child instanceof AugmentationIdentifier) {
-            final Set<QName> children = ((AugmentationIdentifier) child).getPossibleChildNames();
-            checkArgument(!children.isEmpty(), "Augmentation without childs must not be used in data");
-            return children.iterator().next();
-        }
-        return child.getNodeType();
-    }
-
     final DataObjectSerializer eventStreamSerializer() {
         final DataObjectSerializer existing = (DataObjectSerializer) EVENT_STREAM_SERIALIZER.getAcquire(this);
         return existing != null ? existing : loadEventStreamSerializer();
@@ -270,17 +263,16 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends Runtime
         return witness == null ? loaded : (DataObjectSerializer) witness;
     }
 
-    @Override
-    public NormalizedNode serialize(final D data) {
-        final NormalizedNodeResult result = new NormalizedNodeResult();
+    final @NonNull NormalizedNode serializeImpl(final @NonNull D data) {
+        final var result = new NormalizationResultHolder();
         // We create DOM stream writer which produces normalized nodes
-        final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+        final var domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
         try {
             eventStreamSerializer().serialize(data, new BindingToNormalizedStreamWriter(this, domWriter));
         } catch (final IOException e) {
             throw new IllegalStateException("Failed to serialize Binding DTO",e);
         }
-        return result.getResult();
+        return result.getResult().data();
     }
 
     static final <T extends NormalizedNode> @NonNull T checkDataArgument(final @NonNull Class<T> expectedType,