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