Hide CodecContextSupplier
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / ChoiceCodecContext.java
index f4c4ffcda4ed80f8fd22f040a7b7c65268b21d44..a7ec5fabb26744a05b1317d33d9097cc606f1e20 100644 (file)
@@ -23,7 +23,6 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
-import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import org.eclipse.jdt.annotation.NonNull;
@@ -36,11 +35,11 @@ import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
 import org.opendaylight.yangtools.yang.binding.BindingObject;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.binding.contract.Naming;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 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.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -95,22 +94,26 @@ import org.slf4j.LoggerFactory;
  * ambiguous reference and issue warn once when they are encountered -- tracking warning information in
  * {@link #ambiguousByCaseChildWarnings}.
  */
-final class ChoiceCodecContext<D extends DataObject> extends DataContainerCodecContext<D, ChoiceRuntimeType>
+final class ChoiceCodecContext<D extends DataObject> extends CommonDataObjectCodecContext<D, ChoiceRuntimeType>
         implements BindingDataObjectCodecTreeNode<D> {
     private static final Logger LOG = LoggerFactory.getLogger(ChoiceCodecContext.class);
 
-    private final ImmutableMap<NodeIdentifier, DataContainerCodecPrototype<?>> byYangCaseChild;
-    private final ImmutableListMultimap<Class<?>, DataContainerCodecPrototype<?>> ambiguousByCaseChildClass;
-    private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClass;
-    private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byClass;
+    private final ImmutableListMultimap<Class<?>, CommonDataObjectCodecPrototype<?>> ambiguousByCaseChildClass;
+    private final ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byCaseChildClass;
+    private final ImmutableMap<NodeIdentifier, CaseCodecPrototype> byYangCaseChild;
+    private final ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byClass;
     private final Set<Class<?>> ambiguousByCaseChildWarnings;
 
-    ChoiceCodecContext(final DataContainerCodecPrototype<ChoiceRuntimeType> prototype) {
+    ChoiceCodecContext(final Class<D> cls, final ChoiceRuntimeType type, final CodecContextFactory factory) {
+        this(new ChoiceCodecPrototype(Item.of(cls), type, factory));
+    }
+
+    ChoiceCodecContext(final ChoiceCodecPrototype prototype) {
         super(prototype);
-        final var byYangCaseChildBuilder = new HashMap<NodeIdentifier, DataContainerCodecPrototype<?>>();
-        final var byClassBuilder = new HashMap<Class<?>, DataContainerCodecPrototype<?>>();
+        final var byYangCaseChildBuilder = new HashMap<NodeIdentifier, CaseCodecPrototype>();
+        final var byClassBuilder = new HashMap<Class<?>, CommonDataObjectCodecPrototype<?>>();
         final var childToCase = SetMultimapBuilder.hashKeys().hashSetValues()
-            .<Class<?>, DataContainerCodecPrototype<?>>build();
+            .<Class<?>, CommonDataObjectCodecPrototype<?>>build();
 
         // Load case statements valid in this choice and keep track of their names
         final var choiceType = prototype.getType();
@@ -138,8 +141,8 @@ final class ChoiceCodecContext<D extends DataObject> extends DataContainerCodecC
         byYangCaseChild = ImmutableMap.copyOf(byYangCaseChildBuilder);
 
         // Move unambiguous child->case mappings to byCaseChildClass, removing them from childToCase
-        final var ambiguousByCaseBuilder = ImmutableListMultimap.<Class<?>, DataContainerCodecPrototype<?>>builder();
-        final var unambiguousByCaseBuilder = ImmutableMap.<Class<?>, DataContainerCodecPrototype<?>>builder();
+        final var ambiguousByCaseBuilder = ImmutableListMultimap.<Class<?>, CommonDataObjectCodecPrototype<?>>builder();
+        final var unambiguousByCaseBuilder = ImmutableMap.<Class<?>, CommonDataObjectCodecPrototype<?>>builder();
         for (var entry : Multimaps.asMap(childToCase).entrySet()) {
             final var cases = entry.getValue();
             if (cases.size() != 1) {
@@ -166,7 +169,7 @@ final class ChoiceCodecContext<D extends DataObject> extends DataContainerCodecC
          * This is required due property of binding specification, that if choice is in grouping schema path location is
          * lost, and users may use incorrect case class using copy builders.
          */
-        final var bySubstitutionBuilder = new HashMap<Class<?>, DataContainerCodecPrototype<?>>();
+        final var bySubstitutionBuilder = new HashMap<Class<?>, CommonDataObjectCodecPrototype<?>>();
         final var context = factory.getRuntimeContext();
         for (var caseType : context.getTypes().allCaseChildren(choiceType)) {
             final var caseName = caseType.getIdentifier();
@@ -201,26 +204,12 @@ final class ChoiceCodecContext<D extends DataObject> extends DataContainerCodecC
     @Override
     public WithStatus getSchema() {
         // FIXME: Bad cast, we should be returning an EffectiveStatement perhaps?
-        return (WithStatus) getType().statement();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> childClass) {
-        final var child = byClass.get(childClass);
-        return (DataContainerCodecContext<C, ?>) childNonNull(child, childClass,
-            "Supplied class %s is not valid case in %s", childClass, bindingArg()).get();
+        return (WithStatus) type().statement();
     }
 
-    @SuppressWarnings("unchecked")
     @Override
-    public <C extends DataObject> Optional<DataContainerCodecContext<C, ?>> possibleStreamChild(
-            final Class<C> childClass) {
-        final var child = byClass.get(childClass);
-        if (child != null) {
-            return Optional.of((DataContainerCodecContext<C, ?>) child.get());
-        }
-        return Optional.empty();
+    CommonDataObjectCodecPrototype<?> streamChildPrototype(final Class<?> childClass) {
+        return byClass.get(childClass);
     }
 
     Iterable<Class<?>> getCaseChildrenClasses() {
@@ -229,15 +218,12 @@ final class ChoiceCodecContext<D extends DataObject> extends DataContainerCodecC
 
     @Override
     public CodecContext yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg) {
-        final DataContainerCodecPrototype<?> cazeProto;
-        if (arg instanceof NodeIdentifierWithPredicates) {
-            cazeProto = byYangCaseChild.get(new NodeIdentifier(arg.getNodeType()));
-        } else {
-            cazeProto = byYangCaseChild.get(arg);
-        }
+        return ((CaseCodecContext<?>) super.yangPathArgumentChild(arg)).yangPathArgumentChild(arg);
+    }
 
-        return childNonNull(cazeProto, arg, "Argument %s is not valid child of %s", arg, getSchema()).get()
-                .yangPathArgumentChild(arg);
+    @Override
+    CaseCodecPrototype yangChildSupplier(final NodeIdentifier arg) {
+        return byYangCaseChild.get(arg);
     }
 
     @Override
@@ -252,7 +238,7 @@ final class ChoiceCodecContext<D extends DataObject> extends DataContainerCodecC
             return null;
         }
         final var caze = byYangCaseChild.get(first.name());
-        return (D) caze.getDataObject().deserialize(data);
+        return ((CaseCodecContext<D>) caze.getCodecContext()).deserialize(data);
     }
 
     @Override
@@ -297,12 +283,13 @@ final class ChoiceCodecContext<D extends DataObject> extends DataContainerCodecC
                         not guaranteed to be stable and is subject to variations based on runtime circumstances. \
                         Please see the stack trace for hints about the source of ambiguity.""",
                         type, bindingArg(), result.getBindingClass(),
-                        Lists.transform(inexact, DataContainerCodecPrototype::getBindingClass), new Throwable());
+                        Lists.transform(inexact, CommonDataObjectCodecPrototype::getBindingClass), new Throwable());
                 }
             }
         }
 
-        return childNonNull(result, type, "Class %s is not child of any cases for %s", type, bindingArg()).get();
+        return childNonNull(result, type, "Class %s is not child of any cases for %s", type, bindingArg())
+            .getCodecContext();
     }
 
     /**
@@ -319,10 +306,8 @@ final class ChoiceCodecContext<D extends DataObject> extends DataContainerCodecC
         checkArgument(DataContainer.class.isAssignableFrom(type), "Supplied type must be derived from DataContainer");
         final var ret = new LinkedList<Class<? extends DataObject>>();
         for (var method : type.getMethods()) {
-            final var entity = getYangModeledReturnType(method, Naming.GETTER_PREFIX);
-            if (entity.isPresent()) {
-                ret.add((Class<? extends DataObject>) entity.orElseThrow());
-            }
+            DataContainerAnalysis.getYangModeledReturnType(method, Naming.GETTER_PREFIX)
+                .ifPresent(entity -> ret.add((Class<? extends DataObject>) entity));
         }
         return ret;
     }