2 * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.mdsal.binding.generator.impl.reactor;
10 import static com.google.common.base.Verify.verify;
11 import static com.google.common.base.Verify.verifyNotNull;
13 import java.util.Comparator;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
16 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
17 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
18 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
19 import org.opendaylight.mdsal.binding.model.util.BindingTypes;
20 import org.opendaylight.yangtools.odlext.model.api.AugmentIdentifierEffectiveStatement;
21 import org.opendaylight.yangtools.yang.common.AbstractQName;
22 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
23 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
26 * A generator corresponding to a {@code augment} statement. This class is further specialized for the two distinct uses
29 abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<AugmentEffectiveStatement> {
31 * Comparator comparing target path length. This is useful for quickly determining order the order in which two
32 * (or more) {@link AbstractAugmentGenerator}s need to be evaluated. This is necessary when augments are layered on
51 * Evaluating these in the order of increasing argument component count solves this without having to perform a full
54 static final Comparator<? super AbstractAugmentGenerator> COMPARATOR =
55 Comparator.comparingInt(augment -> augment.statement().argument().getNodeIdentifiers().size());
57 private AbstractCompositeGenerator<?> targetGen;
59 AbstractAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
60 super(statement, parent);
64 final void pushToInference(final SchemaInferenceStack dataTree) {
65 dataTree.enterSchemaTree(statement().argument());
69 final AbstractQName localName() {
70 throw new UnsupportedOperationException();
74 ClassPlacement classPlacement() {
75 // if the target is a choice we are NOT creating an explicit augmentation, but we still need a phantom to
76 // reserve the appropriate package name
77 final AbstractCompositeGenerator<?> target = targetGenerator();
78 return target instanceof ChoiceGenerator ? ClassPlacement.PHANTOM : super.classPlacement();
82 final Member createMember(final CollisionDomain domain) {
83 final AbstractQName explicitIdentifier = statement()
84 .findFirstEffectiveSubstatementArgument(AugmentIdentifierEffectiveStatement.class).orElse(null);
85 if (explicitIdentifier != null) {
86 return domain.addPrimary(new CamelCaseNamingStrategy(StatementNamespace.DEFAULT, explicitIdentifier));
89 final AbstractCompositeGenerator<?> target = targetGenerator();
90 final AbstractQName ref = target.localName();
92 for (Generator gen : getParent()) {
96 if (gen instanceof AbstractAugmentGenerator
97 && ref.equals(((AbstractAugmentGenerator) gen).targetGenerator().localName())) {
102 return domain.addSecondary(target.getMember(), String.valueOf(offset), statement().argument());
106 final GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
107 final GeneratedTypeBuilder builder = builderFactory.newGeneratedTypeBuilder(typeName());
109 builder.addImplementsType(BindingTypes.augmentation(targetGenerator().getGeneratedType(builderFactory)));
110 addUsesInterfaces(builder, builderFactory);
111 addConcreteInterfaceMethods(builder);
113 addGetterMethods(builder, builderFactory);
114 annotateDeprecatedIfNecessary(builder);
116 return builder.build();
120 final void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
121 // Augments are never added as getters, as they are handled via Augmentable mechanics
124 final void setTargetGenerator(final AbstractExplicitGenerator<?> target) {
125 verify(target instanceof AbstractCompositeGenerator, "Unexpected target %s", target);
126 targetGen = (AbstractCompositeGenerator<?>) target;
127 targetGen.addAugment(this);
130 final @NonNull AbstractCompositeGenerator<?> targetGenerator() {
131 final AbstractCompositeGenerator<?> existing = targetGen;
132 if (existing != null) {
133 return existing.getOriginal();
136 loadTargetGenerator();
137 return verifyNotNull(targetGen, "No target for %s", this).getOriginal();
140 abstract void loadTargetGenerator();