Propagate @NonNull around JavaFileTemplate
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / JavaFileTemplate.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, 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.java.api.generator;
9
10 import static com.google.common.base.Verify.verify;
11 import static java.util.Objects.requireNonNull;
12
13 import java.util.Arrays;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Objects;
17 import java.util.Optional;
18 import java.util.regex.Pattern;
19 import java.util.stream.Collectors;
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.opendaylight.mdsal.binding.model.api.ConcreteType;
22 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty;
23 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
24 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
25 import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
26 import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
27 import org.opendaylight.mdsal.binding.model.api.Restrictions;
28 import org.opendaylight.mdsal.binding.model.api.Type;
29 import org.opendaylight.mdsal.binding.model.util.Types;
30 import org.opendaylight.yangtools.yang.binding.CodeHelpers;
31
32 /**
33  * Base Java file template. Contains a non-null type and imports which the generated code refers to.
34  */
35 class JavaFileTemplate {
36     /**
37      * {@code java.lang.Class} as a JavaTypeName.
38      */
39     static final @NonNull JavaTypeName CLASS = JavaTypeName.create(Class.class);
40     /**
41      * {@code java.lang.Deprecated} as a JavaTypeName.
42      */
43     static final @NonNull JavaTypeName DEPRECATED = JavaTypeName.create(Deprecated.class);
44     /**
45      * {@code java.lang.Override} as a JavaTypeName.
46      */
47     static final @NonNull JavaTypeName OVERRIDE = JavaTypeName.create(Override.class);
48
49     /**
50      * {@code java.lang.SuppressWarnings} as a JavaTypeName.
51      */
52     static final @NonNull JavaTypeName SUPPRESS_WARNINGS = JavaTypeName.create(SuppressWarnings.class);
53
54     /**
55      * {@code java.util.Arrays} as a JavaTypeName.
56      */
57     static final @NonNull JavaTypeName JU_ARRAYS = JavaTypeName.create(Arrays.class);
58     /**
59      * {@code java.util.List} as a JavaTypeName.
60      */
61     static final @NonNull JavaTypeName JU_LIST = JavaTypeName.create(List.class);
62     /**
63      * {@code java.util.Map} as a JavaTypeName.
64      */
65     static final @NonNull JavaTypeName JU_MAP = JavaTypeName.create(Map.class);
66     /**
67      * {@code java.util.Objects} as a JavaTypeName.
68      */
69     static final @NonNull JavaTypeName JU_OBJECTS = JavaTypeName.create(Objects.class);
70     /**
71      * {@code java.util.regex.Pattern} as a JavaTypeName.
72      */
73     static final @NonNull JavaTypeName JUR_PATTERN = JavaTypeName.create(Pattern.class);
74
75     /**
76      * {@code org.eclipse.jdt.annotation.NonNull} as a JavaTypeName.
77      */
78     static final @NonNull JavaTypeName NONNULL = JavaTypeName.create("org.eclipse.jdt.annotation", "NonNull");
79     /**
80      * {@code org.eclipse.jdt.annotation.Nullable} as a JavaTypeName.
81      */
82     static final @NonNull JavaTypeName NULLABLE = JavaTypeName.create("org.eclipse.jdt.annotation", "Nullable");
83
84     /**
85      * {@code org.opendaylight.yangtools.yang.binding.CodeHelpers} as a JavaTypeName.
86      */
87     static final @NonNull JavaTypeName CODEHELPERS = JavaTypeName.create(CodeHelpers.class);
88
89     private final AbstractJavaGeneratedType javaType;
90     private final GeneratedType type;
91
92     JavaFileTemplate(final @NonNull GeneratedType type) {
93         this(new TopLevelJavaGeneratedType(type), type);
94     }
95
96     JavaFileTemplate(final AbstractJavaGeneratedType javaType, final GeneratedType type) {
97         this.javaType = requireNonNull(javaType);
98         this.type = requireNonNull(type);
99     }
100
101     final AbstractJavaGeneratedType javaType() {
102         return javaType;
103     }
104
105     final GeneratedType type() {
106         return type;
107     }
108
109     final GeneratedProperty findProperty(final GeneratedTransferObject gto, final String name) {
110         final Optional<GeneratedProperty> optProp = gto.getProperties().stream()
111                 .filter(prop -> prop.getName().equals(name)).findFirst();
112         if (optProp.isPresent()) {
113             return optProp.get();
114         }
115
116         final GeneratedTransferObject parent = gto.getSuperType();
117         return parent != null ? findProperty(parent, name) : null;
118     }
119
120     final String generateImportBlock() {
121         verify(javaType instanceof TopLevelJavaGeneratedType);
122         return ((TopLevelJavaGeneratedType) javaType).imports().map(name -> "import " + name + ";\n")
123                 .collect(Collectors.joining());
124     }
125
126     final @NonNull String importedJavadocName(final @NonNull Type intype) {
127         return importedName(intype instanceof ParameterizedType ? ((ParameterizedType) intype).getRawType() : intype);
128     }
129
130     final @NonNull String importedName(final @NonNull Type intype) {
131         return javaType.getReferenceString(intype);
132     }
133
134     final @NonNull String importedName(final @NonNull Type intype, final @NonNull String annotation) {
135         return javaType.getReferenceString(intype, annotation);
136     }
137
138     final @NonNull String importedName(final Class<?> cls) {
139         return importedName(Types.typeForClass(cls));
140     }
141
142     final @NonNull String importedName(final @NonNull JavaTypeName intype) {
143         return javaType.getReferenceString(intype);
144     }
145
146     final @NonNull String importedNonNull(final @NonNull Type intype) {
147         return importedName(intype, importedName(NONNULL));
148     }
149
150     final @NonNull String importedNullable(final @NonNull Type intype) {
151         return importedName(intype, importedName(NULLABLE));
152     }
153
154     // Exposed for BuilderTemplate
155     boolean isLocalInnerClass(final JavaTypeName name) {
156         final Optional<JavaTypeName> optEnc = name.immediatelyEnclosingClass();
157         return optEnc.isPresent() && type.getIdentifier().equals(optEnc.get());
158     }
159
160     final CharSequence generateInnerClass(final GeneratedType innerClass) {
161         if (!(innerClass instanceof GeneratedTransferObject)) {
162             return "";
163         }
164
165         final GeneratedTransferObject gto = (GeneratedTransferObject) innerClass;
166         final NestedJavaGeneratedType innerJavaType = javaType.getEnclosedType(innerClass.getIdentifier());
167         return gto.isUnionType() ? new UnionTemplate(innerJavaType, gto).generateAsInnerClass()
168                 : new ClassTemplate(innerJavaType, gto).generateAsInnerClass();
169     }
170
171     /**
172      * Return imported name of java.util class, whose hashCode/equals methods we want to invoke on the property. Returns
173      * {@link Arrays} if the property is an array, {@link Objects} otherwise.
174      *
175      * @param property Generated property
176      * @return Imported class name
177      */
178     final String importedUtilClass(final GeneratedProperty property) {
179         return importedName(property.getReturnType().getName().indexOf('[') != -1 ? JU_ARRAYS : JU_OBJECTS);
180     }
181
182     static final Restrictions restrictionsForSetter(final Type actualType) {
183         return actualType instanceof GeneratedType ? null : getRestrictions(actualType);
184     }
185
186     static final Restrictions getRestrictions(final Type type) {
187         if (type instanceof ConcreteType) {
188             return ((ConcreteType) type).getRestrictions();
189         }
190         if (type instanceof GeneratedTransferObject) {
191             return ((GeneratedTransferObject) type).getRestrictions();
192         }
193         return null;
194     }
195 }