Rework BindingRuntimeTypes 45/98245/100
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 29 Oct 2021 16:06:01 +0000 (18:06 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 8 Mar 2022 13:25:57 +0000 (14:25 +0100)
BindingRuntimeTypes serves to bring together GeneratedTypes and
SchemaNodes. We do this in a a number of different ways, but a lot of
the times this ends up looking a Type and then finding the SchemaNode
which generated it -- and then perhaps inquire children by SchemaNode
(which again is looked up in some way).

Once we have done these cross-lookups, we resolve the Type to a Class
through BindingRuntimeContext and instantiate a
DataContainerCodecPrototype, which holds these (and other) bits
together.

Current code relies on DerivableSchemaNode and SchemaNode-based lookups
to resolve these due to historical reasons. Our Generator infrastructure
already has AbstractExplicitGenerator.getOriginal() to perform the
equivalent operation.

This patch defines a RuntimeType base interface which holds together an
EffectiveStatement and a Generated type. We also define a
RuntimeTypeContainer to expose lookup methods for inquiring child
RuntimeTypes as appropriate.

BindingRuntimeTypes serves as the root of a tree hierarchy, where
RuntimeType is a leaf node and CompositeRuntimeType is an interior
node.

NodeCodecContext and its subclasses are modified to maintain a reference
to their backing RuntimeType and issue appropriate localized lookups.

JIRA: MDSAL-696
Change-Id: I45850d320e01fce0b227512b9f5f7b19331df60e
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
129 files changed:
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java
binding/mdsal-binding-dom-codec-api/src/main/java/module-info.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ActionCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseNodeCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceNodeCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerNodeCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamerGenerator.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/IdentifiableItemCodec.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NodeCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/SchemaRootCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/UnionTypeCodec.java
binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java
binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/Mdsal724Test.java
binding/mdsal-binding-generator/pom.xml
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/BindingRuntimeTypesFactory.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingRuntimeTypes.java [deleted file]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractAugmentGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractDependentGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractExplicitGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeAwareGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ActionGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AugmentRequirement.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CaseGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChoiceGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CollisionDomain.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeSchemaTreeGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ContainerGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/Generator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorContext.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorReactor.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GroupingGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/IdentityGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/InputGenerator.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/KeyGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafListGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ListGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/MatchStrategy.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleAugmentGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OpaqueObjectGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OperationContainerGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OriginalLink.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OutputGenerator.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcInputGenerator.java [moved from binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcContainerGenerator.java with 54% similarity]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcOutputGenerator.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/SchemaTreePlaceholder.java [deleted file]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TargetAugmentEffectiveStatement.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypeReference.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/UsesAugmentGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCaseRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractChoiceRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCompositeRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractGeneratedRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractObjectRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultActionRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnydataRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnyxmlRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAugmentRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultBindingRuntimeTypes.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultContainerRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultGroupingRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultIdentityRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultInputRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultKeyRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafListRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultListRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultModuleRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultNotificationRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultOutputRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultTypedefRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedCaseRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedChoiceRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalCaseRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalChoiceRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeChild.java [deleted file]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeParent.java [deleted file]
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/StatementRepresentation.java [new file with mode: 0644]
binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal600Test.java
binding/mdsal-binding-runtime-api/pom.xml
binding/mdsal-binding-runtime-api/src/main/java/module-info.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AbstractBindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ActionRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnydataRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnyxmlRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AugmentRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CaseRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ChoiceRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CompositeRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerLikeRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DataRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DefaultBindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GeneratedRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GroupingRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/IdentityRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InputRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InvokableRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/KeyRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafListRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ListRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ModuleRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/NotificationRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OpaqueRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OutputRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RpcRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeTypeContainer.java [new file with mode: 0644]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/TypedefRuntimeType.java [new file with mode: 0644]
binding/mdsal-binding-runtime-spi/src/main/java/module-info.java
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ForwardingBindingRuntimeContext.java

index f444c1cf8e3529b135a35c5ee4b156b5eadd6320..cce6e894a2628753e1849b30ae9c2d48228ba980 100644 (file)
@@ -166,8 +166,8 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer
 
     private Method findRpcMethod(final Class<? extends RpcService> key, final RpcDefinition rpcDef)
             throws NoSuchMethodException {
-        final String methodName = BindingMapping.getRpcMethodName(rpcDef.getQName());
-        final Class<?> inputClz = getRuntimeContext().getClassForSchema(rpcDef.getInput());
-        return key.getMethod(methodName, inputClz);
+        final var rpcName = rpcDef.getQName();
+        final var inputClz = getRuntimeContext().getRpcInput(rpcName);
+        return key.getMethod(BindingMapping.getRpcMethodName(rpcName), inputClz);
     }
 }
index 49c432ee6a27481b159c839e8fbe39c2dcc35de1..bb07f6c46f1d698cdc5862112d7a2fed0d045d77 100644 (file)
@@ -8,6 +8,7 @@
 module org.opendaylight.mdsal.binding.dom.codec.api {
     exports org.opendaylight.mdsal.binding.dom.codec.api;
 
+    requires transitive org.opendaylight.yangtools.yang.data.api;
     requires transitive org.opendaylight.mdsal.binding.runtime.api;
     requires org.opendaylight.mdsal.binding.spec.util;
 
index e32716cc0bc3aa798f07b35509a8f79c54d21e40..acd87508ea4c78fc0e5d4d90ce7005e644a50bcf 100644 (file)
@@ -9,27 +9,27 @@ package org.opendaylight.mdsal.binding.dom.codec.impl;
 
 import static java.util.Objects.requireNonNull;
 
-import org.opendaylight.yangtools.yang.model.api.InputSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.OutputSchemaNode;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
 
 /**
  * This is not really a codec context, but rather a holder of input and output codec contexts.
  */
 final class ActionCodecContext {
-    private final DataContainerCodecContext<?, InputSchemaNode> input;
-    private final DataContainerCodecContext<?, OutputSchemaNode> output;
+    private final DataContainerCodecContext<?, InputRuntimeType> input;
+    private final DataContainerCodecContext<?, OutputRuntimeType> output;
 
-    ActionCodecContext(final DataContainerCodecContext<?, InputSchemaNode> input,
-        final DataContainerCodecContext<?, OutputSchemaNode> output) {
+    ActionCodecContext(final DataContainerCodecContext<?, InputRuntimeType> input,
+        final DataContainerCodecContext<?, OutputRuntimeType> output) {
         this.input = requireNonNull(input);
         this.output = requireNonNull(output);
     }
 
-    DataContainerCodecContext<?, InputSchemaNode> input() {
+    DataContainerCodecContext<?, InputRuntimeType> input() {
         return input;
     }
 
-    DataContainerCodecContext<?, OutputSchemaNode> output() {
+    DataContainerCodecContext<?, OutputRuntimeType> output() {
         return output;
     }
 }
index 46bfd48fd36f323eb43a945e3e782da3a391adf9..cc58db2b56ca4f10aee8a43536604082a95839ad 100644 (file)
@@ -8,16 +8,16 @@
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
 import com.google.common.base.Preconditions;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 
 final class AugmentationNodeContext<D extends DataObject & Augmentation<?>>
-        extends DataObjectCodecContext<D, AugmentationSchemaNode> {
+        extends DataObjectCodecContext<D, AugmentRuntimeType> {
 
-    AugmentationNodeContext(final DataContainerCodecPrototype<AugmentationSchemaNode> prototype) {
+    AugmentationNodeContext(final DataContainerCodecPrototype<AugmentRuntimeType> prototype) {
         super(prototype);
     }
 
index 809e56d669840e9478e4d829807afd53d942d6f6..ff51f42affe92ae5766aebbcce5f6a8f92047d33 100644 (file)
@@ -51,8 +51,8 @@ import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader;
 import org.opendaylight.mdsal.binding.dom.codec.spi.AbstractBindingNormalizedNodeSerializer;
 import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices;
 import org.opendaylight.mdsal.binding.dom.codec.spi.BindingSchemaMapping;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.concepts.IllegalArgumentCodec;
@@ -83,15 +83,15 @@ import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeS
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeAware;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeDefinitionAware;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
@@ -344,17 +344,24 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri
 
     @Override
     public ImmutableMap<Method, ValueNodeCodecContext> getLeafNodes(final Class<?> type,
-            final DataNodeContainer schema) {
+            final EffectiveStatement<?, ?> schema) {
         final Map<String, DataSchemaNode> getterToLeafSchema = new HashMap<>();
-        for (final DataSchemaNode leaf : schema.getChildNodes()) {
-            if (leaf instanceof TypedDataSchemaNode || leaf instanceof AnyxmlSchemaNode
-                    || leaf instanceof AnydataSchemaNode) {
-                getterToLeafSchema.put(BindingSchemaMapping.getGetterMethodName(leaf), leaf);
+        for (var stmt : schema.effectiveSubstatements()) {
+            if (stmt instanceof TypedDataSchemaNode) {
+                putLeaf(getterToLeafSchema, (TypedDataSchemaNode) stmt);
+            } else if (stmt instanceof AnydataSchemaNode) {
+                putLeaf(getterToLeafSchema, (AnydataSchemaNode) stmt);
+            } else if (stmt instanceof AnyxmlSchemaNode) {
+                putLeaf(getterToLeafSchema, (AnyxmlSchemaNode) stmt);
             }
         }
         return getLeafNodesUsingReflection(type, getterToLeafSchema);
     }
 
+    private static void putLeaf(final Map<String, DataSchemaNode> map, final DataSchemaNode leaf) {
+        map.put(BindingSchemaMapping.getGetterMethodName(leaf), leaf);
+    }
+
     private ImmutableMap<Method, ValueNodeCodecContext> getLeafNodesUsingReflection(
             final Class<?> parentClass, final Map<String, DataSchemaNode> getterToLeafSchema) {
         final Map<Method, ValueNodeCodecContext> leaves = new HashMap<>();
@@ -447,27 +454,34 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri
                 throw new IllegalStateException("Unable to load codec for " + valueType, e);
             }
         } else if (typeDef instanceof LeafrefTypeDefinition) {
-            final Entry<GeneratedType, WithStatus> typeWithSchema = context.getTypeWithSchema(valueType);
-            final WithStatus schema = typeWithSchema.getValue();
-            checkState(schema instanceof TypeDefinition, "Unexpected schema %s", schema);
-            return getCodec(valueType, (TypeDefinition<?>) schema);
+            final var typeWithSchema = context.getTypeWithSchema(valueType);
+            final var schema = typeWithSchema.statement();
+            final TypeDefinition<?> def;
+            if (schema instanceof TypeDefinitionAware) {
+                def = ((TypeDefinitionAware) schema).getTypeDefinition();
+            } else if (schema instanceof TypeAware) {
+                def = ((TypeAware) schema).getType();
+            } else {
+                throw new IllegalStateException("Unexpected schema " + schema);
+            }
+            return getCodec(valueType, def);
         }
         return ValueTypeCodec.getCodecFor(valueType, typeDef);
     }
 
     @Override
-    public IdentifiableItemCodec getPathArgumentCodec(final Class<?> listClz, final ListSchemaNode schema) {
+    public IdentifiableItemCodec getPathArgumentCodec(final Class<?> listClz, final ListRuntimeType type) {
         final Optional<Class<Identifier<?>>> optIdentifier = ClassLoaderUtils.findFirstGenericArgument(listClz,
                 Identifiable.class);
         checkState(optIdentifier.isPresent(), "Failed to find identifier for %s", listClz);
 
         final Class<Identifier<?>> identifier = optIdentifier.get();
         final Map<QName, ValueContext> valueCtx = new HashMap<>();
-        for (final ValueNodeCodecContext leaf : getLeafNodes(identifier, schema).values()) {
+        for (final ValueNodeCodecContext leaf : getLeafNodes(identifier, type.statement()).values()) {
             final QName name = leaf.getDomPathArgument().getNodeType();
             valueCtx.put(name, new ValueContext(identifier, leaf));
         }
-        return IdentifiableItemCodec.of(schema, identifier, listClz, valueCtx);
+        return IdentifiableItemCodec.of(type.statement(), identifier, listClz, valueCtx);
     }
 
     @SuppressWarnings("unchecked")
index 4dda319a073a7d8bbb553e664aeed24935e5b384..413be40bb45374b6911d1995284440b926c86070 100644 (file)
@@ -11,26 +11,28 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 
 import java.util.List;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
 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.data.api.YangInstanceIdentifier;
 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.CaseSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 
-final class CaseNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, CaseSchemaNode> {
-    CaseNodeCodecContext(final DataContainerCodecPrototype<CaseSchemaNode> prototype) {
+final class CaseNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, CaseRuntimeType> {
+    CaseNodeCodecContext(final DataContainerCodecPrototype<CaseRuntimeType> prototype) {
         super(prototype);
     }
 
     @Override
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    Item<?> createBindingArg(final Class<?> childClass, final DataSchemaNode childSchema) {
+    Item<?> createBindingArg(final Class<?> childClass, final EffectiveStatement<?, ?> childSchema) {
         // FIXME: MDSAL-697: see overridden method for further guidance
-        return childSchema.isAddedByUses() ? Item.of((Class)getBindingClass(), (Class)childClass)
-            : super.createBindingArg(childClass, childSchema);
+        return childSchema instanceof AddedByUsesAware && ((AddedByUsesAware) childSchema).isAddedByUses()
+            ? Item.of((Class)getBindingClass(), (Class)childClass)
+                : super.createBindingArg(childClass, childSchema);
     }
 
     @Override
index dc2f6a409492bb09b566ab9c303314bb9c03a836..e170ccd254ab0b417fff3c4317a50aa658b9d62b 100644 (file)
@@ -28,7 +28,12 @@ import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
@@ -39,9 +44,8 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
 import org.opendaylight.yangtools.yang.data.util.NormalizedNodeSchemaUtils;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -92,7 +96,7 @@ import org.slf4j.LoggerFactory;
  * ambiguous reference and issue warn once when they are encountered -- tracking warning information in
  * {@link #ambiguousByCaseChildWarnings}.
  */
-final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCodecContext<D, ChoiceSchemaNode> {
+final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCodecContext<D, ChoiceRuntimeType> {
     private static final Logger LOG = LoggerFactory.getLogger(ChoiceNodeCodecContext.class);
 
     private final ImmutableMap<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChild;
@@ -101,7 +105,7 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
     private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byClass;
     private final Set<Class<?>> ambiguousByCaseChildWarnings;
 
-    ChoiceNodeCodecContext(final DataContainerCodecPrototype<ChoiceSchemaNode> prototype) {
+    ChoiceNodeCodecContext(final DataContainerCodecPrototype<ChoiceRuntimeType> prototype) {
         super(prototype);
         final Map<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChildBuilder =
             new HashMap<>();
@@ -110,10 +114,11 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
             SetMultimapBuilder.hashKeys().hashSetValues().build();
         final Set<Class<?>> potentialSubstitutions = new HashSet<>();
         // Walks all cases for supplied choice in current runtime context
-        for (final Class<?> caze : factory().getRuntimeContext().getCases(getBindingClass())) {
+        // FIXME: 9.0.0: factory short-circuits to prototype, just as getBindingClass() does
+        for (final Class<?> caze : loadCaseClasses()) {
             // We try to load case using exact match thus name
             // and original schema must equals
-            final DataContainerCodecPrototype<CaseSchemaNode> cazeDef = loadCase(caze);
+            final DataContainerCodecPrototype<CaseRuntimeType> cazeDef = loadCase(caze);
             // If we have case definition, this case is instantiated
             // at current location and thus is valid in context of parent choice
             if (cazeDef != null) {
@@ -125,17 +130,21 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
                     childToCase.put(cazeChild, cazeDef);
                 }
                 // Updates collection of YANG instance identifier to case
-                for (final DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) {
-                    if (cazeChild.isAugmenting()) {
-                        final AugmentationSchemaNode augment =
-                            NormalizedNodeSchemaUtils.findCorrespondingAugment(cazeDef.getSchema(), cazeChild);
-                        if (augment != null) {
-                            byYangCaseChildBuilder.put(DataSchemaContextNode.augmentationIdentifierFrom(augment),
-                                cazeDef);
-                            continue;
+                for (var stmt : cazeDef.getType().statement().effectiveSubstatements()) {
+                    if (stmt instanceof DataSchemaNode) {
+                        final DataSchemaNode cazeChild = (DataSchemaNode) stmt;
+                        if (cazeChild.isAugmenting()) {
+                            final AugmentationSchemaNode augment = NormalizedNodeSchemaUtils.findCorrespondingAugment(
+                                // FIXME: bad cast
+                                (DataSchemaNode) cazeDef.getType().statement(), cazeChild);
+                            if (augment != null) {
+                                byYangCaseChildBuilder.put(DataSchemaContextNode.augmentationIdentifierFrom(augment),
+                                    cazeDef);
+                                continue;
+                            }
                         }
+                        byYangCaseChildBuilder.put(NodeIdentifier.create(cazeChild.getQName()), cazeDef);
                     }
-                    byYangCaseChildBuilder.put(NodeIdentifier.create(cazeChild.getQName()), cazeDef);
                 }
             } else {
                 /*
@@ -189,6 +198,28 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
         byClass = ImmutableMap.copyOf(byClassBuilder);
     }
 
+    private List<Class<?>> loadCaseClasses() {
+        final var context = factory().getRuntimeContext();
+        final var type = getType();
+
+        return Stream.concat(type.validCaseChildren().stream(), type.additionalCaseChildren().stream())
+            .map(caseChild -> {
+                final var caseName = caseChild.getIdentifier();
+                try {
+                    return context.loadClass(caseName);
+                } catch (ClassNotFoundException e) {
+                    throw new IllegalStateException("Failed to load class for " + caseName, e);
+                }
+            })
+            .collect(Collectors.toUnmodifiableList());
+    }
+
+    @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) {
@@ -212,15 +243,14 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
         return Iterables.concat(byCaseChildClass.keySet(), ambiguousByCaseChildClass.keySet());
     }
 
-    protected DataContainerCodecPrototype<CaseSchemaNode> loadCase(final Class<?> childClass) {
-        final Optional<CaseSchemaNode> childSchema = factory().getRuntimeContext().getCaseSchemaDefinition(getSchema(),
-            childClass);
-        if (childSchema.isPresent()) {
-            return DataContainerCodecPrototype.from(childClass, childSchema.get(), factory());
+    protected DataContainerCodecPrototype<CaseRuntimeType> loadCase(final Class<?> childClass) {
+        final var child = getType().bindingCaseChild(JavaTypeName.create(childClass));
+        if (child == null) {
+            LOG.debug("Supplied class {} is not valid case in schema {}", childClass, getSchema());
+            return null;
         }
 
-        LOG.debug("Supplied class {} is not valid case in schema {}", childClass, getSchema());
-        return null;
+        return DataContainerCodecPrototype.from(childClass, child, factory());
     }
 
     @Override
index 6c25e9a1b2ae8cc7e4f2b12369cd6013d90ecf2e..0c4a86af75c9ad901894519a4aabb2452caf4867 100644 (file)
@@ -9,15 +9,16 @@ package org.opendaylight.mdsal.binding.dom.codec.impl;
 
 import static com.google.common.base.Preconditions.checkState;
 
+import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerLike;
 
-final class ContainerNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, ContainerLike>
+final class ContainerNodeCodecContext<D extends DataObject>
+        extends DataObjectCodecContext<D, ContainerLikeRuntimeType<?, ?>>
         implements RpcInputCodec<D> {
 
-    ContainerNodeCodecContext(final DataContainerCodecPrototype<ContainerLike> prototype) {
+    ContainerNodeCodecContext(final DataContainerCodecPrototype<ContainerLikeRuntimeType<?, ?>> prototype) {
         super(prototype);
     }
 
index 6c99bc898843a94c8328db3a157e84543cdab272..dc0566be9e580609dc2cf15dd7ec1e8ee1b3ad7d 100644 (file)
@@ -29,6 +29,8 @@ import org.opendaylight.mdsal.binding.dom.codec.api.MissingSchemaException;
 import org.opendaylight.mdsal.binding.dom.codec.api.MissingSchemaForClassException;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BindingObject;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -41,9 +43,8 @@ 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.model.api.DocumentedNode.WithStatus;
 
-abstract class DataContainerCodecContext<D extends DataObject, T extends WithStatus> extends NodeCodecContext
+abstract class DataContainerCodecContext<D extends DataObject, T extends RuntimeTypeContainer> extends NodeCodecContext
         implements BindingDataObjectCodecTreeNode<D>  {
     private static final VarHandle EVENT_STREAM_SERIALIZER;
 
@@ -66,9 +67,8 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends WithSta
         this.prototype = requireNonNull(prototype);
     }
 
-    @Override
-    public final T getSchema() {
-        return prototype.getSchema();
+    public final @NonNull T getType() {
+        return prototype.getType();
     }
 
     @Override
@@ -201,7 +201,7 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends WithSta
     private IllegalArgumentException childNullException(final Class<?> childClass, final String message,
             final Object... args) {
         final BindingRuntimeContext runtimeContext = factory().getRuntimeContext();
-        final WithStatus schema;
+        final CompositeRuntimeType schema;
         if (Augmentation.class.isAssignableFrom(childClass)) {
             schema = runtimeContext.getAugmentationDefinition(childClass.asSubclass(Augmentation.class));
         } else {
index 2a6abd3d7942472a169cdb8dfbac015303d0f5e2..4ab8c5e161924d9c34c85091d701d50da1786e18 100644 (file)
@@ -7,16 +7,29 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
+import static com.google.common.base.Verify.verify;
+
 import com.google.common.collect.Iterables;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.VarHandle;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode.ChildAddressabilitySummary;
 import org.opendaylight.mdsal.binding.dom.codec.impl.NodeCodecContext.CodecContextFactory;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.DataRoot;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -26,20 +39,16 @@ import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerLike;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class DataContainerCodecPrototype<T extends WithStatus> implements NodeContextSupplier {
+final class DataContainerCodecPrototype<T extends RuntimeTypeContainer> implements NodeContextSupplier {
     private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecPrototype.class);
 
     private static final VarHandle INSTANCE;
@@ -53,7 +62,7 @@ final class DataContainerCodecPrototype<T extends WithStatus> implements NodeCon
         }
     }
 
-    private final T schema;
+    private final T type;
     private final QNameModule namespace;
     private final CodecContextFactory factory;
     private final Item<?> bindingArg;
@@ -65,16 +74,16 @@ final class DataContainerCodecPrototype<T extends WithStatus> implements NodeCon
     private volatile DataContainerCodecContext<?, T> instance;
 
     @SuppressWarnings("unchecked")
-    private DataContainerCodecPrototype(final Class<?> cls, final PathArgument arg, final T nodeSchema,
+    private DataContainerCodecPrototype(final Class<?> cls, final PathArgument arg, final T type,
             final CodecContextFactory factory) {
-        this(Item.of((Class<? extends DataObject>) cls), arg, nodeSchema, factory);
+        this(Item.of((Class<? extends DataObject>) cls), arg, type, factory);
     }
 
-    private DataContainerCodecPrototype(final Item<?> bindingArg, final PathArgument arg, final T nodeSchema,
+    private DataContainerCodecPrototype(final Item<?> bindingArg, final PathArgument arg, final T type,
             final CodecContextFactory factory) {
         this.bindingArg = bindingArg;
         this.yangArg = arg;
-        this.schema = nodeSchema;
+        this.type = type;
         this.factory = factory;
 
         if (arg instanceof AugmentationIdentifier) {
@@ -84,10 +93,14 @@ final class DataContainerCodecPrototype<T extends WithStatus> implements NodeCon
             this.namespace = arg.getNodeType().getModule();
         }
 
-        this.childAddressabilitySummary = computeChildAddressabilitySummary(nodeSchema);
+        this.childAddressabilitySummary = type instanceof RuntimeType
+            ? computeChildAddressabilitySummary(((RuntimeType) type).statement())
+                // BindingRuntimeTypes, does not matter
+                : ChildAddressabilitySummary.MIXED;
     }
 
-    private static ChildAddressabilitySummary computeChildAddressabilitySummary(final WithStatus nodeSchema) {
+    private static ChildAddressabilitySummary computeChildAddressabilitySummary(final Object nodeSchema) {
+        // FIXME: rework this to work on EffectiveStatements
         if (nodeSchema instanceof DataNodeContainer) {
             boolean haveAddressable = false;
             boolean haveUnaddressable = false;
@@ -160,35 +173,40 @@ final class DataContainerCodecPrototype<T extends WithStatus> implements NodeCon
         return ChildAddressabilitySummary.UNADDRESSABLE;
     }
 
-    static DataContainerCodecPrototype<EffectiveModelContext> rootPrototype(final CodecContextFactory factory) {
-        final EffectiveModelContext schema = factory.getRuntimeContext().getEffectiveModelContext();
-        final NodeIdentifier arg = NodeIdentifier.create(SchemaContext.NAME);
-        return new DataContainerCodecPrototype<>(DataRoot.class, arg, schema, factory);
+    static DataContainerCodecPrototype<BindingRuntimeTypes> rootPrototype(final CodecContextFactory factory) {
+        return new DataContainerCodecPrototype<>(DataRoot.class, NodeIdentifier.create(SchemaContext.NAME),
+            factory.getRuntimeContext().getTypes(), factory);
     }
 
-    static <T extends DataSchemaNode> DataContainerCodecPrototype<T> from(final Class<?> cls, final T schema,
+    static <T extends CompositeRuntimeType> DataContainerCodecPrototype<T> from(final Class<?> cls, final T type,
             final CodecContextFactory factory) {
-        return new DataContainerCodecPrototype<>(cls, NodeIdentifier.create(schema.getQName()), schema, factory);
+        return new DataContainerCodecPrototype<>(cls, createIdentifier(type), type, factory);
     }
 
-    static <T extends DataSchemaNode> DataContainerCodecPrototype<T> from(final Item<?> bindingArg, final T schema,
+    static <T extends CompositeRuntimeType> DataContainerCodecPrototype<T> from(final Item<?> bindingArg, final T type,
             final CodecContextFactory factory) {
-        return new DataContainerCodecPrototype<>(bindingArg, NodeIdentifier.create(schema.getQName()), schema, factory);
+        return new DataContainerCodecPrototype<>(bindingArg, createIdentifier(type), type, factory);
+    }
+
+    static DataContainerCodecPrototype<AugmentRuntimeType> from(final Class<?> augClass,
+            final AugmentationIdentifier arg, final AugmentRuntimeType schema, final CodecContextFactory factory) {
+        return new DataContainerCodecPrototype<>(augClass, arg, schema, factory);
     }
 
-    static DataContainerCodecPrototype<AugmentationSchemaNode> from(final Class<?> augClass,
-            final AugmentationIdentifier arg, final AugmentationSchemaNode schema, final CodecContextFactory factory) {
+    static DataContainerCodecPrototype<NotificationRuntimeType> from(final Class<?> augClass,
+            final NotificationRuntimeType schema, final CodecContextFactory factory) {
+        final PathArgument arg = NodeIdentifier.create(schema.statement().argument());
         return new DataContainerCodecPrototype<>(augClass, arg, schema, factory);
     }
 
-    static DataContainerCodecPrototype<NotificationDefinition> from(final Class<?> augClass,
-            final NotificationDefinition schema, final CodecContextFactory factory) {
-        final PathArgument arg = NodeIdentifier.create(schema.getQName());
-        return new DataContainerCodecPrototype<>(augClass,arg, schema, factory);
+    private static @NonNull NodeIdentifier createIdentifier(final CompositeRuntimeType type) {
+        final Object arg = type.statement().argument();
+        verify(arg instanceof QName, "Unexpected type %s argument %s", type, arg);
+        return NodeIdentifier.create((QName) arg);
     }
 
-    T getSchema() {
-        return schema;
+    @NonNull T getType() {
+        return type;
     }
 
     ChildAddressabilitySummary getChildAddressabilitySummary() {
@@ -231,24 +249,19 @@ final class DataContainerCodecPrototype<T extends WithStatus> implements NodeCon
     // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object
     private @NonNull DataContainerCodecContext<?, T> createInstance() {
         // FIXME: make protected abstract
-        if (schema instanceof ContainerLike) {
+        if (type instanceof ContainerLikeRuntimeType) {
             return new ContainerNodeCodecContext(this);
-        } else if (schema instanceof ListSchemaNode) {
+        } else if (type instanceof ListRuntimeType) {
             return Identifiable.class.isAssignableFrom(getBindingClass())
-                    ? KeyedListNodeCodecContext.create((DataContainerCodecPrototype<ListSchemaNode>) this)
+                    ? KeyedListNodeCodecContext.create((DataContainerCodecPrototype<ListRuntimeType>) this)
                             : new ListNodeCodecContext(this);
-        } else if (schema instanceof ChoiceSchemaNode) {
+        } else if (type instanceof ChoiceRuntimeType) {
             return new ChoiceNodeCodecContext(this);
-        } else if (schema instanceof AugmentationSchemaNode) {
+        } else if (type instanceof AugmentRuntimeType) {
             return new AugmentationNodeContext(this);
-        } else if (schema instanceof CaseSchemaNode) {
+        } else if (type instanceof CaseRuntimeType) {
             return new CaseNodeCodecContext(this);
         }
-        throw new IllegalArgumentException("Unsupported type " + getBindingClass() + " " + schema);
-    }
-
-    // FIXME: eliminate with above createInstance() item
-    boolean isChoice() {
-        return schema instanceof ChoiceSchemaNode;
+        throw new IllegalArgumentException("Unsupported type " + getBindingClass() + " " + type);
     }
 }
index fd1c2eea8bd9ee66a94922fbd777e740d8f4c5d6..52a7b06be46e728825533b2e1108251549d81ae8 100644 (file)
@@ -14,6 +14,8 @@ import com.google.common.annotations.Beta;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
@@ -27,8 +29,13 @@ import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
 import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
 import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
@@ -45,10 +52,9 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -56,7 +62,7 @@ import org.slf4j.LoggerFactory;
  * This class is an implementation detail. It is public only due to technical reasons and may change at any time.
  */
 @Beta
-public abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeContainer & WithStatus>
+public abstract class DataObjectCodecContext<D extends DataObject, T extends CompositeRuntimeType>
         extends DataContainerCodecContext<D, T> {
     private static final Logger LOG = LoggerFactory.getLogger(DataObjectCodecContext.class);
     private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class,
@@ -97,7 +103,8 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
 
         final Class<D> bindingClass = getBindingClass();
 
-        final ImmutableMap<Method, ValueNodeCodecContext> tmpLeaves = factory().getLeafNodes(bindingClass, getSchema());
+        final ImmutableMap<Method, ValueNodeCodecContext> tmpLeaves = factory().getLeafNodes(bindingClass,
+            getType().statement());
         final Map<Class<? extends DataContainer>, Method> clsToMethod =
             BindingReflections.getChildrenClassToMethod(bindingClass);
 
@@ -133,7 +140,7 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
 
             // FIXME: It really feels like we should be specializing DataContainerCodecPrototype so as to ditch
             //        createInstance() and then we could do an instanceof check instead.
-            if (childProto.isChoice()) {
+            if (childProto.getType() instanceof ChoiceRuntimeType) {
                 final ChoiceNodeCodecContext<?> choice = (ChoiceNodeCodecContext<?>) childProto.get();
                 for (final Class<?> cazeChild : choice.getCaseChildrenClasses()) {
                     byBindingArgClassBuilder.put(cazeChild, childProto);
@@ -151,13 +158,14 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
         this.byBindingArgClass = byStreamClassBuilder.equals(byBindingArgClassBuilder) ? this.byStreamClass
                 : ImmutableMap.copyOf(byBindingArgClassBuilder);
 
-        final ImmutableMap<AugmentationIdentifier, Type> possibleAugmentations;
+        final Iterable<AugmentRuntimeType> possibleAugmentations;
         if (Augmentable.class.isAssignableFrom(bindingClass)) {
-            possibleAugmentations = factory().getRuntimeContext().getAvailableAugmentationTypes(getSchema());
+            final var type = getType();
+            possibleAugmentations = Iterables.concat(type.augments(), type.mismatchedAugments());
             generatedClass = CodecDataObjectGenerator.generateAugmentable(prototype.getFactory().getLoader(),
                 bindingClass, tmpLeaves, tmpDataObjects, keyMethod);
         } else {
-            possibleAugmentations = ImmutableMap.of();
+            possibleAugmentations = List.of();
             generatedClass = CodecDataObjectGenerator.generate(prototype.getFactory().getLoader(), bindingClass,
                 tmpLeaves, tmpDataObjects, keyMethod);
         }
@@ -165,7 +173,7 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
         // Iterate over all possible augmentations, indexing them as needed
         final Map<PathArgument, DataContainerCodecPrototype<?>> augByYang = new HashMap<>();
         final Map<Class<?>, DataContainerCodecPrototype<?>> augByStream = new HashMap<>();
-        for (final Type augment : possibleAugmentations.values()) {
+        for (final AugmentRuntimeType augment : possibleAugmentations) {
             final DataContainerCodecPrototype<?> augProto = getAugmentationPrototype(augment);
             final PathArgument augYangArg = augProto.getYangArg();
             if (augByYang.putIfAbsent(augYangArg, augProto) == null) {
@@ -189,12 +197,17 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
         proxyConstructor = ctor.asType(DATAOBJECT_TYPE);
     }
 
-    @SuppressWarnings("unchecked")
     @Override
+    public final WithStatus getSchema() {
+        // FIXME: Bad cast, we should be returning an EffectiveStatement perhaps?
+        return (WithStatus) getType().statement();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
     public <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> childClass) {
-        final DataContainerCodecPrototype<?> childProto = streamChildPrototype(childClass);
-        return (DataContainerCodecContext<C, ?>) childNonNull(childProto, childClass, " Child %s is not valid child.",
-                childClass).get();
+        return (DataContainerCodecContext<C, ?>) childNonNull(streamChildPrototype(childClass), childClass,
+            "Child %s is not valid child of %s", getBindingClass(), childClass).get();
     }
 
     private DataContainerCodecPrototype<?> streamChildPrototype(final Class<?> childClass) {
@@ -274,10 +287,12 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
     }
 
     private DataContainerCodecPrototype<?> loadChildPrototype(final Class<? extends DataContainer> childClass) {
-        final DataSchemaNode childSchema = childNonNull(
-            factory().getRuntimeContext().findChildSchemaDefinition(getSchema(), namespace(), childClass), childClass,
-            "Node %s does not have child named %s", getSchema(), childClass);
-        return DataContainerCodecPrototype.from(createBindingArg(childClass, childSchema), childSchema, factory());
+        final var type = getType();
+        final var child = childNonNull(type.bindingChild(JavaTypeName.create(childClass)), childClass,
+            "Node %s does not have child named %s", type, childClass);
+
+        return DataContainerCodecPrototype.from(createBindingArg(childClass, child.statement()),
+            (CompositeRuntimeType) child, factory());
     }
 
     // FIXME: MDSAL-697: move this method into BindingRuntimeContext
@@ -287,7 +302,7 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
     //                   the equivalent of Map.Entry<Item, DataSchemaNode>, along with the override we create here. One
     //                   more input we may need to provide is our bindingClass().
     @SuppressWarnings("unchecked")
-    Item<?> createBindingArg(final Class<?> childClass, final DataSchemaNode childSchema) {
+    Item<?> createBindingArg(final Class<?> childClass, final EffectiveStatement<?, ?> childSchema) {
         return Item.of((Class<? extends DataObject>) childClass);
     }
 
@@ -340,13 +355,14 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
                         .put(childClass, prototype)
                         .build();
 
-            final Object witness = MISMATCHED_AUGMENTED.compareAndExchangeRelease(this, expected, newMismatched);
+            final var witness = (ImmutableMap<Class<?>, DataContainerCodecPrototype<?>>)
+                MISMATCHED_AUGMENTED.compareAndExchangeRelease(this, expected, newMismatched);
             if (witness == expected) {
                 LOG.trace("Cached mismatched augmentation {} -> {} in {}", childClass, prototype, this);
                 return prototype;
             }
 
-            expected = (ImmutableMap<Class<?>, DataContainerCodecPrototype<?>>) witness;
+            expected = witness;
             final DataContainerCodecPrototype<?> existing = expected.get(childClass);
             if (existing != null) {
                 LOG.trace("Using raced mismatched augmentation {} -> {} in {}", childClass, existing, this);
@@ -367,19 +383,23 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
         return cls.equals(loaded);
     }
 
-    private @NonNull DataContainerCodecPrototype<?> getAugmentationPrototype(final Type value) {
+    private @NonNull DataContainerCodecPrototype<?> getAugmentationPrototype(final AugmentRuntimeType augment) {
         final BindingRuntimeContext ctx = factory().getRuntimeContext();
 
+        final GeneratedType javaType = augment.javaType();
         final Class<? extends Augmentation<?>> augClass;
         try {
-            augClass = ctx.loadClass(value);
+            augClass = ctx.loadClass(javaType);
         } catch (final ClassNotFoundException e) {
-            throw new IllegalStateException("RuntimeContext references type " + value + " but failed to its class", e);
+            throw new IllegalStateException(
+                "RuntimeContext references type " + javaType + " but failed to load its class", e);
         }
 
-        final Entry<AugmentationIdentifier, AugmentationSchemaNode> augSchema =
-                ctx.getResolvedAugmentationSchema(getSchema(), augClass);
-        return DataContainerCodecPrototype.from(augClass, augSchema.getKey(), augSchema.getValue(), factory());
+        // TODO: at some point we need the effective children
+        return DataContainerCodecPrototype.from(augClass, new AugmentationIdentifier(augment.statement()
+            .streamEffectiveSubstatements(SchemaTreeEffectiveStatement.class)
+            .map(SchemaTreeEffectiveStatement::getIdentifier)
+            .collect(ImmutableSet.toImmutableSet())), augment, factory());
     }
 
     @SuppressWarnings("checkstyle:illegalCatch")
@@ -410,9 +430,15 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
             }
         }
         for (final DataContainerCodecPrototype<?> value : augmentationByStream.values()) {
-            final NormalizedNode augData = data.childByArg(value.getYangArg());
-            if (augData != null) {
-                map.put(value.getBindingClass(), value.get().deserializeObject(augData));
+            final var augClass = value.getBindingClass();
+            // Do not perform duplicate deserialization if we have already created the corresponding augmentation
+            // and validate whether the proposed augmentation is valid ion this instantiation context.
+            if (!map.containsKey(augClass) && getType().augments().contains(value.getType())) {
+                final NormalizedNode augData = data.childByArg(value.getYangArg());
+                if (augData != null) {
+                    // ... make sure we do not replace an e
+                    map.putIfAbsent(augClass, value.get().deserializeObject(augData));
+                }
             }
         }
         return map;
index b007379a0de6762576d23c32899a149cff3c9ad9..c8b4b3e2541a724cf3af9a104dd7c9916934371e 100644 (file)
@@ -21,7 +21,6 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 import net.bytebuddy.ByteBuddy;
 import net.bytebuddy.description.field.FieldDescription;
@@ -73,7 +72,6 @@ import org.opendaylight.yangtools.yang.model.api.ContainerLike;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -178,8 +176,8 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
     static Class<? extends DataObjectStreamer<?>> generateStreamer(final CodecClassLoader loader,
             final CodecContextFactory registry, final Class<?> type) {
 
-        final Entry<GeneratedType, WithStatus> typeAndSchema = registry.getRuntimeContext().getTypeWithSchema(type);
-        final WithStatus schema = typeAndSchema.getValue();
+        final var typeAndSchema = registry.getRuntimeContext().getTypeWithSchema(type);
+        final var schema = typeAndSchema.statement();
 
         final StackManipulation startEvent;
         if (schema instanceof ContainerLike || schema instanceof NotificationDefinition) {
@@ -199,8 +197,9 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
         }
 
         return loader.generateClass(type, "streamer",
-            new DataObjectStreamerGenerator<>(registry, typeAndSchema.getKey(), (DataNodeContainer) schema, type,
-                    startEvent));
+            // FIXME: cast to GeneratedType: we really should adjust getTypeWithSchema()
+            new DataObjectStreamerGenerator<>(registry, (GeneratedType) typeAndSchema.javaType(),
+                (DataNodeContainer) schema, type, startEvent));
     }
 
     @Override
index ecad6df385ed59efcfdc141396b2a00668b3e53d..f7ef432da873185892d7d356afd62fe11fc75d5d 100644 (file)
@@ -20,6 +20,7 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.concepts.AbstractIllegalArgumentCodec;
@@ -30,7 +31,8 @@ import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,7 +48,7 @@ abstract class IdentifiableItemCodec
         private final MethodHandle ctor;
         private final QName keyName;
 
-        SingleKey(final ListSchemaNode schema, final Class<? extends Identifier<?>> keyClass,
+        SingleKey(final ListEffectiveStatement schema, final Class<? extends Identifier<?>> keyClass,
                 final Class<?> identifiable, final QName keyName, final ValueContext keyContext) {
             super(schema, keyClass, identifiable);
             this.keyContext = requireNonNull(keyContext);
@@ -71,19 +73,20 @@ abstract class IdentifiableItemCodec
         private final ImmutableList<QName> keysInBindingOrder;
         private final MethodHandle ctor;
 
-        MultiKey(final ListSchemaNode schema, final Class<? extends Identifier<?>> keyClass,
+        MultiKey(final ListEffectiveStatement schema, final Class<? extends Identifier<?>> keyClass,
                 final Class<?> identifiable, final Map<QName, ValueContext> keyValueContexts) {
             super(schema, keyClass, identifiable);
 
             final MethodHandle tmpCtor = getConstructor(keyClass, keyValueContexts.size());
             final MethodHandle inv = MethodHandles.spreadInvoker(tmpCtor.type(), 0);
-            this.ctor = inv.asType(inv.type().changeReturnType(Identifier.class)).bindTo(tmpCtor);
+            ctor = inv.asType(inv.type().changeReturnType(Identifier.class)).bindTo(tmpCtor);
 
             /*
              * We need to re-index to make sure we instantiate nodes in the order in which they are defined. We will
              * also need to instantiate values in the same order.
              */
-            final List<QName> keyDef = schema.getKeyDefinition();
+            final Set<QName> keyDef = schema.findFirstEffectiveSubstatementArgument(KeyEffectiveStatement.class)
+                .orElseThrow();
             predicateTemplate = ImmutableOffsetMapTemplate.ordered(keyDef);
             this.keyValueContexts = predicateTemplate.instantiateTransformed(keyValueContexts, (key, value) -> value);
 
@@ -96,7 +99,7 @@ abstract class IdentifiableItemCodec
             final List<QName> tmp = new ArrayList<>(keyDef);
             // This is not terribly efficient but gets the job done
             tmp.sort(Comparator.comparing(qname -> BindingMapping.getPropertyName(qname.getLocalName())));
-            this.keysInBindingOrder = ImmutableList.copyOf(tmp.equals(keyDef) ? keyDef : tmp);
+            keysInBindingOrder = ImmutableList.copyOf(tmp.equals(List.copyOf(keyDef)) ? keyDef : tmp);
         }
 
         @Override
@@ -127,13 +130,13 @@ abstract class IdentifiableItemCodec
     private final Class<?> identifiable;
     private final QName qname;
 
-    IdentifiableItemCodec(final ListSchemaNode schema, final Class<? extends Identifier<?>> keyClass,
+    IdentifiableItemCodec(final ListEffectiveStatement schema, final Class<? extends Identifier<?>> keyClass,
             final Class<?> identifiable) {
         this.identifiable = requireNonNull(identifiable);
-        this.qname = schema.getQName();
+        qname = schema.argument();
     }
 
-    static IdentifiableItemCodec of(final ListSchemaNode schema,
+    static IdentifiableItemCodec of(final ListEffectiveStatement schema,
             final Class<? extends Identifier<?>> keyClass, final Class<?> identifiable,
                     final Map<QName, ValueContext> keyValueContexts) {
         switch (keyValueContexts.size()) {
index 7d140c2120d2c8e7be8a7af76269a00bfeef327c..189d443abcc9e26e1722f266db214af503f0e0a8 100644 (file)
@@ -14,21 +14,23 @@ import java.lang.reflect.Method;
 import java.util.List;
 import java.util.Map;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
 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.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.common.Ordering;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.OrderedByEffectiveStatement;
 
 abstract class KeyedListNodeCodecContext<I extends Identifier<D>, D extends DataObject & Identifiable<I>>
         extends ListNodeCodecContext<D> {
     private static final class Ordered<I extends Identifier<D>, D extends DataObject & Identifiable<I>>
             extends KeyedListNodeCodecContext<I, D> {
-        Ordered(final DataContainerCodecPrototype<ListSchemaNode> prototype, final Method keyMethod,
+        Ordered(final DataContainerCodecPrototype<ListRuntimeType> prototype, final Method keyMethod,
                 final IdentifiableItemCodec codec) {
             super(prototype, keyMethod, codec);
         }
@@ -36,7 +38,7 @@ abstract class KeyedListNodeCodecContext<I extends Identifier<D>, D extends Data
 
     static final class Unordered<I extends Identifier<D>, D extends DataObject & Identifiable<I>>
             extends KeyedListNodeCodecContext<I, D> {
-        Unordered(final DataContainerCodecPrototype<ListSchemaNode> prototype, final Method keyMethod,
+        Unordered(final DataContainerCodecPrototype<ListRuntimeType> prototype, final Method keyMethod,
                 final IdentifiableItemCodec codec) {
             super(prototype, keyMethod, codec);
         }
@@ -49,14 +51,14 @@ abstract class KeyedListNodeCodecContext<I extends Identifier<D>, D extends Data
 
     private final IdentifiableItemCodec codec;
 
-    KeyedListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype,
+    KeyedListNodeCodecContext(final DataContainerCodecPrototype<ListRuntimeType> prototype,
             final Method keyMethod, final IdentifiableItemCodec codec) {
         super(prototype, keyMethod);
         this.codec = requireNonNull(codec);
     }
 
     @SuppressWarnings("rawtypes")
-    static KeyedListNodeCodecContext create(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
+    static KeyedListNodeCodecContext create(final DataContainerCodecPrototype<ListRuntimeType> prototype) {
         final Class<?> bindingClass = prototype.getBindingClass();
         final Method keyMethod;
         try {
@@ -65,10 +67,12 @@ abstract class KeyedListNodeCodecContext<I extends Identifier<D>, D extends Data
             throw new IllegalStateException("Required method not available", e);
         }
 
-        final ListSchemaNode schema = prototype.getSchema();
-        final IdentifiableItemCodec codec = prototype.getFactory().getPathArgumentCodec(bindingClass, schema);
-        return schema.isUserOrdered() ? new Ordered<>(prototype, keyMethod, codec)
-                : new Unordered<>(prototype, keyMethod, codec);
+        final ListRuntimeType type = prototype.getType();
+        final IdentifiableItemCodec codec = prototype.getFactory().getPathArgumentCodec(bindingClass, type);
+
+        return type.statement().findFirstEffectiveSubstatementArgument(OrderedByEffectiveStatement.class)
+            .orElse(Ordering.SYSTEM) == Ordering.SYSTEM ? new Unordered<>(prototype, keyMethod, codec)
+                : new Ordered<>(prototype, keyMethod, codec);
     }
 
     @Override
index 921fb1659e1d0b2657bf52d1c72e43aed9fdee61..e69b6e9281c5c45750dfa1b02b22564589a15f99 100644 (file)
@@ -10,20 +10,20 @@ package org.opendaylight.mdsal.binding.dom.codec.impl;
 import java.lang.reflect.Method;
 import java.util.List;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
-class ListNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, ListSchemaNode> {
-    ListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
+class ListNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, ListRuntimeType> {
+    ListNodeCodecContext(final DataContainerCodecPrototype<ListRuntimeType> prototype) {
         super(prototype);
     }
 
-    ListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype,
+    ListNodeCodecContext(final DataContainerCodecPrototype<ListRuntimeType> prototype,
             final Method keyMethod) {
         super(prototype, keyMethod);
     }
index 2c2429130cbacc65aebbabec7b9c538957d9cb2a..8ce77a21608b198c23e6bd2375b0c742353a6806 100644 (file)
@@ -15,11 +15,11 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode;
 import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader;
 import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 
 /**
  * Location specific context for schema nodes, which contains codec specific information to properly serialize
@@ -64,16 +64,16 @@ abstract class NodeCodecContext implements BindingCodecTreeNode {
          * @param schema  Instantiated schema of binding type.
          * @return Map of local name to leaf node context.
          */
-        ImmutableMap<Method, ValueNodeCodecContext> getLeafNodes(Class<?> type, DataNodeContainer schema);
+        ImmutableMap<Method, ValueNodeCodecContext> getLeafNodes(Class<?> type, EffectiveStatement<?, ?> schema);
 
         /**
          * Returns Path argument codec for list item.
          *
-         * @param type Type of list item
-         * @param schema Schema of list item
+         * @param listClz Type of list item
+         * @param type Schema of list item
          * @return Path argument codec for supplied list item.
          */
-        IdentifiableItemCodec getPathArgumentCodec(Class<?> type, ListSchemaNode schema);
+        IdentifiableItemCodec getPathArgumentCodec(Class<?> listClz, ListRuntimeType type);
 
         /**
          * Return the codec loader associated with this factory.
index 6c0ed42e7cb5e3494cd568d21b8bc3b22df75d10..8f7d92f949ad594969e1571d74bd40485c9a6bf4 100644 (file)
@@ -36,16 +36,16 @@ import net.bytebuddy.jar.asm.Opcodes;
 import net.bytebuddy.matcher.ElementMatchers;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.GeneratorResult;
+import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.EventInstantAware;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 
-final class NotificationCodecContext<D extends DataObject & Notification>
-        extends DataObjectCodecContext<D, NotificationDefinition> {
+final class NotificationCodecContext<D extends DataObject & Notification<D>>
+        extends DataObjectCodecContext<D, NotificationRuntimeType> {
     private static final Generic EVENT_INSTANT_AWARE = TypeDefinition.Sort.describe(EventInstantAware.class);
 
     private static final String EVENT_INSTANT_NAME;
@@ -69,7 +69,7 @@ final class NotificationCodecContext<D extends DataObject & Notification>
 
     private final MethodHandle eventProxy;
 
-    NotificationCodecContext(final Class<?> key, final NotificationDefinition schema,
+    NotificationCodecContext(final Class<?> key, final NotificationRuntimeType schema,
             final CodecContextFactory factory) {
         super(DataContainerCodecPrototype.from(key, schema, factory));
         final Class<D> bindingClass = getBindingClass();
index bfa286ac54267f1aea8728fc8883c6a4c1636043..29bbebf469e3cc52de1fbefae5a4c862c2bce3e2 100644 (file)
@@ -21,11 +21,22 @@ import com.google.common.util.concurrent.UncheckedExecutionException;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
+import java.util.function.BiFunction;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.DataRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.yangtools.util.ClassLoaderUtils;
@@ -43,19 +54,15 @@ import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerLike;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 
-final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCodecContext<D, EffectiveModelContext> {
+final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCodecContext<D, BindingRuntimeTypes> {
 
     private final LoadingCache<Class<? extends DataObject>, DataContainerCodecContext<?, ?>> childrenByClass =
         CacheBuilder.newBuilder().build(new CacheLoader<>() {
@@ -86,10 +93,13 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
             @Override
             public NotificationCodecContext<?> load(final Class<?> key) {
                 checkArgument(key.isInterface(), "Supplied class must be interface.");
+
+                // TODO: we should be able to work with bindingChild() instead of schemaTreeChild() here
                 final QName qname = BindingReflections.findQName(key);
-                final NotificationDefinition schema = getSchema().findNotification(qname).orElseThrow(
-                    () -> new IllegalArgumentException("Supplied " + key + " is not valid notification"));
-                return new NotificationCodecContext<>(key, schema, factory());
+                final RuntimeType child = getType().schemaTreeChild(qname);
+                checkArgument(child instanceof NotificationRuntimeType, "Supplied %s is not valid notification",
+                    key);
+                return new NotificationCodecContext<>(key, (NotificationRuntimeType) child, factory());
             }
         });
 
@@ -97,10 +107,22 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
         .build(new CacheLoader<Class<?>, ContainerNodeCodecContext<?>>() {
             @Override
             public ContainerNodeCodecContext<?> load(final Class<?> key) {
+                final BiFunction<BindingRuntimeTypes, QName, Optional<? extends ContainerLikeRuntimeType<?, ?>>> lookup;
+                if (RpcInput.class.isAssignableFrom(key)) {
+                    lookup = BindingRuntimeTypes::findRpcInput;
+                } else if (RpcOutput.class.isAssignableFrom(key)) {
+                    lookup = BindingRuntimeTypes::findRpcOutput;
+                } else {
+                    throw new IllegalArgumentException(key + " does not represent an RPC container");
+                }
+
+                final CodecContextFactory factory = factory();
+                final BindingRuntimeContext context = factory.getRuntimeContext();
+
                 final QName qname = BindingReflections.findQName(key);
                 final QNameModule qnameModule = qname.getModule();
-                final Module module = getSchema().findModule(qnameModule).orElseThrow(
-                    () -> new IllegalArgumentException("Failed to find module for " + qnameModule));
+                final Module module = context.getEffectiveModelContext().findModule(qnameModule)
+                    .orElseThrow(() -> new IllegalArgumentException("Failed to find module for " + qnameModule));
                 final String className = BindingMapping.getClassName(qname);
 
                 for (final RpcDefinition potential : module.getRpcs()) {
@@ -115,8 +137,12 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
                     if (key.getSimpleName().equals(BindingMapping.getClassName(potentialQName) + className)) {
                         final ContainerLike schema = getRpcDataSchema(potential, qname);
                         checkArgument(schema != null, "Schema for %s does not define input / output.", potentialQName);
-                        return (ContainerNodeCodecContext<?>) DataContainerCodecPrototype.from(key, schema, factory())
-                            .get();
+
+                        final ContainerLikeRuntimeType<?, ?> type = lookup.apply(context.getTypes(), potentialQName)
+                            .orElseThrow(() -> new IllegalArgumentException("Cannot find runtime type for " + key));
+
+                        return (ContainerNodeCodecContext) DataContainerCodecPrototype.from(key,
+                            (ContainerLikeRuntimeType<?, ?>) type, factory).get();
                     }
                 }
 
@@ -127,14 +153,19 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
     private final LoadingCache<QName, DataContainerCodecContext<?,?>> childrenByQName =
         CacheBuilder.newBuilder().build(new CacheLoader<>() {
             @Override
-            public DataContainerCodecContext<?, ?> load(final QName qname) {
-                final DataSchemaNode childSchema = getSchema().dataChildByName(qname);
-                childNonNull(childSchema, qname, "Argument %s is not valid child of %s", qname, getSchema());
+            public DataContainerCodecContext<?, ?> load(final QName qname) throws ClassNotFoundException {
+                final var type = getType();
+                final var child = childNonNull(type.schemaTreeChild(qname), qname,
+                    "Argument %s is not valid child of %s", qname, type);
+                if (!(child instanceof DataRuntimeType)) {
+                    throw IncorrectNestingException.create("Argument %s is not valid data tree child of %s", qname,
+                        type);
+                }
+
+                // TODO: improve this check?
+                final var childSchema = child.statement();
                 if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceSchemaNode) {
-                    @SuppressWarnings("unchecked")
-                    final Class<? extends DataObject> childCls = (Class<? extends DataObject>)
-                        factory().getRuntimeContext().getClassForSchema(childSchema);
-                    return streamChild(childCls);
+                    return streamChild(factory().getRuntimeContext().loadClass(child.javaType()));
                 }
 
                 throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
@@ -145,11 +176,22 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
         CacheBuilder.newBuilder().build(new CacheLoader<>() {
             @Override
             public RpcInputCodec<?> load(final Absolute key) {
-                final ContainerLike schema = getRpcDataSchema(getSchema(), key);
-                @SuppressWarnings("unchecked")
-                final Class<? extends DataContainer> cls = (Class<? extends DataContainer>)
-                    factory().getRuntimeContext().getClassForSchema(schema);
-                return getRpc(cls);
+                final var rpcName = key.firstNodeIdentifier();
+                final var context = factory().getRuntimeContext();
+
+                final Class<? extends DataContainer> container;
+                switch (key.lastNodeIdentifier().getLocalName()) {
+                    case "input":
+                        container = context.getRpcInput(rpcName);
+                        break;
+                    case "output":
+                        container = context.getRpcOutput(rpcName);
+                        break;
+                    default:
+                        throw new IllegalArgumentException("Unhandled path " + key);
+                }
+
+                return getRpc(container);
             }
         });
 
@@ -157,18 +199,14 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
         CacheBuilder.newBuilder().build(new CacheLoader<>() {
             @Override
             public NotificationCodecContext<?> load(final Absolute key) {
-                final SchemaTreeEffectiveStatement<?> stmt = getSchema().findSchemaTreeNode(key)
-                    .orElseThrow(() -> new IllegalArgumentException("Cannot find statement at " + key));
-                checkArgument(stmt instanceof NotificationDefinition, "Statement %s is not a notification", stmt);
-
-                @SuppressWarnings("unchecked")
-                final Class<? extends Notification<?>> clz = (Class<? extends Notification<?>>)
-                    factory().getRuntimeContext().getClassForSchema((NotificationDefinition) stmt);
-                return getNotification(clz);
+                final Class<?> cls = factory().getRuntimeContext().getClassForSchema(key);
+                checkArgument(Notification.class.isAssignableFrom(cls), "Path %s does not represent a notification",
+                    key);
+                return getNotificationImpl(cls);
             }
         });
 
-    private SchemaRootCodecContext(final DataContainerCodecPrototype<EffectiveModelContext> dataPrototype) {
+    private SchemaRootCodecContext(final DataContainerCodecPrototype<BindingRuntimeTypes> dataPrototype) {
         super(dataPrototype);
     }
 
@@ -183,6 +221,11 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
         return new SchemaRootCodecContext<>(DataContainerCodecPrototype.rootPrototype(factory));
     }
 
+    @Override
+    public WithStatus getSchema() {
+        return getType().getEffectiveModelContext();
+    }
+
     @SuppressWarnings("unchecked")
     @Override
     public <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> childClass) {
@@ -209,12 +252,16 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
         return getOrRethrow(actionsByClass, action);
     }
 
+    NotificationCodecContext<?> getNotification(final Absolute notification) {
+        return getOrRethrow(notificationsByPath, notification);
+    }
+
     NotificationCodecContext<?> getNotification(final Class<? extends Notification<?>> notification) {
-        return getOrRethrow(notificationsByClass, notification);
+        return getNotificationImpl(notification);
     }
 
-    NotificationCodecContext<?> getNotification(final Absolute notification) {
-        return getOrRethrow(notificationsByPath, notification);
+    private NotificationCodecContext<?> getNotificationImpl(final Class<?> notification) {
+        return getOrRethrow(notificationsByClass, notification);
     }
 
     ContainerNodeCodecContext<?> getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
@@ -226,10 +273,12 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
     }
 
     DataContainerCodecContext<?, ?> createDataTreeChildContext(final Class<? extends DataObject> key) {
-        final QName qname = BindingReflections.findQName(key);
-        final DataSchemaNode childSchema = childNonNull(getSchema().dataChildByName(qname), key,
+        final RuntimeType childSchema = childNonNull(getType().bindingChild(JavaTypeName.create(key)), key,
             "%s is not top-level item.", key);
-        return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
+        if (childSchema instanceof CompositeRuntimeType && childSchema instanceof DataRuntimeType) {
+            return DataContainerCodecPrototype.from(key, (CompositeRuntimeType) childSchema, factory()).get();
+        }
+        throw IncorrectNestingException.create("%s is not a valid data tree child of %s", key, this);
     }
 
     ActionCodecContext createActionContext(final Class<? extends Action<?, ?, ?>> action) {
@@ -249,12 +298,12 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
         final ParameterizedType paramType = optParamType.get();
         final Type[] args = paramType.getActualTypeArguments();
         checkArgument(args.length == expectedArgsLength, "Unexpected (%s) Action generatic arguments", args.length);
-        final ActionDefinition schema = factory().getRuntimeContext().getActionDefinition(action);
+        final ActionRuntimeType schema = factory().getRuntimeContext().getActionDefinition(action);
         return new ActionCodecContext(
-                DataContainerCodecPrototype.from(asClass(args[inputOffset], RpcInput.class), schema.getInput(),
-                        factory()).get(),
-                DataContainerCodecPrototype.from(asClass(args[outputOffset], RpcOutput.class), schema.getOutput(),
-                        factory()).get());
+            DataContainerCodecPrototype.from(asClass(args[inputOffset], RpcInput.class), schema.input(),
+                factory()).get(),
+            DataContainerCodecPrototype.from(asClass(args[outputOffset], RpcOutput.class), schema.output(),
+                factory()).get());
     }
 
     private static <T extends DataObject> Class<? extends T> asClass(final Type type, final Class<T> target) {
@@ -269,6 +318,8 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
      * @param qname input or output QName with namespace same as RPC
      * @return input or output schema. Returns null if RPC does not have input/output specified.
      */
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+        justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private static @Nullable ContainerLike getRpcDataSchema(final @NonNull RpcDefinition rpc,
             final @NonNull QName qname) {
         requireNonNull(rpc, "Rpc Schema must not be null");
@@ -283,40 +334,14 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
         }
     }
 
-    /**
-     * Returns RPC Input or Output Data container from RPC definition.
-     *
-     * @param schema SchemaContext in which lookup should be performed.
-     * @param path Schema path of RPC input/output data container
-     * @return Notification schema or null, if notification is not present in schema context.
-     */
-    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
-        justification = "https://github.com/spotbugs/spotbugs/issues/811")
-    private static @Nullable ContainerLike getRpcDataSchema(final @NonNull EffectiveModelContext schema,
-            final @NonNull Absolute path) {
-        requireNonNull(schema, "Schema context must not be null.");
-        requireNonNull(path, "Schema path must not be null.");
-        final Iterator<QName> it = path.getNodeIdentifiers().iterator();
-        checkArgument(it.hasNext(), "Rpc must have QName.");
-        final QName rpcName = it.next();
-        checkArgument(it.hasNext(), "input or output must be part of path.");
-        final QName inOrOut = it.next();
-        for (final RpcDefinition potential : schema.getOperations()) {
-            if (rpcName.equals(potential.getQName())) {
-                return getRpcDataSchema(potential, inOrOut);
-            }
-        }
-        return null;
-    }
-
     ChoiceNodeCodecContext<?> createChoiceDataContext(final Class<? extends DataObject> caseType) {
         final Class<?> choiceClass = findCaseChoice(caseType);
         checkArgument(choiceClass != null, "Class %s is not a valid case representation", caseType);
-        final DataSchemaNode schema = factory().getRuntimeContext().getSchemaDefinition(choiceClass);
-        checkArgument(schema instanceof ChoiceSchemaNode, "Class %s does not refer to a choice", caseType);
+        final CompositeRuntimeType schema = factory().getRuntimeContext().getSchemaDefinition(choiceClass);
+        checkArgument(schema instanceof ChoiceRuntimeType, "Class %s does not refer to a choice", caseType);
 
-        final DataContainerCodecContext<?, ChoiceSchemaNode> choice = DataContainerCodecPrototype.from(choiceClass,
-            (ChoiceSchemaNode)schema, factory()).get();
+        final DataContainerCodecContext<?, ChoiceRuntimeType> choice = DataContainerCodecPrototype.from(choiceClass,
+            (ChoiceRuntimeType)schema, factory()).get();
         Verify.verify(choice instanceof ChoiceNodeCodecContext);
         return (ChoiceNodeCodecContext<?>) choice;
     }
index 778104fb68d970705884a050c8044bbaf0431e09..41710c97c77a304a5bb34a02c57b981ed5ec0b55 100644 (file)
@@ -17,7 +17,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.Callable;
 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.runtime.api.RuntimeGeneratedUnion;
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.concepts.IllegalArgumentCodec;
@@ -36,7 +36,7 @@ final class UnionTypeCodec extends ReflectionBasedCodec {
             final BindingCodecContext codecContext) {
         return () -> {
             final List<String> unionProperties = extractUnionProperties(codecContext.getRuntimeContext()
-                .getTypeWithSchema(unionCls).getKey());
+                .getTypeWithSchema(unionCls).javaType());
             final List<TypeDefinition<?>> unionTypes = unionType.getTypes();
             verify(unionTypes.size() == unionProperties.size(), "Mismatched union types %s and properties %s",
                 unionTypes, unionProperties);
@@ -56,7 +56,7 @@ final class UnionTypeCodec extends ReflectionBasedCodec {
         };
     }
 
-    private static List<String> extractUnionProperties(final GeneratedType type) {
+    private static List<String> extractUnionProperties(final Type type) {
         verify(type instanceof GeneratedTransferObject, "Unexpected runtime type %s", type);
 
         GeneratedTransferObject gto = (GeneratedTransferObject) type;
index c80f1e72f48656ab47ba68c00a0900f15f309406..9b4ad7e90f12261194a094c491a42d30f3d8597e 100644 (file)
@@ -195,7 +195,7 @@ public class InstanceIdentifierSerializeDeserializeTest extends AbstractBindingC
             () -> codecContext.fromYangInstanceIdentifier(yiid));
         assertThat(ex.getMessage(),
             startsWith("Argument (urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:bi:ba:notification"
-                + "?revision=2015-02-05)out-of-pixie-dust-notification is not valid child of "));
+                + "?revision=2015-02-05)out-of-pixie-dust-notification is not valid data tree child of "));
     }
 
     @Test
index 33da2fe7ece7e8635add12a28e7d993fe986e086..8f72441c8bfa4534653325242bdbd5284be53a74 100644 (file)
@@ -7,8 +7,6 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
-import static org.hamcrest.CoreMatchers.startsWith;
-import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThrows;
 
@@ -26,7 +24,9 @@ public class Mdsal724Test extends AbstractBindingCodecTest {
         final var iid = InstanceIdentifier.create((Class) OutOfPixieDustNotification.class);
 
         final var ex = assertThrows(IllegalArgumentException.class, () -> codecContext.toYangInstanceIdentifier(iid));
-        assertThat(ex.getMessage(), startsWith("Supplied class must not be a notification ("));
+        assertEquals("interface org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test"
+            + ".bi.ba.notification.rev150205.OutOfPixieDustNotification is not a valid data tree child of "
+            + "SchemaRootCodecContext [interface org.opendaylight.yangtools.yang.binding.DataRoot]", ex.getMessage());
     }
 
     @Test
index e1d636fe76f3b7827ba3ec630e1093e0ce7adc84..18152110849f975fa853c09bf20c62798071fb4a 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-model-util</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-xpath-api</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.mdsal</groupId>
             <artifactId>yang-binding</artifactId>
index 8c5a49450416f788b0ba575d17911ea1b09bde7a..49953954cc3156bee7f22173a176640b7ffa4fef 100644 (file)
@@ -10,92 +10,117 @@ package org.opendaylight.mdsal.binding.generator.impl;
 import static com.google.common.base.Verify.verify;
 
 import com.google.common.base.Stopwatch;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.IdentityHashMap;
 import java.util.Map;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.AbstractExplicitGenerator;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.Generator;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.GeneratorReactor;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.IdentityGenerator;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.ModuleGenerator;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.RpcGenerator;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.RpcInputGenerator;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.RpcOutputGenerator;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.TypeBuilderFactory;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultBindingRuntimeTypes;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
 import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.concepts.Mutable;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 final class BindingRuntimeTypesFactory implements Mutable {
     private static final Logger LOG = LoggerFactory.getLogger(BindingRuntimeTypesFactory.class);
 
-    private final Map<Type, AugmentationSchemaNode> augmentationToSchema = new HashMap<>();
-    private final Map<Type, WithStatus> typeToSchema = new HashMap<>();
-    private final Map<QName, Type> identities = new HashMap<>();
-
-    // Note: we are keying through WithStatus, but these nodes compare on semantics, so equivalent schema nodes
-    //       can result in two distinct types. We certainly need to keep them separate.
-    private final Map<WithStatus, Type> schemaToType = new IdentityHashMap<>();
+    // Modules, indexed by their QNameModule
+    private final Map<QNameModule, ModuleRuntimeType> modules = new HashMap<>();
+    // Identities, indexed by their QName
+    private final Map<QName, IdentityRuntimeType> identities = new HashMap<>();
+    // All known types, indexed by their JavaTypeName
+    private final Map<JavaTypeName, RuntimeType> allTypes = new HashMap<>();
+    // All RpcOutputs, indexed by their RPC's QName
+    private final Map<QName, OutputRuntimeType> rpcOutputs = new HashMap<>();
+    // All RpcInputs, indexed by their RPC's QName
+    private final Map<QName, InputRuntimeType> rpcInputs = new HashMap<>();
 
     private BindingRuntimeTypesFactory() {
         // Hidden on purpose
     }
 
     static @NonNull BindingRuntimeTypes createTypes(final @NonNull EffectiveModelContext context) {
-        final Collection<ModuleGenerator> moduleGens = new GeneratorReactor(context)
-            .execute(TypeBuilderFactory.runtime())
-            .values();
+        final var moduleGens = new GeneratorReactor(context).execute(TypeBuilderFactory.runtime());
 
         final Stopwatch sw = Stopwatch.createStarted();
         final BindingRuntimeTypesFactory factory = new BindingRuntimeTypesFactory();
-        factory.indexTypes(moduleGens);
+        factory.indexModules(moduleGens);
         LOG.debug("Indexed {} generators in {}", moduleGens.size(), sw);
 
-        return new DefaultBindingRuntimeTypes(context, factory.augmentationToSchema, factory.typeToSchema,
-            factory.schemaToType, factory.identities);
+        return new DefaultBindingRuntimeTypes(context, factory.modules, factory.allTypes, factory.identities,
+            factory.rpcInputs, factory.rpcOutputs);
     }
 
-    private void indexTypes(final Iterable<? extends Generator> generators) {
-        for (Generator gen : generators) {
-            gen.generatedType().ifPresent(type -> indexType(gen, type));
-            indexTypes(gen);
-        }
-    }
+    private void indexModules(final Map<QNameModule, ModuleGenerator> moduleGens) {
+        for (var entry : moduleGens.entrySet()) {
+            final var modGen = entry.getValue();
 
-    private void indexType(final @NonNull Generator generator, final @NonNull GeneratedType type) {
-        if (generator instanceof AbstractExplicitGenerator) {
-            final EffectiveStatement<?, ?> stmt = ((AbstractExplicitGenerator<?>) generator).statement();
-            if (stmt instanceof IdentityEffectiveStatement) {
-                identities.put(((IdentityEffectiveStatement) stmt).argument(), type);
-            } else if (stmt instanceof AugmentEffectiveStatement) {
-                verify(stmt instanceof AugmentationSchemaNode, "Unexpected statement %s", stmt);
-                augmentationToSchema.put(type, (AugmentationSchemaNode) stmt);
-            }
+            // index the module's runtime type
+            modGen.runtimeType().ifPresent(type -> {
+                safePut(modules, "modules", entry.getKey(), type);
+            });
 
-            final WithStatus schema;
-            if (stmt instanceof TypedDataSchemaNode) {
-                schema = ((TypedDataSchemaNode) stmt).getType();
-            } else if (stmt instanceof TypedefEffectiveStatement) {
-                schema = ((TypedefEffectiveStatement) stmt).getTypeDefinition();
-            } else if (stmt instanceof WithStatus) {
-                schema = (WithStatus) stmt;
-            } else {
-                return;
+            // index module's identities and RPC input/outputs
+            for (var gen : modGen) {
+                if (gen instanceof IdentityGenerator) {
+                    ((IdentityGenerator) gen).runtimeType().ifPresent(identity -> {
+                        safePut(identities, "identities", identity.statement().argument(), identity);
+                    });
+                }
+                // FIXME: do not collect these once we they generate a proper RuntimeType
+                if (gen instanceof RpcGenerator) {
+                    final QName rpcName = ((RpcGenerator) gen).statement().argument();
+                    for (var subgen : gen) {
+                        if (subgen instanceof RpcInputGenerator) {
+                            ((RpcInputGenerator) subgen).runtimeType()
+                                .ifPresent(input -> rpcInputs.put(rpcName, input));
+                        } else if (subgen instanceof RpcOutputGenerator) {
+                            ((RpcOutputGenerator) subgen).runtimeType()
+                                .ifPresent(output -> rpcOutputs.put(rpcName, output));
+                        }
+                    }
+                }
             }
+        }
 
-            typeToSchema.put(type, schema);
-            final var prevType = schemaToType.put(schema, type);
-            verify(prevType == null, "Conflicting types %s and %s on %s", type, prevType, schema);
+        indexRuntimeTypes(moduleGens.values());
+    }
+
+    private void indexRuntimeTypes(final Iterable<? extends Generator> generators) {
+        for (Generator gen : generators) {
+            if (gen instanceof AbstractExplicitGenerator && gen.generatedType().isPresent()) {
+                final var type = ((AbstractExplicitGenerator<?, ?>) gen).runtimeType().orElseThrow();
+                final var javaType = type.javaType();
+                if (javaType instanceof GeneratedType) {
+                    final var name = javaType.getIdentifier();
+                    final var prev = allTypes.put(name, type);
+                    verify(prev == null || prev == type, "Conflict on runtime type mapping of %s between %s and %s",
+                        name, prev, type);
+                }
+            }
+            indexRuntimeTypes(gen);
         }
     }
+
+    private static <K, V> void safePut(final Map<K, V> map, final String name, final K key, final V value) {
+        final var prev = map.put(key, value);
+        verify(prev == null, "Conflict in %s, key %s conflicts on %s versus %s", name, key, prev, value);
+    }
 }
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingRuntimeTypes.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingRuntimeTypes.java
deleted file mode 100644 (file)
index 3f21a81..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.generator.impl;
-
-import static com.google.common.base.Verify.verify;
-import static com.google.common.base.Verify.verifyNotNull;
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.MultimapBuilder;
-import java.util.Collection;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-final class DefaultBindingRuntimeTypes implements BindingRuntimeTypes {
-    private static final Logger LOG = LoggerFactory.getLogger(DefaultBindingRuntimeTypes.class);
-
-    private final @NonNull EffectiveModelContext schemaContext;
-    private final ImmutableMap<Type, AugmentationSchemaNode> typeToAugmentation;
-    private final ImmutableMap<Type, WithStatus> typeToSchema;
-    private final ImmutableMultimap<Type, Type> choiceToCases;
-    private final ImmutableMap<QName, Type> identities;
-    // Not Immutable as we use two different implementations
-    private final Map<WithStatus, Type> schemaToType;
-
-    DefaultBindingRuntimeTypes(final EffectiveModelContext schemaContext,
-            final Map<Type, AugmentationSchemaNode> typeToAugmentation,
-            final Map<Type, WithStatus> typeToSchema, final Map<WithStatus, Type> schemaToType,
-            final Map<QName, Type> identities) {
-        this.schemaContext = requireNonNull(schemaContext);
-        this.typeToAugmentation = ImmutableMap.copyOf(typeToAugmentation);
-        this.typeToSchema = ImmutableMap.copyOf(typeToSchema);
-        this.identities = ImmutableMap.copyOf(identities);
-
-        // Careful to use identity for SchemaNodes, but only if needed
-        // FIXME: 8.0.0: YT should be switching to identity for equals(), so this should become unnecessary
-        Map<WithStatus, Type> copy;
-        try {
-            copy = ImmutableMap.copyOf(schemaToType);
-        } catch (IllegalArgumentException e) {
-            LOG.debug("Equality-duplicates found in {}", schemaToType.keySet());
-            copy = new IdentityHashMap<>(schemaToType);
-        }
-
-        this.schemaToType = copy;
-
-        // Two-phase indexing of choice/case nodes. First we load all choices. Note we are using typeToSchema argument,
-        // not field, so as not to instantiate its entrySet.
-        final Set<GeneratedType> choiceTypes = typeToSchema.entrySet().stream()
-            .filter(entry -> entry.getValue() instanceof ChoiceEffectiveStatement)
-            .map(entry -> {
-                final Type key = entry.getKey();
-                verify(key instanceof GeneratedType, "Unexpected choice type %s", key);
-                return (GeneratedType) key;
-            })
-            .collect(Collectors.toUnmodifiableSet());
-
-        final Multimap<Type, Type> builder = MultimapBuilder.hashKeys(choiceTypes.size()).arrayListValues().build();
-        for (Entry<Type, WithStatus> entry : typeToSchema.entrySet()) {
-            if (entry.getValue() instanceof CaseEffectiveStatement) {
-                final Type type = entry.getKey();
-                verify(type instanceof GeneratedType, "Unexpected case type %s", type);
-                builder.put(verifyNotNull(implementedChoiceType(((GeneratedType) type).getImplements(), choiceTypes),
-                    "Cannot determine choice type for %s", type), type);
-            }
-        }
-
-        choiceToCases = ImmutableMultimap.copyOf(builder);
-    }
-
-    private static GeneratedType implementedChoiceType(final List<Type> impls, final Set<GeneratedType> choiceTypes) {
-        for (Type impl : impls) {
-            if (impl instanceof GeneratedType && choiceTypes.contains(impl)) {
-                return (GeneratedType) impl;
-            }
-        }
-        return null;
-    }
-
-    DefaultBindingRuntimeTypes(final EffectiveModelContext schemaContext,
-            final Map<Type, AugmentationSchemaNode> typeToAugmentation,
-            final BiMap<Type, WithStatus> typeToDefiningSchema, final Map<QName, Type> identities) {
-        this(schemaContext, typeToAugmentation, typeToDefiningSchema, typeToDefiningSchema.inverse(), identities);
-    }
-
-    @Override
-    public EffectiveModelContext getEffectiveModelContext() {
-        return schemaContext;
-    }
-
-    @Override
-    public Optional<AugmentationSchemaNode> findAugmentation(final Type type) {
-        return Optional.ofNullable(typeToAugmentation.get(type));
-    }
-
-    @Override
-    public Optional<Type> findIdentity(final QName qname) {
-        return Optional.ofNullable(identities.get(qname));
-    }
-
-    @Override
-    public Optional<WithStatus> findSchema(final Type type) {
-        return Optional.ofNullable(typeToSchema.get(type));
-    }
-
-    @Override
-    public Optional<Type> findType(final WithStatus schema) {
-        return Optional.ofNullable(schemaToType.get(schema));
-    }
-
-    @Override
-    public Optional<Type> findOriginalAugmentationType(final AugmentationSchemaNode augment) {
-        // If the augment statement does not contain any child nodes, we did not generate an augmentation, as it would
-        // be plain littering.
-        // FIXME: MDSAL-695: this check is rather costly (involves filtering), can we just rely on the not being found
-        //                   in the end? all we are saving is essentially two map lookups after all...
-        if (augment.getChildNodes().isEmpty()) {
-            return Optional.empty();
-        }
-
-        // FIXME: MDSAL-695: We should have enough information from mdsal-binding-generator to receive a (sparse) Map
-        //                   for current -> original lookup. When combined with schemaToType, this amounts to the
-        //                   inverse view of what 'typeToSchema' holds
-        AugmentationSchemaNode current = augment;
-        while (true) {
-            // If this augmentation has been added through 'uses foo { augment bar { ... } }', we need to invert that
-            // walk and arrive at the original declaration site, as that is where we generated 'grouping foo's
-            // augmentation. That site may have a different module, hence the augment namespace may be different.
-            final Optional<AugmentationSchemaNode> original = current.getOriginalDefinition();
-            if (original.isEmpty()) {
-                return findType(current);
-            }
-            current = original.orElseThrow();
-        }
-    }
-
-    @Override
-    public Multimap<Type, Type> getChoiceToCases() {
-        return choiceToCases;
-    }
-
-    @Override
-    public Collection<Type> findCases(final Type choiceType) {
-        return choiceToCases.get(choiceType);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("typeToAugmentation", typeToAugmentation)
-                .add("typeToSchema", typeToSchema)
-                .add("choiceToCases", choiceToCases)
-                .add("identities", identities)
-                .toString();
-    }
-}
index b9c92cd1cb89bece58f184a5e15971c901224e9e..5a018acdb50257cf2d33f860b10bdd25190deded 100644 (file)
@@ -13,23 +13,30 @@ import static java.util.Objects.requireNonNull;
 
 import java.util.Comparator;
 import java.util.Iterator;
+import java.util.List;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultAugmentRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.odlext.model.api.AugmentIdentifierEffectiveStatement;
 import org.opendaylight.yangtools.yang.common.AbstractQName;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * A generator corresponding to a {@code augment} statement. This class is further specialized for the two distinct uses
  * an augment is used.
  */
-abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<AugmentEffectiveStatement> {
+abstract class AbstractAugmentGenerator
+        extends AbstractCompositeGenerator<AugmentEffectiveStatement, AugmentRuntimeType> {
     /**
      * Comparator comparing target path length. This is useful for quickly determining order the order in which two
      * (or more) {@link AbstractAugmentGenerator}s need to be evaluated. This is necessary when augments are layered on
@@ -78,9 +85,10 @@ abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<Augme
         return otherIt.hasNext() ? -1 : 0;
     };
 
-    private AbstractCompositeGenerator<?> targetGen;
+    private AugmentEffectiveStatement effectiveStatement;
+    private AbstractCompositeGenerator<?, ?> targetGen;
 
-    AbstractAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+    AbstractAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -98,7 +106,7 @@ abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<Augme
     ClassPlacement classPlacement() {
         // if the target is a choice we are NOT creating an explicit augmentation, but we still need a phantom to
         // reserve the appropriate package name
-        final AbstractCompositeGenerator<?> target = targetGenerator();
+        final AbstractCompositeGenerator<?, ?> target = targetGenerator();
         return target instanceof ChoiceGenerator ? ClassPlacement.PHANTOM : super.classPlacement();
     }
 
@@ -139,17 +147,37 @@ abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<Augme
         return builder.build();
     }
 
+    @Override
+    final AugmentEffectiveStatement effectiveStatement() {
+        return verifyNotNull(effectiveStatement, "Effective statement not set in %s", this);
+    }
+
+    @Override
+    final AugmentRuntimeType createRuntimeType(final GeneratedType type, final AugmentEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        verify(statement instanceof TargetAugmentEffectiveStatement, "Unexpected statement %s", statement);
+        return new DefaultAugmentRuntimeType(type, ((TargetAugmentEffectiveStatement) statement).delegate(), children,
+            augments);
+    }
+
     @Override
     final void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
         // Augments are never added as getters, as they are handled via Augmentable mechanics
     }
 
-    final void setTargetGenerator(final AbstractCompositeGenerator<?> targetGenerator) {
+    final void setTargetGenerator(final AbstractCompositeGenerator<?, ?> targetGenerator) {
         verify(targetGen == null, "Attempted to relink %s, already have target %s", this, targetGen);
         targetGen = requireNonNull(targetGenerator);
     }
 
-    final @NonNull AbstractCompositeGenerator<?> targetGenerator() {
+    final @NonNull AbstractCompositeGenerator<?, ?> targetGenerator() {
         return verifyNotNull(targetGen, "No target for %s", this);
     }
+
+    final void setTargetStatement(final EffectiveStatement<?, ?> targetStatement) {
+        verify(targetStatement instanceof SchemaTreeAwareEffectiveStatement, "Unexpected target statement %s",
+            targetStatement);
+        effectiveStatement = new TargetAugmentEffectiveStatement(statement(),
+            (SchemaTreeAwareEffectiveStatement<?, ?>) targetStatement);
+    }
 }
index d4ed8314b06f2144f7ee8fd33256256b6c0bcec0..e88739a72ce0a4dc9012a12fa7700a7cd6c1c4ee 100644 (file)
@@ -8,23 +8,25 @@
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
 import static com.google.common.base.Verify.verify;
+import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.stream.Collectors;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeParent;
 import org.opendaylight.mdsal.binding.model.api.Enumeration;
 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware;
 import org.opendaylight.yangtools.yang.model.api.CopyableNode;
@@ -112,24 +114,20 @@ import org.slf4j.LoggerFactory;
  * with linking original instances in the tree iteration order. The part dealing with augment attachment lives mostly
  * in {@link AugmentRequirement}.
  */
-public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?, ?>>
-        extends AbstractExplicitGenerator<T> implements SchemaTreeParent<T> {
+public abstract class AbstractCompositeGenerator<S extends EffectiveStatement<?, ?>, R extends CompositeRuntimeType>
+        extends AbstractExplicitGenerator<S, R> {
     private static final Logger LOG = LoggerFactory.getLogger(AbstractCompositeGenerator.class);
 
     // FIXME: we want to allocate this lazily to lower memory footprint
     private final @NonNull CollisionDomain domain = new CollisionDomain(this);
     private final @NonNull List<Generator> childGenerators;
-    /**
-     * {@link SchemaTreeChild} children of this generator. Generator linkage is ensured on first access.
-     */
-    private final @NonNull List<SchemaTreeChild<?, ?>> schemaTreeChildren;
 
     /**
      * List of {@code augment} statements targeting this generator. This list is maintained only for the primary
      * incarnation. This list is an evolving entity until after we have finished linkage of original statements. It is
      * expected to be stable at the start of {@code step 2} in {@link GeneratorReactor#execute(TypeBuilderFactory)}.
      */
-    private List<AbstractAugmentGenerator> augments = List.of();
+    private @NonNull List<AbstractAugmentGenerator> augments = List.of();
 
     /**
      * List of {@code grouping} statements this statement references. This field is set once by
@@ -142,27 +140,21 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
      * have some children which have not completed linking. Once we have completed linking of all children, including
      * {@link #unlinkedChildren}, this will be set to {@code null}.
      */
-    private List<AbstractCompositeGenerator<?>> unlinkedComposites = List.of();
+    private List<AbstractCompositeGenerator<?, ?>> unlinkedComposites = List.of();
     /**
      * List of children which have not had their original linked. This list starts of as null. When we first attempt
      * linkage, it becomes non-null.
      */
     private List<Generator> unlinkedChildren;
 
-    AbstractCompositeGenerator(final T statement) {
+    AbstractCompositeGenerator(final S statement) {
         super(statement);
-
-        final var children = createChildren(statement);
-        childGenerators = children.getKey();
-        schemaTreeChildren = children.getValue();
+        childGenerators = createChildren(statement);
     }
 
-    AbstractCompositeGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+    AbstractCompositeGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
-
-        final var children = createChildren(statement);
-        childGenerators = children.getKey();
-        schemaTreeChildren = children.getValue();
+        childGenerators = createChildren(statement);
     }
 
     @Override
@@ -170,14 +162,77 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
         return childGenerators.iterator();
     }
 
+    @NonNull S effectiveStatement() {
+        return statement();
+    }
+
+    @Override
+    public final R createRuntimeType() {
+        return generatedType()
+            .map(type -> {
+                final var stmt = effectiveStatement();
+                return createRuntimeType(type, stmt, indexChildren(stmt), augmentRuntimeTypes());
+            })
+            .orElse(null);
+    }
+
+    abstract @NonNull R createRuntimeType(@NonNull GeneratedType type, @NonNull S statement,
+        @NonNull List<RuntimeType> children, @NonNull List<AugmentRuntimeType> augments);
+
     @Override
-    public List<SchemaTreeChild<?, ?>> schemaTreeChildren() {
-        for (var child : schemaTreeChildren) {
-            if (child instanceof SchemaTreePlaceholder) {
-                ((SchemaTreePlaceholder<?, ?>) child).setGenerator(this);
+    final R rebaseRuntimeType(final R type, final S statement) {
+        return createRuntimeType(type.javaType(), statement, indexChildren(statement), augmentRuntimeTypes());
+    }
+
+    private @NonNull List<RuntimeType> indexChildren(final @NonNull S statement) {
+        final var childMap = new ArrayList<RuntimeType>();
+
+        for (var stmt : statement.effectiveSubstatements()) {
+            if (stmt instanceof SchemaTreeEffectiveStatement) {
+                final var child = (SchemaTreeEffectiveStatement<?>) stmt;
+                final var qname = child.getIdentifier();
+
+                // Note: getOriginal() is needed for augments of cases
+                @SuppressWarnings("rawtypes")
+                final AbstractExplicitGenerator childGen = getOriginal().resolveRuntimeChild(statement.argument(),
+                    qname);
+                @SuppressWarnings("unchecked")
+                final Optional<RuntimeType> rt = childGen.runtimeTypeOf(child);
+                rt.ifPresent(childMap::add);
             }
         }
-        return schemaTreeChildren;
+
+        return childMap;
+    }
+
+    private @NonNull AbstractExplicitGenerator<?, ?> resolveRuntimeChild(final Object parentArg, final QName qname) {
+        final var exact = findSchemaTreeGenerator(qname);
+        if (exact != null) {
+            return exact;
+        }
+
+        // TODO: this is quite hacky: what we are trying to do is rebase the lookup QName to parent QName, as the only
+        //       way we should be arriving here is through uses -> grouping squash
+        verify(parentArg instanceof QName, "Cannot deal with parent argument %s", parentArg);
+        final var namespace = ((QName) parentArg).getModule();
+
+        verify(namespace.equals(qname.getModule()), "Cannot deal with %s in namespace %s", qname, namespace);
+        final var local = qname.bindTo(getQName().getModule());
+        return verifyNotNull(findSchemaTreeGenerator(local), "Failed to find %s as %s in %s", qname, local, this);
+    }
+
+    final @NonNull List<AbstractAugmentGenerator> augments() {
+        return augments;
+    }
+
+    private @NonNull List<AugmentRuntimeType> augmentRuntimeTypes() {
+        // Augments are attached to original instance: at least CaseGenerator is instantiated in non-original place
+        // and thus we need to go back to original
+        return getOriginal().augments.stream()
+            .map(AbstractAugmentGenerator::runtimeType)
+            .filter(Optional::isPresent)
+            .map(Optional::orElseThrow)
+            .collect(ImmutableList.toImmutableList());
     }
 
     @Override
@@ -185,17 +240,17 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
         return childGenerators.isEmpty();
     }
 
-    final @Nullable AbstractExplicitGenerator<?> findGenerator(final List<EffectiveStatement<?, ?>> stmtPath) {
+    final @Nullable AbstractExplicitGenerator<?, ?> findGenerator(final List<EffectiveStatement<?, ?>> stmtPath) {
         return findGenerator(MatchStrategy.identity(), stmtPath, 0);
     }
 
-    final @Nullable AbstractExplicitGenerator<?> findGenerator(final MatchStrategy childStrategy,
+    final @Nullable AbstractExplicitGenerator<?, ?> findGenerator(final MatchStrategy childStrategy,
             // TODO: Wouldn't this method be nicer with Deque<EffectiveStatement<?, ?>> ?
             final List<EffectiveStatement<?, ?>> stmtPath, final int offset) {
         final EffectiveStatement<?, ?> stmt = stmtPath.get(offset);
 
         // Try direct children first, which is simple
-        AbstractExplicitGenerator<?> ret = childStrategy.findGenerator(stmt, childGenerators);
+        AbstractExplicitGenerator<?, ?> ret = childStrategy.findGenerator(stmt, childGenerators);
         if (ret != null) {
             final int next = offset + 1;
             if (stmtPath.size() == next) {
@@ -204,7 +259,7 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
             }
             if (ret instanceof AbstractCompositeGenerator) {
                 // We know how to descend down
-                return ((AbstractCompositeGenerator<?>) ret).findGenerator(childStrategy, stmtPath, next);
+                return ((AbstractCompositeGenerator<?, ?>) ret).findGenerator(childStrategy, stmtPath, next);
             }
             // Yeah, don't know how to continue here
             return null;
@@ -272,7 +327,7 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
                 requirements.add(((UsesAugmentGenerator) child).startLinkage());
             }
             if (child instanceof AbstractCompositeGenerator) {
-                ((AbstractCompositeGenerator<?>) child).startUsesAugmentLinkage(requirements);
+                ((AbstractCompositeGenerator<?, ?>) child).startUsesAugmentLinkage(requirements);
             }
         }
     }
@@ -299,7 +354,7 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
         if (unlinkedChildren == null) {
             unlinkedChildren = childGenerators.stream()
                 .filter(AbstractExplicitGenerator.class::isInstance)
-                .map(child -> (AbstractExplicitGenerator<?>) child)
+                .map(child -> (AbstractExplicitGenerator<?, ?>) child)
                 .collect(Collectors.toList());
         }
 
@@ -310,7 +365,7 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
             while (it.hasNext()) {
                 final var child = it.next();
                 if (child instanceof AbstractExplicitGenerator) {
-                    if (((AbstractExplicitGenerator<?>) child).linkOriginalGenerator()) {
+                    if (((AbstractExplicitGenerator<?, ?>) child).linkOriginalGenerator()) {
                         progress = LinkageProgress.SOME;
                         it.remove();
 
@@ -319,7 +374,7 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
                             if (unlinkedComposites.isEmpty()) {
                                 unlinkedComposites = new ArrayList<>();
                             }
-                            unlinkedComposites.add((AbstractCompositeGenerator<?>) child);
+                            unlinkedComposites.add((AbstractCompositeGenerator<?, ?>) child);
                         }
                     }
                 }
@@ -354,20 +409,21 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
     }
 
     @Override
-    final AbstractCompositeGenerator<T> getOriginal() {
-        return (AbstractCompositeGenerator<T>) super.getOriginal();
+    final AbstractCompositeGenerator<S, R> getOriginal() {
+        return (AbstractCompositeGenerator<S, R>) super.getOriginal();
     }
 
     @Override
-    final AbstractCompositeGenerator<T> tryOriginal() {
-        return (AbstractCompositeGenerator<T>) super.tryOriginal();
+    final AbstractCompositeGenerator<S, R> tryOriginal() {
+        return (AbstractCompositeGenerator<S, R>) super.tryOriginal();
     }
 
-    final <S extends EffectiveStatement<?, ?>> @Nullable OriginalLink<S> originalChild(final QName childQName) {
+    final <X extends EffectiveStatement<?, ?>, Y extends RuntimeType> @Nullable OriginalLink<X, Y> originalChild(
+            final QName childQName) {
         // First try groupings/augments ...
         var found = findInferredGenerator(childQName);
         if (found != null) {
-            return (OriginalLink<S>) OriginalLink.partial(found);
+            return (OriginalLink<X, Y>) OriginalLink.partial(found);
         }
 
         // ... no luck, we really need to start looking at our origin
@@ -376,7 +432,7 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
             final QName prevQName = childQName.bindTo(prev.getQName().getModule());
             found = prev.findSchemaTreeGenerator(prevQName);
             if (found != null) {
-                return (OriginalLink<S>) found.originalLink();
+                return (OriginalLink<X, Y>) found.originalLink();
             }
         }
 
@@ -384,8 +440,8 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
     }
 
     @Override
-    final AbstractExplicitGenerator<?> findSchemaTreeGenerator(final QName qname) {
-        final AbstractExplicitGenerator<?> found = super.findSchemaTreeGenerator(qname);
+    final AbstractExplicitGenerator<?, ?> findSchemaTreeGenerator(final QName qname) {
+        final AbstractExplicitGenerator<?, ?> found = super.findSchemaTreeGenerator(qname);
         return found != null ? found : findInferredGenerator(qname);
     }
 
@@ -409,7 +465,7 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
         return null;
     }
 
-    private @Nullable AbstractExplicitGenerator<?> findInferredGenerator(final QName qname) {
+    private @Nullable AbstractExplicitGenerator<?, ?> findInferredGenerator(final QName qname) {
         // First search our local groupings ...
         for (var grouping : groupings) {
             final var gen = grouping.findSchemaTreeGenerator(qname.bindTo(grouping.statement().argument().getModule()));
@@ -450,7 +506,7 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
         for (Generator child : this) {
             // Only process explicit generators here
             if (child instanceof AbstractExplicitGenerator) {
-                ((AbstractExplicitGenerator<?>) child).addAsGetterMethod(builder, builderFactory);
+                ((AbstractExplicitGenerator<?, ?>) child).addAsGetterMethod(builder, builderFactory);
             }
 
             final GeneratedType enclosedType = child.enclosedType(builderFactory);
@@ -464,97 +520,70 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
         }
     }
 
-    private Entry<List<Generator>, List<SchemaTreeChild<?, ?>>> createChildren(
-            final EffectiveStatement<?, ?> statement) {
+    private @NonNull List<Generator> createChildren(final EffectiveStatement<?, ?> statement) {
         final var tmp = new ArrayList<Generator>();
         final var tmpAug = new ArrayList<AbstractAugmentGenerator>();
-        final var tmpSchema = new ArrayList<SchemaTreeChild<?, ?>>();
 
         for (var stmt : statement.effectiveSubstatements()) {
             if (stmt instanceof ActionEffectiveStatement) {
-                final var cast = (ActionEffectiveStatement) stmt;
-                if (isAugmenting(cast)) {
-                    tmpSchema.add(new SchemaTreePlaceholder<>(cast, ActionGenerator.class));
-                } else {
-                    tmp.add(new ActionGenerator(cast, this));
+                if (!isAugmenting(stmt)) {
+                    tmp.add(new ActionGenerator((ActionEffectiveStatement) stmt, this));
                 }
             } else if (stmt instanceof AnydataEffectiveStatement) {
-                final var cast = (AnydataEffectiveStatement) stmt;
-                if (isAugmenting(stmt)) {
-                    tmpSchema.add(new SchemaTreePlaceholder<>(cast, OpaqueObjectGenerator.class));
-                } else {
-                    tmp.add(new OpaqueObjectGenerator<>(cast, this));
+                if (!isAugmenting(stmt)) {
+                    tmp.add(new OpaqueObjectGenerator.Anydata((AnydataEffectiveStatement) stmt, this));
                 }
             } else if (stmt instanceof AnyxmlEffectiveStatement) {
-                final var cast = (AnyxmlEffectiveStatement) stmt;
-                if (isAugmenting(stmt)) {
-                    tmpSchema.add(new SchemaTreePlaceholder<>(cast, OpaqueObjectGenerator.class));
-                } else {
-                    tmp.add(new OpaqueObjectGenerator<>(cast, this));
+                if (!isAugmenting(stmt)) {
+                    tmp.add(new OpaqueObjectGenerator.Anyxml((AnyxmlEffectiveStatement) stmt, this));
                 }
             } else if (stmt instanceof CaseEffectiveStatement) {
                 tmp.add(new CaseGenerator((CaseEffectiveStatement) stmt, this));
             } else if (stmt instanceof ChoiceEffectiveStatement) {
-                final var cast = (ChoiceEffectiveStatement) stmt;
                 // FIXME: use isOriginalDeclaration() ?
-                if (isAddedByUses(stmt)) {
-                    tmpSchema.add(new SchemaTreePlaceholder<>(cast, ChoiceGenerator.class));
-                } else {
-                    tmp.add(new ChoiceGenerator(cast, this));
+                if (!isAddedByUses(stmt)) {
+                    tmp.add(new ChoiceGenerator((ChoiceEffectiveStatement) stmt, this));
                 }
             } else if (stmt instanceof ContainerEffectiveStatement) {
-                final var cast = (ContainerEffectiveStatement) stmt;
                 if (isOriginalDeclaration(stmt)) {
                     tmp.add(new ContainerGenerator((ContainerEffectiveStatement) stmt, this));
-                } else {
-                    tmpSchema.add(new SchemaTreePlaceholder<>(cast, ContainerGenerator.class));
                 }
             } else if (stmt instanceof GroupingEffectiveStatement) {
                 tmp.add(new GroupingGenerator((GroupingEffectiveStatement) stmt, this));
             } else if (stmt instanceof IdentityEffectiveStatement) {
                 tmp.add(new IdentityGenerator((IdentityEffectiveStatement) stmt, this));
             } else if (stmt instanceof InputEffectiveStatement) {
+                final var cast = (InputEffectiveStatement) stmt;
                 // FIXME: do not generate legacy RPC layout
-                tmp.add(this instanceof RpcGenerator ? new RpcContainerGenerator((InputEffectiveStatement) stmt, this)
-                    : new OperationContainerGenerator((InputEffectiveStatement) stmt, this));
+                tmp.add(this instanceof RpcGenerator ? new RpcInputGenerator(cast, this)
+                    : new InputGenerator(cast, this));
             } else if (stmt instanceof LeafEffectiveStatement) {
-                final var cast = (LeafEffectiveStatement) stmt;
-                if (isAugmenting(stmt)) {
-                    tmpSchema.add(new SchemaTreePlaceholder<>(cast, LeafGenerator.class));
-                } else {
-                    tmp.add(new LeafGenerator(cast, this));
+                if (!isAugmenting(stmt)) {
+                    tmp.add(new LeafGenerator((LeafEffectiveStatement) stmt, this));
                 }
             } else if (stmt instanceof LeafListEffectiveStatement) {
-                final var cast = (LeafListEffectiveStatement) stmt;
-                if (isAugmenting(stmt)) {
-                    tmpSchema.add(new SchemaTreePlaceholder<>(cast, LeafListGenerator.class));
-                } else {
+                if (!isAugmenting(stmt)) {
                     tmp.add(new LeafListGenerator((LeafListEffectiveStatement) stmt, this));
                 }
             } else if (stmt instanceof ListEffectiveStatement) {
-                final var cast = (ListEffectiveStatement) stmt;
                 if (isOriginalDeclaration(stmt)) {
-                    final ListGenerator listGen = new ListGenerator(cast, this);
+                    final ListGenerator listGen = new ListGenerator((ListEffectiveStatement) stmt, this);
                     tmp.add(listGen);
 
                     final KeyGenerator keyGen = listGen.keyGenerator();
                     if (keyGen != null) {
                         tmp.add(keyGen);
                     }
-                } else {
-                    tmpSchema.add(new SchemaTreePlaceholder<>(cast, ListGenerator.class));
                 }
             } else if (stmt instanceof NotificationEffectiveStatement) {
-                final var cast = (NotificationEffectiveStatement) stmt;
-                if (isAugmenting(stmt)) {
-                    tmpSchema.add(new SchemaTreePlaceholder<>(cast, NotificationGenerator.class));
-                } else {
-                    tmp.add(new NotificationGenerator(cast, this));
+                if (!isAugmenting(stmt)) {
+                    tmp.add(new NotificationGenerator((NotificationEffectiveStatement) stmt, this));
                 }
             } else if (stmt instanceof OutputEffectiveStatement) {
+                final var cast = (OutputEffectiveStatement) stmt;
                 // FIXME: do not generate legacy RPC layout
-                tmp.add(this instanceof RpcGenerator ? new RpcContainerGenerator((OutputEffectiveStatement) stmt, this)
-                    : new OperationContainerGenerator((OutputEffectiveStatement) stmt, this));
+                tmp.add(this instanceof RpcGenerator ? new RpcOutputGenerator(cast, this)
+                    : new OutputGenerator(cast, this));
             } else if (stmt instanceof RpcEffectiveStatement) {
                 tmp.add(new RpcGenerator((RpcEffectiveStatement) stmt, this));
             } else if (stmt instanceof TypedefEffectiveStatement) {
@@ -589,13 +618,6 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
             }
         }
 
-        // Add any SchemaTreeChild generators to the list
-        for (var child : tmp) {
-            if (child instanceof SchemaTreeChild) {
-                tmpSchema.add((SchemaTreeChild<?, ?>) child);
-            }
-        }
-
         // Sort augments and add them last. This ensures child iteration order always reflects potential
         // interdependencies, hence we do not need to worry about them. This is extremely important, as there are a
         // number of places where we would have to either move the logic to parent statement and explicitly filter/sort
@@ -624,7 +646,7 @@ public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?,
             }
         }
 
-        return Map.entry(List.copyOf(tmp), List.copyOf(tmpSchema));
+        return List.copyOf(tmp);
     }
 
     // Utility equivalent of (!isAddedByUses(stmt) && !isAugmenting(stmt)). Takes advantage of relationship between
index 438b19b9f5a46532f220290b89a2074e3fa0d42f..ff91540a5a0e00f5ee740978630b827fa94699cb 100644 (file)
@@ -7,13 +7,15 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 
 /**
  * A simple {@link Generator} which (potentially) has dependencies on other generators.
  */
-abstract class AbstractDependentGenerator<T extends EffectiveStatement<?, ?>> extends AbstractExplicitGenerator<T> {
-    AbstractDependentGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+abstract class AbstractDependentGenerator<S extends EffectiveStatement<?, ?>, R extends RuntimeType>
+        extends AbstractExplicitGenerator<S, R> {
+    AbstractDependentGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
index 10cac0c71c5d2b669934ae1e86689a40bb15acb0..3ca83a023da644a1810f1292f44bb8a3cf01eeec 100644 (file)
@@ -12,15 +12,18 @@ import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.base.MoreObjects.ToStringHelper;
+import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
+import org.opendaylight.mdsal.binding.generator.impl.tree.StatementRepresentation;
 import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.api.TypeMemberComment;
 import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotableTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.yang.common.AbstractQName;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -35,11 +38,11 @@ import org.slf4j.LoggerFactory;
 /**
  * An explicit {@link Generator}, associated with a particular {@link EffectiveStatement}.
  */
-public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?, ?>> extends Generator
-        implements CopyableNode {
+public abstract class AbstractExplicitGenerator<S extends EffectiveStatement<?, ?>, R extends RuntimeType>
+        extends Generator implements CopyableNode, StatementRepresentation<S> {
     private static final Logger LOG = LoggerFactory.getLogger(AbstractExplicitGenerator.class);
 
-    private final @NonNull T statement;
+    private final @NonNull S statement;
 
     /**
      * Field tracking previous incarnation (along reverse of 'uses' and 'augment' axis) of this statement. This field
@@ -50,30 +53,66 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
      *   <li>a generator which is one step closer to the original definition</li>
      * </ul>
      */
-    private AbstractExplicitGenerator<T> prev;
+    private AbstractExplicitGenerator<S, R> prev;
     /**
      * Field holding the original incarnation, i.e. the terminal node along {@link #prev} links.
      */
-    private AbstractExplicitGenerator<T> orig;
+    private AbstractExplicitGenerator<S, R> orig;
+    /**
+     * Field containing and indicator holding the runtime type, if applicable.
+     */
+    private @Nullable R runtimeType;
+    private boolean runtimeTypeInitialized;
 
-    AbstractExplicitGenerator(final T statement) {
+    AbstractExplicitGenerator(final S statement) {
         this.statement = requireNonNull(statement);
     }
 
-    AbstractExplicitGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+    AbstractExplicitGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(parent);
         this.statement = requireNonNull(statement);
     }
 
+    @Override
+    public final @NonNull S statement() {
+        return statement;
+    }
+
     /**
-     * Return the {@link EffectiveStatement} associated with this generator.
+     * Return the {@link RuntimeType} associated with this object, of applicable.
      *
-     * @return An EffectiveStatement
+     * @return Associated run-time type, or empty
      */
-    public final @NonNull T statement() {
-        return statement;
+    public final Optional<R> runtimeType() {
+        if (!runtimeTypeInitialized) {
+            runtimeType = createRuntimeType();
+            runtimeTypeInitialized = true;
+        }
+        return Optional.ofNullable(runtimeType);
     }
 
+    final Optional<R> runtimeTypeOf(final @NonNull S stmt) {
+        return recursiveRuntimeType().map(childType -> rebaseRuntimeType(childType, stmt));
+    }
+
+    public final Optional<R> recursiveRuntimeType() {
+        AbstractExplicitGenerator<S, R> gen = this;
+        do {
+            final var ret = gen.runtimeType();
+            if (ret.isPresent()) {
+                return ret;
+            }
+
+            gen = gen.previous();
+        } while (gen != null);
+
+        return Optional.empty();
+    }
+
+    abstract @Nullable R createRuntimeType();
+
+    abstract @NonNull R rebaseRuntimeType(@NonNull R type, @NonNull S statement);
+
     @Override
     public final boolean isAddedByUses() {
         return statement instanceof AddedByUsesAware && ((AddedByUsesAware) statement).isAddedByUses();
@@ -104,7 +143,7 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
                 return true;
             }
 
-            final var link = getParent().<T>originalChild(getQName());
+            final var link = getParent().<S, R>originalChild(getQName());
             if (link == null) {
                 LOG.trace("Cannot link {} yet", this);
                 return false;
@@ -134,7 +173,7 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
      *
      * @return Previous incarnation or {@code null}
      */
-    final @Nullable AbstractExplicitGenerator<T> previous() {
+    final @Nullable AbstractExplicitGenerator<S, R> previous() {
         final var local = verifyNotNull(prev, "Generator %s does not have linkage to previous instance resolved", this);
         return local == this ? null : local;
     }
@@ -144,11 +183,11 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
      *
      * @return Original incarnation of this generator
      */
-    @NonNull AbstractExplicitGenerator<T> getOriginal() {
+    @NonNull AbstractExplicitGenerator<S, R> getOriginal() {
         return verifyNotNull(orig, "Generator %s does not have linkage to original instance resolved", this);
     }
 
-    @Nullable AbstractExplicitGenerator<T> tryOriginal() {
+    @Nullable AbstractExplicitGenerator<S, R> tryOriginal() {
         return orig;
     }
 
@@ -157,7 +196,7 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
      *
      * @return Link towards the original generator.
      */
-    final @NonNull OriginalLink<T> originalLink() {
+    final @NonNull OriginalLink<S, R> originalLink() {
         final var local = prev;
         if (local == null) {
             return OriginalLink.partial(this);
@@ -168,14 +207,14 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
         }
     }
 
-    @Nullable AbstractExplicitGenerator<?> findSchemaTreeGenerator(final QName qname) {
+    @Nullable AbstractExplicitGenerator<?, ?> findSchemaTreeGenerator(final QName qname) {
         return findLocalSchemaTreeGenerator(qname);
     }
 
-    final @Nullable AbstractExplicitGenerator<?> findLocalSchemaTreeGenerator(final QName qname) {
+    final @Nullable AbstractExplicitGenerator<?, ?> findLocalSchemaTreeGenerator(final QName qname) {
         for (Generator child : this) {
             if (child instanceof AbstractExplicitGenerator) {
-                final AbstractExplicitGenerator<?> gen = (AbstractExplicitGenerator<?>) child;
+                final AbstractExplicitGenerator<?, ?> gen = (AbstractExplicitGenerator<?, ?>) child;
                 final EffectiveStatement<?, ?> stmt = gen.statement();
                 if (stmt instanceof SchemaTreeEffectiveStatement && qname.equals(stmt.argument())) {
                     return gen;
index a93efef124d26c70962a7db7558b06ee341580b0..eb98a613509936c89ffc2bc44afec48e51e418e0 100644 (file)
@@ -9,13 +9,13 @@ package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
 import static com.google.common.base.Verify.verify;
 
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
 import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.odlext.model.api.ContextReferenceEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.TypeAware;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
@@ -26,22 +26,16 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 /**
  * Common base class for {@link LeafGenerator} and {@link LeafListGenerator}.
  */
-abstract class AbstractTypeAwareGenerator<T extends DataTreeEffectiveStatement<?>,
-        G extends AbstractTypeAwareGenerator<T, G>>
-        extends AbstractTypeObjectGenerator<T> implements SchemaTreeChild<T, G> {
+abstract class AbstractTypeAwareGenerator<T extends DataTreeEffectiveStatement<?>, R extends RuntimeType,
+        G extends AbstractTypeAwareGenerator<T, R, G>>
+        extends AbstractTypeObjectGenerator<T, R> {
     private IdentityGenerator contextType;
 
-    AbstractTypeAwareGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+    AbstractTypeAwareGenerator(final T statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
         verify(statement instanceof TypeAware, "Unexpected statement %s", statement);
     }
 
-    @Override
-    @SuppressWarnings("unchecked")
-    public final G generator() {
-        return (G) this;
-    }
-
     @Override
     final void pushToInference(final SchemaInferenceStack dataTree) {
         dataTree.enterDataTree(statement().getIdentifier());
@@ -62,7 +56,9 @@ abstract class AbstractTypeAwareGenerator<T extends DataTreeEffectiveStatement<?
 
     @Override
     final TypeDefinition<?> extractTypeDefinition() {
-        return ((TypedDataSchemaNode) statement()).getType();
+        final var stmt = statement();
+        verify(stmt instanceof TypedDataSchemaNode, "Unexpected statement %s", stmt);
+        return ((TypedDataSchemaNode) stmt).getType();
     }
 
     @Override
index 54e08cb1a33c79f3948a91b82d407fe97954e02d..2c41edb80b4ef86274aa392810fbae5e96c936ea 100644 (file)
@@ -42,6 +42,7 @@ import org.opendaylight.mdsal.binding.model.ri.TypeConstants;
 import org.opendaylight.mdsal.binding.model.ri.Types;
 import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.AbstractEnumerationBuilder;
 import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.GeneratedPropertyBuilderImpl;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.binding.RegexPatterns;
@@ -222,7 +223,8 @@ import org.slf4j.LoggerFactory;
  * type indirection in YANG constructs is therefore explicitly excluded from the generated Java code, but the Binding
  * Specification still takes them into account when determining types as outlined above.
  */
-abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> extends AbstractDependentGenerator<T> {
+abstract class AbstractTypeObjectGenerator<S extends EffectiveStatement<?, ?>, R extends RuntimeType>
+        extends AbstractDependentGenerator<S, R> {
     private static final class UnionDependencies implements Immutable {
         private final Map<EffectiveStatement<?, ?>, TypeReference> identityTypes = new HashMap<>();
         private final Map<EffectiveStatement<?, ?>, TypeReference> leafTypes = new HashMap<>();
@@ -294,9 +296,15 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
     private TypeReference refType;
     private List<GeneratedType> auxiliaryGeneratedTypes = List.of();
     private UnionDependencies unionDependencies;
-    private List<AbstractTypeObjectGenerator<?>> inferred = List.of();
+    private List<AbstractTypeObjectGenerator<?, ?>> inferred = List.of();
 
-    AbstractTypeObjectGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+    /**
+     * The type of single-element return type of the getter method associated with this generator. This is retained for
+     * run-time type purposes. It may be uninitialized, in which case this object must have a generated type.
+     */
+    private Type methodReturnTypeElement;
+
+    AbstractTypeObjectGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
         type = statement().findFirstEffectiveSubstatement(TypeEffectiveStatement.class).orElseThrow();
     }
@@ -317,16 +325,16 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
             return;
         }
 
-        final AbstractExplicitGenerator<?> prev = previous();
+        final AbstractExplicitGenerator<S, R> prev = previous();
         if (prev != null) {
             verify(prev instanceof AbstractTypeObjectGenerator, "Unexpected previous %s", prev);
-            ((AbstractTypeObjectGenerator<?>) prev).linkInferred(this);
+            ((AbstractTypeObjectGenerator<S, R>) prev).linkInferred(this);
         } else {
             linkBaseGen(context.resolveTypedef(typeName));
         }
     }
 
-    private void linkInferred(final AbstractTypeObjectGenerator<?> downstream) {
+    private void linkInferred(final AbstractTypeObjectGenerator<?, ?> downstream) {
         if (inferred == null) {
             downstream.linkBaseGen(verifyNotNull(baseGen, "Mismatch on linking between %s and %s", this, downstream));
             return;
@@ -340,13 +348,13 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
 
     private void linkBaseGen(final TypedefGenerator upstreamBaseGen) {
         verify(baseGen == null, "Attempted to replace base %s with %s in %s", baseGen, upstreamBaseGen, this);
-        final List<AbstractTypeObjectGenerator<?>> downstreams = verifyNotNull(inferred,
+        final List<AbstractTypeObjectGenerator<?, ?>> downstreams = verifyNotNull(inferred,
             "Duplicated linking of %s", this);
         baseGen = verifyNotNull(upstreamBaseGen);
         baseGen.addDerivedGenerator(this);
         inferred = null;
 
-        for (AbstractTypeObjectGenerator<?> downstream : downstreams) {
+        for (AbstractTypeObjectGenerator<?, ?> downstream : downstreams) {
             downstream.linkBaseGen(upstreamBaseGen);
         }
     }
@@ -364,7 +372,7 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
                 .map(context::resolveIdentity)
                 .collect(Collectors.toUnmodifiableList()));
         } else if (TypeDefinitions.LEAFREF.equals(arg)) {
-            final AbstractTypeObjectGenerator<?> targetGenerator = context.resolveLeafref(
+            final AbstractTypeObjectGenerator<?, ?> targetGenerator = context.resolveLeafref(
                 type.findFirstEffectiveSubstatementArgument(PathEffectiveStatement.class).orElseThrow());
             checkArgument(targetGenerator != this, "Effective model contains self-referencing leaf %s",
                 statement().argument());
@@ -448,7 +456,30 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
         return methodReturnElementType(builderFactory);
     }
 
+    @Override
+    final R createRuntimeType() {
+        if (methodReturnTypeElement != null) {
+            return createRuntimeType(methodReturnTypeElement);
+        }
+        final var genType = generatedType();
+        if (genType.isPresent()) {
+            return createRuntimeType(genType.orElseThrow());
+        }
+        final var prev = verifyNotNull(previous(), "No previous generator for %s", this);
+        return prev.runtimeType().orElse(null);
+    }
+
+    abstract @NonNull R createRuntimeType(Type type);
+
     final @NonNull Type methodReturnElementType(final @NonNull TypeBuilderFactory builderFactory) {
+        var local = methodReturnTypeElement;
+        if (local == null) {
+            methodReturnTypeElement = local = createMethodReturnElementType(builderFactory);
+        }
+        return local;
+    }
+
+    private @NonNull Type createMethodReturnElementType(final @NonNull TypeBuilderFactory builderFactory) {
         final GeneratedType generatedType = tryGeneratedType(builderFactory);
         if (generatedType != null) {
             // We have generated a type here, so return it. This covers 'bits', 'enumeration' and 'union'.
@@ -460,7 +491,7 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
             return refType.methodReturnType(builderFactory);
         }
 
-        final AbstractExplicitGenerator<?> prev = previous();
+        final AbstractExplicitGenerator<?, ?> prev = previous();
         if (prev != null) {
             // We have been added through augment/uses, defer to the original definition
             return prev.methodReturnType(builderFactory);
@@ -518,8 +549,8 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
             return;
         }
 
-        final AbstractTypeObjectGenerator<?> prev =
-            (AbstractTypeObjectGenerator<?>) verifyNotNull(previous(), "Missing previous link in %s", this);
+        final AbstractTypeObjectGenerator<?, ?> prev =
+            (AbstractTypeObjectGenerator<?, ?>) verifyNotNull(previous(), "Missing previous link in %s", this);
         if (prev.refType instanceof ResolvedLeafref) {
             // We should be already inheriting the correct type
             return;
@@ -715,7 +746,7 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
                     Type baseType = SIMPLE_TYPES.get(subName);
                     if (baseType == null) {
                         // This has to be a reference to a typedef, let's lookup it up and pick up its type
-                        final AbstractTypeObjectGenerator<?> baseGen = verifyNotNull(
+                        final AbstractTypeObjectGenerator<?, ?> baseGen = verifyNotNull(
                             dependencies.baseTypes.get(subName), "Cannot resolve base type %s in %s", subName,
                             definingStatement);
                         baseType = baseGen.methodReturnType(builderFactory);
index f6dd71b5f5a9b0dc3b5d3be13f0df5e5e2a93e0b..8b0c9b9b22c7ddd97084fee0cf5119e1eea0ddda 100644 (file)
@@ -7,12 +7,17 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import java.util.List;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultActionRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
@@ -21,8 +26,8 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 /**
  * Generator corresponding to a {@code action} statement.
  */
-final class ActionGenerator extends CompositeSchemaTreeGenerator<ActionEffectiveStatement, ActionGenerator> {
-    ActionGenerator(final ActionEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class ActionGenerator extends CompositeSchemaTreeGenerator<ActionEffectiveStatement, ActionRuntimeType> {
+    ActionGenerator(final ActionEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -55,13 +60,19 @@ final class ActionGenerator extends CompositeSchemaTreeGenerator<ActionEffective
         return builder.build();
     }
 
+    @Override
+    ActionRuntimeType createRuntimeType(final GeneratedType type, final ActionEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        return new DefaultActionRuntimeType(type, statement, children, augments);
+    }
+
     private @NonNull Type implementedType(final TypeBuilderFactory builderFactory) {
         final GeneratedType input = getChild(this, InputEffectiveStatement.class).getOriginal()
             .getGeneratedType(builderFactory);
         final GeneratedType output = getChild(this, OutputEffectiveStatement.class).getOriginal()
             .getGeneratedType(builderFactory);
 
-        final AbstractCompositeGenerator<?> parent = getParent();
+        final AbstractCompositeGenerator<?, ?> parent = getParent();
         if (parent instanceof ListGenerator) {
             final KeyGenerator keyGen = ((ListGenerator) parent).keyGenerator();
             if (keyGen != null) {
index 461a3111503410d2323668e458566820b7b51649..deef7580f0d690118cccaa4db7bd4b29263785c9 100644 (file)
@@ -43,11 +43,11 @@ final class AugmentRequirement implements Mutable {
     private final @NonNull AbstractAugmentGenerator augment;
     private final @NonNull Iterator<QName> remaining;
 
-    private @NonNull AbstractCompositeGenerator<?> target;
+    private @NonNull AbstractCompositeGenerator<?, ?> target;
     private QNameModule localNamespace;
     private QName qname;
 
-    private AugmentRequirement(final AbstractAugmentGenerator augment, final AbstractCompositeGenerator<?> target) {
+    private AugmentRequirement(final AbstractAugmentGenerator augment, final AbstractCompositeGenerator<?, ?> target) {
         this.augment = requireNonNull(augment);
         this.target = requireNonNull(target);
         remaining = augment.statement().argument().getNodeIdentifiers().iterator();
@@ -119,14 +119,14 @@ final class AugmentRequirement implements Mutable {
         return LinkageProgress.NONE;
     }
 
-    private @NonNull LinkageProgress moveTo(final @NonNull AbstractCompositeGenerator<?> newTarget) {
+    private @NonNull LinkageProgress moveTo(final @NonNull AbstractCompositeGenerator<?, ?> newTarget) {
         target = newTarget;
         return tryProgress();
     }
 
-    private @NonNull LinkageProgress progressTo(final @NonNull AbstractExplicitGenerator<?> newTarget) {
+    private @NonNull LinkageProgress progressTo(final @NonNull AbstractExplicitGenerator<?, ?> newTarget) {
         verify(newTarget instanceof AbstractCompositeGenerator, "Unexpected generator %s", newTarget);
-        target = (AbstractCompositeGenerator<?>) newTarget;
+        target = (AbstractCompositeGenerator<?, ?>) newTarget;
         qname = remaining.hasNext() ? remaining.next() : null;
         return tryProgress();
     }
index 84a29c0a85792c16320b1e45a33b5fd244051b41..1b3bc495db6487f65e8d42dbdc235f69e9129166 100644 (file)
@@ -9,17 +9,23 @@ package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
 import static com.google.common.base.Verify.verify;
 
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DerivedCaseRuntimeType;
+import org.opendaylight.mdsal.binding.generator.impl.rt.OriginalCaseRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Generator corresponding to a {@code case} statement.
  */
-final class CaseGenerator extends CompositeSchemaTreeGenerator<CaseEffectiveStatement, CaseGenerator> {
-    CaseGenerator(final CaseEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class CaseGenerator extends CompositeSchemaTreeGenerator<CaseEffectiveStatement, CaseRuntimeType> {
+    CaseGenerator(final CaseEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -36,10 +42,10 @@ final class CaseGenerator extends CompositeSchemaTreeGenerator<CaseEffectiveStat
         // We also are implementing target choice's type. This is tricky, as we need to cover two distinct cases:
         // - being a child of a choice (i.e. normal definition)
         // - being a child of an augment (i.e. augmented into a choice)
-        final AbstractCompositeGenerator<?> parent = getParent();
+        final AbstractCompositeGenerator<?, ?> parent = getParent();
         final ChoiceGenerator choice;
         if (parent instanceof AbstractAugmentGenerator) {
-            final AbstractCompositeGenerator<?> target = ((AbstractAugmentGenerator) parent).targetGenerator();
+            final AbstractCompositeGenerator<?, ?> target = ((AbstractAugmentGenerator) parent).targetGenerator();
             verify(target instanceof ChoiceGenerator, "Unexpected parent augment %s target %s", parent, target);
             choice = (ChoiceGenerator) target;
         } else {
@@ -66,4 +72,13 @@ final class CaseGenerator extends CompositeSchemaTreeGenerator<CaseEffectiveStat
 
         return builder.build();
     }
+
+    @Override
+    CaseRuntimeType createRuntimeType(final GeneratedType type, final CaseEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        final var original = getOriginal();
+        return statement.equals(original.statement())
+            ? new OriginalCaseRuntimeType(type, statement, children, augments)
+                : new DerivedCaseRuntimeType(type, statement, children, augments, original.runtimeType().orElseThrow());
+    }
 }
index c45a09985725ff61e8ca9da4f20ac7adc09e4e44..1a6ac7fe5bc4146853c54ec5b0d8bebdf0e0b55f 100644 (file)
@@ -7,18 +7,27 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import com.google.common.collect.Iterables;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DerivedChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.generator.impl.rt.OriginalChoiceRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Generator corresponding to a {@code choice} statement.
  */
-final class ChoiceGenerator extends CompositeSchemaTreeGenerator<ChoiceEffectiveStatement, ChoiceGenerator> {
-    ChoiceGenerator(final ChoiceEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class ChoiceGenerator extends CompositeSchemaTreeGenerator<ChoiceEffectiveStatement, ChoiceRuntimeType> {
+    ChoiceGenerator(final ChoiceEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -42,4 +51,40 @@ final class ChoiceGenerator extends CompositeSchemaTreeGenerator<ChoiceEffective
 
         return builder.build();
     }
+
+    @Override
+    ChoiceRuntimeType createRuntimeType(final GeneratedType type, final ChoiceEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        final var original = getOriginal();
+        if (!statement.equals(original.statement())) {
+            return new DerivedChoiceRuntimeType(type, statement, children, augments,
+                original.runtimeType().orElseThrow());
+        }
+
+        // Pick up any case statements added by augments which are not reflected in our children. This can happen when
+        // a choice is added via uses into two different places and then augmented. Since groupings are reused, validity
+        // of such use is not guarded by compile-time checks.
+        //
+        // Furthermore such case statements can be freely propagated via copy builders and thus can occur in unexpected
+        // places. If that happens, though, the two case statements can be equivalent, e.g. by having the exact same
+        // shape -- in which case Binding -> DOM translation needs to correct this mishap and play pretend the correct
+        // case was used.
+        final var augmentedCases = new ArrayList<CaseRuntimeType>();
+        for (var augment : original.augments()) {
+            for (var gen : augment) {
+                if (gen instanceof CaseGenerator) {
+                    ((CaseGenerator) gen).runtimeType().ifPresent(augmented -> {
+                        for (var child : Iterables.concat(children, augmentedCases)) {
+                            if (child instanceof CaseRuntimeType && child.javaType().equals(augmented.javaType())) {
+                                return;
+                            }
+                        }
+                        augmentedCases.add(augmented);
+                    });
+                }
+            }
+        }
+
+        return new OriginalChoiceRuntimeType(type, statement, children, augments, augmentedCases);
+    }
 }
index 9cd5aac5327374fc8c5c3e08986af13d4dc1e716..ea6453e76ac546d4e4f1b46439474f5cb5c56f9e 100644 (file)
@@ -21,6 +21,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map.Entry;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.yang.common.AbstractQName;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
@@ -139,7 +140,7 @@ final class CollisionDomain {
 
         Secondary(final Generator gen, final Member primary, final String classSuffix) {
             super(gen);
-            this.classPrimary = requireNonNull(primary);
+            classPrimary = requireNonNull(primary);
             this.classSuffix = requireNonNull(classSuffix);
             primary.addSecondary(this);
         }
@@ -217,12 +218,12 @@ final class CollisionDomain {
         }
     }
 
-    private final AbstractCompositeGenerator<?> gen;
+    private final AbstractCompositeGenerator<?, ?> gen;
 
     private List<Member> members = List.of();
     private boolean solved;
 
-    CollisionDomain(final AbstractCompositeGenerator<?> gen) {
+    CollisionDomain(final AbstractCompositeGenerator<?, ?> gen) {
         this.gen = requireNonNull(gen);
     }
 
@@ -239,9 +240,14 @@ final class CollisionDomain {
         return addMember(new LeafSecondary(memberGen, primary, classSuffix));
     }
 
-    @NonNull Member addSecondary(final RpcContainerGenerator memberGen, final Member primary, final String classSuffix,
-            final AbstractQName packageSuffix) {
-        return addMember(new SuffixSecondary(memberGen, primary, classSuffix, packageSuffix));
+    @NonNull Member addSecondary(final RpcInputGenerator memberGen, final Member primary) {
+        return addMember(new SuffixSecondary(memberGen, primary, BindingMapping.RPC_INPUT_SUFFIX,
+            memberGen.statement().argument()));
+    }
+
+    @NonNull Member addSecondary(final RpcOutputGenerator memberGen, final Member primary) {
+        return addMember(new SuffixSecondary(memberGen, primary, BindingMapping.RPC_OUTPUT_SUFFIX,
+            memberGen.statement().argument()));
     }
 
     @NonNull Member addSecondary(final AbstractAugmentGenerator memberGen, final Member classPrimary,
index c92707d774db5c2eb048f73d85c4fe2e3b5c19a6..196316b2bd372511a0c810e5c81aec9fd48e6601 100644 (file)
@@ -7,22 +7,15 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 
 /**
  * Abstract base class for {@link AbstractCompositeGenerator}s which are also {@link SchemaTreeChild}ren.
  */
-abstract class CompositeSchemaTreeGenerator<S extends SchemaTreeEffectiveStatement<?>,
-        G extends CompositeSchemaTreeGenerator<S, G>>
-        extends AbstractCompositeGenerator<S> implements SchemaTreeChild<S, G> {
-    CompositeSchemaTreeGenerator(final S statement, final AbstractCompositeGenerator<?> parent) {
+abstract class CompositeSchemaTreeGenerator<S extends SchemaTreeEffectiveStatement<?>, R extends CompositeRuntimeType>
+        extends AbstractCompositeGenerator<S, R> {
+    CompositeSchemaTreeGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public final G generator() {
-        return (G) this;
-    }
 }
index cd2752f1ae45e312eb0b6919879f87825f15b5b6..6a8b7e3029fa042d4b7bba72c7163e2dbbd2db61 100644 (file)
@@ -7,16 +7,21 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultContainerRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Generator corresponding to a {@code container} statement.
  */
-final class ContainerGenerator extends CompositeSchemaTreeGenerator<ContainerEffectiveStatement, ContainerGenerator> {
-    ContainerGenerator(final ContainerEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class ContainerGenerator extends CompositeSchemaTreeGenerator<ContainerEffectiveStatement, ContainerRuntimeType> {
+    ContainerGenerator(final ContainerEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -45,4 +50,10 @@ final class ContainerGenerator extends CompositeSchemaTreeGenerator<ContainerEff
 
         return builder.build();
     }
+
+    @Override
+    ContainerRuntimeType createRuntimeType(final GeneratedType type, final ContainerEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        return new DefaultContainerRuntimeType(type, statement, children, augments);
+    }
 }
index 10d5e098898ce79d3e9a9186c1cf5fb03a9c8dbb..6fd9a25e5ab8f4a558db980d9c3a6f30164ece90 100644 (file)
@@ -60,7 +60,7 @@ public abstract class Generator implements Iterable<Generator> {
     private static final JavaTypeName DEPRECATED_ANNOTATION = JavaTypeName.create(Deprecated.class);
     static final JavaTypeName OVERRIDE_ANNOTATION = JavaTypeName.create(Override.class);
 
-    private final AbstractCompositeGenerator<?> parent;
+    private final AbstractCompositeGenerator<?, ?> parent;
 
     private Optional<Member> member;
     private GeneratorResult result;
@@ -71,7 +71,7 @@ public abstract class Generator implements Iterable<Generator> {
         parent = null;
     }
 
-    Generator(final AbstractCompositeGenerator<?> parent) {
+    Generator(final AbstractCompositeGenerator<?, ?> parent) {
         this.parent = requireNonNull(parent);
     }
 
@@ -94,7 +94,7 @@ public abstract class Generator implements Iterable<Generator> {
      *
      * @return Parent generator
      */
-    final @NonNull AbstractCompositeGenerator<?> getParent() {
+    final @NonNull AbstractCompositeGenerator<?, ?> getParent() {
         return verifyNotNull(parent, "No parent for %s", this);
     }
 
@@ -239,7 +239,7 @@ public abstract class Generator implements Iterable<Generator> {
         return JavaTypeName.create(getPackageParent().javaPackage(), assignedName());
     }
 
-    @NonNull AbstractCompositeGenerator<?> getPackageParent() {
+    @NonNull AbstractCompositeGenerator<?, ?> getPackageParent() {
         return getParent();
     }
 
@@ -253,7 +253,7 @@ public abstract class Generator implements Iterable<Generator> {
     }
 
     final void addImplementsChildOf(final GeneratedTypeBuilder builder) {
-        AbstractCompositeGenerator<?> ancestor = getParent();
+        AbstractCompositeGenerator<?, ?> ancestor = getParent();
         while (true) {
             // choice/case hierarchy does not factor into 'ChildOf' hierarchy, hence we need to skip them
             if (ancestor instanceof CaseGenerator || ancestor instanceof ChoiceGenerator) {
@@ -263,7 +263,7 @@ public abstract class Generator implements Iterable<Generator> {
 
             // if we into a choice we need to follow the hierararchy of that choice
             if (ancestor instanceof AbstractAugmentGenerator) {
-                final AbstractCompositeGenerator<?> target = ((AbstractAugmentGenerator) ancestor).targetGenerator();
+                final AbstractCompositeGenerator<?, ?> target = ((AbstractAugmentGenerator) ancestor).targetGenerator();
                 if (target instanceof ChoiceGenerator) {
                     ancestor = target;
                     continue;
@@ -369,12 +369,12 @@ public abstract class Generator implements Iterable<Generator> {
         defineImplementedInterfaceMethod(builder, Type.of(builder)).setDefault(true);
     }
 
-    static final <T extends EffectiveStatement<?, ?>> AbstractExplicitGenerator<T> getChild(final Generator parent,
+    static final <T extends EffectiveStatement<?, ?>> AbstractExplicitGenerator<T, ?> getChild(final Generator parent,
             final Class<T> type) {
         for (Generator child : parent) {
             if (child instanceof AbstractExplicitGenerator) {
                 @SuppressWarnings("unchecked")
-                final AbstractExplicitGenerator<T> explicit = (AbstractExplicitGenerator<T>)child;
+                final AbstractExplicitGenerator<T, ?> explicit = (AbstractExplicitGenerator<T, ?>)child;
                 if (type.isInstance(explicit.statement())) {
                     return explicit;
                 }
index fb17e65bfe22edff54dafd9d08e973d45f7a03fe..ea42c5cae82291d52bcb459b91323e04bdbf41a1 100644 (file)
@@ -11,13 +11,19 @@ import edu.umd.cs.findbugs.annotations.Nullable;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.PathExpression;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.spi.AbstractEffectiveModelContextProvider;
 
 /**
  * Abstract view on generation tree as viewed by a particular {@link Generator}.
  */
-abstract class GeneratorContext {
+abstract class GeneratorContext extends AbstractEffectiveModelContextProvider {
+    GeneratorContext(final EffectiveModelContext modelContext) {
+        super(modelContext);
+    }
+
     /**
      * Resolve generator for the type object pointed to by a {@code path} expression, or {@code null} it the if cannot
      * the current generator is nested inside a {@code grouping} and the generator cannot be found.
@@ -27,7 +33,7 @@ abstract class GeneratorContext {
      * @throws NullPointerException if {@code path} is {@code null}
      * @throws IllegalStateException if this generator is not inside a {@code grouping} and the path cannot be resolved
      */
-    abstract @Nullable AbstractTypeObjectGenerator<?> resolveLeafref(@NonNull PathExpression path);
+    abstract @Nullable AbstractTypeObjectGenerator<?, ?> resolveLeafref(@NonNull PathExpression path);
 
     /**
      * Resolve a tree-scoped namespace reference. This covers {@code typedef} and {@code grouping} statements, as per
@@ -40,7 +46,7 @@ abstract class GeneratorContext {
      * @throws NullPointerException if any argument is null
      * @throws IllegalStateException if the generator cannot be found
      */
-    abstract <E extends EffectiveStatement<QName, ?>, G extends AbstractExplicitGenerator<E>>
+    abstract <E extends EffectiveStatement<QName, ?>, G extends AbstractExplicitGenerator<E, ?>>
         @NonNull G resolveTreeScoped(@NonNull Class<G> type, @NonNull QName argument);
 
     abstract @NonNull ModuleGenerator resolveModule(@NonNull QNameModule namespace);
index f8214ad1445247f3e4d6878234037ee7e1f92bd4..a201f5a5ab4471a51127b88d5704374017a5ac55 100644 (file)
@@ -71,6 +71,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
     private State state = State.INITIALIZED;
 
     public GeneratorReactor(final EffectiveModelContext context) {
+        super(context);
         inferenceStack = SchemaInferenceStack.of(context);
 
         // Construct modules and their subtrees. Dependency sort is very much needed here, as it establishes order of
@@ -245,13 +246,13 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
             gen.ensureMember();
             collectCollisionDomains(result, gen);
             if (gen instanceof AbstractCompositeGenerator) {
-                result.add(((AbstractCompositeGenerator<?>) gen).domain());
+                result.add(((AbstractCompositeGenerator<?, ?>) gen).domain());
             }
         }
     }
 
     @Override
-    <E extends EffectiveStatement<QName, ?>, G extends AbstractExplicitGenerator<E>> G resolveTreeScoped(
+    <E extends EffectiveStatement<QName, ?>, G extends AbstractExplicitGenerator<E, ?>> G resolveTreeScoped(
             final Class<G> type, final QName argument) {
         LOG.trace("Searching for tree-scoped argument {} at {}", argument, stack);
 
@@ -297,7 +298,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
     }
 
     @Override
-    AbstractTypeObjectGenerator<?> resolveLeafref(final PathExpression path) {
+    AbstractTypeObjectGenerator<?, ?> resolveLeafref(final PathExpression path) {
         LOG.trace("Resolving path {}", path);
         verify(inferenceStack.isEmpty(), "Unexpected data tree state %s", inferenceStack);
         try {
@@ -319,7 +320,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
         }
     }
 
-    private @NonNull AbstractTypeAwareGenerator<?, ?> strictResolvePath(final @NonNull PathExpression path) {
+    private @NonNull AbstractTypeAwareGenerator<?, ?, ?> strictResolvePath(final @NonNull PathExpression path) {
         try {
             inferenceStack.resolvePathExpression(path);
         } catch (IllegalArgumentException e) {
@@ -328,7 +329,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
         return mapToGenerator();
     }
 
-    private @Nullable AbstractTypeAwareGenerator<?, ?> lenientResolveLeafref(final @NonNull PathExpression path) {
+    private @Nullable AbstractTypeAwareGenerator<?, ?, ?> lenientResolveLeafref(final @NonNull PathExpression path) {
         try {
             inferenceStack.resolvePathExpression(path);
         } catch (IllegalArgumentException e) {
@@ -339,7 +340,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
     }
 
     // Map a statement to the corresponding generator
-    private @NonNull AbstractTypeAwareGenerator<?, ?> mapToGenerator() {
+    private @NonNull AbstractTypeAwareGenerator<?, ?, ?> mapToGenerator() {
         // Some preliminaries first: we need to be in the correct module to walk the path
         final ModuleEffectiveStatement module = inferenceStack.currentModule();
         final ModuleGenerator gen = verifyNotNull(generators.get(module.localQNameModule()),
@@ -347,9 +348,9 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
 
         // Now kick of the search
         final List<EffectiveStatement<?, ?>> stmtPath = inferenceStack.toInference().statementPath();
-        final AbstractExplicitGenerator<?> found = gen.findGenerator(stmtPath);
+        final AbstractExplicitGenerator<?, ?> found = gen.findGenerator(stmtPath);
         if (found instanceof AbstractTypeAwareGenerator) {
-            return (AbstractTypeAwareGenerator<?, ?>) found;
+            return (AbstractTypeAwareGenerator<?, ?, ?>) found;
         }
         throw new VerifyException("Statements " + stmtPath + " resulted in unexpected " + found);
     }
@@ -359,7 +360,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
         for (Generator child : parent) {
             if (child instanceof AbstractCompositeGenerator) {
                 LOG.trace("Visiting composite {}", child);
-                final AbstractCompositeGenerator<?> composite = (AbstractCompositeGenerator<?>) child;
+                final var composite = (AbstractCompositeGenerator<?, ?>) child;
                 stack.push(composite);
                 composite.linkUsesDependencies(this);
                 linkUsesDependencies(composite);
@@ -395,7 +396,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
     private void linkDependencies(final Iterable<? extends Generator> parent) {
         for (Generator child : parent) {
             if (child instanceof AbstractDependentGenerator) {
-                ((AbstractDependentGenerator<?>) child).linkDependencies(this);
+                ((AbstractDependentGenerator<?, ?>) child).linkDependencies(this);
             } else if (child instanceof AbstractCompositeGenerator) {
                 stack.push(child);
                 linkDependencies(child);
@@ -408,7 +409,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable
         for (Generator child : parent) {
             stack.push(child);
             if (child instanceof AbstractTypeObjectGenerator) {
-                ((AbstractTypeObjectGenerator<?>) child).bindTypeDefinition(this);
+                ((AbstractTypeObjectGenerator<?, ?>) child).bindTypeDefinition(this);
             } else if (child instanceof AbstractCompositeGenerator) {
                 bindTypeDefinition(child);
             }
index 687c60f65cb18f150d4f8846a7b3548c6271fed1..d789413cacfd0afda7f2b730c7e47f5619be27ee 100644 (file)
@@ -7,18 +7,23 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultGroupingRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.GroupingRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.GroupingEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Generator corresponding to a {@code grouping} statement.
  */
-final class GroupingGenerator extends AbstractCompositeGenerator<GroupingEffectiveStatement> {
-    GroupingGenerator(final GroupingEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class GroupingGenerator extends AbstractCompositeGenerator<GroupingEffectiveStatement, GroupingRuntimeType> {
+    GroupingGenerator(final GroupingEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -49,6 +54,12 @@ final class GroupingGenerator extends AbstractCompositeGenerator<GroupingEffecti
         return builder.build();
     }
 
+    @Override
+    GroupingRuntimeType createRuntimeType(final GeneratedType type, final GroupingEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        return new DefaultGroupingRuntimeType(type, statement, children, augments);
+    }
+
     @Override
     void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
         // groupings are a separate concept
index 307aed28c19a1470b6bde24dae7e8c6680cafb35..e5fc913e726ecafd17000914ead935643879a740 100644 (file)
@@ -11,9 +11,11 @@ import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.BASE_IDENTITY
 
 import java.util.List;
 import java.util.stream.Collectors;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultIdentityRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.BaseEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
@@ -21,10 +23,11 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 /**
  * Generator corresponding to a {@code identity} statement.
  */
-final class IdentityGenerator extends AbstractDependentGenerator<IdentityEffectiveStatement> {
+public final class IdentityGenerator
+        extends AbstractDependentGenerator<IdentityEffectiveStatement, IdentityRuntimeType> {
     private List<IdentityGenerator> baseIdentities = null;
 
-    IdentityGenerator(final IdentityEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+    IdentityGenerator(final IdentityEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -67,6 +70,16 @@ final class IdentityGenerator extends AbstractDependentGenerator<IdentityEffecti
         return builder.build();
     }
 
+    @Override
+    IdentityRuntimeType createRuntimeType() {
+        return generatedType().map(type -> new DefaultIdentityRuntimeType(type, statement())).orElse(null);
+    }
+
+    @Override
+    IdentityRuntimeType rebaseRuntimeType(final IdentityRuntimeType type, final IdentityEffectiveStatement statement) {
+        return new DefaultIdentityRuntimeType(type.javaType(), statement);
+    }
+
     @Override
     void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
         // identities are a separate concept
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/InputGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/InputGenerator.java
new file mode 100644 (file)
index 0000000..2400b4a
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.reactor;
+
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultInputRuntimeType;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+
+/**
+ * Generator corresponding to an {@code input} statement.
+ */
+class InputGenerator extends OperationContainerGenerator<InputEffectiveStatement, InputRuntimeType> {
+    InputGenerator(final InputEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+        super(statement, parent, BindingTypes.RPC_INPUT);
+    }
+
+    @Override
+    final InputRuntimeType createRuntimeType(final GeneratedType type, final InputEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        return new DefaultInputRuntimeType(type, statement, children, augments);
+    }
+}
index 4473a0b1cedce48a6caae3a0c7eb239f68fe328d..4a28b410f16cc7aef0cf9253e8e105b6364fa233 100644 (file)
@@ -7,25 +7,28 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import static com.google.common.base.Verify.verify;
 import static java.util.Objects.requireNonNull;
 
 import java.util.Set;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultKeyRuntimeType;
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.KeyRuntimeType;
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
-final class KeyGenerator extends AbstractExplicitGenerator<KeyEffectiveStatement> {
+final class KeyGenerator extends AbstractExplicitGenerator<KeyEffectiveStatement, KeyRuntimeType> {
     private final ListGenerator listGen;
 
-    KeyGenerator(final KeyEffectiveStatement statement, final AbstractCompositeGenerator<?> parent,
+    KeyGenerator(final KeyEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent,
             final ListGenerator listGen) {
         super(statement, parent);
         this.listGen = requireNonNull(listGen);
@@ -42,7 +45,7 @@ final class KeyGenerator extends AbstractExplicitGenerator<KeyEffectiveStatement
     }
 
     @Override
-    GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
+    GeneratedTransferObject createTypeImpl(final TypeBuilderFactory builderFactory) {
         final GeneratedTOBuilder builder = builderFactory.newGeneratedTOBuilder(typeName());
 
         builder.addImplementsType(BindingTypes.identifier(Type.of(listGen.typeName())));
@@ -73,6 +76,19 @@ final class KeyGenerator extends AbstractExplicitGenerator<KeyEffectiveStatement
         return builder.build();
     }
 
+    @Override
+    KeyRuntimeType createRuntimeType() {
+        return generatedType().map(type -> {
+            verify(type instanceof GeneratedTransferObject, "Unexpected type %s", type);
+            return new DefaultKeyRuntimeType((GeneratedTransferObject) type, statement());
+        }).orElse(null);
+    }
+
+    @Override
+    KeyRuntimeType rebaseRuntimeType(final KeyRuntimeType type, final KeyEffectiveStatement statement) {
+        return new DefaultKeyRuntimeType(type.javaType(), statement);
+    }
+
     @Override
     void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
         // Keys are explicitly handled by their corresponding list
index a872d94c465353fa801ad994d845e40ff695b638..53aadbed255ccee4ce785dfc592f167bda414fbb 100644 (file)
@@ -7,13 +7,26 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultLeafRuntimeType;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.LeafRuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
 
 /**
  * Generator corresponding to a {@code leaf} statement.
  */
-final class LeafGenerator extends AbstractTypeAwareGenerator<LeafEffectiveStatement, LeafGenerator> {
-    LeafGenerator(final LeafEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class LeafGenerator extends AbstractTypeAwareGenerator<LeafEffectiveStatement, LeafRuntimeType, LeafGenerator> {
+    LeafGenerator(final LeafEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
+
+    @Override
+    LeafRuntimeType createRuntimeType(final Type type) {
+        return new DefaultLeafRuntimeType(type, statement());
+    }
+
+    @Override
+    LeafRuntimeType rebaseRuntimeType(final LeafRuntimeType type, final LeafEffectiveStatement statement) {
+        return new DefaultLeafRuntimeType(type.javaType(), statement);
+    }
 }
index 68727b69c32cfc3cdfd74fd8421fa98c07f91b3b..e9f744db9a337e098ebfbab48a6ca93ff5e67b0e 100644 (file)
@@ -7,8 +7,10 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultLeafListRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.ri.Types;
+import org.opendaylight.mdsal.binding.runtime.api.LeafListRuntimeType;
 import org.opendaylight.yangtools.yang.common.Ordering;
 import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.OrderedByEffectiveStatement;
@@ -16,8 +18,9 @@ import org.opendaylight.yangtools.yang.model.api.stmt.OrderedByEffectiveStatemen
 /**
  * Generator corresponding to a {@code leaf-list} statement.
  */
-final class LeafListGenerator extends AbstractTypeAwareGenerator<LeafListEffectiveStatement, LeafListGenerator> {
-    LeafListGenerator(final LeafListEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class LeafListGenerator
+        extends AbstractTypeAwareGenerator<LeafListEffectiveStatement, LeafListRuntimeType, LeafListGenerator> {
+    LeafListGenerator(final LeafListEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -38,4 +41,14 @@ final class LeafListGenerator extends AbstractTypeAwareGenerator<LeafListEffecti
                 throw new IllegalStateException("Unexpected ordering " + ordering);
         }
     }
+
+    @Override
+    LeafListRuntimeType createRuntimeType(final Type type) {
+        return new DefaultLeafListRuntimeType(type, statement());
+    }
+
+    @Override
+    LeafListRuntimeType rebaseRuntimeType(final LeafListRuntimeType type, final LeafListEffectiveStatement statement) {
+        return new DefaultLeafListRuntimeType(type.javaType(), statement);
+    }
 }
index 63a6e8d9afd5195557b470b3ef1339654e58afef..a7c464e392f5f54e07824a5a9d7a5e6c3073dea4 100644 (file)
@@ -9,7 +9,9 @@ package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
 import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.identifiable;
 
+import java.util.List;
 import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultListRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics;
 import org.opendaylight.mdsal.binding.model.api.Type;
@@ -17,6 +19,9 @@ import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilde
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
 import org.opendaylight.mdsal.binding.model.ri.Types;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.yang.common.Ordering;
 import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
@@ -27,10 +32,10 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 /**
  * Generator corresponding to a {@code list} statement.
  */
-final class ListGenerator extends CompositeSchemaTreeGenerator<ListEffectiveStatement, ListGenerator> {
+final class ListGenerator extends CompositeSchemaTreeGenerator<ListEffectiveStatement, ListRuntimeType> {
     private final @Nullable KeyGenerator keyGen;
 
-    ListGenerator(final ListEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+    ListGenerator(final ListEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
         keyGen = statement.findFirstEffectiveSubstatement(KeyEffectiveStatement.class)
             .map(key -> new KeyGenerator(key, parent, this))
@@ -76,6 +81,13 @@ final class ListGenerator extends CompositeSchemaTreeGenerator<ListEffectiveStat
         return builder.build();
     }
 
+    @Override
+    ListRuntimeType createRuntimeType(final GeneratedType type, final ListEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        return new DefaultListRuntimeType(type, statement, children, augments,
+            keyGen != null ? keyGen.runtimeType().orElseThrow() : null);
+    }
+
     @Override
     Type methodReturnType(final TypeBuilderFactory builderFactory) {
         final Type generatedType = super.methodReturnType(builderFactory);
index 3b15fed218d45d3d376303e6e88951fec28c3405..436ac4104721ee99151d67f41f90fc557e9e3e4c 100644 (file)
@@ -28,11 +28,11 @@ abstract class MatchStrategy {
         static final @NonNull Identity INSTANCE = new Identity();
 
         @Override
-        AbstractExplicitGenerator<?> findGenerator(final EffectiveStatement<?, ?> needle,
+        AbstractExplicitGenerator<?, ?> findGenerator(final EffectiveStatement<?, ?> needle,
                 final Iterable<? extends Generator> haystack) {
             for (Generator gen : haystack) {
                 if (gen instanceof AbstractExplicitGenerator) {
-                    final AbstractExplicitGenerator<?> ret = (AbstractExplicitGenerator<?>) gen;
+                    final AbstractExplicitGenerator<?, ?> ret = (AbstractExplicitGenerator<?, ?>) gen;
                     if (needle == ret.statement()) {
                         return ret;
                     }
@@ -49,17 +49,18 @@ abstract class MatchStrategy {
         static final @NonNull OnQName INSTANCE = new OnQName();
 
         @Override
-        final AbstractExplicitGenerator<?> findGenerator(final EffectiveStatement<?, ?> needle,
+        final AbstractExplicitGenerator<?, ?> findGenerator(final EffectiveStatement<?, ?> needle,
                 final Iterable<? extends Generator> haystack) {
             final Object arg = needle.argument();
             verify(arg instanceof QName, "Unexpected argument %s in %s", arg, needle);
             return findGenerator((QName) arg, haystack);
         }
 
-        AbstractExplicitGenerator<?> findGenerator(final QName needle, final Iterable<? extends Generator> haystack) {
+        AbstractExplicitGenerator<?, ?> findGenerator(final QName needle,
+                final Iterable<? extends Generator> haystack) {
             for (Generator gen : haystack) {
                 if (gen instanceof AbstractExplicitGenerator) {
-                    final AbstractExplicitGenerator<?> ret = (AbstractExplicitGenerator<?>) gen;
+                    final AbstractExplicitGenerator<?, ?> ret = (AbstractExplicitGenerator<?, ?>) gen;
                     if (needle.equals(ret.statement().argument())) {
                         return ret;
                     }
@@ -81,7 +82,8 @@ abstract class MatchStrategy {
         }
 
         @Override
-        AbstractExplicitGenerator<?> findGenerator(final QName needle, final Iterable<? extends Generator> haystack) {
+        AbstractExplicitGenerator<?, ?> findGenerator(final QName needle,
+                final Iterable<? extends Generator> haystack) {
             return super.findGenerator(needle.bindTo(module), haystack);
         }
 
@@ -107,7 +109,7 @@ abstract class MatchStrategy {
         return Identity.INSTANCE;
     }
 
-    abstract @Nullable AbstractExplicitGenerator<?> findGenerator(EffectiveStatement<?, ?> needle,
+    abstract @Nullable AbstractExplicitGenerator<?, ?> findGenerator(EffectiveStatement<?, ?> needle,
             Iterable<? extends Generator> haystack);
 
     @Override
index ee590e72bf2db69aabe15d06229d3b18be0489e9..a04587e005be386c26d4c68c222becfe5dc87ff4 100644 (file)
@@ -9,16 +9,20 @@ package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Generator corresponding to a {@code augment} statement used as a child of a {@code module} statement.
  */
 final class ModuleAugmentGenerator extends AbstractAugmentGenerator {
-    ModuleAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+    ModuleAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
     @NonNull AugmentRequirement startLinkage(final GeneratorContext context) {
+        setTargetStatement(SchemaInferenceStack.of(context.getEffectiveModelContext())
+            .enterSchemaTree(statement().argument()));
+
         return new AugmentRequirement(this,
             context.resolveModule(statement().argument().firstNodeIdentifier().getModule()));
     }
index 868487b201f8d0b7c5c33c25fb3332e8ff86abd3..b67f89f7fc0ba359bac1aaef3a76555ce2d00713 100644 (file)
@@ -9,14 +9,19 @@ package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
 import static com.google.common.base.Verify.verifyNotNull;
 
+import java.util.List;
 import java.util.Map;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultModuleRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.yang.common.AbstractQName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
@@ -29,7 +34,7 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
  * Generator corresponding to a {@code module} statement. These generators are roots for generating types for a
  * particular {@link QNameModule} as mapped into the root package.
  */
-public final class ModuleGenerator extends AbstractCompositeGenerator<ModuleEffectiveStatement> {
+public final class ModuleGenerator extends AbstractCompositeGenerator<ModuleEffectiveStatement, ModuleRuntimeType> {
     private final @NonNull JavaTypeName yangModuleInfo;
     private final @NonNull ClassPlacement placement;
 
@@ -81,7 +86,7 @@ public final class ModuleGenerator extends AbstractCompositeGenerator<ModuleEffe
     }
 
     @Override
-    AbstractCompositeGenerator<?> getPackageParent() {
+    AbstractCompositeGenerator<?, ?> getPackageParent() {
         return this;
     }
 
@@ -119,6 +124,12 @@ public final class ModuleGenerator extends AbstractCompositeGenerator<ModuleEffe
         return builder.build();
     }
 
+    @Override
+    ModuleRuntimeType createRuntimeType(final GeneratedType type, final ModuleEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        return new DefaultModuleRuntimeType(type, statement, children, augments);
+    }
+
     @NonNull Member getPrefixMember() {
         return verifyNotNull(prefixMember);
     }
index 1be7ae1112d40223946a64a5a4231704c976f070..c2d4a3827564d33e8e7a0b53dab15d853e536af2 100644 (file)
@@ -7,11 +7,16 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultNotificationRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
@@ -19,8 +24,9 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
  * Generator corresponding to a {@code notification} statement.
  */
 final class NotificationGenerator
-        extends CompositeSchemaTreeGenerator<NotificationEffectiveStatement, NotificationGenerator> {
-    NotificationGenerator(final NotificationEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+        extends CompositeSchemaTreeGenerator<NotificationEffectiveStatement, NotificationRuntimeType> {
+    NotificationGenerator(final NotificationEffectiveStatement statement,
+            final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -51,13 +57,19 @@ final class NotificationGenerator
         return builder.build();
     }
 
+    @Override
+    NotificationRuntimeType createRuntimeType(final GeneratedType type, final NotificationEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        return new DefaultNotificationRuntimeType(type, statement, children, augments);
+    }
+
     @Override
     void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
         // Notifications are a distinct concept
     }
 
     private Type notificationType(final GeneratedTypeBuilder builder, final TypeBuilderFactory builderFactory) {
-        final AbstractCompositeGenerator<?> parent = getParent();
+        final AbstractCompositeGenerator<?, ?> parent = getParent();
         if (parent instanceof ModuleGenerator) {
             return BindingTypes.notification(builder);
         }
index f020779dca5b6b679a5245ab53823f4f6b2ce3d8..63564ce2f621105e56dede5f9434625890fd83c1 100644 (file)
@@ -7,27 +7,60 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultAnydataRuntimeType;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultAnyxmlRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AnydataRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.AnyxmlRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OpaqueRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Common generator for {@code anydata} and {@code anyxml}.
  */
-final class OpaqueObjectGenerator<T extends DataTreeEffectiveStatement<?>> extends AbstractExplicitGenerator<T>
-        implements SchemaTreeChild<T, OpaqueObjectGenerator<T>> {
-    OpaqueObjectGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
-        super(statement, parent);
+abstract class OpaqueObjectGenerator<S extends DataTreeEffectiveStatement<?>, R extends OpaqueRuntimeType>
+        extends AbstractExplicitGenerator<S, R> {
+    static final class Anydata extends OpaqueObjectGenerator<AnydataEffectiveStatement, AnydataRuntimeType> {
+        Anydata(final AnydataEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+            super(statement, parent);
+        }
+
+        @Override
+        AnydataRuntimeType createRuntimeType() {
+            return generatedType().map(type -> new DefaultAnydataRuntimeType(type, statement())).orElse(null);
+        }
+
+        @Override
+        AnydataRuntimeType rebaseRuntimeType(final AnydataRuntimeType type, final AnydataEffectiveStatement statement) {
+            return new DefaultAnydataRuntimeType(type.javaType(), statement);
+        }
     }
 
-    @Override
-    public OpaqueObjectGenerator<T> generator() {
-        return this;
+    static final class Anyxml extends OpaqueObjectGenerator<AnyxmlEffectiveStatement, AnyxmlRuntimeType> {
+        Anyxml(final AnyxmlEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+            super(statement, parent);
+        }
+
+        @Override
+        AnyxmlRuntimeType createRuntimeType() {
+            return generatedType().map(type -> new DefaultAnyxmlRuntimeType(type, statement())).orElse(null);
+        }
+
+        @Override
+        AnyxmlRuntimeType rebaseRuntimeType(final AnyxmlRuntimeType type, final AnyxmlEffectiveStatement statement) {
+            return new DefaultAnyxmlRuntimeType(type.javaType(), statement);
+        }
+    }
+
+    OpaqueObjectGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
+        super(statement, parent);
     }
 
     @Override
index e588743fdaba9610502e4acc20178bb87fc3ee20..35a70e5824649f992ae495afc7e9351badc4429a 100644 (file)
@@ -7,30 +7,26 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import static java.util.Objects.requireNonNull;
+
 import org.opendaylight.mdsal.binding.model.api.ConcreteType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
-import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
-import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Generator corresponding to an {@code input} or an {@code output} statement.
  */
-class OperationContainerGenerator
-        extends CompositeSchemaTreeGenerator<SchemaTreeEffectiveStatement<?>, OperationContainerGenerator> {
+abstract class OperationContainerGenerator<S extends DataTreeEffectiveStatement<?>, R extends CompositeRuntimeType>
+        extends CompositeSchemaTreeGenerator<S, R> {
     private final ConcreteType baseInterface;
 
-    OperationContainerGenerator(final InputEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
-        super(statement, parent);
-        baseInterface = BindingTypes.RPC_INPUT;
-    }
-
-    OperationContainerGenerator(final OutputEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+    OperationContainerGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent,
+            final ConcreteType baseInterface) {
         super(statement, parent);
-        baseInterface = BindingTypes.RPC_OUTPUT;
+        this.baseInterface = requireNonNull(baseInterface);
     }
 
     @Override
@@ -40,7 +36,7 @@ class OperationContainerGenerator
 
     @Override
     final GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
-        final AbstractCompositeGenerator<?> parent = getParent();
+        final AbstractCompositeGenerator<?, ?> parent = getParent();
         if (parent instanceof ActionGenerator && ((ActionGenerator) parent).isAddedByUses()) {
             //        final ActionDefinition orig = findOrigAction(parentSchema, action).get();
             //        // Original definition may live in a different module, make sure we account for that
index 3d9009a42b4c6dfc068e38f2f7bb22799df5178b..a766ca45fb218844b284fc2f27129805feb7cf4a 100644 (file)
@@ -13,27 +13,29 @@ import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 
 /**
  * Link to the original definition of an {@link AbstractExplicitGenerator}.
  */
 // FIXME: sealed when we have JDK17+
-abstract class OriginalLink<T extends EffectiveStatement<?, ?>> {
-    private static final class Complete<T extends EffectiveStatement<?, ?>> extends OriginalLink<T> {
-        private final @NonNull AbstractExplicitGenerator<T> original;
+abstract class OriginalLink<T extends EffectiveStatement<?, ?>, R extends RuntimeType> {
+    private static final class Complete<T extends EffectiveStatement<?, ?>, R extends RuntimeType>
+            extends OriginalLink<T, R> {
+        private final @NonNull AbstractExplicitGenerator<T, R> original;
 
-        Complete(final AbstractExplicitGenerator<T> original) {
+        Complete(final AbstractExplicitGenerator<T, R> original) {
             this.original = requireNonNull(original);
         }
 
         @Override
-        AbstractExplicitGenerator<T> previous() {
+        AbstractExplicitGenerator<T, R> previous() {
             return original;
         }
 
         @Override
-        @NonNull AbstractExplicitGenerator<T> original() {
+        @NonNull AbstractExplicitGenerator<T, R> original() {
             return original;
         }
 
@@ -43,21 +45,22 @@ abstract class OriginalLink<T extends EffectiveStatement<?, ?>> {
         }
     }
 
-    private static final class Partial<T extends EffectiveStatement<?, ?>> extends OriginalLink<T> {
-        private final @NonNull AbstractExplicitGenerator<T> previous;
-        private AbstractExplicitGenerator<T> original;
+    private static final class Partial<T extends EffectiveStatement<?, ?>, R extends RuntimeType>
+            extends OriginalLink<T, R> {
+        private final @NonNull AbstractExplicitGenerator<T, R> previous;
+        private AbstractExplicitGenerator<T, R> original;
 
-        Partial(final AbstractExplicitGenerator<T> previous) {
+        Partial(final AbstractExplicitGenerator<T, R> previous) {
             this.previous = requireNonNull(previous);
         }
 
         @Override
-        AbstractExplicitGenerator<T> previous() {
+        AbstractExplicitGenerator<T, R> previous() {
             return previous;
         }
 
         @Override
-        AbstractExplicitGenerator<T> original() {
+        AbstractExplicitGenerator<T, R> original() {
             if (original == null) {
                 final var link = previous.originalLink();
                 if (link instanceof Complete || link.previous() != previous) {
@@ -77,19 +80,19 @@ abstract class OriginalLink<T extends EffectiveStatement<?, ?>> {
         // Hidden on purpose
     }
 
-    static <T extends EffectiveStatement<?, ?>> @NonNull OriginalLink<T> complete(
-            final AbstractExplicitGenerator<T> original) {
+    static <T extends EffectiveStatement<?, ?>, R extends RuntimeType> @NonNull OriginalLink<T, R> complete(
+            final AbstractExplicitGenerator<T, R> original) {
         return new Complete<>(original);
     }
 
-    static <T extends EffectiveStatement<?, ?>> @NonNull OriginalLink<T> partial(
-            final AbstractExplicitGenerator<T> previous) {
+    static <T extends EffectiveStatement<?, ?>, R extends RuntimeType> @NonNull OriginalLink<T, R> partial(
+            final AbstractExplicitGenerator<T, R> previous) {
         return new Partial<>(previous);
     }
 
-    abstract @NonNull AbstractExplicitGenerator<T> previous();
+    abstract @NonNull AbstractExplicitGenerator<T, R> previous();
 
-    abstract @Nullable AbstractExplicitGenerator<T> original();
+    abstract @Nullable AbstractExplicitGenerator<T, R> original();
 
     abstract ToStringHelper addToStringAttributes(ToStringHelper helper);
 
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OutputGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OutputGenerator.java
new file mode 100644 (file)
index 0000000..320593d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.reactor;
+
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultOutputRuntimeType;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+
+/**
+ * Generator corresponding to an {@code input} statement.
+ */
+class OutputGenerator extends OperationContainerGenerator<OutputEffectiveStatement, OutputRuntimeType> {
+    OutputGenerator(final OutputEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+        super(statement, parent, BindingTypes.RPC_OUTPUT);
+    }
+
+    @Override
+    final OutputRuntimeType createRuntimeType(final GeneratedType type, final OutputEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        return new DefaultOutputRuntimeType(type, statement, children, augments);
+    }
+}
index 39b934e18d44b2a85c50bcff48201fe1a223fe4f..985ac81dd3f581a828171aee1e06cb7753c81a9d 100644 (file)
@@ -7,16 +7,21 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import java.util.List;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RpcRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * Generator corresponding to a {@code rpc} statement.
  */
-final class RpcGenerator extends CompositeSchemaTreeGenerator<RpcEffectiveStatement, RpcGenerator> {
-    RpcGenerator(final RpcEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+// FIXME: hide this once we have RpcRuntimeType
+public final class RpcGenerator extends CompositeSchemaTreeGenerator<RpcEffectiveStatement, RpcRuntimeType> {
+    RpcGenerator(final RpcEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -36,6 +41,12 @@ final class RpcGenerator extends CompositeSchemaTreeGenerator<RpcEffectiveStatem
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    RpcRuntimeType createRuntimeType(final GeneratedType type, final RpcEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
         // RPCs are a separate concept
@@ -7,26 +7,16 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
-import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
-import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
 import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
 
 /**
  * Specialization for legacy RPC services.
  */
-final class RpcContainerGenerator extends OperationContainerGenerator {
-    private final @NonNull String suffix;
-
-    RpcContainerGenerator(final InputEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
-        super(statement, parent);
-        suffix = BindingMapping.RPC_INPUT_SUFFIX;
-    }
-
-    RpcContainerGenerator(final OutputEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+// FIXME: hide this once we have RpcRuntimeType
+public final class RpcInputGenerator extends InputGenerator {
+    RpcInputGenerator(final InputEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
-        suffix = BindingMapping.RPC_OUTPUT_SUFFIX;
     }
 
     @Override
@@ -35,12 +25,12 @@ final class RpcContainerGenerator extends OperationContainerGenerator {
     }
 
     @Override
-    AbstractCompositeGenerator<?> getPackageParent() {
+    AbstractCompositeGenerator<?, ?> getPackageParent() {
         return getParent().getParent();
     }
 
     @Override
     Member createMember(final CollisionDomain domain) {
-        return domain.addSecondary(this, getParent().ensureMember(), suffix, statement().argument());
+        return domain.addSecondary(this, getParent().ensureMember());
     }
 }
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcOutputGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcOutputGenerator.java
new file mode 100644 (file)
index 0000000..b08a259
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.reactor;
+
+import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+
+/**
+ * Specialization for legacy RPC services.
+ */
+// FIXME: hide this once we have RpcRuntimeType
+public final class RpcOutputGenerator extends OutputGenerator {
+    RpcOutputGenerator(final OutputEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+        super(statement, parent);
+    }
+
+    @Override
+    CollisionDomain parentDomain() {
+        return getParent().parentDomain();
+    }
+
+    @Override
+    AbstractCompositeGenerator<?, ?> getPackageParent() {
+        return getParent().getParent();
+    }
+
+    @Override
+    Member createMember(final CollisionDomain domain) {
+        return domain.addSecondary(this, getParent().ensureMember());
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/SchemaTreePlaceholder.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/SchemaTreePlaceholder.java
deleted file mode 100644 (file)
index 9cfd59e..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.generator.impl.reactor;
-
-import static com.google.common.base.Verify.verify;
-import static com.google.common.base.Verify.verifyNotNull;
-import static java.util.Objects.requireNonNull;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
-
-/**
- * A placeholder {@link SchemaTreeChild}.
- *
- */
-final class SchemaTreePlaceholder<S extends SchemaTreeEffectiveStatement<?>,
-        G extends AbstractExplicitGenerator<S> & SchemaTreeChild<S, G>> implements SchemaTreeChild<S, G> {
-    private final @NonNull Class<G> generatorType;
-    private final @NonNull S statement;
-
-    private @Nullable G generator;
-
-    SchemaTreePlaceholder(final S statement, final Class<G> generatorType) {
-        this.statement = requireNonNull(statement);
-        this.generatorType = requireNonNull(generatorType);
-    }
-
-    @Override
-    public S statement() {
-        return statement;
-    }
-
-    @Override
-    public G generator() {
-        final var local = generator;
-        if (local == null) {
-            throw new IllegalStateException("Unresolved generator in " + this);
-        }
-        return local;
-    }
-
-    void setGenerator(final AbstractCompositeGenerator<?> parent) {
-        verify(generator == null, "Attempted to set generator for %s", this);
-        final var qname = getIdentifier();
-        generator = generatorType.cast(verifyNotNull(parent.findSchemaTreeGenerator(qname),
-            "Failed to find generator for child %s in %s", qname, parent));
-    }
-}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TargetAugmentEffectiveStatement.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TargetAugmentEffectiveStatement.java
new file mode 100644 (file)
index 0000000..89d5fd6
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.reactor;
+
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathExpression.QualifiedBound;
+
+final class TargetAugmentEffectiveStatement implements AugmentEffectiveStatement, AugmentationSchemaNode {
+    private final @NonNull List<EffectiveStatement<?, ?>> substatements;
+    private final @NonNull AugmentEffectiveStatement delegate;
+    private final @NonNull AugmentationSchemaNode schemaDelegate;
+
+    TargetAugmentEffectiveStatement(final AugmentEffectiveStatement augment,
+            final SchemaTreeAwareEffectiveStatement<?, ?> target) {
+        delegate = requireNonNull(augment);
+        verify(augment instanceof AugmentationSchemaNode, "Unsupported augment implementation %s", augment);
+        schemaDelegate = (AugmentationSchemaNode) augment;
+
+        final var stmts = augment.effectiveSubstatements();
+        final var builder = ImmutableList.<EffectiveStatement<?, ?>>builderWithExpectedSize(stmts.size());
+        for (var stmt : stmts) {
+            if (stmt instanceof SchemaTreeEffectiveStatement) {
+                final var qname = ((SchemaTreeEffectiveStatement<?>) stmt).getIdentifier();
+                final Optional<? extends SchemaTreeEffectiveStatement<?>> child =
+                    target.get(SchemaTreeAwareEffectiveStatement.Namespace.class, qname);
+                child.ifPresent(builder::add);
+            } else {
+                builder.add(stmt);
+            }
+        }
+
+        substatements = builder.build();
+    }
+
+    @NonNull AugmentEffectiveStatement delegate() {
+        return delegate;
+    }
+
+    @Override
+    public AugmentStatement getDeclared() {
+        return delegate.getDeclared();
+    }
+
+    @Override
+    public SchemaNodeIdentifier argument() {
+        return delegate.argument();
+    }
+
+    @Override
+    public StatementOrigin statementOrigin() {
+        return delegate.statementOrigin();
+    }
+
+    @Override
+    public <K, V, N extends IdentifierNamespace<K, V>> Optional<? extends V> get(final Class<N> namespace,
+            final K identifier) {
+        return Optional.empty();
+    }
+
+    @Override
+    public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(final Class<N> namespace) {
+        return Map.of();
+    }
+
+    @Override
+    public Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+        return substatements;
+    }
+
+    @Override
+    public Collection<? extends TypeDefinition<?>> getTypeDefinitions() {
+        return schemaDelegate.getTypeDefinitions();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Collection<? extends DataSchemaNode> getChildNodes() {
+        return (Collection) Collections2.filter(substatements, DataSchemaNode.class::isInstance);
+    }
+
+    @Override
+    public Collection<? extends GroupingDefinition> getGroupings() {
+        return schemaDelegate.getGroupings();
+    }
+
+    @Override
+    public DataSchemaNode dataChildByName(final QName name) {
+        return getChildNodes().stream().filter(child -> name.equals(child.getQName())).findFirst().orElse(null);
+    }
+
+    @Override
+    public Collection<? extends UsesNode> getUses() {
+        return schemaDelegate.getUses();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Collection<? extends NotificationDefinition> getNotifications() {
+        return (Collection) Collections2.filter(substatements, NotificationDefinition.class::isInstance);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Collection<? extends ActionDefinition> getActions() {
+        return (Collection) Collections2.filter(substatements, ActionDefinition.class::isInstance);
+    }
+
+    @Override
+    public Optional<? extends QualifiedBound> getWhenCondition() {
+        return schemaDelegate.getWhenCondition();
+    }
+
+    @Override
+    public @NonNull Status getStatus() {
+        return schemaDelegate.getStatus();
+    }
+
+    @Override
+    public Optional<String> getDescription() {
+        return schemaDelegate.getDescription();
+    }
+
+    @Override
+    public Optional<String> getReference() {
+        return schemaDelegate.getReference();
+    }
+
+    @Override
+    public AugmentEffectiveStatement asEffectiveStatement() {
+        return this;
+    }
+
+    @Override
+    @Deprecated(forRemoval = true)
+    public Optional<AugmentationSchemaNode> getOriginalDefinition() {
+        return schemaDelegate.getOriginalDefinition();
+    }
+}
index b1f52c1fd839f6c1624d651be06c3b6c1faed1a7..629306c8db50ea49e1ee57c5fa2689f6b77e2852 100644 (file)
@@ -53,9 +53,9 @@ abstract class TypeReference {
     }
 
     static final class ResolvedLeafref extends Leafref {
-        private final AbstractTypeObjectGenerator<?> referencedGenerator;
+        private final AbstractTypeObjectGenerator<?, ?> referencedGenerator;
 
-        private ResolvedLeafref(final AbstractTypeObjectGenerator<?> referencedGenerator) {
+        private ResolvedLeafref(final AbstractTypeObjectGenerator<?, ?> referencedGenerator) {
             this.referencedGenerator = requireNonNull(referencedGenerator);
         }
 
@@ -78,7 +78,7 @@ abstract class TypeReference {
         }
     }
 
-    static @NonNull TypeReference leafRef(final @Nullable AbstractTypeObjectGenerator<?> referencedGenerator) {
+    static @NonNull TypeReference leafRef(final @Nullable AbstractTypeObjectGenerator<?, ?> referencedGenerator) {
         return referencedGenerator == null ? UnresolvedLeafref.INSTANCE : new ResolvedLeafref(referencedGenerator);
     }
 
index 8bca3a398da8ac9d6f33125179d25a8135808b6a..3267b83aa530c022fa0b9d46dde9c0f9f82792f1 100644 (file)
@@ -7,13 +7,18 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
+import static com.google.common.base.Verify.verify;
 import static java.util.Objects.requireNonNull;
 
 import java.util.ArrayList;
 import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultTypedefRuntimeType;
 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding.runtime.api.TypedefRuntimeType;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
@@ -21,14 +26,14 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 /**
  * Generator corresponding to a {@code typedef} statement.
  */
-final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiveStatement> {
+final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiveStatement, TypedefRuntimeType> {
     /**
      * List of all generators for types directly derived from this typedef. We populate this list during initial type
      * linking. It allows us to easily cascade inferences made by this typedef down the type derivation tree.
      */
-    private List<AbstractTypeObjectGenerator<?>> derivedGenerators = null;
+    private List<AbstractTypeObjectGenerator<?, ?>> derivedGenerators = null;
 
-    TypedefGenerator(final TypedefEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+    TypedefGenerator(final TypedefEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -42,7 +47,7 @@ final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiv
         dataTree.enterTypedef(statement().argument());
     }
 
-    void addDerivedGenerator(final AbstractTypeObjectGenerator<?> derivedGenerator) {
+    void addDerivedGenerator(final AbstractTypeObjectGenerator<?, ?> derivedGenerator) {
         if (derivedGenerators == null) {
             derivedGenerators = new ArrayList<>(4);
         }
@@ -53,7 +58,7 @@ final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiv
     void bindDerivedGenerators(final TypeReference reference) {
         // Trigger any derived resolvers ...
         if (derivedGenerators != null) {
-            for (AbstractTypeObjectGenerator<?> derived : derivedGenerators) {
+            for (AbstractTypeObjectGenerator<?, ?> derived : derivedGenerators) {
                 derived.bindTypeDefinition(reference);
             }
         }
@@ -89,6 +94,17 @@ final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiv
         return builder.build();
     }
 
+    @Override
+    TypedefRuntimeType createRuntimeType(final Type type) {
+        verify(type instanceof GeneratedType, "Unexpected type %s", type);
+        return new DefaultTypedefRuntimeType((GeneratedType) type, statement());
+    }
+
+    @Override
+    TypedefRuntimeType rebaseRuntimeType(final TypedefRuntimeType type, final TypedefEffectiveStatement statement) {
+        return new DefaultTypedefRuntimeType(type.javaType(), statement);
+    }
+
     @Override
     void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
         // typedefs are a separate concept
index 81c93f723ef157a94728f4682905a654982ef719..e933dbaaed7a20b35acaa0524700e18ff9f09841 100644 (file)
@@ -13,6 +13,7 @@ import static java.util.Objects.requireNonNull;
 
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UsesEffectiveStatement;
 
 /**
@@ -24,9 +25,20 @@ final class UsesAugmentGenerator extends AbstractAugmentGenerator {
     private GroupingGenerator grouping;
 
     UsesAugmentGenerator(final AugmentEffectiveStatement statement, final UsesEffectiveStatement uses,
-            final AbstractCompositeGenerator<?> parent) {
+            final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
         this.uses = requireNonNull(uses);
+
+        // FIXME: use SchemaTreeAwareEffectiveStatement
+        var stmt = parent.statement();
+        for (var qname : statement.argument().getNodeIdentifiers()) {
+            final var tmp = stmt;
+            stmt = stmt.streamEffectiveSubstatements(SchemaTreeEffectiveStatement.class)
+                .filter(child -> qname.equals(child.argument()))
+                .findFirst()
+                .orElseThrow(() -> new IllegalStateException("Failed to find " + qname + " in " + tmp));
+        }
+        setTargetStatement(stmt);
     }
 
     void resolveGrouping(final UsesEffectiveStatement resolvedUses, final GroupingGenerator resolvedGrouping) {
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCaseRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCaseRuntimeType.java
new file mode 100644 (file)
index 0000000..ec51840
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+
+abstract class AbstractCaseRuntimeType extends AbstractCompositeRuntimeType<CaseEffectiveStatement>
+        implements CaseRuntimeType {
+    AbstractCaseRuntimeType(final GeneratedType bindingType, final CaseEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractChoiceRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractChoiceRuntimeType.java
new file mode 100644 (file)
index 0000000..8f2809e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.collect.Collections2;
+import java.util.Collection;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+
+abstract class AbstractChoiceRuntimeType extends AbstractCompositeRuntimeType<ChoiceEffectiveStatement>
+        implements ChoiceRuntimeType {
+    AbstractChoiceRuntimeType(final GeneratedType bindingType, final ChoiceEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+
+    @Override
+    public final Collection<CaseRuntimeType> validCaseChildren() {
+        return (Collection) Collections2.filter(schemaTreeChildren(), CaseRuntimeType.class::isInstance);
+    }
+
+    @Override
+    public final CaseRuntimeType bindingCaseChild(final JavaTypeName typeName) {
+        final var child = bindingChild(typeName);
+        return child instanceof CaseRuntimeType ? (CaseRuntimeType) child : null;
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCompositeRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCompositeRuntimeType.java
new file mode 100644 (file)
index 0000000..d67f1cf
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.GeneratedRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+
+abstract class AbstractCompositeRuntimeType<S extends EffectiveStatement<?, ?>>
+        extends AbstractRuntimeType<S, GeneratedType> implements CompositeRuntimeType {
+    private final ImmutableMap<JavaTypeName, GeneratedRuntimeType> byClass;
+    private final ImmutableMap<QName, RuntimeType> bySchemaTree;
+    private final @NonNull ImmutableList<AugmentRuntimeType> augments;
+    private final @NonNull ImmutableList<AugmentRuntimeType> mismatchedAugments;
+
+    AbstractCompositeRuntimeType(final GeneratedType bindingType, final S statement, final List<RuntimeType> children,
+            final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement);
+
+        final var substatements = statement.effectiveSubstatements();
+        final var correctBuilder = ImmutableList.<AugmentRuntimeType>builder();
+        final var mismatchedBuilder = ImmutableList.<AugmentRuntimeType>builder();
+        for (var aug : augments) {
+            if (substatements.contains(aug.statement())) {
+                correctBuilder.add(aug);
+            } else {
+                mismatchedBuilder.add(aug);
+            }
+        }
+        this.augments = correctBuilder.build();
+        this.mismatchedAugments = mismatchedBuilder.build();
+
+        byClass = children.stream()
+            .filter(GeneratedRuntimeType.class::isInstance)
+            .map(GeneratedRuntimeType.class::cast)
+            .collect(ImmutableMap.toImmutableMap(GeneratedRuntimeType::getIdentifier, Functions.identity()));
+
+        // Note: this may be over-sized, but we typically deal with schema tree statements, hence it is kind of accurate
+        final var builder = ImmutableMap.<QName, RuntimeType>builderWithExpectedSize(children.size());
+        for (var child : children) {
+            final var stmt = child.statement();
+            if (stmt instanceof SchemaTreeEffectiveStatement) {
+                builder.put(((SchemaTreeEffectiveStatement<?>)stmt).argument(), child);
+            }
+        }
+        bySchemaTree = builder.build();
+    }
+
+    @Override
+    public final List<AugmentRuntimeType> augments() {
+        return augments;
+    }
+
+    @Override
+    public final List<AugmentRuntimeType> mismatchedAugments() {
+        return mismatchedAugments;
+    }
+
+    @Override
+    public final RuntimeType schemaTreeChild(final QName qname) {
+        return bySchemaTree.get(requireNonNull(qname));
+    }
+
+    @Override
+    public final GeneratedRuntimeType bindingChild(final JavaTypeName typeName) {
+        return byClass.get(requireNonNull(typeName));
+    }
+
+    final @NonNull ImmutableCollection<RuntimeType> schemaTreeChildren() {
+        return bySchemaTree.values();
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractGeneratedRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractGeneratedRuntimeType.java
new file mode 100644 (file)
index 0000000..245ccf8
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+abstract class AbstractGeneratedRuntimeType<S extends EffectiveStatement<?, ?>>
+        extends AbstractRuntimeType<S, GeneratedType> {
+    AbstractGeneratedRuntimeType(final GeneratedType bindingType, final S statement) {
+        super(bindingType, statement);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractObjectRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractObjectRuntimeType.java
new file mode 100644 (file)
index 0000000..a3c4cd3
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+abstract class AbstractObjectRuntimeType<S extends EffectiveStatement<?, ?>>
+        extends AbstractRuntimeType<S, GeneratedTransferObject> {
+    AbstractObjectRuntimeType(final GeneratedTransferObject bindingType, final S statement) {
+        super(bindingType, statement);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractRuntimeType.java
new file mode 100644 (file)
index 0000000..c2cb51f
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.MoreObjects;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+abstract class AbstractRuntimeType<S extends EffectiveStatement<?, ?>, T extends Type> implements RuntimeType {
+    private final @NonNull T javaType;
+    private final @NonNull S statement;
+
+    AbstractRuntimeType(final T bindingType, final S statement) {
+        this.javaType = requireNonNull(bindingType);
+        this.statement = requireNonNull(statement);
+    }
+
+    @Override
+    public final T javaType() {
+        return javaType;
+    }
+
+    @Override
+    public final S statement() {
+        return statement;
+    }
+
+    @Override
+    public final String toString() {
+        return MoreObjects.toStringHelper(this).add("javaType", javaType).add("statement", statement).toString();
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultActionRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultActionRuntimeType.java
new file mode 100644 (file)
index 0000000..84af4cc
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
+
+@Beta
+public final class DefaultActionRuntimeType extends AbstractCompositeRuntimeType<ActionEffectiveStatement>
+        implements ActionRuntimeType {
+    private final @NonNull InputRuntimeType input;
+    private final @NonNull OutputRuntimeType output;
+
+    public DefaultActionRuntimeType(final GeneratedType bindingType, final ActionEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+        input = child(children, InputRuntimeType.class);
+        output = child(children, OutputRuntimeType.class);
+    }
+
+    @Override
+    public InputRuntimeType input() {
+        return input;
+    }
+
+    @Override
+    public OutputRuntimeType output() {
+        return output;
+    }
+
+    private static <T extends RuntimeType> @NonNull T child(final List<RuntimeType> list, final Class<T> clazz) {
+        return list.stream().filter(clazz::isInstance).map(clazz::cast).findFirst().orElseThrow();
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnydataRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnydataRuntimeType.java
new file mode 100644 (file)
index 0000000..91b8450
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AnydataRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataEffectiveStatement;
+
+@Beta
+public final class DefaultAnydataRuntimeType extends AbstractGeneratedRuntimeType<AnydataEffectiveStatement>
+        implements AnydataRuntimeType {
+    public DefaultAnydataRuntimeType(final GeneratedType bindingType, final AnydataEffectiveStatement statement) {
+        super(bindingType, statement);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnyxmlRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnyxmlRuntimeType.java
new file mode 100644 (file)
index 0000000..127de3a
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AnyxmlRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
+
+@Beta
+public final class DefaultAnyxmlRuntimeType extends AbstractGeneratedRuntimeType<AnyxmlEffectiveStatement>
+        implements AnyxmlRuntimeType {
+    public DefaultAnyxmlRuntimeType(final GeneratedType bindingType, final AnyxmlEffectiveStatement statement) {
+        super(bindingType, statement);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAugmentRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAugmentRuntimeType.java
new file mode 100644 (file)
index 0000000..3a0de76
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+
+@Beta
+public final class DefaultAugmentRuntimeType extends AbstractCompositeRuntimeType<AugmentEffectiveStatement>
+        implements AugmentRuntimeType {
+    public DefaultAugmentRuntimeType(final GeneratedType bindingType, final AugmentEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultBindingRuntimeTypes.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultBindingRuntimeTypes.java
new file mode 100644 (file)
index 0000000..9bd748f
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSortedMap;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.GeneratedRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+
+/**
+ * The result of BindingGenerator run. Contains mapping between Types and SchemaNodes.
+ */
+public final class DefaultBindingRuntimeTypes implements BindingRuntimeTypes {
+    private final @NonNull EffectiveModelContext context;
+    private final ImmutableMap<QNameModule, ModuleRuntimeType> modulesByNamespace;
+    private final ImmutableSortedMap<String, ModuleRuntimeType> modulesByPackage;
+    private final ImmutableMap<QName, IdentityRuntimeType> identities;
+    private final ImmutableMap<QName, OutputRuntimeType> rpcOutputs;
+    private final ImmutableMap<QName, InputRuntimeType> rpcInputs;
+    private final ImmutableMap<JavaTypeName, RuntimeType> types;
+
+    public DefaultBindingRuntimeTypes(final EffectiveModelContext context,
+            final Map<QNameModule, ModuleRuntimeType> modules, final Map<JavaTypeName, RuntimeType> types,
+            final Map<QName, IdentityRuntimeType> identities, final Map<QName, InputRuntimeType> rpcInputs,
+            final Map<QName, OutputRuntimeType> rpcOutputs) {
+        this.context = requireNonNull(context);
+        this.identities = ImmutableMap.copyOf(identities);
+        this.types = ImmutableMap.copyOf(types);
+        this.rpcInputs = ImmutableMap.copyOf(rpcInputs);
+        this.rpcOutputs = ImmutableMap.copyOf(rpcOutputs);
+
+        modulesByNamespace = ImmutableMap.copyOf(modules);
+        modulesByPackage = ImmutableSortedMap.copyOf(Maps.uniqueIndex(modules.values(),
+            module -> module.getIdentifier().packageName()));
+    }
+
+    @Override
+    public EffectiveModelContext getEffectiveModelContext() {
+        return context;
+    }
+
+    @Override
+    public Optional<IdentityRuntimeType> findIdentity(final QName qname) {
+        return Optional.ofNullable(identities.get(requireNonNull(qname)));
+    }
+
+    @Override
+    public Optional<RuntimeType> findSchema(final JavaTypeName typeName) {
+        return Optional.ofNullable(types.get(requireNonNull(typeName)));
+    }
+
+    @Override
+    public GeneratedRuntimeType bindingChild(final JavaTypeName typeName) {
+        // The type can actually specify a sub-package, hence we to perform an inexact lookup
+        final var entry = modulesByPackage.floorEntry(typeName.packageName());
+        return entry == null ? null : entry.getValue().bindingChild(typeName);
+    }
+
+    @Override
+    public RuntimeType schemaTreeChild(final QName qname) {
+        final var module = modulesByNamespace.get(qname.getModule());
+        return module == null ? null : module.schemaTreeChild(qname);
+    }
+
+    @Override
+    public Optional<InputRuntimeType> findRpcInput(final QName rpcName) {
+        return Optional.ofNullable(rpcInputs.get(requireNonNull(rpcName)));
+    }
+
+    @Override
+    public Optional<OutputRuntimeType> findRpcOutput(final QName rpcName) {
+        return Optional.ofNullable(rpcOutputs.get(requireNonNull(rpcName)));
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("modules", modulesByNamespace.keySet())
+            .add("identities", identities.size())
+            .add("types", types.size())
+            .toString();
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultContainerRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultContainerRuntimeType.java
new file mode 100644 (file)
index 0000000..3a95847
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+
+@Beta
+public final class DefaultContainerRuntimeType extends AbstractCompositeRuntimeType<ContainerEffectiveStatement>
+        implements ContainerRuntimeType {
+    public DefaultContainerRuntimeType(final GeneratedType bindingType, final ContainerEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultGroupingRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultGroupingRuntimeType.java
new file mode 100644 (file)
index 0000000..42f9efe
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.GroupingRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.GroupingEffectiveStatement;
+
+@Beta
+public final class DefaultGroupingRuntimeType extends AbstractCompositeRuntimeType<GroupingEffectiveStatement>
+        implements GroupingRuntimeType {
+    public DefaultGroupingRuntimeType(final GeneratedType bindingType, final GroupingEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultIdentityRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultIdentityRuntimeType.java
new file mode 100644 (file)
index 0000000..50ebf94
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
+
+@Beta
+public final class DefaultIdentityRuntimeType extends AbstractGeneratedRuntimeType<IdentityEffectiveStatement>
+        implements IdentityRuntimeType {
+    public DefaultIdentityRuntimeType(final GeneratedType bindingType, final IdentityEffectiveStatement statement) {
+        super(bindingType, statement);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultInputRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultInputRuntimeType.java
new file mode 100644 (file)
index 0000000..3b6eda8
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+
+@Beta
+public final class DefaultInputRuntimeType extends AbstractCompositeRuntimeType<InputEffectiveStatement>
+        implements InputRuntimeType {
+    public DefaultInputRuntimeType(final GeneratedType bindingType, final InputEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultKeyRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultKeyRuntimeType.java
new file mode 100644 (file)
index 0000000..18a03cc
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.mdsal.binding.runtime.api.KeyRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
+
+@Beta
+public final class DefaultKeyRuntimeType extends AbstractObjectRuntimeType<KeyEffectiveStatement>
+        implements KeyRuntimeType {
+    public DefaultKeyRuntimeType(final GeneratedTransferObject bindingType, final KeyEffectiveStatement statement) {
+        super(bindingType, statement);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafListRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafListRuntimeType.java
new file mode 100644 (file)
index 0000000..165c808
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.LeafListRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
+
+@Beta
+public final class DefaultLeafListRuntimeType extends AbstractRuntimeType<LeafListEffectiveStatement, Type>
+        implements LeafListRuntimeType {
+    public DefaultLeafListRuntimeType(final Type bindingType, final LeafListEffectiveStatement statement) {
+        super(bindingType, statement);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafRuntimeType.java
new file mode 100644 (file)
index 0000000..badccf5
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.LeafRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
+
+@Beta
+public final class DefaultLeafRuntimeType extends AbstractRuntimeType<LeafEffectiveStatement, Type>
+        implements LeafRuntimeType {
+    public DefaultLeafRuntimeType(final Type bindingType, final LeafEffectiveStatement statement) {
+        super(bindingType, statement);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultListRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultListRuntimeType.java
new file mode 100644 (file)
index 0000000..c6e4bca
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.KeyRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
+
+@Beta
+public final class DefaultListRuntimeType extends AbstractCompositeRuntimeType<ListEffectiveStatement>
+        implements ListRuntimeType {
+    private final KeyRuntimeType keyType;
+
+    public DefaultListRuntimeType(final GeneratedType bindingType, final ListEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments, final KeyRuntimeType keyType) {
+        super(bindingType, statement, children, augments);
+        this.keyType = keyType;
+    }
+
+    @Override
+    public KeyRuntimeType keyType() {
+        return keyType;
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultModuleRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultModuleRuntimeType.java
new file mode 100644 (file)
index 0000000..433107a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
+
+@Beta
+public final class DefaultModuleRuntimeType extends AbstractCompositeRuntimeType<ModuleEffectiveStatement>
+        implements ModuleRuntimeType {
+    public DefaultModuleRuntimeType(final GeneratedType bindingType, final ModuleEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultNotificationRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultNotificationRuntimeType.java
new file mode 100644 (file)
index 0000000..ef7866b
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
+
+@Beta
+public final class DefaultNotificationRuntimeType extends AbstractCompositeRuntimeType<NotificationEffectiveStatement>
+        implements NotificationRuntimeType {
+    public DefaultNotificationRuntimeType(final GeneratedType bindingType,
+            final NotificationEffectiveStatement statement, final List<RuntimeType> children,
+            final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultOutputRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultOutputRuntimeType.java
new file mode 100644 (file)
index 0000000..0e4d150
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+
+@Beta
+public final class DefaultOutputRuntimeType extends AbstractCompositeRuntimeType<OutputEffectiveStatement>
+        implements OutputRuntimeType {
+    public DefaultOutputRuntimeType(final GeneratedType bindingType, final OutputEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultTypedefRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultTypedefRuntimeType.java
new file mode 100644 (file)
index 0000000..c63ae5c
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.TypedefRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
+
+@Beta
+public final class DefaultTypedefRuntimeType extends AbstractGeneratedRuntimeType<TypedefEffectiveStatement>
+        implements TypedefRuntimeType {
+    public DefaultTypedefRuntimeType(final GeneratedType bindingType, final TypedefEffectiveStatement statement) {
+        super(bindingType, statement);
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedCaseRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedCaseRuntimeType.java
new file mode 100644 (file)
index 0000000..271f98a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+
+@Beta
+public final class DerivedCaseRuntimeType extends AbstractCaseRuntimeType {
+    private final @NonNull CaseRuntimeType originalType;
+
+    public DerivedCaseRuntimeType(final GeneratedType bindingType, final CaseEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments,
+            final CaseRuntimeType originalType) {
+        super(bindingType, statement, children, augments);
+        this.originalType = requireNonNull(originalType);
+    }
+
+    @Override
+    public @NonNull CaseRuntimeType originalType() {
+        return originalType;
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedChoiceRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedChoiceRuntimeType.java
new file mode 100644 (file)
index 0000000..3a81294
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Iterables;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+
+@Beta
+public final class DerivedChoiceRuntimeType extends AbstractChoiceRuntimeType {
+    private final @NonNull ChoiceRuntimeType originalType;
+
+    public DerivedChoiceRuntimeType(final GeneratedType bindingType, final ChoiceEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments,
+            final ChoiceRuntimeType originalType) {
+        super(bindingType, statement, children, augments);
+        this.originalType = requireNonNull(originalType);
+    }
+
+    @Override
+    public @NonNull ChoiceRuntimeType originalType() {
+        return originalType;
+    }
+
+    @Override
+    public Collection<CaseRuntimeType> additionalCaseChildren() {
+        final var myJavaTypes = Collections2.transform(validCaseChildren(), CaseRuntimeType::getIdentifier);
+        final var result = new ArrayList<CaseRuntimeType>();
+        for (var caseType : Iterables.concat(originalType.validCaseChildren(), originalType.additionalCaseChildren())) {
+            if (!myJavaTypes.contains(caseType.getIdentifier())) {
+                result.add(caseType);
+            }
+        }
+        return result;
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalCaseRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalCaseRuntimeType.java
new file mode 100644 (file)
index 0000000..200518d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+
+@Beta
+public final class OriginalCaseRuntimeType extends AbstractCaseRuntimeType {
+    public OriginalCaseRuntimeType(final GeneratedType bindingType, final CaseEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+        super(bindingType, statement, children, augments);
+    }
+
+    @Override
+    public CaseRuntimeType originalType() {
+        return null;
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalChoiceRuntimeType.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalChoiceRuntimeType.java
new file mode 100644 (file)
index 0000000..f996e42
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+
+@Beta
+public final class OriginalChoiceRuntimeType extends AbstractChoiceRuntimeType {
+    private final @NonNull ImmutableList<CaseRuntimeType> augmentedCases;
+
+    public OriginalChoiceRuntimeType(final GeneratedType bindingType, final ChoiceEffectiveStatement statement,
+            final List<RuntimeType> children, final List<AugmentRuntimeType> augments,
+            final List<CaseRuntimeType> augmentedCases) {
+        super(bindingType, statement, children, augments);
+        this.augmentedCases = ImmutableList.copyOf(augmentedCases);
+    }
+
+    @Override
+    public ChoiceRuntimeType originalType() {
+        return null;
+    }
+
+    @Override
+    public Collection<CaseRuntimeType> additionalCaseChildren() {
+        return augmentedCases;
+    }
+}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeChild.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeChild.java
deleted file mode 100644 (file)
index e3c409c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.generator.impl.tree;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.generator.impl.reactor.AbstractExplicitGenerator;
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
-
-/**
- * An object reflecting a YANG {@code schema node}.
- *
- * @param <S> Concrete {@link SchemaTreeEffectiveStatement} type
- * @param <G> Concrete {@link AbstractExplicitGenerator} type
- */
-// FIXME: do not reference Generator once we have the codegen and runtime views well-defined
-public interface SchemaTreeChild<S extends SchemaTreeEffectiveStatement<?>,
-        G extends AbstractExplicitGenerator<S> & SchemaTreeChild<S, G>> extends Identifiable<QName> {
-    @Override
-    default QName getIdentifier() {
-        return statement().argument();
-    }
-
-    /**
-     * Return the effective YANG statement being represented by this object.
-     *
-     * @return A YANG statement
-     */
-    @NonNull S statement();
-
-    /**
-     * Return the generator responsible for handling the binding type view of this statement. Note that the statement
-     * returned by {@code generator().statement()} may differ from the statement returned by {@link #statement()}.
-     *
-     * @return Underlying binding generator
-     * @throws IllegalStateException if the generator has not been resolved yet
-     */
-    @NonNull G generator();
-}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeParent.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeParent.java
deleted file mode 100644 (file)
index d846bef..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.generator.impl.tree;
-
-import java.util.List;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-
-/**
- * A parent containing a number of {@link SchemaTreeChild} objects.
- *
- * @param <S> Concrete {@link EffectiveStatement} type
- */
-// FIXME: S extends SchemaTreeAwareStatement ... once AugmentEffectiveStatement implements that
-public interface SchemaTreeParent<S extends EffectiveStatement<?, ?>> {
-    /*
-     * Immutable view of children of this object along the {@code schema tree} child axis.
-     *
-     * @return Immutable view of this objects children along the {@code schema tree} child axis.
-     */
-    @NonNull List<SchemaTreeChild<?, ?>> schemaTreeChildren();
-}
diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/StatementRepresentation.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/StatementRepresentation.java
new file mode 100644 (file)
index 0000000..f3127c4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.generator.impl.tree;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+/**
+ * An object representing a view on a particular {@link EffectiveStatement} with a potential to have a
+ * {@link RuntimeType} representation as well.
+ *
+ * @param <S> Statement type
+ * @param <R> Runtime type
+ */
+public interface StatementRepresentation<S extends EffectiveStatement<?, ?>> {
+    /**
+     * Return the effective YANG statement being represented by this object.
+     *
+     * @return A YANG statement
+     */
+    @NonNull S statement();
+}
index 3a529c60558b57aa2270240aaf7c82cff8a161bc..7ce90788f2b7bf5ceb9e47c35911337df432ea06 100644 (file)
@@ -47,14 +47,12 @@ public class Mdsal600Test {
         // The real thing, used to kaboom
         final var runtimeTypes = new DefaultBindingRuntimeGenerator().generateTypeMapping(models);
 
-        // Verify schema-to-type lookup
-        final var barType = runtimeTypes.findType(barTypeSchema).orElseThrow();
-        final var bazType = runtimeTypes.findType(bazTypeSchema).orElseThrow();
-        assertEquals(FOO.createEnclosed("Bar"), barType.getIdentifier());
-        assertEquals(FOO.createEnclosed("Baz"), bazType.getIdentifier());
-
         // Verify type-to-schema lookup
-        assertSame(barTypeSchema, runtimeTypes.findSchema(barType).orElseThrow());
-        assertSame(bazTypeSchema, runtimeTypes.findSchema(bazType).orElseThrow());
+        final var barType = runtimeTypes.findSchema(FOO.createEnclosed("Bar")).orElseThrow();
+        final var bazType = runtimeTypes.findSchema(FOO.createEnclosed("Baz")).orElseThrow();
+
+        // Verify underlying schema lookup
+        assertSame(barSchema, barType.statement());
+        assertSame(bazSchema, bazType.statement());
     }
 }
index 511c9635eb48bc7bd33f993e90a71987b8ee8d41..b71c755d990b34cf8cdc4e528d1ec8ce9afe147b 100644 (file)
     <packaging>bundle</packaging>
 
     <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-data-api</artifactId>
+            <artifactId>concepts</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-repo-spi</artifactId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-api</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-model-util</artifactId>
+            <artifactId>yang-repo-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-repo-spi</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.mdsal</groupId>
index 043ca184c03f76b70aec7ca4210668e2779a4572..3c37cf6762d63dc145d4ee823874d9604ee6fa47 100644 (file)
@@ -8,12 +8,13 @@
 module org.opendaylight.mdsal.binding.runtime.api {
     exports org.opendaylight.mdsal.binding.runtime.api;
 
-    requires transitive org.opendaylight.yangtools.yang.data.api;
+    requires transitive org.opendaylight.yangtools.concepts;
+    requires transitive org.opendaylight.yangtools.yang.common;
     requires transitive org.opendaylight.yangtools.yang.model.api;
     requires transitive org.opendaylight.yangtools.yang.binding;
+    requires transitive org.opendaylight.yangtools.yang.repo.api;
+    requires transitive org.opendaylight.yangtools.yang.repo.spi;
     requires transitive org.opendaylight.mdsal.binding.model.api;
-    requires org.opendaylight.yangtools.yang.model.util;
-    requires org.opendaylight.yangtools.yang.repo.spi;
     requires org.slf4j;
 
     // Annotations
index f7587ee913330b56327c010e913263794cc779ba..dbed269c4af0d895127351403becc4af7433da88 100644 (file)
 package org.opendaylight.mdsal.binding.runtime.api;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
 
 import com.google.common.annotations.Beta;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import java.util.AbstractMap.SimpleEntry;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-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.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.MethodSignature;
-import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
-import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
 import org.opendaylight.yangtools.yang.binding.Action;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.RpcInput;
+import org.opendaylight.yangtools.yang.binding.RpcOutput;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 
 /**
  * Runtime Context for Java YANG Binding classes. It provides information derived from the backing effective model,
  * which is not captured in generated classes (and hence cannot be obtained from {@code BindingReflections}.
- *
- * <p>Some of this information are for example list of all available children for cases
- * {@link #getChoiceCaseChildren(DataNodeContainer)}, since choices are augmentable and new choices may be introduced
- * by additional models. Same goes for all possible augmentations.
  */
 @Beta
 public abstract class AbstractBindingRuntimeContext implements BindingRuntimeContext {
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractBindingRuntimeContext.class);
-
     private final LoadingCache<QName, Class<?>> identityClasses = CacheBuilder.newBuilder().weakValues().build(
         new CacheLoader<QName, Class<?>>() {
             @Override
             public Class<?> load(final QName key) {
-                final Optional<Type> identityType = getTypes().findIdentity(key);
-                checkArgument(identityType.isPresent(), "Supplied QName %s is not a valid identity", key);
+                final var type = getTypes().findIdentity(key).orElseThrow(
+                    () -> new IllegalArgumentException("Supplied QName " + key + " is not a valid identity"));
                 try {
-                    return loadClass(identityType.get());
+                    return loadClass(type.getIdentifier());
                 } catch (final ClassNotFoundException e) {
-                    throw new IllegalArgumentException("Required class " + identityType + "was not found.", e);
+                    throw new IllegalArgumentException("Required class " + type + " was not found.", e);
                 }
             }
         });
 
     @Override
-    public final <T extends Augmentation<?>> AugmentationSchemaNode getAugmentationDefinition(final Class<T> augClass) {
-        return getTypes().findAugmentation(Type.of(augClass)).orElse(null);
+    public final <T extends Augmentation<?>> AugmentRuntimeType getAugmentationDefinition(final Class<T> augClass) {
+        return getTypes().findSchema(JavaTypeName.create(augClass))
+            .filter(AugmentRuntimeType.class::isInstance)
+            .map(AugmentRuntimeType.class::cast)
+            .orElse(null);
     }
 
     @Override
-    public final DataSchemaNode getSchemaDefinition(final Class<?> cls) {
+    public final CompositeRuntimeType getSchemaDefinition(final Class<?> cls) {
         checkArgument(!Augmentation.class.isAssignableFrom(cls), "Supplied class must not be an augmentation (%s is)",
             cls);
         checkArgument(!Action.class.isAssignableFrom(cls), "Supplied class must not be an action (%s is)", cls);
         checkArgument(!Notification.class.isAssignableFrom(cls), "Supplied class must not be a notification (%s is)",
             cls);
-        return (DataSchemaNode) getTypes().findSchema(Type.of(cls)).orElse(null);
-    }
-
-    @Override
-    public final DataSchemaNode findChildSchemaDefinition(final DataNodeContainer parentSchema,
-            final QNameModule parentNamespace, final Class<?> childClass) {
-        final DataSchemaNode origDef = getSchemaDefinition(childClass);
-        if (origDef == null) {
-            // Weird, the child does not have an associated definition
-            return null;
-        }
-
-        // Direct instantiation or use in same module in which grouping was defined.
-        final QName origName = origDef.getQName();
-        final DataSchemaNode sameName = parentSchema.dataChildByName(origName);
-        if (sameName != null) {
-            // Check if it is:
-            // - exactly same schema node, or
-            // - instantiated node was added via uses statement and is instantiation of same grouping
-            if (origDef.equals(sameName) || origDef.equals(getRootOriginalIfPossible(sameName))) {
-                return sameName;
-            }
-
-            // Node has same name, but clearly is different
-            return null;
-        }
-
-        // We are looking for instantiation via uses in other module
-        final DataSchemaNode potential = parentSchema.dataChildByName(origName.bindTo(parentNamespace));
-        // We check if it is really instantiated from same definition as class was derived
-        if (potential != null && origDef.equals(getRootOriginalIfPossible(potential))) {
-            return potential;
-        }
-        return null;
-    }
-
-    private static @Nullable SchemaNode getRootOriginalIfPossible(final SchemaNode data) {
-        SchemaNode previous = null;
-        SchemaNode next = originalNodeOf(data);
-        while (next != null) {
-            previous = next;
-            next = originalNodeOf(next);
-        }
-        return previous;
+        return (CompositeRuntimeType) getTypes().findSchema(JavaTypeName.create(cls)).orElse(null);
     }
 
     @Override
-    public final ActionDefinition getActionDefinition(final Class<? extends Action<?, ?, ?>> cls) {
-        return (ActionDefinition) getTypes().findSchema(Type.of(cls)).orElse(null);
+    public final ActionRuntimeType getActionDefinition(final Class<? extends Action<?, ?, ?>> cls) {
+        return (ActionRuntimeType) getTypes().findSchema(JavaTypeName.create(cls)).orElse(null);
     }
 
     @Override
-    public final Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
-            final DataNodeContainer target, final Class<? extends Augmentation<?>> aug) {
-        final AugmentationSchemaNode origSchema = getAugmentationDefinition(aug);
-        checkArgument(origSchema != null, "Augmentation %s is not known in current schema context", aug);
-        /*
-         * FIXME: Validate augmentation schema lookup
-         *
-         * Currently this algorithm, does not verify if instantiated child nodes
-         * are real one derived from augmentation schema. The problem with
-         * full validation is, if user used copy builders, he may use
-         * augmentation which was generated for different place.
-         *
-         * If this augmentations have same definition, we emit same identifier
-         * with data and it is up to underlying user to validate data.
-         *
-         */
-        final Set<QName> childNames = new HashSet<>();
-        final Set<DataSchemaNode> realChilds = new HashSet<>();
-        for (final DataSchemaNode child : origSchema.getChildNodes()) {
-            final DataSchemaNode dataChildQNname = target.dataChildByName(child.getQName());
-            final String childLocalName = child.getQName().getLocalName();
-            if (dataChildQNname == null) {
-                for (DataSchemaNode dataSchemaNode : target.getChildNodes()) {
-                    if (childLocalName.equals(dataSchemaNode.getQName().getLocalName())) {
-                        realChilds.add(dataSchemaNode);
-                        childNames.add(dataSchemaNode.getQName());
-                    }
-                }
-            } else {
-                realChilds.add(dataChildQNname);
-                childNames.add(child.getQName());
-            }
-        }
-
-        final AugmentationIdentifier identifier = AugmentationIdentifier.create(childNames);
-        final AugmentationSchemaNode proxy = new EffectiveAugmentationSchema(origSchema, realChilds);
-        return new SimpleEntry<>(identifier, proxy);
+    public final RuntimeType getTypeWithSchema(final Class<?> type) {
+        return getTypes().findSchema(JavaTypeName.create(type))
+            .orElseThrow(() -> new IllegalArgumentException("Failed to find schema for " + type));
     }
 
     @Override
-    public final Optional<CaseSchemaNode> getCaseSchemaDefinition(final ChoiceSchemaNode schema,
-            final Class<?> childClass) {
-        final DataSchemaNode origSchema = getSchemaDefinition(childClass);
-        checkArgument(origSchema instanceof CaseSchemaNode, "Supplied schema %s is not case.", origSchema);
-
-        /* FIXME: Make sure that if there are multiple augmentations of same
-         * named case, with same structure we treat it as equals
-         * this is due property of Binding specification and copy builders
-         * that user may be unaware that he is using incorrect case
-         * which was generated for choice inside grouping.
-         */
-        return findInstantiatedCase(schema, (CaseSchemaNode) origSchema);
+    public final Class<?> getClassForSchema(final Absolute schema) {
+        final var child = getTypes().schemaTreeChild(schema);
+        checkArgument(child != null, "Failed to find binding type for %s", schema);
+        return loadClass(child);
     }
 
     @Override
-    public final Entry<GeneratedType, WithStatus> getTypeWithSchema(final Class<?> type) {
-        return getTypeWithSchema(getTypes(), Type.of(type));
-    }
-
-    private static @NonNull Entry<GeneratedType, WithStatus> getTypeWithSchema(final BindingRuntimeTypes types,
-            final Type referencedType) {
-        final WithStatus schema = types.findSchema(referencedType).orElseThrow(
-            () -> new NullPointerException("Failed to find schema for type " + referencedType));
-        final Type definedType = types.findType(schema).orElseThrow(
-            () -> new NullPointerException("Failed to find defined type for " + referencedType + " schema " + schema));
-
-        if (definedType instanceof GeneratedTypeBuilder) {
-            return new SimpleEntry<>(((GeneratedTypeBuilder) definedType).build(), schema);
-        }
-        checkArgument(definedType instanceof GeneratedType, "Type %s is not a GeneratedType", referencedType);
-        return new SimpleEntry<>((GeneratedType) definedType, schema);
+    public final Class<?> getIdentityClass(final QName input) {
+        return identityClasses.getUnchecked(input);
     }
 
     @Override
-    public final Map<Type, Entry<Type, Type>> getChoiceCaseChildren(final DataNodeContainer schema) {
-        return getChoiceCaseChildren(getTypes(), schema);
-    }
-
-    private static @NonNull ImmutableMap<Type, Entry<Type, Type>> getChoiceCaseChildren(final BindingRuntimeTypes types,
-            final DataNodeContainer schema) {
-        final Map<Type, Entry<Type, Type>> childToCase = new HashMap<>();
-
-        for (final ChoiceSchemaNode choice :  Iterables.filter(schema.getChildNodes(), ChoiceSchemaNode.class)) {
-            final ChoiceSchemaNode originalChoice = getOriginalSchema(choice);
-            final Optional<Type> optType = types.findType(originalChoice);
-            checkState(optType.isPresent(), "Failed to find generated type for choice %s", originalChoice);
-            final Type choiceType = optType.get();
-
-            for (Type caze : types.findCases(choiceType)) {
-                final Entry<Type,Type> caseIdentifier = new SimpleEntry<>(choiceType, caze);
-                final HashSet<Type> caseChildren = new HashSet<>();
-                if (caze instanceof GeneratedTypeBuilder) {
-                    caze = ((GeneratedTypeBuilder) caze).build();
-                }
-                collectAllContainerTypes((GeneratedType) caze, caseChildren);
-                for (final Type caseChild : caseChildren) {
-                    childToCase.put(caseChild, caseIdentifier);
-                }
-            }
-        }
-        return ImmutableMap.copyOf(childToCase);
+    public final Class<? extends RpcInput> getRpcInput(final QName rpcName) {
+        return loadClass(getTypes().findRpcInput(rpcName)
+            .orElseThrow(() -> new IllegalArgumentException("Failed to find RpcInput for " + rpcName)))
+            .asSubclass(RpcInput.class);
     }
 
     @Override
-    public final Set<Class<?>> getCases(final Class<?> choice) {
-        final Collection<Type> cazes = getTypes().findCases(Type.of(choice));
-        final Set<Class<?>> ret = new HashSet<>(cazes.size());
-        for (final Type caze : cazes) {
-            try {
-                ret.add(loadClass(caze));
-            } catch (final ClassNotFoundException e) {
-                LOG.warn("Failed to load class for case {}, ignoring it", caze, e);
-            }
-        }
-        return ret;
+    public final Class<? extends RpcOutput> getRpcOutput(final QName rpcName) {
+        return loadClass(getTypes().findRpcOutput(rpcName)
+            .orElseThrow(() -> new IllegalArgumentException("Failed to find RpcOutput for " + rpcName)))
+            .asSubclass(RpcOutput.class);
     }
 
-    @Override
-    public final Class<?> getClassForSchema(final SchemaNode childSchema) {
-        final SchemaNode origSchema = getOriginalSchema(childSchema);
-        final Optional<Type> clazzType = getTypes().findType(origSchema);
-        checkArgument(clazzType.isPresent(), "Failed to find binding type for %s (original %s)",
-            childSchema, origSchema);
-
+    private Class<?> loadClass(final RuntimeType type) {
         try {
-            return loadClass(clazzType.get());
+            return loadClass(type.javaType());
         } catch (final ClassNotFoundException e) {
             throw new IllegalStateException(e);
         }
     }
-
-    @Override
-    public final ImmutableMap<AugmentationIdentifier, Type> getAvailableAugmentationTypes(
-            final DataNodeContainer container) {
-        if (container instanceof AugmentationTarget) {
-            final var augmentations = ((AugmentationTarget) container).getAvailableAugmentations();
-            if (!augmentations.isEmpty()) {
-                final var identifierToType = new HashMap<AugmentationIdentifier, Type>();
-                final var types = getTypes();
-                for (var augment : augmentations) {
-                    types.findOriginalAugmentationType(augment).ifPresent(augType -> {
-                        identifierToType.put(getAugmentationIdentifier(augment), augType);
-                    });
-                }
-                return ImmutableMap.copyOf(identifierToType);
-            }
-        }
-        return ImmutableMap.of();
-    }
-
-    @Override
-    public final Class<?> getIdentityClass(final QName input) {
-        return identityClasses.getUnchecked(input);
-    }
-
-    private static AugmentationIdentifier getAugmentationIdentifier(final AugmentationSchemaNode augment) {
-        // FIXME: use DataSchemaContextNode.augmentationIdentifierFrom() once it does caching
-        return AugmentationIdentifier.create(augment.getChildNodes().stream().map(DataSchemaNode::getQName)
-            .collect(ImmutableSet.toImmutableSet()));
-    }
-
-    private static Set<Type> collectAllContainerTypes(final GeneratedType type, final Set<Type> collection) {
-        for (final MethodSignature definition : type.getMethodDefinitions()) {
-            Type childType = definition.getReturnType();
-            if (childType instanceof ParameterizedType) {
-                childType = ((ParameterizedType) childType).getActualTypeArguments()[0];
-            }
-            if (childType instanceof GeneratedType || childType instanceof GeneratedTypeBuilder) {
-                collection.add(childType);
-            }
-        }
-        for (final Type parent : type.getImplements()) {
-            if (parent instanceof GeneratedType) {
-                collectAllContainerTypes((GeneratedType) parent, collection);
-            }
-        }
-        return collection;
-    }
-
-    private static <T extends SchemaNode> T getOriginalSchema(final T choice) {
-        @SuppressWarnings("unchecked")
-        final T original = (T) originalNodeOf(choice);
-        if (original != null) {
-            return original;
-        }
-        return choice;
-    }
-
-    private static @NonNull Optional<CaseSchemaNode> findInstantiatedCase(final ChoiceSchemaNode instantiatedChoice,
-            final CaseSchemaNode originalDefinition) {
-        CaseSchemaNode potential = instantiatedChoice.findCase(originalDefinition.getQName()).orElse(null);
-        if (originalDefinition.equals(potential)) {
-            return Optional.of(potential);
-        }
-        if (potential != null) {
-            SchemaNode potentialRoot = originalNodeOf(potential);
-            if (originalDefinition.equals(potentialRoot)) {
-                return Optional.of(potential);
-            }
-        }
-
-        // We try to find case by name, then lookup its root definition
-        // and compare it with original definition
-        // This solves case, if choice was inside grouping
-        // which was used in different module and thus namespaces are
-        // different, but local names are still same.
-        //
-        // Still we need to check equality of definition, because local name is not
-        // sufficient to uniquelly determine equality of cases
-        //
-        for (CaseSchemaNode caze : instantiatedChoice.findCaseNodes(originalDefinition.getQName().getLocalName())) {
-            if (originalDefinition.equals(originalNodeOf(caze))) {
-                return Optional.of(caze);
-            }
-        }
-        return Optional.empty();
-    }
-
-    private static @Nullable SchemaNode originalNodeOf(final SchemaNode node) {
-        return node instanceof DerivableSchemaNode ? ((DerivableSchemaNode) node).getOriginal().orElse(null) : null;
-    }
 }
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ActionRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ActionRuntimeType.java
new file mode 100644 (file)
index 0000000..7113d0d
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code action} statement.
+ */
+@Beta
+public interface ActionRuntimeType extends InvokableRuntimeType {
+    @Override
+    ActionEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnydataRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnydataRuntimeType.java
new file mode 100644 (file)
index 0000000..5119880
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code anydata} statement.
+ */
+@Beta
+public interface AnydataRuntimeType extends OpaqueRuntimeType {
+    @Override
+    AnydataEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnyxmlRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnyxmlRuntimeType.java
new file mode 100644 (file)
index 0000000..bb232bf
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code anyxml} statement.
+ */
+@Beta
+public interface AnyxmlRuntimeType extends OpaqueRuntimeType {
+    @Override
+    AnyxmlEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AugmentRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AugmentRuntimeType.java
new file mode 100644 (file)
index 0000000..479fe94
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code augment} statement.
+ */
+@Beta
+public interface AugmentRuntimeType extends CompositeRuntimeType, DataRuntimeType {
+    @Override
+    AugmentEffectiveStatement statement();
+}
index 9fe1e546a0ee3098a46a267d3717e56536eab49a..109656a7bd6337f0b9eb142ddba6d2febf7f6d11 100644 (file)
@@ -8,47 +8,37 @@
 package org.opendaylight.mdsal.binding.runtime.api;
 
 import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
-import java.util.Map.Entry;
-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.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.binding.Action;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.RpcInput;
+import org.opendaylight.yangtools.yang.binding.RpcOutput;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 
 /**
  * Runtime Context for Java YANG Binding classes. It provides information derived from the backing effective model,
  * which is not captured in generated classes (and hence cannot be obtained from {@code BindingReflections}.
- *
- * <p>Some of this information are for example list of all available children for cases
- * {@link #getChoiceCaseChildren(DataNodeContainer)}, since choices are augmentable and new choices may be introduced
- * by additional models. Same goes for all possible augmentations.
  */
 @Beta
 // FIXME: refactor return to follow foo()/getFoo()/findFoo() naming
 public interface BindingRuntimeContext extends EffectiveModelContextProvider, Immutable {
     @NonNull BindingRuntimeTypes getTypes();
 
-    @NonNull <T> Class<T> loadClass(Type type) throws ClassNotFoundException;
+    @NonNull <T> Class<T> loadClass(JavaTypeName type) throws ClassNotFoundException;
+
+    default @NonNull <T> Class<T> loadClass(final Type type) throws ClassNotFoundException {
+        return loadClass(type.getIdentifier());
+    }
 
     @Override
     default EffectiveModelContext getEffectiveModelContext() {
@@ -66,16 +56,12 @@ public interface BindingRuntimeContext extends EffectiveModelContextProvider, Im
      * which may be present in runtime for them, thus returned schema is unsuitable
      * for use for validation of data.
      *
-     * <p>For retrieving {@link AugmentationSchemaNode}, which will contains
-     * full model for child nodes, you should use method
-     * {@link #getResolvedAugmentationSchema(DataNodeContainer, Class)}
-     * which will return augmentation schema derived from supplied augmentation target
-     * schema.
-     *
+     * @param <T> Augmentation class type
      * @param augClass Augmentation class
      * @return Schema of augmentation or null if augmentation is not known in this context
+     * @throws NullPointerException if {@code augClass} is null
      */
-    <T extends Augmentation<?>> @Nullable AugmentationSchemaNode getAugmentationDefinition(Class<T> augClass);
+    <T extends Augmentation<?>> @Nullable AugmentRuntimeType getAugmentationDefinition(Class<T> augClass);
 
     /**
      * Returns defining {@link DataSchemaNode} for supplied class.
@@ -90,27 +76,9 @@ public interface BindingRuntimeContext extends EffectiveModelContextProvider, Im
      * @param cls Class which represents list, container, choice or case.
      * @return Schema node, from which class was generated.
      */
-    @Nullable DataSchemaNode getSchemaDefinition(Class<?> cls);
-
-    // FIXME: document this thing and perhaps move it to BindingRuntimeTypes?
-    @Nullable DataSchemaNode findChildSchemaDefinition(DataNodeContainer parentSchema, QNameModule parentNamespace,
-        Class<?> childClass);
-
-    @Nullable ActionDefinition getActionDefinition(Class<? extends Action<?, ?, ?>> cls);
-
-    @NonNull Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
-            DataNodeContainer target, Class<? extends Augmentation<?>> aug);
+    @Nullable CompositeRuntimeType getSchemaDefinition(Class<?> cls);
 
-    /**
-     * Returns resolved case schema for supplied class.
-     *
-     * @param schema Resolved parent choice schema
-     * @param childClass Class representing case.
-     * @return Optionally a resolved case schema,.empty if the choice is not legal in
-     *         the given context.
-     * @throws IllegalArgumentException If supplied class does not represent case.
-     */
-    @NonNull Optional<CaseSchemaNode> getCaseSchemaDefinition(ChoiceSchemaNode schema, Class<?> childClass);
+    @Nullable ActionRuntimeType getActionDefinition(Class<? extends Action<?, ?, ?>> cls);
 
     /**
      * Returns schema ({@link DataSchemaNode}, {@link AugmentationSchemaNode} or {@link TypeDefinition})
@@ -123,23 +91,14 @@ public interface BindingRuntimeContext extends EffectiveModelContextProvider, Im
      *     {@link DataSchemaNode}, {@link AugmentationSchemaNode} or {@link TypeDefinition}
      *     which was used to generate supplied class.
      */
-    @NonNull Entry<GeneratedType, WithStatus> getTypeWithSchema(Class<?> type);
-
-    @NonNull Map<Type, Entry<Type, Type>> getChoiceCaseChildren(DataNodeContainer schema);
+    @NonNull RuntimeType getTypeWithSchema(Class<?> type);
 
-    @NonNull Set<Class<?>> getCases(Class<?> choice);
+    @NonNull Class<? extends RpcInput> getRpcInput(QName rpcName);
 
-    @NonNull Class<?> getClassForSchema(SchemaNode childSchema);
+    @NonNull Class<? extends RpcOutput> getRpcOutput(QName rpcName);
 
-    /**
-     * Return the mapping of a particular {@link DataNodeContainer}'s available augmentations. This method deals with
-     * resolving {@code uses foo { augment bar { ... } } } scenarios by returning the augmentation created for
-     * {@code grouping foo}'s Binding representation.
-     *
-     * @param container {@link DataNodeContainer} to examine
-     * @return a mapping from local {@link AugmentationIdentifier}s to their corresponding Binding augmentations
-     */
-    @NonNull ImmutableMap<AugmentationIdentifier, Type> getAvailableAugmentationTypes(DataNodeContainer container);
+    // FIXME: 9.0.0: this needs to accept an EffectiveStatementInference
+    @NonNull Class<?> getClassForSchema(Absolute schema);
 
     @NonNull Class<?> getIdentityClass(QName input);
 }
index d0ac16642ab2fbe5979223eccbdfe1f15bd1d7fb..73235013f51ca3d187b1708bdf65ae66dc2cd944 100644 (file)
@@ -8,33 +8,34 @@
 package org.opendaylight.mdsal.binding.runtime.api;
 
 import com.google.common.annotations.Beta;
-import com.google.common.collect.Multimap;
-import java.util.Collection;
 import java.util.Optional;
-import org.opendaylight.mdsal.binding.model.api.Type;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 
 /**
  * The result of BindingGenerator run. Contains mapping between Types and SchemaNodes.
  */
 @Beta
-public interface BindingRuntimeTypes extends EffectiveModelContextProvider, Immutable {
+public interface BindingRuntimeTypes extends EffectiveModelContextProvider, RuntimeTypeContainer, Immutable {
 
-    Optional<AugmentationSchemaNode> findAugmentation(Type type);
+    Optional<IdentityRuntimeType> findIdentity(QName qname);
 
-    Optional<Type> findIdentity(QName qname);
+    Optional<RuntimeType> findSchema(JavaTypeName typeName);
 
-    Optional<WithStatus> findSchema(Type type);
+    Optional<InputRuntimeType> findRpcInput(QName rpcName);
 
-    Optional<Type> findType(WithStatus schema);
+    Optional<OutputRuntimeType> findRpcOutput(QName rpcName);
 
-    Optional<Type> findOriginalAugmentationType(AugmentationSchemaNode augment);
-
-    Multimap<Type, Type> getChoiceToCases();
-
-    Collection<Type> findCases(Type choiceType);
+    default @Nullable RuntimeType schemaTreeChild(final Absolute path) {
+        final var it = path.getNodeIdentifiers().iterator();
+        var tmp = schemaTreeChild(it.next());
+        while (it.hasNext() && tmp instanceof RuntimeTypeContainer) {
+            tmp = ((RuntimeTypeContainer) tmp).schemaTreeChild(it.next());
+        }
+        return tmp;
+    }
 }
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CaseRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CaseRuntimeType.java
new file mode 100644 (file)
index 0000000..8818903
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code case} statement.
+ */
+@Beta
+public interface CaseRuntimeType extends CompositeRuntimeType, DataRuntimeType {
+    @Override
+    CaseEffectiveStatement statement();
+
+    /**
+     * Return the runtime type for the original manifestation of this type's {@code case} statement. Returns
+     * {@code null} if this type is the original.
+     *
+     * @return Original manifestatation, or {@code null} if this is the original manifestation.
+     */
+    @Nullable CaseRuntimeType originalType();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ChoiceRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ChoiceRuntimeType.java
new file mode 100644 (file)
index 0000000..9a2fa97
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import java.util.Collection;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code choice} statement.
+ */
+@Beta
+public interface ChoiceRuntimeType extends CompositeRuntimeType, DataRuntimeType {
+    @Override
+    ChoiceEffectiveStatement statement();
+
+    /**
+     * Returns resolved {@link CaseRuntimeType} for specified binding class name.
+     *
+     * @param typeName Binding class name
+     * @return {@link CaseRuntimeType}, or null if absent
+     * @throws NullPointerException if {@code typeName} is null
+     */
+    @Nullable CaseRuntimeType bindingCaseChild(JavaTypeName typeName);
+
+    /**
+     * Return the runtime type for the original manifestation of this type's {@code choice} statement.
+     * Returns {@code null} if this type is the original.
+     *
+     * @return Original manifestatation, or {@code null} if this is the original manifestation.
+     */
+    @Nullable ChoiceRuntimeType originalType();
+
+    /**
+     * Return all {@link CaseRuntimeType} valid at this type's statement.
+     *
+     * @return Valid {@link CaseRuntimeType}s
+     */
+    @NonNull Collection<CaseRuntimeType> validCaseChildren();
+
+    /**
+     * Return any additional {@link CaseRuntimeType}s which may be encountered when dealing with DataObjects supported
+     * by this type. These are not strictly valid in YANG view of modeled data, but may have potentially-equivalent
+     * representation, such as in the following case:
+     * <pre>
+     *   <code>
+     *     grouping one {
+     *       container foo {
+     *         choice bar;
+     *       }
+     *     }
+     *
+     *     container foo {
+     *       uses grp;
+     *     }
+     *
+     *     container bar {
+     *       uses grp;
+     *     }
+     *
+     *     augment /foo/foo/bar {
+     *       case baz
+     *     }
+     *
+     *     augment /bar/foo/bar {
+     *       case xyzzy;
+     *     }
+     *   </code>
+     * </pre>
+     * and, more notably, the two augments being in different modules. Since {@code choice bar}'s is part of a reusable
+     * construct, {@code grouping one}, DataObjects' copy builders can propagate them without translating them to the
+     * appropriate manifestation -- and they can do nothing about that as they lack the complete view of the effecitve
+     * model.
+     *
+     * @return Additional {@link CaseRuntimeType}s
+     */
+    @NonNull Collection<CaseRuntimeType> additionalCaseChildren();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CompositeRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CompositeRuntimeType.java
new file mode 100644 (file)
index 0000000..6d565a2
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * A {@link RuntimeType} which is also a {@link RuntimeTypeContainer}.
+ */
+@Beta
+public interface CompositeRuntimeType extends GeneratedRuntimeType, RuntimeTypeContainer {
+    /**
+     * Return the {@link AugmentRuntimeType}s extending this type, matching the underlying {@link #statement()}.
+     *
+     * @return {@link AugmentRuntimeType}s extending this type.
+     */
+    @NonNull List<AugmentRuntimeType> augments();
+
+    /**
+     * Return the {@link AugmentRuntimeType}s extending extending a namesake of this type.
+     *
+     * @return {@link AugmentRuntimeType}s extending a namesake of this type.
+     */
+    @NonNull List<AugmentRuntimeType> mismatchedAugments();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerLikeRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerLikeRuntimeType.java
new file mode 100644 (file)
index 0000000..1f69491
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a statement with similar semantics as {@code container} statement.
+ */
+@Beta
+public interface ContainerLikeRuntimeType<D extends DeclaredStatement<QName>,
+        E extends DataTreeEffectiveStatement<D> & DataTreeAwareEffectiveStatement<QName, D>>
+        extends CompositeRuntimeType, DataRuntimeType {
+    @Override
+    E statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerRuntimeType.java
new file mode 100644 (file)
index 0000000..2d2cbd9
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code container} statement.
+ */
+@Beta
+public interface ContainerRuntimeType
+        extends ContainerLikeRuntimeType<ContainerStatement, ContainerEffectiveStatement> {
+
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DataRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DataRuntimeType.java
new file mode 100644 (file)
index 0000000..2513d8c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+
+/**
+ * Marker interface for concrete {@link RuntimeType}s relevant when dealing data hierarchy. This interface does not have
+ * a direct relationship with the {@code data tree} YANG construct, nor with {@code YangInstanceIdentifier} addressing.
+ * Its primary role is differentiating between various types when considered in the context of
+ * {@link RuntimeTypeContainer}'s child methods and related inferences. In particular, {@link DataRuntimeType}s are
+ * relevant when considering whether or not a particular RuntimeType child is part of the data encoding (according to
+ * the Binding Specification) to the {@code schema tree} layout.
+ *
+ * <p>
+ * DataRuntimeTypes are considered part of the {@code data tree} information encoded by the Binding Specification and
+ * thus need to be considered as child nodes when considering other data-bearing construct, such as
+ * {@code NormalizedNode}. That relationship may not be straightforward, but notably it excludes constructs like
+ * {@link NotificationRuntimeType}, {@link IdentityRuntimeType}, {@link ActionRuntimeType}, {@link GroupingRuntimeType},
+ * and similar, as those exist in outside of {@code data tree} contract, but are still part of what
+ * {@link RuntimeTypeContainer#bindingChild(JavaTypeName)} considers as child constructs.
+ */
+@Beta
+public interface DataRuntimeType extends RuntimeType {
+    // Marker interface, no further contract is specified
+}
index a4c1da1e2b7ca01e82ba19452dc9507a6a334260..292f003c9815a2c5730598db187d47d5dc9e5ba5 100644 (file)
@@ -11,16 +11,11 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
 import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
 
 /**
  * Runtime Context for Java YANG Binding classes. It provides information derived from the backing effective model,
  * which is not captured in generated classes (and hence cannot be obtained from {@code BindingReflections}.
- *
- * <p>Some of this information are for example list of all available children for cases
- * {@link #getChoiceCaseChildren(DataNodeContainer)}, since choices are augmentable and new choices may be introduced
- * by additional models. Same goes for all possible augmentations.
  */
 @Beta
 public final class DefaultBindingRuntimeContext extends AbstractBindingRuntimeContext {
@@ -38,7 +33,7 @@ public final class DefaultBindingRuntimeContext extends AbstractBindingRuntimeCo
     }
 
     @Override
-    public <T> Class<T> loadClass(Type type) throws ClassNotFoundException {
-        return moduleInfos.loadClass(type.getFullyQualifiedName());
+    public <T> Class<T> loadClass(final JavaTypeName type) throws ClassNotFoundException {
+        return moduleInfos.loadClass(type.toString());
     }
 }
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GeneratedRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GeneratedRuntimeType.java
new file mode 100644 (file)
index 0000000..2359582
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.yangtools.concepts.Identifiable;
+
+/**
+ * A {@link RuntimeType} associated with a {@link GeneratedType}.
+ */
+@Beta
+public interface GeneratedRuntimeType extends RuntimeType, Identifiable<JavaTypeName> {
+    @Override
+    GeneratedType javaType();
+
+    @Override
+    default JavaTypeName getIdentifier() {
+        return javaType().getIdentifier();
+    }
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GroupingRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GroupingRuntimeType.java
new file mode 100644 (file)
index 0000000..abf1813
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.GroupingEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code grouping} statement.
+ */
+@Beta
+public interface GroupingRuntimeType extends CompositeRuntimeType {
+    @Override
+    GroupingEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/IdentityRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/IdentityRuntimeType.java
new file mode 100644 (file)
index 0000000..bf61530
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code identity} statement.
+ */
+@Beta
+public interface IdentityRuntimeType extends GeneratedRuntimeType {
+    @Override
+    IdentityEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InputRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InputRuntimeType.java
new file mode 100644 (file)
index 0000000..07e9a5e
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code input} statement.
+ */
+@Beta
+public interface InputRuntimeType extends ContainerLikeRuntimeType<InputStatement, InputEffectiveStatement> {
+
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InvokableRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InvokableRuntimeType.java
new file mode 100644 (file)
index 0000000..f49013b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * Common interface for run-time types associated with invokable operations, such as those defined by {@code action} and
+ * {@code rpc} statements.
+ */
+@Beta
+public interface InvokableRuntimeType extends CompositeRuntimeType {
+    /**
+     * Return the run-time type for this action's input.
+     *
+     * @return Input run-time type
+     */
+    @NonNull InputRuntimeType input();
+
+    /**
+     * Return the run-time type for this action's output.
+     *
+     * @return Output run-time type
+     */
+    @NonNull OutputRuntimeType output();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/KeyRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/KeyRuntimeType.java
new file mode 100644 (file)
index 0000000..d606f93
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code key} statement.
+ */
+@Beta
+public interface KeyRuntimeType extends GeneratedRuntimeType {
+    @Override
+    KeyEffectiveStatement statement();
+
+    @Override
+    GeneratedTransferObject javaType();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafListRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafListRuntimeType.java
new file mode 100644 (file)
index 0000000..355ceac
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
+
+@Beta
+public interface LeafListRuntimeType extends DataRuntimeType {
+    @Override
+    LeafListEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafRuntimeType.java
new file mode 100644 (file)
index 0000000..29c6f92
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
+
+@Beta
+public interface LeafRuntimeType extends DataRuntimeType {
+    @Override
+    LeafEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ListRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ListRuntimeType.java
new file mode 100644 (file)
index 0000000..4e952d4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code list} statement.
+ */
+@Beta
+public interface ListRuntimeType extends CompositeRuntimeType, DataRuntimeType {
+    @Override
+    ListEffectiveStatement statement();
+
+    /**
+     * Return the run-time type for this list's {@code key} statement, if present.
+     *
+     * @return This list's key run-time type, or null if not present
+     */
+    @Nullable KeyRuntimeType keyType();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ModuleRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ModuleRuntimeType.java
new file mode 100644 (file)
index 0000000..5aaa86f
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code module} statement.
+ */
+@Beta
+public interface ModuleRuntimeType extends CompositeRuntimeType {
+    @Override
+    ModuleEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/NotificationRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/NotificationRuntimeType.java
new file mode 100644 (file)
index 0000000..a89be0b
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code notification} statement.
+ */
+@Beta
+public interface NotificationRuntimeType extends CompositeRuntimeType {
+    @Override
+    NotificationEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OpaqueRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OpaqueRuntimeType.java
new file mode 100644 (file)
index 0000000..7989970
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an opaque construct, like {@code anydata} and {@code anyxml}.
+ */
+@Beta
+public interface OpaqueRuntimeType extends GeneratedRuntimeType, DataRuntimeType {
+    @Override
+    DataTreeEffectiveStatement<?> statement();
+
+    @Override
+    GeneratedType javaType();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OutputRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OutputRuntimeType.java
new file mode 100644 (file)
index 0000000..8b4f26c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code output} statement.
+ */
+@Beta
+public interface OutputRuntimeType extends ContainerLikeRuntimeType<OutputStatement, OutputEffectiveStatement> {
+
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RpcRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RpcRuntimeType.java
new file mode 100644 (file)
index 0000000..aff6548
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code rpc} statement.
+ */
+@Beta
+public interface RpcRuntimeType extends InvokableRuntimeType {
+    @Override
+    RpcEffectiveStatement statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeType.java
new file mode 100644 (file)
index 0000000..4e706d5
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+/**
+ * Base interface for all run-time type information about a particular {@link Type}.
+ */
+@Beta
+public interface RuntimeType extends Immutable {
+    /**
+     * Java type associated with this run-time type.
+     *
+     * @return Java Type
+     */
+    @NonNull Type javaType();
+
+    /**
+     * Return the {@link EffectiveStatement} associated with this run-time type.
+     *
+     * @return Effective statement
+     */
+    @NonNull EffectiveStatement<?, ?> statement();
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeTypeContainer.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeTypeContainer.java
new file mode 100644 (file)
index 0000000..1acbae7
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * An object containing {@link RuntimeType}s.
+ */
+@Beta
+public interface RuntimeTypeContainer extends Immutable {
+    /**
+     * Look up a child {@link RuntimeType} by its {@code schema tree} {@link QName}. Note the returned child does not
+     * necessarily match usual data addressing rules and will resolve non-data tree statements, such as
+     * {@code notification}, {@code rpc} and {@code action}. Callers should check the traits exposed by the returned
+     * object before accepting it.
+     *
+     * <p>
+     * One important omission is this method <b>does not</b> resolve nodes which have been added via {@code augment}
+     * statement. Those are exposed indirectly as children of {@link AugmentRuntimeType}s returned via
+     * {@link CompositeRuntimeType#augments()}, if applicable.
+     *
+     * @param qname {@code schema node} identifier
+     * @return Corresponding {@link RuntimeType}, or null if not found
+     * @throws NullPointerException if {@code qname} is null
+     */
+    @Nullable RuntimeType schemaTreeChild(QName qname);
+
+    /**
+     * Look up a child by the {@link JavaTypeName} of its generated class. This lookup, while very similar to
+     * {@link #schemaTreeChild(QName)}, does not precisely match the {@code schema tree} nor does it match
+     * {@code YangInstanceIdentifier} addressing.
+     * It will resolve constructs generated for {@code choice}, {@code case}, {@code notification}, {@code rpc},
+     * {@code action} and most notably for {@code grouping}, {@code identity}, {@code typedef} and {@code augment}
+     * statements. Callers should check the traits exposed by the returned object before accepting it.
+     *
+     * @param typeName Java class name of the generated class.
+     * @return Corresponding {@link RuntimeType}, or null if not found
+     * @throws NullPointerException if {@code typeName} is null
+     */
+    @Nullable GeneratedRuntimeType bindingChild(JavaTypeName typeName);
+
+    // FIXME: consider removing this method
+    default @Nullable RuntimeType bindingChild(final Type type) {
+        return bindingChild(type.getIdentifier());
+    }
+}
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/TypedefRuntimeType.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/TypedefRuntimeType.java
new file mode 100644 (file)
index 0000000..3d56fc9
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.runtime.api;
+
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code typedef} statement.
+ */
+public interface TypedefRuntimeType extends GeneratedRuntimeType {
+    @Override
+    TypedefEffectiveStatement statement();
+
+    @Override
+    GeneratedType javaType();
+}
index 7f5d452ade7ac14f5f33566b3b78d195c22908b2..ea8a90c818298540bb2df1efe494f5faa8557538 100644 (file)
@@ -11,9 +11,11 @@ module org.opendaylight.mdsal.binding.runtime.spi {
     requires transitive org.opendaylight.yangtools.yang.parser.api;
     requires transitive org.opendaylight.mdsal.binding.runtime.api;
     requires org.opendaylight.yangtools.concepts;
+    requires org.opendaylight.yangtools.util;
+    requires org.opendaylight.yangtools.yang.model.api;
     requires org.opendaylight.yangtools.yang.parser.impl;
+    requires org.opendaylight.mdsal.binding.model.api;
     requires org.opendaylight.mdsal.binding.spec.util;
-    requires org.opendaylight.yangtools.util;
     requires org.slf4j;
 
     uses org.opendaylight.yangtools.yang.parser.api.YangParserFactory;
index 978d5059ba5cc11f8893f9e7cdcf2280a66b34c1..eec58a27db605fee8215f2fa158f4c47e406de67 100644 (file)
@@ -9,28 +9,19 @@ package org.opendaylight.mdsal.binding.runtime.spi;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ForwardingObject;
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
 import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
 import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.yangtools.yang.binding.Action;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.RpcInput;
+import org.opendaylight.yangtools.yang.binding.RpcOutput;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 
 @Beta
 public abstract class ForwardingBindingRuntimeContext extends ForwardingObject implements BindingRuntimeContext {
@@ -43,69 +34,47 @@ public abstract class ForwardingBindingRuntimeContext extends ForwardingObject i
     }
 
     @Override
-    public <T extends Augmentation<?>> AugmentationSchemaNode getAugmentationDefinition(final Class<T> augClass) {
+    public <T extends Augmentation<?>> AugmentRuntimeType getAugmentationDefinition(final Class<T> augClass) {
         return delegate().getAugmentationDefinition(augClass);
     }
 
     @Override
-    public DataSchemaNode getSchemaDefinition(final Class<?> cls) {
+    public CompositeRuntimeType getSchemaDefinition(final Class<?> cls) {
         return delegate().getSchemaDefinition(cls);
     }
 
     @Override
-    public DataSchemaNode findChildSchemaDefinition(final DataNodeContainer parentSchema,
-            final QNameModule parentNamespace, final Class<?> childClass) {
-        return delegate().findChildSchemaDefinition(parentSchema, parentNamespace, childClass);
-    }
-
-    @Override
-    public ActionDefinition getActionDefinition(final Class<? extends Action<?, ?, ?>> cls) {
+    public ActionRuntimeType getActionDefinition(final Class<? extends Action<?, ?, ?>> cls) {
         return delegate().getActionDefinition(cls);
     }
 
     @Override
-    public Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
-            final DataNodeContainer target, final Class<? extends Augmentation<?>> aug) {
-        return delegate().getResolvedAugmentationSchema(target, aug);
-    }
-
-    @Override
-    public Optional<CaseSchemaNode> getCaseSchemaDefinition(final ChoiceSchemaNode schema, final Class<?> childClass) {
-        return delegate().getCaseSchemaDefinition(schema, childClass);
-    }
-
-    @Override
-    public Entry<GeneratedType, WithStatus> getTypeWithSchema(final Class<?> type) {
+    public RuntimeType getTypeWithSchema(final Class<?> type) {
         return delegate().getTypeWithSchema(type);
     }
 
     @Override
-    public Map<Type, Entry<Type, Type>> getChoiceCaseChildren(final DataNodeContainer schema) {
-        return delegate().getChoiceCaseChildren(schema);
-    }
-
-    @Override
-    public Set<Class<?>> getCases(final Class<?> choice) {
-        return delegate().getCases(choice);
+    public Class<?> getClassForSchema(final Absolute schema) {
+        return delegate().getClassForSchema(schema);
     }
 
     @Override
-    public Class<?> getClassForSchema(final SchemaNode childSchema) {
-        return delegate().getClassForSchema(childSchema);
+    public Class<?> getIdentityClass(final QName input) {
+        return delegate().getIdentityClass(input);
     }
 
     @Override
-    public ImmutableMap<AugmentationIdentifier, Type> getAvailableAugmentationTypes(final DataNodeContainer container) {
-        return delegate().getAvailableAugmentationTypes(container);
+    public <T> Class<T> loadClass(final JavaTypeName typeName) throws ClassNotFoundException {
+        return delegate().loadClass(typeName);
     }
 
     @Override
-    public Class<?> getIdentityClass(final QName input) {
-        return delegate().getIdentityClass(input);
+    public Class<? extends RpcInput> getRpcInput(final QName rpcName) {
+        return delegate().getRpcInput(rpcName);
     }
 
     @Override
-    public <T> Class<T> loadClass(final Type type) throws ClassNotFoundException {
-        return delegate().loadClass(type);
+    public Class<? extends RpcOutput> getRpcOutput(final QName rpcName) {
+        return delegate().getRpcOutput(rpcName);
     }
 }