Retain grouping/uses instantiation vectors
[mdsal.git] / binding / mdsal-binding-generator / src / main / java / org / opendaylight / mdsal / binding / generator / impl / reactor / GroupingGenerator.java
index 8697f97bc39a1d1aeb2e28ce457229bbc4067a1e..5df077961327ecf20f0cbc43277adac74dc34f2a 100644 (file)
@@ -7,12 +7,12 @@
  */
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
-import static com.google.common.base.Verify.verify;
-
+import com.google.common.base.VerifyException;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 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;
@@ -26,10 +26,35 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
  * Generator corresponding to a {@code grouping} statement.
  */
 final class GroupingGenerator extends AbstractCompositeGenerator<GroupingEffectiveStatement, GroupingRuntimeType> {
+    // Linkage towards concrete data tree instantiations of this grouping. This can contain two different kinds of
+    // generators:
+    // - GroupingGenerators which provide next step in the linkage
+    // - other composite generators, which are the actual instantiations
+    private List<AbstractCompositeGenerator<?, ?>> users;
+
     GroupingGenerator(final GroupingEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
+    void addUser(final AbstractCompositeGenerator<?, ?> user) {
+        if (users == null) {
+            // We are adding the first user: allocate a small set and notify the groupings we use that we are a user
+            users = new ArrayList<>();
+            for (var grouping : groupings()) {
+                grouping.addUser(this);
+            }
+        }
+        users.add(user);
+    }
+
+    boolean hasUser() {
+        return users != null;
+    }
+
+    void freezeUsers() {
+        users = users == null ? List.of() : users.stream().distinct().collect(Collectors.toUnmodifiableList());
+    }
+
     @Override
     StatementNamespace namespace() {
         return StatementNamespace.GROUPING;
@@ -42,13 +67,13 @@ final class GroupingGenerator extends AbstractCompositeGenerator<GroupingEffecti
 
     @Override
     GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
-        final GeneratedTypeBuilder builder = builderFactory.newGeneratedTypeBuilder(typeName());
+        final var builder = builderFactory.newGeneratedTypeBuilder(typeName());
         builder.addImplementsType(BindingTypes.DATA_OBJECT);
         narrowImplementedInterface(builder);
         addUsesInterfaces(builder, builderFactory);
         addGetterMethods(builder, builderFactory);
 
-        final ModuleGenerator module = currentModule();
+        final var module = currentModule();
         module.addQNameConstant(builder, statement().argument());
 
         annotateDeprecatedIfNecessary(builder);
@@ -65,15 +90,26 @@ final class GroupingGenerator extends AbstractCompositeGenerator<GroupingEffecti
     @Override
     CompositeRuntimeTypeBuilder<GroupingEffectiveStatement, GroupingRuntimeType> createBuilder(
             final GroupingEffectiveStatement statement) {
+        final var local = users;
+        if (local == null) {
+            throw new VerifyException(this + " has unresolved users");
+        }
+
+        final var vectors = local.stream()
+            .map(AbstractCompositeGenerator::getRuntimeType)
+            .distinct()
+            .collect(Collectors.toUnmodifiableList());
+
         return new CompositeRuntimeTypeBuilder<>(statement) {
             @Override
             GroupingRuntimeType build(final GeneratedType type, final GroupingEffectiveStatement statement,
                     final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
                 // Groupings cannot be targeted by 'augment'
-                verify(augments.isEmpty(), "Unexpected augments %s", augments);
-                return new DefaultGroupingRuntimeType(type, statement, children);
+                if (augments.isEmpty()) {
+                    return new DefaultGroupingRuntimeType(type, statement, children, vectors);
+                }
+                throw new VerifyException("Unexpected augments " + augments);
             }
         };
     }
-
 }