Refactor "value" property access
[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 String generateImportBlock() {
110         verify(javaType instanceof TopLevelJavaGeneratedType);
111         return ((TopLevelJavaGeneratedType) javaType).imports().map(name -> "import " + name + ";\n")
112                 .collect(Collectors.joining());
113     }
114
115     final @NonNull String importedJavadocName(final @NonNull Type intype) {
116         return importedName(intype instanceof ParameterizedType ? ((ParameterizedType) intype).getRawType() : intype);
117     }
118
119     final @NonNull String importedName(final @NonNull Type intype) {
120         return javaType.getReferenceString(intype);
121     }
122
123     final @NonNull String importedName(final @NonNull Type intype, final @NonNull String annotation) {
124         return javaType.getReferenceString(intype, annotation);
125     }
126
127     final @NonNull String importedName(final Class<?> cls) {
128         return importedName(Types.typeForClass(cls));
129     }
130
131     final @NonNull String importedName(final @NonNull JavaTypeName intype) {
132         return javaType.getReferenceString(intype);
133     }
134
135     final @NonNull String importedNonNull(final @NonNull Type intype) {
136         return importedName(intype, importedName(NONNULL));
137     }
138
139     final @NonNull String importedNullable(final @NonNull Type intype) {
140         return importedName(intype, importedName(NULLABLE));
141     }
142
143     // Exposed for BuilderTemplate
144     boolean isLocalInnerClass(final JavaTypeName name) {
145         final Optional<JavaTypeName> optEnc = name.immediatelyEnclosingClass();
146         return optEnc.isPresent() && type.getIdentifier().equals(optEnc.get());
147     }
148
149     final CharSequence generateInnerClass(final GeneratedType innerClass) {
150         if (!(innerClass instanceof GeneratedTransferObject)) {
151             return "";
152         }
153
154         final GeneratedTransferObject gto = (GeneratedTransferObject) innerClass;
155         final NestedJavaGeneratedType innerJavaType = javaType.getEnclosedType(innerClass.getIdentifier());
156         return gto.isUnionType() ? new UnionTemplate(innerJavaType, gto).generateAsInnerClass()
157                 : new ClassTemplate(innerJavaType, gto).generateAsInnerClass();
158     }
159
160     /**
161      * Return imported name of java.util class, whose hashCode/equals methods we want to invoke on the property. Returns
162      * {@link Arrays} if the property is an array, {@link Objects} otherwise.
163      *
164      * @param property Generated property
165      * @return Imported class name
166      */
167     final String importedUtilClass(final GeneratedProperty property) {
168         return importedName(property.getReturnType().getName().indexOf('[') != -1 ? JU_ARRAYS : JU_OBJECTS);
169     }
170
171     static final Restrictions restrictionsForSetter(final Type actualType) {
172         return actualType instanceof GeneratedType ? null : getRestrictions(actualType);
173     }
174
175     static final Restrictions getRestrictions(final Type type) {
176         if (type instanceof ConcreteType) {
177             return ((ConcreteType) type).getRestrictions();
178         }
179         if (type instanceof GeneratedTransferObject) {
180             return ((GeneratedTransferObject) type).getRestrictions();
181         }
182         return null;
183     }
184 }