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;
12 import static java.util.Objects.requireNonNull;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultTypedefRuntimeType;
17 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
18 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
19 import org.opendaylight.mdsal.binding.model.api.Type;
20 import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition;
21 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
22 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
23 import org.opendaylight.mdsal.binding.model.ri.TypeConstants;
24 import org.opendaylight.mdsal.binding.model.ri.Types;
25 import org.opendaylight.mdsal.binding.runtime.api.TypedefRuntimeType;
26 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
27 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
28 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
29 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
32 * Generator corresponding to a {@code typedef} statement.
34 final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiveStatement, TypedefRuntimeType> {
36 * List of all generators for types directly derived from this typedef. We populate this list during initial type
37 * linking. It allows us to easily cascade inferences made by this typedef down the type derivation tree.
39 private List<AbstractTypeObjectGenerator<?, ?>> derivedGenerators = null;
41 TypedefGenerator(final TypedefEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
42 super(statement, parent);
46 StatementNamespace namespace() {
47 return StatementNamespace.TYPEDEF;
51 void pushToInference(final SchemaInferenceStack dataTree) {
52 dataTree.enterTypedef(statement().argument());
55 void addDerivedGenerator(final AbstractTypeObjectGenerator<?, ?> derivedGenerator) {
56 if (derivedGenerators == null) {
57 derivedGenerators = new ArrayList<>(4);
59 derivedGenerators.add(requireNonNull(derivedGenerator));
63 void bindDerivedGenerators(final TypeReference reference) {
64 // Trigger any derived resolvers ...
65 if (derivedGenerators != null) {
66 for (AbstractTypeObjectGenerator<?, ?> derived : derivedGenerators) {
67 derived.bindTypeDefinition(reference);
70 // ... and make sure nobody can come in late
71 derivedGenerators = List.of();
75 ClassPlacement classPlacementImpl() {
76 return ClassPlacement.TOP_LEVEL;
80 TypeDefinition<?> extractTypeDefinition() {
81 return statement().getTypeDefinition();
85 GeneratedTransferObject createDerivedType(final TypeBuilderFactory builderFactory,
86 final GeneratedTransferObject baseType) {
87 final GeneratedTOBuilder builder = builderFactory.newGeneratedTOBuilder(typeName());
88 builder.setTypedef(true);
89 builder.setExtendsType(baseType);
90 builder.setIsUnion(baseType.isUnionType());
91 builder.setRestrictions(computeRestrictions());
92 YangSourceDefinition.of(currentModule().statement(), statement()).ifPresent(builder::setYangSourceDefinition);
94 final TypeDefinition<?> typedef = statement().getTypeDefinition();
95 annotateDeprecatedIfNecessary(typedef, builder);
96 addStringRegExAsConstant(builder, resolveRegExpressions(typedef));
97 addUnits(builder, typedef);
99 if (typedef instanceof BitsTypeDefinition bits) {
100 addValidBits(builder, bits, baseType);
103 makeSerializable(builder);
104 return builder.build();
107 private static void addValidBits(final GeneratedTOBuilder builder, final BitsTypeDefinition typedef,
108 final GeneratedTransferObject baseType) {
109 final var baseDef = verifyNotNull(baseBitsDefinition(baseType), "Could not find definition in %s", baseType);
110 final var myBits = typedef.getBits();
111 if (myBits.size() != baseDef.getBits().size()) {
112 builder.addConstant(Types.immutableSetTypeFor(Types.STRING), TypeConstants.VALID_NAMES_NAME, typedef);
116 private static BitsTypeDefinition baseBitsDefinition(final GeneratedTransferObject gto) {
118 while (wlk != null) {
119 for (var constant : wlk.getConstantDefinitions()) {
120 if (TypeConstants.VALID_NAMES_NAME.equals(constant.getName())) {
121 return (BitsTypeDefinition) constant.getValue();
125 wlk = wlk.getSuperType();
131 TypedefRuntimeType createExternalRuntimeType(final Type type) {
132 verify(type instanceof GeneratedType, "Unexpected type %s", type);
133 return new DefaultTypedefRuntimeType((GeneratedType) type, statement());
137 TypedefRuntimeType createInternalRuntimeType(final AugmentResolver resolver,
138 final TypedefEffectiveStatement statement, final Type type) {
139 // 'typedef' statements are not schema tree statements, they should not have internal references
140 throw new UnsupportedOperationException("Should never be called");
144 void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
145 // typedefs are a separate concept