d523b60f8dfeacb21565001a99a92a46e8330a61
[mdsal.git] / binding / mdsal-binding-generator / src / main / java / org / opendaylight / mdsal / binding / generator / impl / reactor / TypedefGenerator.java
1 /*
2  * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.binding.generator.impl.reactor;
9
10 import static com.google.common.base.Verify.verify;
11 import static java.util.Objects.requireNonNull;
12
13 import java.util.ArrayList;
14 import java.util.List;
15 import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultTypedefRuntimeType;
16 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
17 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
18 import org.opendaylight.mdsal.binding.model.api.Type;
19 import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition;
20 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
21 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
22 import org.opendaylight.mdsal.binding.runtime.api.TypedefRuntimeType;
23 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
24 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
26
27 /**
28  * Generator corresponding to a {@code typedef} statement.
29  */
30 final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiveStatement, TypedefRuntimeType> {
31     /**
32      * List of all generators for types directly derived from this typedef. We populate this list during initial type
33      * linking. It allows us to easily cascade inferences made by this typedef down the type derivation tree.
34      */
35     private List<AbstractTypeObjectGenerator<?, ?>> derivedGenerators = null;
36
37     TypedefGenerator(final TypedefEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
38         super(statement, parent);
39     }
40
41     @Override
42     StatementNamespace namespace() {
43         return StatementNamespace.TYPEDEF;
44     }
45
46     @Override
47     void pushToInference(final SchemaInferenceStack dataTree) {
48         dataTree.enterTypedef(statement().argument());
49     }
50
51     void addDerivedGenerator(final AbstractTypeObjectGenerator<?, ?> derivedGenerator) {
52         if (derivedGenerators == null) {
53             derivedGenerators = new ArrayList<>(4);
54         }
55         derivedGenerators.add(requireNonNull(derivedGenerator));
56     }
57
58     @Override
59     void bindDerivedGenerators(final TypeReference reference) {
60         // Trigger any derived resolvers ...
61         if (derivedGenerators != null) {
62             for (AbstractTypeObjectGenerator<?, ?> derived : derivedGenerators) {
63                 derived.bindTypeDefinition(reference);
64             }
65         }
66         // ... and make sure nobody can come in late
67         derivedGenerators = List.of();
68     }
69
70     @Override
71     ClassPlacement classPlacementImpl() {
72         return ClassPlacement.TOP_LEVEL;
73     }
74
75     @Override
76     TypeDefinition<?> extractTypeDefinition() {
77         return statement().getTypeDefinition();
78     }
79
80     @Override
81     GeneratedTransferObject createDerivedType(final TypeBuilderFactory builderFactory,
82             final GeneratedTransferObject baseType) {
83         final GeneratedTOBuilder builder = builderFactory.newGeneratedTOBuilder(typeName());
84         builder.setTypedef(true);
85         builder.setExtendsType(baseType);
86         builder.setIsUnion(baseType.isUnionType());
87         builder.setRestrictions(computeRestrictions());
88         YangSourceDefinition.of(currentModule().statement(), statement()).ifPresent(builder::setYangSourceDefinition);
89
90         final TypeDefinition<?> typedef = statement().getTypeDefinition();
91         annotateDeprecatedIfNecessary(typedef, builder);
92         addStringRegExAsConstant(builder, resolveRegExpressions(typedef));
93         addUnits(builder, typedef);
94
95         makeSerializable(builder);
96         return builder.build();
97     }
98
99     @Override
100     TypedefRuntimeType createExternalRuntimeType(final Type type) {
101         verify(type instanceof GeneratedType, "Unexpected type %s", type);
102         return new DefaultTypedefRuntimeType((GeneratedType) type, statement());
103     }
104
105     @Override
106     TypedefRuntimeType createInternalRuntimeType(final AugmentResolver resolver,
107             final TypedefEffectiveStatement statement, final Type type) {
108         // 'typedef' statements are not schema tree statements, they should not have internal references
109         throw new UnsupportedOperationException("Should never be called");
110     }
111
112     @Override
113     void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
114         // typedefs are a separate concept
115     }
116 }