Generate javadoc for augments
[mdsal.git] / binding / mdsal-binding-generator / src / main / java / org / opendaylight / mdsal / binding / generator / impl / reactor / AbstractAugmentGenerator.java
index b9c92cd1cb89bece58f184a5e15971c901224e9e..d48e841929b81ff106c8cc81729270e0f08b9099 100644 (file)
@@ -11,25 +11,39 @@ 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.Comparator;
 import java.util.Iterator;
+import java.util.List;
+import java.util.function.Function;
 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.YangSourceDefinition;
 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.CaseRuntimeType;
+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.ChoiceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement.SchemaTreeNamespace;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
  * A generator corresponding to a {@code augment} statement. This class is further specialized for the two distinct uses
  * an augment is used.
  */
-abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<AugmentEffectiveStatement> {
+abstract class AbstractAugmentGenerator
+        extends AbstractCompositeGenerator<AugmentEffectiveStatement, AugmentRuntimeType> {
     /**
      * Comparator comparing target path length. This is useful for quickly determining order the order in which two
      * (or more) {@link AbstractAugmentGenerator}s need to be evaluated. This is necessary when augments are layered on
@@ -78,9 +92,9 @@ abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<Augme
         return otherIt.hasNext() ? -1 : 0;
     };
 
-    private AbstractCompositeGenerator<?> targetGen;
+    private AbstractCompositeGenerator<?, ?> targetGen;
 
-    AbstractAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+    AbstractAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
         super(statement, parent);
     }
 
@@ -98,7 +112,7 @@ abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<Augme
     ClassPlacement classPlacement() {
         // if the target is a choice we are NOT creating an explicit augmentation, but we still need a phantom to
         // reserve the appropriate package name
-        final AbstractCompositeGenerator<?> target = targetGenerator();
+        final AbstractCompositeGenerator<?, ?> target = targetGenerator();
         return target instanceof ChoiceGenerator ? ClassPlacement.PHANTOM : super.classPlacement();
     }
 
@@ -129,6 +143,7 @@ abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<Augme
     final GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
         final GeneratedTypeBuilder builder = builderFactory.newGeneratedTypeBuilder(typeName());
 
+        YangSourceDefinition.of(currentModule().statement(), statement()).ifPresent(builder::setYangSourceDefinition);
         builder.addImplementsType(BindingTypes.augmentation(targetGenerator().getGeneratedType(builderFactory)));
         addUsesInterfaces(builder, builderFactory);
         addConcreteInterfaceMethods(builder);
@@ -139,17 +154,66 @@ abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<Augme
         return builder.build();
     }
 
+    boolean matchesInstantiated(final AugmentEffectiveStatement statement) {
+        return statement().equals(statement);
+    }
+
+    final void fillRuntimeCasesIn(final AugmentResolver resolver, final ChoiceEffectiveStatement stmt,
+            final List<CaseRuntimeType> toList) {
+        toList.addAll(createBuilder(effectiveIn(stmt)).populate(resolver, this).getCaseChilden());
+    }
+
+    final @NonNull AugmentRuntimeType runtimeTypeIn(final AugmentResolver resolver,
+            final EffectiveStatement<?, ?> stmt) {
+        verify(stmt instanceof SchemaTreeAwareEffectiveStatement, "Unexpected target statement %s", stmt);
+        return verifyNotNull(createInternalRuntimeType(resolver,
+            effectiveIn((SchemaTreeAwareEffectiveStatement<?, ?>) stmt)));
+    }
+
+    abstract @NonNull TargetAugmentEffectiveStatement effectiveIn(SchemaTreeAwareEffectiveStatement<?, ?> target);
+
+    final @NonNull TargetAugmentEffectiveStatement effectiveIn(final SchemaTreeAwareEffectiveStatement<?, ?> target,
+            final Function<QName, QName> transform) {
+        final var augment = statement();
+        final var stmts = augment.effectiveSubstatements();
+        final var builder = ImmutableList.<EffectiveStatement<?, ?>>builderWithExpectedSize(stmts.size());
+        for (var child : stmts) {
+            if (child instanceof SchemaTreeEffectiveStatement) {
+                final var qname = ((SchemaTreeEffectiveStatement<?>) child).getIdentifier();
+                // Note: a match in target may be missing -- for example if it was 'deviate unsupported'
+                target.get(SchemaTreeNamespace.class, transform.apply(qname)).ifPresent(builder::add);
+            } else {
+                builder.add(child);
+            }
+        }
+        return new TargetAugmentEffectiveStatement(augment, target, builder.build());
+    }
+
     @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) {
+    @Override
+    CompositeRuntimeTypeBuilder<AugmentEffectiveStatement, AugmentRuntimeType> createBuilder(
+            final AugmentEffectiveStatement statement) {
+        return new CompositeRuntimeTypeBuilder<>(statement) {
+            @Override
+            AugmentRuntimeType build(final GeneratedType type, final AugmentEffectiveStatement statement,
+                    final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+                // 'augment' cannot be targeted by augment
+                verify(augments.isEmpty(), "Unexpected augments %s", augments);
+                return new DefaultAugmentRuntimeType(type, statement, children);
+            }
+        };
+    }
+
+    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);
     }
 }