From ecdcdb340457ded6898193197e88ea33c84d58ae Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Fri, 29 Oct 2021 18:06:01 +0200 Subject: [PATCH 1/1] Rework BindingRuntimeTypes 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 --- .../dom/adapter/CurrentAdapterSerializer.java | 6 +- .../src/main/java/module-info.java | 1 + .../dom/codec/impl/ActionCodecContext.java | 16 +- .../codec/impl/AugmentationNodeContext.java | 6 +- .../dom/codec/impl/BindingCodecContext.java | 46 ++- .../dom/codec/impl/CaseNodeCodecContext.java | 16 +- .../codec/impl/ChoiceNodeCodecContext.java | 74 ++-- .../codec/impl/ContainerNodeCodecContext.java | 7 +- .../codec/impl/DataContainerCodecContext.java | 12 +- .../impl/DataContainerCodecPrototype.java | 93 ++--- .../codec/impl/DataObjectCodecContext.java | 86 +++-- .../impl/DataObjectStreamerGenerator.java | 11 +- .../dom/codec/impl/IdentifiableItemCodec.java | 21 +- .../codec/impl/KeyedListNodeCodecContext.java | 22 +- .../dom/codec/impl/ListNodeCodecContext.java | 8 +- .../dom/codec/impl/NodeCodecContext.java | 12 +- .../codec/impl/NotificationCodecContext.java | 8 +- .../codec/impl/SchemaRootCodecContext.java | 177 ++++++---- .../dom/codec/impl/UnionTypeCodec.java | 6 +- ...nceIdentifierSerializeDeserializeTest.java | 2 +- .../binding/dom/codec/impl/Mdsal724Test.java | 6 +- binding/mdsal-binding-generator/pom.xml | 4 + .../impl/BindingRuntimeTypesFactory.java | 125 ++++--- .../impl/DefaultBindingRuntimeTypes.java | 182 ---------- .../reactor/AbstractAugmentGenerator.java | 40 ++- .../reactor/AbstractCompositeGenerator.java | 226 ++++++------ .../reactor/AbstractDependentGenerator.java | 6 +- .../reactor/AbstractExplicitGenerator.java | 77 +++- .../reactor/AbstractTypeAwareGenerator.java | 20 +- .../reactor/AbstractTypeObjectGenerator.java | 57 ++- .../impl/reactor/ActionGenerator.java | 17 +- .../impl/reactor/AugmentRequirement.java | 10 +- .../generator/impl/reactor/CaseGenerator.java | 23 +- .../impl/reactor/ChoiceGenerator.java | 49 ++- .../impl/reactor/CollisionDomain.java | 18 +- .../reactor/CompositeSchemaTreeGenerator.java | 15 +- .../impl/reactor/ContainerGenerator.java | 15 +- .../generator/impl/reactor/Generator.java | 16 +- .../impl/reactor/GeneratorContext.java | 12 +- .../impl/reactor/GeneratorReactor.java | 23 +- .../impl/reactor/GroupingGenerator.java | 15 +- .../impl/reactor/IdentityGenerator.java | 17 +- .../impl/reactor/InputGenerator.java | 32 ++ .../generator/impl/reactor/KeyGenerator.java | 24 +- .../generator/impl/reactor/LeafGenerator.java | 17 +- .../impl/reactor/LeafListGenerator.java | 17 +- .../generator/impl/reactor/ListGenerator.java | 16 +- .../generator/impl/reactor/MatchStrategy.java | 16 +- .../impl/reactor/ModuleAugmentGenerator.java | 6 +- .../impl/reactor/ModuleGenerator.java | 15 +- .../impl/reactor/NotificationGenerator.java | 18 +- .../impl/reactor/OpaqueObjectGenerator.java | 49 ++- .../reactor/OperationContainerGenerator.java | 24 +- .../generator/impl/reactor/OriginalLink.java | 39 ++- .../impl/reactor/OutputGenerator.java | 32 ++ .../generator/impl/reactor/RpcGenerator.java | 15 +- ...rGenerator.java => RpcInputGenerator.java} | 20 +- .../impl/reactor/RpcOutputGenerator.java | 36 ++ .../impl/reactor/SchemaTreePlaceholder.java | 55 --- .../TargetAugmentEffectiveStatement.java | 169 +++++++++ .../generator/impl/reactor/TypeReference.java | 6 +- .../impl/reactor/TypedefGenerator.java | 26 +- .../impl/reactor/UsesAugmentGenerator.java | 14 +- .../impl/rt/AbstractCaseRuntimeType.java | 23 ++ .../impl/rt/AbstractChoiceRuntimeType.java | 38 ++ .../impl/rt/AbstractCompositeRuntimeType.java | 91 +++++ .../impl/rt/AbstractGeneratedRuntimeType.java | 18 + .../impl/rt/AbstractObjectRuntimeType.java | 18 + .../impl/rt/AbstractRuntimeType.java | 41 +++ .../impl/rt/DefaultActionRuntimeType.java | 47 +++ .../impl/rt/DefaultAnydataRuntimeType.java | 21 ++ .../impl/rt/DefaultAnyxmlRuntimeType.java | 21 ++ .../impl/rt/DefaultAugmentRuntimeType.java | 24 ++ .../impl/rt/DefaultBindingRuntimeTypes.java | 104 ++++++ .../impl/rt/DefaultContainerRuntimeType.java | 25 ++ .../impl/rt/DefaultGroupingRuntimeType.java | 25 ++ .../impl/rt/DefaultIdentityRuntimeType.java | 21 ++ .../impl/rt/DefaultInputRuntimeType.java | 25 ++ .../impl/rt/DefaultKeyRuntimeType.java | 21 ++ .../impl/rt/DefaultLeafListRuntimeType.java | 21 ++ .../impl/rt/DefaultLeafRuntimeType.java | 21 ++ .../impl/rt/DefaultListRuntimeType.java | 34 ++ .../impl/rt/DefaultModuleRuntimeType.java | 25 ++ .../rt/DefaultNotificationRuntimeType.java | 26 ++ .../impl/rt/DefaultOutputRuntimeType.java | 25 ++ .../impl/rt/DefaultTypedefRuntimeType.java | 21 ++ .../impl/rt/DerivedCaseRuntimeType.java | 36 ++ .../impl/rt/DerivedChoiceRuntimeType.java | 53 +++ .../impl/rt/OriginalCaseRuntimeType.java | 29 ++ .../impl/rt/OriginalChoiceRuntimeType.java | 42 +++ .../generator/impl/tree/SchemaTreeChild.java | 45 --- .../generator/impl/tree/SchemaTreeParent.java | 27 -- .../impl/tree/StatementRepresentation.java | 28 ++ .../binding/generator/impl/Mdsal600Test.java | 14 +- binding/mdsal-binding-runtime-api/pom.xml | 18 +- .../src/main/java/module-info.java | 7 +- .../api/AbstractBindingRuntimeContext.java | 331 ++---------------- .../runtime/api/ActionRuntimeType.java | 20 ++ .../runtime/api/AnydataRuntimeType.java | 20 ++ .../runtime/api/AnyxmlRuntimeType.java | 20 ++ .../runtime/api/AugmentRuntimeType.java | 20 ++ .../runtime/api/BindingRuntimeContext.java | 79 +---- .../runtime/api/BindingRuntimeTypes.java | 31 +- .../binding/runtime/api/CaseRuntimeType.java | 29 ++ .../runtime/api/ChoiceRuntimeType.java | 86 +++++ .../runtime/api/CompositeRuntimeType.java | 32 ++ .../runtime/api/ContainerLikeRuntimeType.java | 25 ++ .../runtime/api/ContainerRuntimeType.java | 21 ++ .../binding/runtime/api/DataRuntimeType.java | 32 ++ .../api/DefaultBindingRuntimeContext.java | 11 +- .../runtime/api/GeneratedRuntimeType.java | 27 ++ .../runtime/api/GroupingRuntimeType.java | 20 ++ .../runtime/api/IdentityRuntimeType.java | 20 ++ .../binding/runtime/api/InputRuntimeType.java | 20 ++ .../runtime/api/InvokableRuntimeType.java | 32 ++ .../binding/runtime/api/KeyRuntimeType.java | 24 ++ .../runtime/api/LeafListRuntimeType.java | 17 + .../binding/runtime/api/LeafRuntimeType.java | 17 + .../binding/runtime/api/ListRuntimeType.java | 28 ++ .../runtime/api/ModuleRuntimeType.java | 20 ++ .../runtime/api/NotificationRuntimeType.java | 20 ++ .../runtime/api/OpaqueRuntimeType.java | 24 ++ .../runtime/api/OutputRuntimeType.java | 20 ++ .../binding/runtime/api/RpcRuntimeType.java | 20 ++ .../binding/runtime/api/RuntimeType.java | 34 ++ .../runtime/api/RuntimeTypeContainer.java | 57 +++ .../runtime/api/TypedefRuntimeType.java | 22 ++ .../src/main/java/module-info.java | 4 +- .../spi/ForwardingBindingRuntimeContext.java | 75 ++-- 129 files changed, 3176 insertions(+), 1366 deletions(-) delete mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingRuntimeTypes.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/InputGenerator.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OutputGenerator.java rename binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/{RpcContainerGenerator.java => RpcInputGenerator.java} (54%) create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcOutputGenerator.java delete mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/SchemaTreePlaceholder.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TargetAugmentEffectiveStatement.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCaseRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractChoiceRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCompositeRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractGeneratedRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractObjectRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultActionRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnydataRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnyxmlRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAugmentRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultBindingRuntimeTypes.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultContainerRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultGroupingRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultIdentityRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultInputRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultKeyRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafListRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultListRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultModuleRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultNotificationRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultOutputRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultTypedefRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedCaseRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedChoiceRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalCaseRuntimeType.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalChoiceRuntimeType.java delete mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeChild.java delete mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeParent.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/StatementRepresentation.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ActionRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnydataRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnyxmlRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AugmentRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CaseRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ChoiceRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CompositeRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerLikeRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DataRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GeneratedRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GroupingRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/IdentityRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InputRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InvokableRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/KeyRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafListRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ListRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ModuleRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/NotificationRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OpaqueRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OutputRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RpcRuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeType.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeTypeContainer.java create mode 100644 binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/TypedefRuntimeType.java diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java index f444c1cf8e..cce6e894a2 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java @@ -166,8 +166,8 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer private Method findRpcMethod(final Class 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); } } diff --git a/binding/mdsal-binding-dom-codec-api/src/main/java/module-info.java b/binding/mdsal-binding-dom-codec-api/src/main/java/module-info.java index 49c432ee6a..bb07f6c46f 100644 --- a/binding/mdsal-binding-dom-codec-api/src/main/java/module-info.java +++ b/binding/mdsal-binding-dom-codec-api/src/main/java/module-info.java @@ -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; diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ActionCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ActionCodecContext.java index e32716cc0b..acd87508ea 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ActionCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ActionCodecContext.java @@ -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 input; - private final DataContainerCodecContext output; + private final DataContainerCodecContext input; + private final DataContainerCodecContext output; - ActionCodecContext(final DataContainerCodecContext input, - final DataContainerCodecContext output) { + ActionCodecContext(final DataContainerCodecContext input, + final DataContainerCodecContext output) { this.input = requireNonNull(input); this.output = requireNonNull(output); } - DataContainerCodecContext input() { + DataContainerCodecContext input() { return input; } - DataContainerCodecContext output() { + DataContainerCodecContext output() { return output; } } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java index 46bfd48fd3..cc58db2b56 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java @@ -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> - extends DataObjectCodecContext { + extends DataObjectCodecContext { - AugmentationNodeContext(final DataContainerCodecPrototype prototype) { + AugmentationNodeContext(final DataContainerCodecPrototype prototype) { super(prototype); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java index 809e56d669..ff51f42aff 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java @@ -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 getLeafNodes(final Class type, - final DataNodeContainer schema) { + final EffectiveStatement schema) { final Map 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 map, final DataSchemaNode leaf) { + map.put(BindingSchemaMapping.getGetterMethodName(leaf), leaf); + } + private ImmutableMap getLeafNodesUsingReflection( final Class parentClass, final Map getterToLeafSchema) { final Map 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 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>> optIdentifier = ClassLoaderUtils.findFirstGenericArgument(listClz, Identifiable.class); checkState(optIdentifier.isPresent(), "Failed to find identifier for %s", listClz); final Class> identifier = optIdentifier.get(); final Map 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") diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseNodeCodecContext.java index 4dda319a07..413be40bb4 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseNodeCodecContext.java @@ -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 extends DataObjectCodecContext { - CaseNodeCodecContext(final DataContainerCodecPrototype prototype) { +final class CaseNodeCodecContext extends DataObjectCodecContext { + CaseNodeCodecContext(final DataContainerCodecPrototype 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 diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceNodeCodecContext.java index dc2f6a4094..e170ccd254 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceNodeCodecContext.java @@ -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 extends DataContainerCodecContext { +final class ChoiceNodeCodecContext extends DataContainerCodecContext { private static final Logger LOG = LoggerFactory.getLogger(ChoiceNodeCodecContext.class); private final ImmutableMap> byYangCaseChild; @@ -101,7 +105,7 @@ final class ChoiceNodeCodecContext extends DataContainerCo private final ImmutableMap, DataContainerCodecPrototype> byClass; private final Set> ambiguousByCaseChildWarnings; - ChoiceNodeCodecContext(final DataContainerCodecPrototype prototype) { + ChoiceNodeCodecContext(final DataContainerCodecPrototype prototype) { super(prototype); final Map> byYangCaseChildBuilder = new HashMap<>(); @@ -110,10 +114,11 @@ final class ChoiceNodeCodecContext extends DataContainerCo SetMultimapBuilder.hashKeys().hashSetValues().build(); final Set> 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 cazeDef = loadCase(caze); + final DataContainerCodecPrototype 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 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 extends DataContainerCo byClass = ImmutableMap.copyOf(byClassBuilder); } + private List> 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 DataContainerCodecContext streamChild(final Class childClass) { @@ -212,15 +243,14 @@ final class ChoiceNodeCodecContext extends DataContainerCo return Iterables.concat(byCaseChildClass.keySet(), ambiguousByCaseChildClass.keySet()); } - protected DataContainerCodecPrototype loadCase(final Class childClass) { - final Optional childSchema = factory().getRuntimeContext().getCaseSchemaDefinition(getSchema(), - childClass); - if (childSchema.isPresent()) { - return DataContainerCodecPrototype.from(childClass, childSchema.get(), factory()); + protected DataContainerCodecPrototype 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 diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerNodeCodecContext.java index 6c25e9a1b2..0c4a86af75 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerNodeCodecContext.java @@ -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 extends DataObjectCodecContext +final class ContainerNodeCodecContext + extends DataObjectCodecContext> implements RpcInputCodec { - ContainerNodeCodecContext(final DataContainerCodecPrototype prototype) { + ContainerNodeCodecContext(final DataContainerCodecPrototype> prototype) { super(prototype); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java index 6c99bc8988..dc0566be9e 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java @@ -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 extends NodeCodecContext +abstract class DataContainerCodecContext extends NodeCodecContext implements BindingDataObjectCodecTreeNode { private static final VarHandle EVENT_STREAM_SERIALIZER; @@ -66,9 +67,8 @@ abstract class DataContainerCodecContext 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 { diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java index 2a6abd3d79..4ab8c5e161 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java @@ -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 implements NodeContextSupplier { +final class DataContainerCodecPrototype implements NodeContextSupplier { private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecPrototype.class); private static final VarHandle INSTANCE; @@ -53,7 +62,7 @@ final class DataContainerCodecPrototype 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 implements NodeCon private volatile DataContainerCodecContext 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) cls), arg, nodeSchema, factory); + this(Item.of((Class) 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 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 implements NodeCon return ChildAddressabilitySummary.UNADDRESSABLE; } - static DataContainerCodecPrototype 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 rootPrototype(final CodecContextFactory factory) { + return new DataContainerCodecPrototype<>(DataRoot.class, NodeIdentifier.create(SchemaContext.NAME), + factory.getRuntimeContext().getTypes(), factory); } - static DataContainerCodecPrototype from(final Class cls, final T schema, + static DataContainerCodecPrototype 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 DataContainerCodecPrototype from(final Item bindingArg, final T schema, + static DataContainerCodecPrototype 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 from(final Class augClass, + final AugmentationIdentifier arg, final AugmentRuntimeType schema, final CodecContextFactory factory) { + return new DataContainerCodecPrototype<>(augClass, arg, schema, factory); } - static DataContainerCodecPrototype from(final Class augClass, - final AugmentationIdentifier arg, final AugmentationSchemaNode schema, final CodecContextFactory factory) { + static DataContainerCodecPrototype 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 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 implements NodeCon // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object private @NonNull DataContainerCodecContext 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) this) + ? KeyedListNodeCodecContext.create((DataContainerCodecPrototype) 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); } } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java index fd1c2eea8b..52a7b06be4 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java @@ -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 +public abstract class DataObjectCodecContext extends DataContainerCodecContext { 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 bindingClass = getBindingClass(); - final ImmutableMap tmpLeaves = factory().getLeafNodes(bindingClass, getSchema()); + final ImmutableMap tmpLeaves = factory().getLeafNodes(bindingClass, + getType().statement()); final Map, Method> clsToMethod = BindingReflections.getChildrenClassToMethod(bindingClass); @@ -133,7 +140,7 @@ public abstract class DataObjectCodecContext choice = (ChoiceNodeCodecContext) childProto.get(); for (final Class cazeChild : choice.getCaseChildrenClasses()) { byBindingArgClassBuilder.put(cazeChild, childProto); @@ -151,13 +158,14 @@ public abstract class DataObjectCodecContext possibleAugmentations; + final Iterable 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> augByYang = new HashMap<>(); final Map, 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 DataContainerCodecContext streamChild(final Class childClass) { - final DataContainerCodecPrototype childProto = streamChildPrototype(childClass); - return (DataContainerCodecContext) childNonNull(childProto, childClass, " Child %s is not valid child.", - childClass).get(); + return (DataContainerCodecContext) 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 loadChildPrototype(final Class 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, 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) childClass); } @@ -340,13 +355,14 @@ public abstract class DataObjectCodecContext, DataContainerCodecPrototype>) + MISMATCHED_AUGMENTED.compareAndExchangeRelease(this, expected, newMismatched); if (witness == expected) { LOG.trace("Cached mismatched augmentation {} -> {} in {}", childClass, prototype, this); return prototype; } - expected = (ImmutableMap, 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 getAugmentationPrototype(final Type value) { + private @NonNull DataContainerCodecPrototype getAugmentationPrototype(final AugmentRuntimeType augment) { final BindingRuntimeContext ctx = factory().getRuntimeContext(); + final GeneratedType javaType = augment.javaType(); final Class> 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 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 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; diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamerGenerator.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamerGenerator.java index b007379a0d..c8b4b3e254 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamerGenerator.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectStreamerGenerator.java @@ -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> impleme static Class> generateStreamer(final CodecClassLoader loader, final CodecContextFactory registry, final Class type) { - final Entry 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> 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 diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/IdentifiableItemCodec.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/IdentifiableItemCodec.java index ecad6df385..f7ef432da8 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/IdentifiableItemCodec.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/IdentifiableItemCodec.java @@ -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> keyClass, + SingleKey(final ListEffectiveStatement schema, final Class> 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 keysInBindingOrder; private final MethodHandle ctor; - MultiKey(final ListSchemaNode schema, final Class> keyClass, + MultiKey(final ListEffectiveStatement schema, final Class> keyClass, final Class identifiable, final Map 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 keyDef = schema.getKeyDefinition(); + final Set 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 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> keyClass, + IdentifiableItemCodec(final ListEffectiveStatement schema, final Class> 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> keyClass, final Class identifiable, final Map keyValueContexts) { switch (keyValueContexts.size()) { diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java index 7d140c2120..189d443abc 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java @@ -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, D extends DataObject & Identifiable> extends ListNodeCodecContext { private static final class Ordered, D extends DataObject & Identifiable> extends KeyedListNodeCodecContext { - Ordered(final DataContainerCodecPrototype prototype, final Method keyMethod, + Ordered(final DataContainerCodecPrototype prototype, final Method keyMethod, final IdentifiableItemCodec codec) { super(prototype, keyMethod, codec); } @@ -36,7 +38,7 @@ abstract class KeyedListNodeCodecContext, D extends Data static final class Unordered, D extends DataObject & Identifiable> extends KeyedListNodeCodecContext { - Unordered(final DataContainerCodecPrototype prototype, final Method keyMethod, + Unordered(final DataContainerCodecPrototype prototype, final Method keyMethod, final IdentifiableItemCodec codec) { super(prototype, keyMethod, codec); } @@ -49,14 +51,14 @@ abstract class KeyedListNodeCodecContext, D extends Data private final IdentifiableItemCodec codec; - KeyedListNodeCodecContext(final DataContainerCodecPrototype prototype, + KeyedListNodeCodecContext(final DataContainerCodecPrototype prototype, final Method keyMethod, final IdentifiableItemCodec codec) { super(prototype, keyMethod); this.codec = requireNonNull(codec); } @SuppressWarnings("rawtypes") - static KeyedListNodeCodecContext create(final DataContainerCodecPrototype prototype) { + static KeyedListNodeCodecContext create(final DataContainerCodecPrototype prototype) { final Class bindingClass = prototype.getBindingClass(); final Method keyMethod; try { @@ -65,10 +67,12 @@ abstract class KeyedListNodeCodecContext, 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 diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java index 921fb1659e..e69b6e9281 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java @@ -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 extends DataObjectCodecContext { - ListNodeCodecContext(final DataContainerCodecPrototype prototype) { +class ListNodeCodecContext extends DataObjectCodecContext { + ListNodeCodecContext(final DataContainerCodecPrototype prototype) { super(prototype); } - ListNodeCodecContext(final DataContainerCodecPrototype prototype, + ListNodeCodecContext(final DataContainerCodecPrototype prototype, final Method keyMethod) { super(prototype, keyMethod); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NodeCodecContext.java index 2c2429130c..8ce77a2160 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NodeCodecContext.java @@ -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 getLeafNodes(Class type, DataNodeContainer schema); + ImmutableMap 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. diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java index 6c0ed42e7c..8f7d92f949 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java @@ -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 - extends DataObjectCodecContext { +final class NotificationCodecContext> + extends DataObjectCodecContext { 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 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 bindingClass = getBindingClass(); diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/SchemaRootCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/SchemaRootCodecContext.java index bfa286ac54..29bbebf469 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/SchemaRootCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/SchemaRootCodecContext.java @@ -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 extends DataContainerCodecContext { +final class SchemaRootCodecContext extends DataContainerCodecContext { private final LoadingCache, DataContainerCodecContext> childrenByClass = CacheBuilder.newBuilder().build(new CacheLoader<>() { @@ -86,10 +93,13 @@ final class SchemaRootCodecContext 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 extends DataContainerCo .build(new CacheLoader, ContainerNodeCodecContext>() { @Override public ContainerNodeCodecContext load(final Class key) { + final BiFunction>> 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 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 extends DataContainerCo private final LoadingCache> 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 childCls = (Class) - 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 extends DataContainerCo CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override public RpcInputCodec load(final Absolute key) { - final ContainerLike schema = getRpcDataSchema(getSchema(), key); - @SuppressWarnings("unchecked") - final Class cls = (Class) - factory().getRuntimeContext().getClassForSchema(schema); - return getRpc(cls); + final var rpcName = key.firstNodeIdentifier(); + final var context = factory().getRuntimeContext(); + + final Class 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 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> clz = (Class>) - 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 dataPrototype) { + private SchemaRootCodecContext(final DataContainerCodecPrototype dataPrototype) { super(dataPrototype); } @@ -183,6 +221,11 @@ final class SchemaRootCodecContext extends DataContainerCo return new SchemaRootCodecContext<>(DataContainerCodecPrototype.rootPrototype(factory)); } + @Override + public WithStatus getSchema() { + return getType().getEffectiveModelContext(); + } + @SuppressWarnings("unchecked") @Override public DataContainerCodecContext streamChild(final Class childClass) { @@ -209,12 +252,16 @@ final class SchemaRootCodecContext extends DataContainerCo return getOrRethrow(actionsByClass, action); } + NotificationCodecContext getNotification(final Absolute notification) { + return getOrRethrow(notificationsByPath, notification); + } + NotificationCodecContext getNotification(final Class> 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 rpcInputOrOutput) { @@ -226,10 +273,12 @@ final class SchemaRootCodecContext extends DataContainerCo } DataContainerCodecContext createDataTreeChildContext(final Class 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> action) { @@ -249,12 +298,12 @@ final class SchemaRootCodecContext 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 Class asClass(final Type type, final Class target) { @@ -269,6 +318,8 @@ final class SchemaRootCodecContext 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 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 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 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 choice = DataContainerCodecPrototype.from(choiceClass, - (ChoiceSchemaNode)schema, factory()).get(); + final DataContainerCodecContext choice = DataContainerCodecPrototype.from(choiceClass, + (ChoiceRuntimeType)schema, factory()).get(); Verify.verify(choice instanceof ChoiceNodeCodecContext); return (ChoiceNodeCodecContext) choice; } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/UnionTypeCodec.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/UnionTypeCodec.java index 778104fb68..41710c97c7 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/UnionTypeCodec.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/UnionTypeCodec.java @@ -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 unionProperties = extractUnionProperties(codecContext.getRuntimeContext() - .getTypeWithSchema(unionCls).getKey()); + .getTypeWithSchema(unionCls).javaType()); final List> 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 extractUnionProperties(final GeneratedType type) { + private static List extractUnionProperties(final Type type) { verify(type instanceof GeneratedTransferObject, "Unexpected runtime type %s", type); GeneratedTransferObject gto = (GeneratedTransferObject) type; diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java index c80f1e72f4..9b4ad7e90f 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java @@ -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 diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/Mdsal724Test.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/Mdsal724Test.java index 33da2fe7ec..8f72441c8b 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/Mdsal724Test.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/Mdsal724Test.java @@ -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 diff --git a/binding/mdsal-binding-generator/pom.xml b/binding/mdsal-binding-generator/pom.xml index e1d636fe76..1815211084 100644 --- a/binding/mdsal-binding-generator/pom.xml +++ b/binding/mdsal-binding-generator/pom.xml @@ -52,6 +52,10 @@ org.opendaylight.yangtools yang-model-util + + org.opendaylight.yangtools + yang-xpath-api + org.opendaylight.mdsal yang-binding diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/BindingRuntimeTypesFactory.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/BindingRuntimeTypesFactory.java index 8c5a494504..49953954cc 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/BindingRuntimeTypesFactory.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/BindingRuntimeTypesFactory.java @@ -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 augmentationToSchema = new HashMap<>(); - private final Map typeToSchema = new HashMap<>(); - private final Map 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 schemaToType = new IdentityHashMap<>(); + // Modules, indexed by their QNameModule + private final Map modules = new HashMap<>(); + // Identities, indexed by their QName + private final Map identities = new HashMap<>(); + // All known types, indexed by their JavaTypeName + private final Map allTypes = new HashMap<>(); + // All RpcOutputs, indexed by their RPC's QName + private final Map rpcOutputs = new HashMap<>(); + // All RpcInputs, indexed by their RPC's QName + private final Map rpcInputs = new HashMap<>(); private BindingRuntimeTypesFactory() { // Hidden on purpose } static @NonNull BindingRuntimeTypes createTypes(final @NonNull EffectiveModelContext context) { - final Collection 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 generators) { - for (Generator gen : generators) { - gen.generatedType().ifPresent(type -> indexType(gen, type)); - indexTypes(gen); - } - } + private void indexModules(final Map 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 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 void safePut(final Map 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 index 3f21a81125..0000000000 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingRuntimeTypes.java +++ /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 typeToAugmentation; - private final ImmutableMap typeToSchema; - private final ImmutableMultimap choiceToCases; - private final ImmutableMap identities; - // Not Immutable as we use two different implementations - private final Map schemaToType; - - DefaultBindingRuntimeTypes(final EffectiveModelContext schemaContext, - final Map typeToAugmentation, - final Map typeToSchema, final Map schemaToType, - final Map 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 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 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 builder = MultimapBuilder.hashKeys(choiceTypes.size()).arrayListValues().build(); - for (Entry 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 impls, final Set choiceTypes) { - for (Type impl : impls) { - if (impl instanceof GeneratedType && choiceTypes.contains(impl)) { - return (GeneratedType) impl; - } - } - return null; - } - - DefaultBindingRuntimeTypes(final EffectiveModelContext schemaContext, - final Map typeToAugmentation, - final BiMap typeToDefiningSchema, final Map identities) { - this(schemaContext, typeToAugmentation, typeToDefiningSchema, typeToDefiningSchema.inverse(), identities); - } - - @Override - public EffectiveModelContext getEffectiveModelContext() { - return schemaContext; - } - - @Override - public Optional findAugmentation(final Type type) { - return Optional.ofNullable(typeToAugmentation.get(type)); - } - - @Override - public Optional findIdentity(final QName qname) { - return Optional.ofNullable(identities.get(qname)); - } - - @Override - public Optional findSchema(final Type type) { - return Optional.ofNullable(typeToSchema.get(type)); - } - - @Override - public Optional findType(final WithStatus schema) { - return Optional.ofNullable(schemaToType.get(schema)); - } - - @Override - public Optional 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 original = current.getOriginalDefinition(); - if (original.isEmpty()) { - return findType(current); - } - current = original.orElseThrow(); - } - } - - @Override - public Multimap getChoiceToCases() { - return choiceToCases; - } - - @Override - public Collection 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(); - } -} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractAugmentGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractAugmentGenerator.java index b9c92cd1cb..5a018acdb5 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractAugmentGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractAugmentGenerator.java @@ -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 { +abstract class AbstractAugmentGenerator + extends AbstractCompositeGenerator { /** * 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 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 target = targetGenerator(); + final AbstractCompositeGenerator target = targetGenerator(); return target instanceof ChoiceGenerator ? ClassPlacement.PHANTOM : super.classPlacement(); } @@ -139,17 +147,37 @@ abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator children, final List 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); + } } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java index d4ed8314b0..e88739a72c 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java @@ -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> - extends AbstractExplicitGenerator implements SchemaTreeParent { +public abstract class AbstractCompositeGenerator, R extends CompositeRuntimeType> + extends AbstractExplicitGenerator { 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 childGenerators; - /** - * {@link SchemaTreeChild} children of this generator. Generator linkage is ensured on first access. - */ - private final @NonNull List> 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 augments = List.of(); + private @NonNull List 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> unlinkedComposites = List.of(); + private List> 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 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 { + 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 children, @NonNull List augments); + @Override - public List> 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 indexChildren(final @NonNull S statement) { + final var childMap = new ArrayList(); + + 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 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 augments() { + return augments; + } + + private @NonNull List 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 findGenerator(final List> stmtPath) { + final @Nullable AbstractExplicitGenerator findGenerator(final List> 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> ? final List> 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) 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) child).startUsesAugmentLinkage(requirements); + ((AbstractCompositeGenerator) child).startUsesAugmentLinkage(requirements); } } } @@ -299,7 +354,7 @@ public abstract class AbstractCompositeGenerator (AbstractExplicitGenerator) child) + .map(child -> (AbstractExplicitGenerator) child) .collect(Collectors.toList()); } @@ -310,7 +365,7 @@ public abstract class AbstractCompositeGenerator) child).linkOriginalGenerator()) { + if (((AbstractExplicitGenerator) child).linkOriginalGenerator()) { progress = LinkageProgress.SOME; it.remove(); @@ -319,7 +374,7 @@ public abstract class AbstractCompositeGenerator(); } - unlinkedComposites.add((AbstractCompositeGenerator) child); + unlinkedComposites.add((AbstractCompositeGenerator) child); } } } @@ -354,20 +409,21 @@ public abstract class AbstractCompositeGenerator getOriginal() { - return (AbstractCompositeGenerator) super.getOriginal(); + final AbstractCompositeGenerator getOriginal() { + return (AbstractCompositeGenerator) super.getOriginal(); } @Override - final AbstractCompositeGenerator tryOriginal() { - return (AbstractCompositeGenerator) super.tryOriginal(); + final AbstractCompositeGenerator tryOriginal() { + return (AbstractCompositeGenerator) super.tryOriginal(); } - final > @Nullable OriginalLink originalChild(final QName childQName) { + final , Y extends RuntimeType> @Nullable OriginalLink originalChild( + final QName childQName) { // First try groupings/augments ... var found = findInferredGenerator(childQName); if (found != null) { - return (OriginalLink) OriginalLink.partial(found); + return (OriginalLink) OriginalLink.partial(found); } // ... no luck, we really need to start looking at our origin @@ -376,7 +432,7 @@ public abstract class AbstractCompositeGenerator) found.originalLink(); + return (OriginalLink) found.originalLink(); } } @@ -384,8 +440,8 @@ public abstract class AbstractCompositeGenerator 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 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) child).addAsGetterMethod(builder, builderFactory); + ((AbstractExplicitGenerator) child).addAsGetterMethod(builder, builderFactory); } final GeneratedType enclosedType = child.enclosedType(builderFactory); @@ -464,97 +520,70 @@ public abstract class AbstractCompositeGenerator, List>> createChildren( - final EffectiveStatement statement) { + private @NonNull List createChildren(final EffectiveStatement statement) { final var tmp = new ArrayList(); final var tmpAug = new ArrayList(); - final var tmpSchema = new ArrayList>(); 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) 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> extends AbstractExplicitGenerator { - AbstractDependentGenerator(final T statement, final AbstractCompositeGenerator parent) { +abstract class AbstractDependentGenerator, R extends RuntimeType> + extends AbstractExplicitGenerator { + AbstractDependentGenerator(final S statement, final AbstractCompositeGenerator parent) { super(statement, parent); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractExplicitGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractExplicitGenerator.java index 10cac0c71c..3ca83a023d 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractExplicitGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractExplicitGenerator.java @@ -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> extends Generator - implements CopyableNode { +public abstract class AbstractExplicitGenerator, R extends RuntimeType> + extends Generator implements CopyableNode, StatementRepresentation { 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 AbstractExplicitGeneratora generator which is one step closer to the original definition * */ - private AbstractExplicitGenerator prev; + private AbstractExplicitGenerator prev; /** * Field holding the original incarnation, i.e. the terminal node along {@link #prev} links. */ - private AbstractExplicitGenerator orig; + private AbstractExplicitGenerator 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 runtimeType() { + if (!runtimeTypeInitialized) { + runtimeType = createRuntimeType(); + runtimeTypeInitialized = true; + } + return Optional.ofNullable(runtimeType); } + final Optional runtimeTypeOf(final @NonNull S stmt) { + return recursiveRuntimeType().map(childType -> rebaseRuntimeType(childType, stmt)); + } + + public final Optional recursiveRuntimeType() { + AbstractExplicitGenerator 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 AbstractExplicitGeneratororiginalChild(getQName()); + final var link = getParent().originalChild(getQName()); if (link == null) { LOG.trace("Cannot link {} yet", this); return false; @@ -134,7 +173,7 @@ public abstract class AbstractExplicitGenerator previous() { + final @Nullable AbstractExplicitGenerator 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 getOriginal() { + @NonNull AbstractExplicitGenerator getOriginal() { return verifyNotNull(orig, "Generator %s does not have linkage to original instance resolved", this); } - @Nullable AbstractExplicitGenerator tryOriginal() { + @Nullable AbstractExplicitGenerator tryOriginal() { return orig; } @@ -157,7 +196,7 @@ public abstract class AbstractExplicitGenerator originalLink() { + final @NonNull OriginalLink originalLink() { final var local = prev; if (local == null) { return OriginalLink.partial(this); @@ -168,14 +207,14 @@ public abstract class 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; diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeAwareGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeAwareGenerator.java index a93efef124..eb98a61350 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeAwareGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeAwareGenerator.java @@ -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, - G extends AbstractTypeAwareGenerator> - extends AbstractTypeObjectGenerator implements SchemaTreeChild { +abstract class AbstractTypeAwareGenerator, R extends RuntimeType, + G extends AbstractTypeAwareGenerator> + extends AbstractTypeObjectGenerator { 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 extractTypeDefinition() { - return ((TypedDataSchemaNode) statement()).getType(); + final var stmt = statement(); + verify(stmt instanceof TypedDataSchemaNode, "Unexpected statement %s", stmt); + return ((TypedDataSchemaNode) stmt).getType(); } @Override diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java index 54e08cb1a3..2c41edb80b 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java @@ -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> extends AbstractDependentGenerator { +abstract class AbstractTypeObjectGenerator, R extends RuntimeType> + extends AbstractDependentGenerator { private static final class UnionDependencies implements Immutable { private final Map, TypeReference> identityTypes = new HashMap<>(); private final Map, TypeReference> leafTypes = new HashMap<>(); @@ -294,9 +296,15 @@ abstract class AbstractTypeObjectGenerator> e private TypeReference refType; private List auxiliaryGeneratedTypes = List.of(); private UnionDependencies unionDependencies; - private List> inferred = List.of(); + private List> 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> e return; } - final AbstractExplicitGenerator prev = previous(); + final AbstractExplicitGenerator prev = previous(); if (prev != null) { verify(prev instanceof AbstractTypeObjectGenerator, "Unexpected previous %s", prev); - ((AbstractTypeObjectGenerator) prev).linkInferred(this); + ((AbstractTypeObjectGenerator) 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> e private void linkBaseGen(final TypedefGenerator upstreamBaseGen) { verify(baseGen == null, "Attempted to replace base %s with %s in %s", baseGen, upstreamBaseGen, this); - final List> downstreams = verifyNotNull(inferred, + final List> 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> 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> 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> 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> 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> 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); diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ActionGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ActionGenerator.java index f6dd71b5f5..8b0c9b9b22 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ActionGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ActionGenerator.java @@ -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 { - ActionGenerator(final ActionEffectiveStatement statement, final AbstractCompositeGenerator parent) { +final class ActionGenerator extends CompositeSchemaTreeGenerator { + ActionGenerator(final ActionEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } @@ -55,13 +60,19 @@ final class ActionGenerator extends CompositeSchemaTreeGenerator children, final List 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) { diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AugmentRequirement.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AugmentRequirement.java index 461a311150..deef7580f0 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AugmentRequirement.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AugmentRequirement.java @@ -43,11 +43,11 @@ final class AugmentRequirement implements Mutable { private final @NonNull AbstractAugmentGenerator augment; private final @NonNull Iterator 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(); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CaseGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CaseGenerator.java index 84a29c0a85..1b3bc495db 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CaseGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CaseGenerator.java @@ -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 { - CaseGenerator(final CaseEffectiveStatement statement, final AbstractCompositeGenerator parent) { +final class CaseGenerator extends CompositeSchemaTreeGenerator { + CaseGenerator(final CaseEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } @@ -36,10 +42,10 @@ final class CaseGenerator extends CompositeSchemaTreeGenerator 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 children, final List 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()); + } } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChoiceGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChoiceGenerator.java index c45a099857..1a6ac7fe5b 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChoiceGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChoiceGenerator.java @@ -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 { - ChoiceGenerator(final ChoiceEffectiveStatement statement, final AbstractCompositeGenerator parent) { +final class ChoiceGenerator extends CompositeSchemaTreeGenerator { + ChoiceGenerator(final ChoiceEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } @@ -42,4 +51,40 @@ final class ChoiceGenerator extends CompositeSchemaTreeGenerator children, final List 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(); + 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); + } } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CollisionDomain.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CollisionDomain.java index 9cd5aac532..ea6453e76a 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CollisionDomain.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CollisionDomain.java @@ -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 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, diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeSchemaTreeGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeSchemaTreeGenerator.java index c92707d774..196316b2bd 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeSchemaTreeGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeSchemaTreeGenerator.java @@ -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, - G extends CompositeSchemaTreeGenerator> - extends AbstractCompositeGenerator implements SchemaTreeChild { - CompositeSchemaTreeGenerator(final S statement, final AbstractCompositeGenerator parent) { +abstract class CompositeSchemaTreeGenerator, R extends CompositeRuntimeType> + extends AbstractCompositeGenerator { + CompositeSchemaTreeGenerator(final S statement, final AbstractCompositeGenerator parent) { super(statement, parent); } - - @Override - @SuppressWarnings("unchecked") - public final G generator() { - return (G) this; - } } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ContainerGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ContainerGenerator.java index cd2752f1ae..6a8b7e3029 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ContainerGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ContainerGenerator.java @@ -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 { - ContainerGenerator(final ContainerEffectiveStatement statement, final AbstractCompositeGenerator parent) { +final class ContainerGenerator extends CompositeSchemaTreeGenerator { + ContainerGenerator(final ContainerEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } @@ -45,4 +50,10 @@ final class ContainerGenerator extends CompositeSchemaTreeGenerator children, final List augments) { + return new DefaultContainerRuntimeType(type, statement, children, augments); + } } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/Generator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/Generator.java index 10d5e09889..6fd9a25e5a 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/Generator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/Generator.java @@ -60,7 +60,7 @@ public abstract class Generator implements Iterable { 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; private GeneratorResult result; @@ -71,7 +71,7 @@ public abstract class Generator implements Iterable { parent = null; } - Generator(final AbstractCompositeGenerator parent) { + Generator(final AbstractCompositeGenerator parent) { this.parent = requireNonNull(parent); } @@ -94,7 +94,7 @@ public abstract class Generator implements Iterable { * * @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 { return JavaTypeName.create(getPackageParent().javaPackage(), assignedName()); } - @NonNull AbstractCompositeGenerator getPackageParent() { + @NonNull AbstractCompositeGenerator getPackageParent() { return getParent(); } @@ -253,7 +253,7 @@ public abstract class Generator implements Iterable { } 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 { // 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 { defineImplementedInterfaceMethod(builder, Type.of(builder)).setDefault(true); } - static final > AbstractExplicitGenerator getChild(final Generator parent, + static final > AbstractExplicitGenerator getChild(final Generator parent, final Class type) { for (Generator child : parent) { if (child instanceof AbstractExplicitGenerator) { @SuppressWarnings("unchecked") - final AbstractExplicitGenerator explicit = (AbstractExplicitGenerator)child; + final AbstractExplicitGenerator explicit = (AbstractExplicitGenerator)child; if (type.isInstance(explicit.statement())) { return explicit; } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorContext.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorContext.java index fb17e65bfe..ea42c5cae8 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorContext.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorContext.java @@ -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 , G extends AbstractExplicitGenerator> + abstract , G extends AbstractExplicitGenerator> @NonNull G resolveTreeScoped(@NonNull Class type, @NonNull QName argument); abstract @NonNull ModuleGenerator resolveModule(@NonNull QNameModule namespace); diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorReactor.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorReactor.java index f8214ad144..a201f5a5ab 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorReactor.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorReactor.java @@ -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 - , G extends AbstractExplicitGenerator> G resolveTreeScoped( + , G extends AbstractExplicitGenerator> G resolveTreeScoped( final Class 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> 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 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); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GroupingGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GroupingGenerator.java index 687c60f65c..d789413cac 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GroupingGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GroupingGenerator.java @@ -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 { - GroupingGenerator(final GroupingEffectiveStatement statement, final AbstractCompositeGenerator parent) { +final class GroupingGenerator extends AbstractCompositeGenerator { + GroupingGenerator(final GroupingEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } @@ -49,6 +54,12 @@ final class GroupingGenerator extends AbstractCompositeGenerator children, final List augments) { + return new DefaultGroupingRuntimeType(type, statement, children, augments); + } + @Override void addAsGetterMethod(final GeneratedTypeBuilderBase builder, final TypeBuilderFactory builderFactory) { // groupings are a separate concept diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/IdentityGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/IdentityGenerator.java index 307aed28c1..e5fc913e72 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/IdentityGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/IdentityGenerator.java @@ -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 { +public final class IdentityGenerator + extends AbstractDependentGenerator { private List 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 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 index 0000000000..2400b4a9ee --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/InputGenerator.java @@ -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 { + 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 children, final List augments) { + return new DefaultInputRuntimeType(type, statement, children, augments); + } +} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/KeyGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/KeyGenerator.java index 4473a0b1ce..4a28b410f1 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/KeyGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/KeyGenerator.java @@ -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 { +final class KeyGenerator extends AbstractExplicitGenerator { 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 { + 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 diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafGenerator.java index a872d94c46..53aadbed25 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafGenerator.java @@ -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 { - LeafGenerator(final LeafEffectiveStatement statement, final AbstractCompositeGenerator parent) { +final class LeafGenerator extends AbstractTypeAwareGenerator { + 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); + } } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafListGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafListGenerator.java index 68727b69c3..e9f744db9a 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafListGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafListGenerator.java @@ -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 { - LeafListGenerator(final LeafListEffectiveStatement statement, final AbstractCompositeGenerator parent) { +final class LeafListGenerator + extends AbstractTypeAwareGenerator { + LeafListGenerator(final LeafListEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } @@ -38,4 +41,14 @@ final class LeafListGenerator extends AbstractTypeAwareGenerator { +final class ListGenerator extends CompositeSchemaTreeGenerator { 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 children, final List 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); diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/MatchStrategy.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/MatchStrategy.java index 3b15fed218..436ac41047 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/MatchStrategy.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/MatchStrategy.java @@ -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 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 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 haystack) { + AbstractExplicitGenerator findGenerator(final QName needle, + final Iterable 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 haystack) { + AbstractExplicitGenerator findGenerator(final QName needle, + final Iterable 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 haystack); @Override diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleAugmentGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleAugmentGenerator.java index ee590e72bf..a04587e005 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleAugmentGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleAugmentGenerator.java @@ -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())); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleGenerator.java index 868487b201..b67f89f7fc 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ModuleGenerator.java @@ -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 { +public final class ModuleGenerator extends AbstractCompositeGenerator { private final @NonNull JavaTypeName yangModuleInfo; private final @NonNull ClassPlacement placement; @@ -81,7 +86,7 @@ public final class ModuleGenerator extends AbstractCompositeGenerator getPackageParent() { + AbstractCompositeGenerator getPackageParent() { return this; } @@ -119,6 +124,12 @@ public final class ModuleGenerator extends AbstractCompositeGenerator children, final List augments) { + return new DefaultModuleRuntimeType(type, statement, children, augments); + } + @NonNull Member getPrefixMember() { return verifyNotNull(prefixMember); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java index 1be7ae1112..c2d4a38275 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java @@ -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 { - NotificationGenerator(final NotificationEffectiveStatement statement, final AbstractCompositeGenerator parent) { + extends CompositeSchemaTreeGenerator { + 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 children, final List 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); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OpaqueObjectGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OpaqueObjectGenerator.java index f020779dca..63564ce2f6 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OpaqueObjectGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OpaqueObjectGenerator.java @@ -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> extends AbstractExplicitGenerator - implements SchemaTreeChild> { - OpaqueObjectGenerator(final T statement, final AbstractCompositeGenerator parent) { - super(statement, parent); +abstract class OpaqueObjectGenerator, R extends OpaqueRuntimeType> + extends AbstractExplicitGenerator { + static final class Anydata extends OpaqueObjectGenerator { + 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 generator() { - return this; + static final class Anyxml extends OpaqueObjectGenerator { + 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 diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OperationContainerGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OperationContainerGenerator.java index e588743fda..35a70e5824 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OperationContainerGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OperationContainerGenerator.java @@ -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, OperationContainerGenerator> { +abstract class OperationContainerGenerator, R extends CompositeRuntimeType> + extends CompositeSchemaTreeGenerator { 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 diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OriginalLink.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OriginalLink.java index 3d9009a42b..a766ca45fb 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OriginalLink.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OriginalLink.java @@ -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> { - private static final class Complete> extends OriginalLink { - private final @NonNull AbstractExplicitGenerator original; +abstract class OriginalLink, R extends RuntimeType> { + private static final class Complete, R extends RuntimeType> + extends OriginalLink { + private final @NonNull AbstractExplicitGenerator original; - Complete(final AbstractExplicitGenerator original) { + Complete(final AbstractExplicitGenerator original) { this.original = requireNonNull(original); } @Override - AbstractExplicitGenerator previous() { + AbstractExplicitGenerator previous() { return original; } @Override - @NonNull AbstractExplicitGenerator original() { + @NonNull AbstractExplicitGenerator original() { return original; } @@ -43,21 +45,22 @@ abstract class OriginalLink> { } } - private static final class Partial> extends OriginalLink { - private final @NonNull AbstractExplicitGenerator previous; - private AbstractExplicitGenerator original; + private static final class Partial, R extends RuntimeType> + extends OriginalLink { + private final @NonNull AbstractExplicitGenerator previous; + private AbstractExplicitGenerator original; - Partial(final AbstractExplicitGenerator previous) { + Partial(final AbstractExplicitGenerator previous) { this.previous = requireNonNull(previous); } @Override - AbstractExplicitGenerator previous() { + AbstractExplicitGenerator previous() { return previous; } @Override - AbstractExplicitGenerator original() { + AbstractExplicitGenerator original() { if (original == null) { final var link = previous.originalLink(); if (link instanceof Complete || link.previous() != previous) { @@ -77,19 +80,19 @@ abstract class OriginalLink> { // Hidden on purpose } - static > @NonNull OriginalLink complete( - final AbstractExplicitGenerator original) { + static , R extends RuntimeType> @NonNull OriginalLink complete( + final AbstractExplicitGenerator original) { return new Complete<>(original); } - static > @NonNull OriginalLink partial( - final AbstractExplicitGenerator previous) { + static , R extends RuntimeType> @NonNull OriginalLink partial( + final AbstractExplicitGenerator previous) { return new Partial<>(previous); } - abstract @NonNull AbstractExplicitGenerator previous(); + abstract @NonNull AbstractExplicitGenerator previous(); - abstract @Nullable AbstractExplicitGenerator original(); + abstract @Nullable AbstractExplicitGenerator 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 index 0000000000..320593d7e6 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OutputGenerator.java @@ -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 { + 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 children, final List augments) { + return new DefaultOutputRuntimeType(type, statement, children, augments); + } +} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java index 39b934e18d..985ac81dd3 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java @@ -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 { - RpcGenerator(final RpcEffectiveStatement statement, final AbstractCompositeGenerator parent) { +// FIXME: hide this once we have RpcRuntimeType +public final class RpcGenerator extends CompositeSchemaTreeGenerator { + RpcGenerator(final RpcEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } @@ -36,6 +41,12 @@ final class RpcGenerator extends CompositeSchemaTreeGenerator children, final List augments) { + throw new UnsupportedOperationException(); + } + @Override void addAsGetterMethod(final GeneratedTypeBuilderBase builder, final TypeBuilderFactory builderFactory) { // RPCs are a separate concept diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcContainerGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcInputGenerator.java similarity index 54% rename from binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcContainerGenerator.java rename to binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcInputGenerator.java index 4643c3a0e8..c3a15e92d7 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcContainerGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcInputGenerator.java @@ -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 index 0000000000..b08a259871 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcOutputGenerator.java @@ -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 index 9cfd59ef52..0000000000 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/SchemaTreePlaceholder.java +++ /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, - G extends AbstractExplicitGenerator & SchemaTreeChild> implements SchemaTreeChild { - private final @NonNull Class generatorType; - private final @NonNull S statement; - - private @Nullable G generator; - - SchemaTreePlaceholder(final S statement, final Class 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 index 0000000000..89d5fd690c --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TargetAugmentEffectiveStatement.java @@ -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> 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.>builderWithExpectedSize(stmts.size()); + for (var stmt : stmts) { + if (stmt instanceof SchemaTreeEffectiveStatement) { + final var qname = ((SchemaTreeEffectiveStatement) stmt).getIdentifier(); + final Optional> 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 > Optional get(final Class namespace, + final K identifier) { + return Optional.empty(); + } + + @Override + public > Map getAll(final Class namespace) { + return Map.of(); + } + + @Override + public Collection> effectiveSubstatements() { + return substatements; + } + + @Override + public Collection> getTypeDefinitions() { + return schemaDelegate.getTypeDefinitions(); + } + + @Override + @SuppressWarnings("unchecked") + public Collection getChildNodes() { + return (Collection) Collections2.filter(substatements, DataSchemaNode.class::isInstance); + } + + @Override + public Collection 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 getUses() { + return schemaDelegate.getUses(); + } + + @Override + @SuppressWarnings("unchecked") + public Collection getNotifications() { + return (Collection) Collections2.filter(substatements, NotificationDefinition.class::isInstance); + } + + @Override + @SuppressWarnings("unchecked") + public Collection getActions() { + return (Collection) Collections2.filter(substatements, ActionDefinition.class::isInstance); + } + + @Override + public Optional getWhenCondition() { + return schemaDelegate.getWhenCondition(); + } + + @Override + public @NonNull Status getStatus() { + return schemaDelegate.getStatus(); + } + + @Override + public Optional getDescription() { + return schemaDelegate.getDescription(); + } + + @Override + public Optional getReference() { + return schemaDelegate.getReference(); + } + + @Override + public AugmentEffectiveStatement asEffectiveStatement() { + return this; + } + + @Override + @Deprecated(forRemoval = true) + public Optional getOriginalDefinition() { + return schemaDelegate.getOriginalDefinition(); + } +} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypeReference.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypeReference.java index b1f52c1fd8..629306c8db 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypeReference.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypeReference.java @@ -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); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java index 8bca3a398d..3267b83aa5 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java @@ -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 { +final class TypedefGenerator extends AbstractTypeObjectGenerator { /** * 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> derivedGenerators = null; + private List> 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 derivedGenerator) { + void addDerivedGenerator(final AbstractTypeObjectGenerator derivedGenerator) { if (derivedGenerators == null) { derivedGenerators = new ArrayList<>(4); } @@ -53,7 +58,7 @@ final class TypedefGenerator extends AbstractTypeObjectGenerator derived : derivedGenerators) { + for (AbstractTypeObjectGenerator derived : derivedGenerators) { derived.bindTypeDefinition(reference); } } @@ -89,6 +94,17 @@ final class TypedefGenerator extends AbstractTypeObjectGenerator builder, final TypeBuilderFactory builderFactory) { // typedefs are a separate concept diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/UsesAugmentGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/UsesAugmentGenerator.java index 81c93f723e..e933dbaaed 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/UsesAugmentGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/UsesAugmentGenerator.java @@ -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 index 0000000000..ec518405b9 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCaseRuntimeType.java @@ -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 + implements CaseRuntimeType { + AbstractCaseRuntimeType(final GeneratedType bindingType, final CaseEffectiveStatement statement, + final List children, final List 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 index 0000000000..8f2809e19c --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractChoiceRuntimeType.java @@ -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 + implements ChoiceRuntimeType { + AbstractChoiceRuntimeType(final GeneratedType bindingType, final ChoiceEffectiveStatement statement, + final List children, final List augments) { + super(bindingType, statement, children, augments); + } + + @Override + public final Collection 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 index 0000000000..d67f1cf94c --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractCompositeRuntimeType.java @@ -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> + extends AbstractRuntimeType implements CompositeRuntimeType { + private final ImmutableMap byClass; + private final ImmutableMap bySchemaTree; + private final @NonNull ImmutableList augments; + private final @NonNull ImmutableList mismatchedAugments; + + AbstractCompositeRuntimeType(final GeneratedType bindingType, final S statement, final List children, + final List augments) { + super(bindingType, statement); + + final var substatements = statement.effectiveSubstatements(); + final var correctBuilder = ImmutableList.builder(); + final var mismatchedBuilder = ImmutableList.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.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 augments() { + return augments; + } + + @Override + public final List 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 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 index 0000000000..245ccf882d --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractGeneratedRuntimeType.java @@ -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> + extends AbstractRuntimeType { + 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 index 0000000000..a3c4cd3706 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractObjectRuntimeType.java @@ -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> + extends AbstractRuntimeType { + 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 index 0000000000..c2cb51fec6 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/AbstractRuntimeType.java @@ -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, 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 index 0000000000..84af4cc2f8 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultActionRuntimeType.java @@ -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 + implements ActionRuntimeType { + private final @NonNull InputRuntimeType input; + private final @NonNull OutputRuntimeType output; + + public DefaultActionRuntimeType(final GeneratedType bindingType, final ActionEffectiveStatement statement, + final List children, final List 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 @NonNull T child(final List list, final Class 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 index 0000000000..91b8450cae --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnydataRuntimeType.java @@ -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 + 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 index 0000000000..127de3a4a9 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAnyxmlRuntimeType.java @@ -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 + 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 index 0000000000..3a0de76f95 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultAugmentRuntimeType.java @@ -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 + implements AugmentRuntimeType { + public DefaultAugmentRuntimeType(final GeneratedType bindingType, final AugmentEffectiveStatement statement, + final List children, final List 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 index 0000000000..9bd748f7dd --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultBindingRuntimeTypes.java @@ -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 modulesByNamespace; + private final ImmutableSortedMap modulesByPackage; + private final ImmutableMap identities; + private final ImmutableMap rpcOutputs; + private final ImmutableMap rpcInputs; + private final ImmutableMap types; + + public DefaultBindingRuntimeTypes(final EffectiveModelContext context, + final Map modules, final Map types, + final Map identities, final Map rpcInputs, + final Map 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 findIdentity(final QName qname) { + return Optional.ofNullable(identities.get(requireNonNull(qname))); + } + + @Override + public Optional 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 findRpcInput(final QName rpcName) { + return Optional.ofNullable(rpcInputs.get(requireNonNull(rpcName))); + } + + @Override + public Optional 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 index 0000000000..3a9584793a --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultContainerRuntimeType.java @@ -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 + implements ContainerRuntimeType { + public DefaultContainerRuntimeType(final GeneratedType bindingType, final ContainerEffectiveStatement statement, + final List children, final List 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 index 0000000000..42f9efecac --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultGroupingRuntimeType.java @@ -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 + implements GroupingRuntimeType { + public DefaultGroupingRuntimeType(final GeneratedType bindingType, final GroupingEffectiveStatement statement, + final List children, final List 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 index 0000000000..50ebf94b45 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultIdentityRuntimeType.java @@ -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 + 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 index 0000000000..3b6eda8059 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultInputRuntimeType.java @@ -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 + implements InputRuntimeType { + public DefaultInputRuntimeType(final GeneratedType bindingType, final InputEffectiveStatement statement, + final List children, final List 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 index 0000000000..18a03cc7ad --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultKeyRuntimeType.java @@ -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 + 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 index 0000000000..165c80825c --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafListRuntimeType.java @@ -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 + 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 index 0000000000..badccf5bd2 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultLeafRuntimeType.java @@ -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 + 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 index 0000000000..c6e4bca188 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultListRuntimeType.java @@ -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 + implements ListRuntimeType { + private final KeyRuntimeType keyType; + + public DefaultListRuntimeType(final GeneratedType bindingType, final ListEffectiveStatement statement, + final List children, final List 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 index 0000000000..433107a6d8 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultModuleRuntimeType.java @@ -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 + implements ModuleRuntimeType { + public DefaultModuleRuntimeType(final GeneratedType bindingType, final ModuleEffectiveStatement statement, + final List children, final List 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 index 0000000000..ef7866b4e4 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultNotificationRuntimeType.java @@ -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 + implements NotificationRuntimeType { + public DefaultNotificationRuntimeType(final GeneratedType bindingType, + final NotificationEffectiveStatement statement, final List children, + final List 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 index 0000000000..0e4d150809 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultOutputRuntimeType.java @@ -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 + implements OutputRuntimeType { + public DefaultOutputRuntimeType(final GeneratedType bindingType, final OutputEffectiveStatement statement, + final List children, final List 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 index 0000000000..c63ae5c8f0 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DefaultTypedefRuntimeType.java @@ -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 + 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 index 0000000000..271f98ace1 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedCaseRuntimeType.java @@ -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 children, final List 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 index 0000000000..3a81294583 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/DerivedChoiceRuntimeType.java @@ -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 children, final List augments, + final ChoiceRuntimeType originalType) { + super(bindingType, statement, children, augments); + this.originalType = requireNonNull(originalType); + } + + @Override + public @NonNull ChoiceRuntimeType originalType() { + return originalType; + } + + @Override + public Collection additionalCaseChildren() { + final var myJavaTypes = Collections2.transform(validCaseChildren(), CaseRuntimeType::getIdentifier); + final var result = new ArrayList(); + 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 index 0000000000..200518d21d --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalCaseRuntimeType.java @@ -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 children, final List 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 index 0000000000..f996e42184 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/rt/OriginalChoiceRuntimeType.java @@ -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 augmentedCases; + + public OriginalChoiceRuntimeType(final GeneratedType bindingType, final ChoiceEffectiveStatement statement, + final List children, final List augments, + final List augmentedCases) { + super(bindingType, statement, children, augments); + this.augmentedCases = ImmutableList.copyOf(augmentedCases); + } + + @Override + public ChoiceRuntimeType originalType() { + return null; + } + + @Override + public Collection 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 index e3c409c93f..0000000000 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeChild.java +++ /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 Concrete {@link SchemaTreeEffectiveStatement} type - * @param Concrete {@link AbstractExplicitGenerator} type - */ -// FIXME: do not reference Generator once we have the codegen and runtime views well-defined -public interface SchemaTreeChild, - G extends AbstractExplicitGenerator & SchemaTreeChild> extends Identifiable { - @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 index d846befd56..0000000000 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeParent.java +++ /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 Concrete {@link EffectiveStatement} type - */ -// FIXME: S extends SchemaTreeAwareStatement ... once AugmentEffectiveStatement implements that -public interface SchemaTreeParent> { - /* - * 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> 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 index 0000000000..f3127c4890 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/StatementRepresentation.java @@ -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 Statement type + * @param Runtime type + */ +public interface StatementRepresentation> { + /** + * Return the effective YANG statement being represented by this object. + * + * @return A YANG statement + */ + @NonNull S statement(); +} diff --git a/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal600Test.java b/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal600Test.java index 3a529c6055..7ce90788f2 100644 --- a/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal600Test.java +++ b/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal600Test.java @@ -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()); } } diff --git a/binding/mdsal-binding-runtime-api/pom.xml b/binding/mdsal-binding-runtime-api/pom.xml index 511c9635eb..b71c755d99 100644 --- a/binding/mdsal-binding-runtime-api/pom.xml +++ b/binding/mdsal-binding-runtime-api/pom.xml @@ -20,17 +20,29 @@ bundle + + com.google.guava + guava + org.opendaylight.yangtools - yang-data-api + concepts org.opendaylight.yangtools - yang-repo-spi + yang-common + + + org.opendaylight.yangtools + yang-model-api org.opendaylight.yangtools - yang-model-util + yang-repo-api + + + org.opendaylight.yangtools + yang-repo-spi org.opendaylight.mdsal diff --git a/binding/mdsal-binding-runtime-api/src/main/java/module-info.java b/binding/mdsal-binding-runtime-api/src/main/java/module-info.java index 043ca184c0..3c37cf6762 100644 --- a/binding/mdsal-binding-runtime-api/src/main/java/module-info.java +++ b/binding/mdsal-binding-runtime-api/src/main/java/module-info.java @@ -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 diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AbstractBindingRuntimeContext.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AbstractBindingRuntimeContext.java index f7587ee913..dbed269c4a 100644 --- a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AbstractBindingRuntimeContext.java +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AbstractBindingRuntimeContext.java @@ -8,359 +8,100 @@ 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}. - * - *

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> identityClasses = CacheBuilder.newBuilder().weakValues().build( new CacheLoader>() { @Override public Class load(final QName key) { - final Optional 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 > AugmentationSchemaNode getAugmentationDefinition(final Class augClass) { - return getTypes().findAugmentation(Type.of(augClass)).orElse(null); + public final > AugmentRuntimeType getAugmentationDefinition(final Class 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> cls) { - return (ActionDefinition) getTypes().findSchema(Type.of(cls)).orElse(null); + public final ActionRuntimeType getActionDefinition(final Class> cls) { + return (ActionRuntimeType) getTypes().findSchema(JavaTypeName.create(cls)).orElse(null); } @Override - public final Entry getResolvedAugmentationSchema( - final DataNodeContainer target, final Class> 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 childNames = new HashSet<>(); - final Set 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 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 getTypeWithSchema(final Class type) { - return getTypeWithSchema(getTypes(), Type.of(type)); - } - - private static @NonNull Entry 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> getChoiceCaseChildren(final DataNodeContainer schema) { - return getChoiceCaseChildren(getTypes(), schema); - } - - private static @NonNull ImmutableMap> getChoiceCaseChildren(final BindingRuntimeTypes types, - final DataNodeContainer schema) { - final Map> childToCase = new HashMap<>(); - - for (final ChoiceSchemaNode choice : Iterables.filter(schema.getChildNodes(), ChoiceSchemaNode.class)) { - final ChoiceSchemaNode originalChoice = getOriginalSchema(choice); - final Optional 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 caseIdentifier = new SimpleEntry<>(choiceType, caze); - final HashSet 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 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> getCases(final Class choice) { - final Collection cazes = getTypes().findCases(Type.of(choice)); - final Set> 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 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 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 getAvailableAugmentationTypes( - final DataNodeContainer container) { - if (container instanceof AugmentationTarget) { - final var augmentations = ((AugmentationTarget) container).getAvailableAugmentations(); - if (!augmentations.isEmpty()) { - final var identifierToType = new HashMap(); - 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 collectAllContainerTypes(final GeneratedType type, final Set 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 getOriginalSchema(final T choice) { - @SuppressWarnings("unchecked") - final T original = (T) originalNodeOf(choice); - if (original != null) { - return original; - } - return choice; - } - - private static @NonNull Optional 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 index 0000000000..7113d0deb1 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ActionRuntimeType.java @@ -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 index 0000000000..51198804b2 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnydataRuntimeType.java @@ -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 index 0000000000..bb232bf138 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AnyxmlRuntimeType.java @@ -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 index 0000000000..479fe9458e --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AugmentRuntimeType.java @@ -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(); +} diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeContext.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeContext.java index 9fe1e546a0..109656a7bd 100644 --- a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeContext.java +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeContext.java @@ -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}. - * - *

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 Class loadClass(Type type) throws ClassNotFoundException; + @NonNull Class loadClass(JavaTypeName type) throws ClassNotFoundException; + + default @NonNull Class 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. * - *

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 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 */ - > @Nullable AugmentationSchemaNode getAugmentationDefinition(Class augClass); + > @Nullable AugmentRuntimeType getAugmentationDefinition(Class 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> cls); - - @NonNull Entry getResolvedAugmentationSchema( - DataNodeContainer target, Class> 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 getCaseSchemaDefinition(ChoiceSchemaNode schema, Class childClass); + @Nullable ActionRuntimeType getActionDefinition(Class> 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 getTypeWithSchema(Class type); - - @NonNull Map> getChoiceCaseChildren(DataNodeContainer schema); + @NonNull RuntimeType getTypeWithSchema(Class type); - @NonNull Set> getCases(Class choice); + @NonNull Class getRpcInput(QName rpcName); - @NonNull Class getClassForSchema(SchemaNode childSchema); + @NonNull Class 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 getAvailableAugmentationTypes(DataNodeContainer container); + // FIXME: 9.0.0: this needs to accept an EffectiveStatementInference + @NonNull Class getClassForSchema(Absolute schema); @NonNull Class getIdentityClass(QName input); } diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java index d0ac16642a..73235013f5 100644 --- a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java @@ -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 findAugmentation(Type type); + Optional findIdentity(QName qname); - Optional findIdentity(QName qname); + Optional findSchema(JavaTypeName typeName); - Optional findSchema(Type type); + Optional findRpcInput(QName rpcName); - Optional findType(WithStatus schema); + Optional findRpcOutput(QName rpcName); - Optional findOriginalAugmentationType(AugmentationSchemaNode augment); - - Multimap getChoiceToCases(); - - Collection 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 index 0000000000..8818903e59 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CaseRuntimeType.java @@ -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 index 0000000000..9a2fa97b3b --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ChoiceRuntimeType.java @@ -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 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: + *

+     *   
+     *     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;
+     *     }
+     *   
+     * 
+ * 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 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 index 0000000000..6d565a26a4 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/CompositeRuntimeType.java @@ -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 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 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 index 0000000000..1f69491ec4 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerLikeRuntimeType.java @@ -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, + E extends DataTreeEffectiveStatement & DataTreeAwareEffectiveStatement> + 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 index 0000000000..2d2cbd920e --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ContainerRuntimeType.java @@ -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 { + +} 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 index 0000000000..2513d8cb28 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DataRuntimeType.java @@ -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. + * + *

+ * 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 +} diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DefaultBindingRuntimeContext.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DefaultBindingRuntimeContext.java index a4c1da1e2b..292f003c98 100644 --- a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DefaultBindingRuntimeContext.java +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DefaultBindingRuntimeContext.java @@ -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}. - * - *

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 Class loadClass(Type type) throws ClassNotFoundException { - return moduleInfos.loadClass(type.getFullyQualifiedName()); + public Class 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 index 0000000000..2359582490 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GeneratedRuntimeType.java @@ -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 { + @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 index 0000000000..abf1813754 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/GroupingRuntimeType.java @@ -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 index 0000000000..bf61530817 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/IdentityRuntimeType.java @@ -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 index 0000000000..07e9a5ea21 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InputRuntimeType.java @@ -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 { + +} 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 index 0000000000..f49013bbaf --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/InvokableRuntimeType.java @@ -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 index 0000000000..d606f93047 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/KeyRuntimeType.java @@ -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 index 0000000000..355ceac37a --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafListRuntimeType.java @@ -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 index 0000000000..29c6f92aab --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/LeafRuntimeType.java @@ -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 index 0000000000..4e952d4e58 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ListRuntimeType.java @@ -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 index 0000000000..5aaa86f9e0 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ModuleRuntimeType.java @@ -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 index 0000000000..a89be0b8ea --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/NotificationRuntimeType.java @@ -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 index 0000000000..79899702a3 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OpaqueRuntimeType.java @@ -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 index 0000000000..8b4f26c368 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/OutputRuntimeType.java @@ -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 { + +} 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 index 0000000000..aff65482e1 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RpcRuntimeType.java @@ -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 index 0000000000..4e706d5408 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeType.java @@ -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 index 0000000000..1acbae79b1 --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/RuntimeTypeContainer.java @@ -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. + * + *

+ * One important omission is this method does not 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 index 0000000000..3d56fc9ebf --- /dev/null +++ b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/TypedefRuntimeType.java @@ -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(); +} diff --git a/binding/mdsal-binding-runtime-spi/src/main/java/module-info.java b/binding/mdsal-binding-runtime-spi/src/main/java/module-info.java index 7f5d452ade..ea8a90c818 100644 --- a/binding/mdsal-binding-runtime-spi/src/main/java/module-info.java +++ b/binding/mdsal-binding-runtime-spi/src/main/java/module-info.java @@ -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; diff --git a/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ForwardingBindingRuntimeContext.java b/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ForwardingBindingRuntimeContext.java index 978d5059ba..eec58a27db 100644 --- a/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ForwardingBindingRuntimeContext.java +++ b/binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ForwardingBindingRuntimeContext.java @@ -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 > AugmentationSchemaNode getAugmentationDefinition(final Class augClass) { + public > AugmentRuntimeType getAugmentationDefinition(final Class 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> cls) { + public ActionRuntimeType getActionDefinition(final Class> cls) { return delegate().getActionDefinition(cls); } @Override - public Entry getResolvedAugmentationSchema( - final DataNodeContainer target, final Class> aug) { - return delegate().getResolvedAugmentationSchema(target, aug); - } - - @Override - public Optional getCaseSchemaDefinition(final ChoiceSchemaNode schema, final Class childClass) { - return delegate().getCaseSchemaDefinition(schema, childClass); - } - - @Override - public Entry getTypeWithSchema(final Class type) { + public RuntimeType getTypeWithSchema(final Class type) { return delegate().getTypeWithSchema(type); } @Override - public Map> getChoiceCaseChildren(final DataNodeContainer schema) { - return delegate().getChoiceCaseChildren(schema); - } - - @Override - public Set> 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 getAvailableAugmentationTypes(final DataNodeContainer container) { - return delegate().getAvailableAugmentationTypes(container); + public Class loadClass(final JavaTypeName typeName) throws ClassNotFoundException { + return delegate().loadClass(typeName); } @Override - public Class getIdentityClass(final QName input) { - return delegate().getIdentityClass(input); + public Class getRpcInput(final QName rpcName) { + return delegate().getRpcInput(rpcName); } @Override - public Class loadClass(final Type type) throws ClassNotFoundException { - return delegate().loadClass(type); + public Class getRpcOutput(final QName rpcName) { + return delegate().getRpcOutput(rpcName); } } -- 2.36.6