5f097171d3eedab4ed6aa55b1c840f1839ae32b0
[mdsal.git] / binding / mdsal-binding-generator / src / main / java / org / opendaylight / mdsal / binding / generator / impl / reactor / YangDataGenerator.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 java.util.Objects.requireNonNull;
11
12 import java.util.List;
13 import org.eclipse.jdt.annotation.NonNull;
14 import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
15 import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultYangDataRuntimeType;
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.ri.BindingTypes;
20 import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
21 import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
22 import org.opendaylight.mdsal.binding.runtime.api.YangDataRuntimeType;
23 import org.opendaylight.yangtools.rfc8040.model.api.YangDataEffectiveStatement;
24 import org.opendaylight.yangtools.yang.common.UnresolvedQName;
25 import org.opendaylight.yangtools.yang.common.UnresolvedQName.Unqualified;
26 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
27
28 /**
29  * Generator corresponding to a {@code rc:yang-data} statement.
30  */
31 abstract sealed class YangDataGenerator
32         extends AbstractCompositeGenerator<YangDataEffectiveStatement, YangDataRuntimeType> {
33     private static final class WithIdentifier extends YangDataGenerator {
34         private final @NonNull Unqualified identifier;
35
36         WithIdentifier(final YangDataEffectiveStatement statement, final ModuleGenerator parent,
37                 final Unqualified identifier) {
38             super(statement, parent);
39             this.identifier = requireNonNull(identifier);
40         }
41
42         @Override
43         CamelCaseNamingStrategy createNamingStrategy() {
44             return new CamelCaseNamingStrategy(namespace(), identifier);
45         }
46     }
47
48     private static final class WithString extends YangDataGenerator {
49         WithString(final YangDataEffectiveStatement statement, final ModuleGenerator parent) {
50             super(statement, parent);
51         }
52
53         @Override
54         YangDataNamingStrategy createNamingStrategy() {
55             return new YangDataNamingStrategy(statement().argument());
56         }
57     }
58
59     private YangDataGenerator(final YangDataEffectiveStatement statement, final ModuleGenerator parent) {
60         super(statement, parent);
61     }
62
63     static @NonNull YangDataGenerator of(final YangDataEffectiveStatement statement, final ModuleGenerator parent) {
64         // yang-data's argument is not guaranteed to comply with YANG 'identifier', but it usually does. If it does, we
65         // use the usual mechanics, but if it does not, we have to deal with any old string, similar to what we do for
66         // bit names. Here we decide which path to take.
67         final String templateName = statement.argument().name();
68         final var identifier = UnresolvedQName.tryLocalName(templateName);
69         return identifier != null ? new WithIdentifier(statement, parent, identifier)
70             : new WithString(statement, parent);
71     }
72
73     @Override
74     final void pushToInference(final SchemaInferenceStack dataTree) {
75         dataTree.enterYangData(statement().argument());
76     }
77
78     @Override
79     final ClassPlacement classPlacement() {
80         return ClassPlacement.TOP_LEVEL;
81     }
82
83     @Override
84     final Member createMember(final CollisionDomain domain) {
85         return domain.addPrimary(this, createNamingStrategy());
86     }
87
88     abstract @NonNull ClassNamingStrategy createNamingStrategy();
89
90     @Override
91     final StatementNamespace namespace() {
92         return StatementNamespace.YANG_DATA;
93     }
94
95     @Override
96     final GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
97         final GeneratedTypeBuilder builder = builderFactory.newGeneratedTypeBuilder(typeName());
98
99         builder.addImplementsType(BindingTypes.yangData(builder));
100         addUsesInterfaces(builder, builderFactory);
101         addConcreteInterfaceMethods(builder);
102
103         addGetterMethods(builder, builderFactory);
104
105         final var module = currentModule();
106         module.addNameConstant(builder, statement().argument());
107
108         builder.setModuleName(module.statement().argument().getLocalName());
109         builderFactory.addCodegenInformation(module, statement(), builder);
110
111         return builder.build();
112     }
113
114     @Override
115     final CompositeRuntimeTypeBuilder<YangDataEffectiveStatement, YangDataRuntimeType> createBuilder(
116             final YangDataEffectiveStatement statement) {
117         return new CompositeRuntimeTypeBuilder<>(statement) {
118             @Override
119             YangDataRuntimeType build(final GeneratedType type, final YangDataEffectiveStatement statement,
120                     final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
121                 return new DefaultYangDataRuntimeType(type, statement, children);
122             }
123         };
124     }
125
126     @Override
127     final void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
128         // is not a part of any structure
129     }
130 }