629306c8db50ea49e1ee57c5fa2689f6b77e2852
[mdsal.git] / binding / mdsal-binding-generator / src / main / java / org / opendaylight / mdsal / binding / generator / impl / reactor / TypeReference.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 java.util.stream.Collectors;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.eclipse.jdt.annotation.Nullable;
16 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
17 import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
18 import org.opendaylight.mdsal.binding.model.api.Type;
19 import org.opendaylight.mdsal.binding.model.ri.Types;
20
21 abstract class TypeReference {
22     private static final class Identityref extends TypeReference {
23         private final List<IdentityGenerator> referencedGenerators;
24
25         private ParameterizedType returnType;
26
27         Identityref(final List<IdentityGenerator> referencedGenerators) {
28             this.referencedGenerators = requireNonNull(referencedGenerators);
29         }
30
31         @Override
32         Type methodReturnType(final TypeBuilderFactory builderFactory) {
33             if (returnType == null) {
34                 final List<GeneratedType> referencedTypes = referencedGenerators.stream()
35                     .map(gen -> gen.getGeneratedType(builderFactory))
36                     .collect(Collectors.toUnmodifiableList());
37                 // FIXME: This deals only with RFC6020 semantics. In order to deal with full RFC7950 semantics, we need
38                 //        to analyze all the types and come up with the lowest-common denominator and use that as the
39                 //        return type. We also need to encode restrictions, so that builder generator ends up checking
40                 //        identities being passed -- because the identities may be completely unrelated, in which case
41                 //        we cannot generate type-safe code.
42                 returnType = Types.classType(Types.wildcardTypeFor(referencedTypes.get(0).getIdentifier()));
43             }
44             return returnType;
45         }
46     }
47
48     // Note: this is exposed only for legacy naming handling
49     abstract static class Leafref extends TypeReference {
50         private Leafref() {
51             // Hidden on purpose
52         }
53     }
54
55     static final class ResolvedLeafref extends Leafref {
56         private final AbstractTypeObjectGenerator<?, ?> referencedGenerator;
57
58         private ResolvedLeafref(final AbstractTypeObjectGenerator<?, ?> referencedGenerator) {
59             this.referencedGenerator = requireNonNull(referencedGenerator);
60         }
61
62         @Override
63         Type methodReturnType(final TypeBuilderFactory builderFactory) {
64             return referencedGenerator.methodReturnElementType(builderFactory);
65         }
66     }
67
68     private static final class UnresolvedLeafref extends Leafref {
69         static final @NonNull UnresolvedLeafref INSTANCE = new UnresolvedLeafref();
70
71         private UnresolvedLeafref() {
72             // Hidden on purpose
73         }
74
75         @Override
76         Type methodReturnType(final TypeBuilderFactory builderFactory) {
77             return Types.objectType();
78         }
79     }
80
81     static @NonNull TypeReference leafRef(final @Nullable AbstractTypeObjectGenerator<?, ?> referencedGenerator) {
82         return referencedGenerator == null ? UnresolvedLeafref.INSTANCE : new ResolvedLeafref(referencedGenerator);
83     }
84
85     static @NonNull TypeReference identityRef(final List<IdentityGenerator> referencedGenerators) {
86         return new Identityref(referencedGenerators);
87     }
88
89     abstract @NonNull Type methodReturnType(@NonNull TypeBuilderFactory builderFactory);
90 }