Cleanup AbstractBindingRuntimeContext.getAvailableAugmentationTypes() 09/97909/9
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 15 Oct 2021 16:01:22 +0000 (18:01 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 15 Oct 2021 18:10:44 +0000 (20:10 +0200)
We are performing lookups along augmentation instantiation axis using
APIs which are going away. Cleanup the code and move the traversal to
BindingRuntimeTypes.

Leave a FIXME for getting the required intelligence from
GeneratorReactor as well as some sorely-needed documentation as to what
exactly is going on.

JIRA: MDSAL-695
Change-Id: I6dd7ad7807546091bfbc5cced48b574d6bff49e2
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AbstractBindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java

index 14889c53dd0642a6a34f7988564375a506ce72a6..f75c0e6ac3bd3ed6a34ec05d832fce28fcb94f98 100644 (file)
@@ -317,6 +317,20 @@ abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?, ?>> ex
             } else if (stmt instanceof TypedefEffectiveStatement) {
                 tmp.add(new TypedefGenerator((TypedefEffectiveStatement) stmt, this));
             } else if (stmt instanceof AugmentEffectiveStatement) {
+                // FIXME: MDSAL-695: So here we are ignoring any augment which is not in a module, while the 'uses'
+                //                   processing takes care of the rest. There are two problems here:
+                //
+                //                   1) this could be an augment introduced through uses -- in this case we are picking
+                //                      confusing it with this being its declaration site, we should probably be
+                //                      ignoring it, but then
+                //
+                //                   2) we are losing track of AugmentEffectiveStatement for which we do not generate
+                //                      interfaces -- and recover it at runtime through explicit walk along the
+                //                      corresponding AugmentationSchemaNode.getOriginalDefinition() pointer
+                //
+                //                   So here is where we should decide how to handle this augment, and make sure we
+                //                   retain information about this being an alias. That will serve as the base for keys
+                //                   in the augment -> original map we provide to BindingRuntimeTypes.
                 if (this instanceof ModuleGenerator) {
                     tmpAug.add(new ModuleAugmentGenerator((AugmentEffectiveStatement) stmt, this));
                 }
index 876cdd42a79f09cfeca7f7a9cd712556140a441a..0cf67bc68fed7eefeb8134cf249d7651b799defa 100644 (file)
@@ -284,25 +284,18 @@ public abstract class AbstractBindingRuntimeContext implements BindingRuntimeCon
     public final ImmutableMap<AugmentationIdentifier, Type> getAvailableAugmentationTypes(
             final DataNodeContainer container) {
         if (container instanceof AugmentationTarget) {
-            final Map<AugmentationIdentifier, Type> identifierToType = new HashMap<>();
-            final BindingRuntimeTypes types = getTypes();
-            for (final AugmentationSchemaNode augment : ((AugmentationTarget) container).getAvailableAugmentations()) {
-                // Augmentation must have child nodes if is to be used with Binding classes
-                AugmentationSchemaNode augOrig = augment;
-                while (augOrig.getOriginalDefinition().isPresent()) {
-                    augOrig = augOrig.getOriginalDefinition().get();
-                }
-
-                if (!augment.getChildNodes().isEmpty()) {
-                    final Optional<Type> augType = types.findType(augOrig);
-                    if (augType.isPresent()) {
-                        identifierToType.put(getAugmentationIdentifier(augment), augType.get());
-                    }
+            final var augmentations = ((AugmentationTarget) container).getAvailableAugmentations();
+            if (!augmentations.isEmpty()) {
+                final var identifierToType = new HashMap<AugmentationIdentifier, Type>();
+                final var types = getTypes();
+                for (var augment : augmentations) {
+                    types.findOriginalAugmentationType(augment).ifPresent(augType -> {
+                        identifierToType.put(getAugmentationIdentifier(augment), augType);
+                    });
                 }
+                return ImmutableMap.copyOf(identifierToType);
             }
-            return ImmutableMap.copyOf(identifierToType);
         }
-
         return ImmutableMap.of();
     }
 
index 5ee85731b139e4f72acbef10ed263512ab57f4e3..66830d30e5a175960248920d90ff7b46519f55dd 100644 (file)
@@ -134,6 +134,14 @@ public interface BindingRuntimeContext extends EffectiveModelContextProvider, Im
 
     @NonNull Class<?> getClassForSchema(SchemaNode childSchema);
 
+    /**
+     * Return the mapping of a particular {@link DataNodeContainer}'s available augmentations. This method deals with
+     * resolving {@code uses foo { augment bar { ... } } } scenarios by returning the augmentation created for
+     * {@code grouping foo}'s Binding representation.
+     *
+     * @param container {@link DataNodeContainer} to examine
+     * @return a mapping from local {@link AugmentationIdentifier}s to their corresponding Binding augmentations
+     */
     @NonNull ImmutableMap<AugmentationIdentifier, Type> getAvailableAugmentationTypes(DataNodeContainer container);
 
     @NonNull Class<?> getIdentityClass(QName input);
index 2367c33d52ff1422cb28cd9cadf513f732a31d6d..55d6f150de4bda624212cf21bf7fc23a41903c6f 100644 (file)
@@ -161,6 +161,31 @@ public final class BindingRuntimeTypes implements EffectiveModelContextProvider,
         return Optional.ofNullable(schemaToType.get(schema));
     }
 
+    public Optional<Type> findOriginalAugmentationType(final AugmentationSchemaNode augment) {
+        // If the augment statement does not contain any child nodes, we did not generate an augmentation, as it would
+        // be plain littering.
+        // FIXME: MDSAL-695: this check is rather costly (involves filtering), can we just rely on the not being found
+        //                   in the end? all we are saving is essentially two map lookups after all...
+        if (augment.getChildNodes().isEmpty()) {
+            return Optional.empty();
+        }
+
+        // FIXME: MDSAL-695: We should have enough information from mdsal-binding-generator to receive a (sparse) Map
+        //                   for current -> original lookup. When combined with schemaToType, this amounts to the
+        //                   inverse view of what 'typeToSchema' holds
+        AugmentationSchemaNode current = augment;
+        while (true) {
+            // If this augmentation has been added through 'uses foo { augment bar { ... } }', we need to invert that
+            // walk and arrive at the original declaration site, as that is where we generated 'grouping foo's
+            // augmentation. That site may have a different module, hence the augment namespace may be different.
+            final Optional<AugmentationSchemaNode> original = current.getOriginalDefinition();
+            if (original.isEmpty()) {
+                return findType(current);
+            }
+            current = original.orElseThrow();
+        }
+    }
+
     public Multimap<Type, Type> getChoiceToCases() {
         return choiceToCases;
     }