Cache most common importedName(Class) references
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / InterfaceTemplate.xtend
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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 extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME
11 import static extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.getGetterMethodForNonnull
12 import static extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.isGetterMethodName
13 import static extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.isNonnullMethodName
14
15 import java.util.List
16 import org.gaul.modernizer_maven_annotations.SuppressModernizer
17 import org.opendaylight.mdsal.binding.model.api.AnnotationType
18 import org.opendaylight.mdsal.binding.model.api.Constant
19 import org.opendaylight.mdsal.binding.model.api.Enumeration
20 import org.opendaylight.mdsal.binding.model.api.GeneratedType
21 import org.opendaylight.mdsal.binding.model.api.MethodSignature
22 import org.opendaylight.mdsal.binding.model.api.Type
23 import org.opendaylight.mdsal.binding.model.util.TypeConstants
24
25 /**
26  * Template for generating JAVA interfaces.
27  */
28  @SuppressModernizer
29 class InterfaceTemplate extends BaseTemplate {
30     /**
31      * List of constant instances which are generated as JAVA public static final attributes.
32      */
33     val List<Constant> consts
34
35     /**
36      * List of method signatures which are generated as method declarations.
37      */
38     val List<MethodSignature> methods
39
40     /**
41      * List of enumeration which are generated as JAVA enum type.
42      */
43     val List<Enumeration> enums
44
45     /**
46      * List of generated types which are enclosed inside <code>genType</code>
47      */
48     val List<GeneratedType> enclosedGeneratedTypes
49
50     /**
51      * Creates the instance of this class which is used for generating the interface file source
52      * code from <code>genType</code>.
53      *
54      * @throws NullPointerException if <code>genType</code> is <code>null</code>
55      */
56     new(GeneratedType genType) {
57         super(genType)
58         consts = genType.constantDefinitions
59         methods = genType.methodDefinitions
60         enums = genType.enumerations
61         enclosedGeneratedTypes = genType.enclosedTypes
62     }
63
64     /**
65      * Template method which generate the whole body of the interface.
66      *
67      * @return string with code for interface body in JAVA format
68      */
69     override body() '''
70         «wrapToDocumentation(formatDataForJavaDoc(type))»
71         «type.annotations.generateAnnotations»
72         public interface «type.name»
73             «superInterfaces»
74         {
75
76             «generateInnerClasses»
77
78             «generateEnums»
79
80             «generateConstants»
81
82             «generateMethods»
83
84         }
85
86     '''
87
88     def private generateAnnotations(List<AnnotationType> annotations) '''
89         «IF annotations !== null && !annotations.empty»
90             «FOR annotation : annotations»
91                 «annotation.generateAnnotation»
92             «ENDFOR»
93         «ENDIF»
94     '''
95
96     /**
97      * Template method which generates the interface name declaration.
98      *
99      * @return string with the code for the interface declaration in JAVA format
100      */
101     def private superInterfaces()
102     '''
103     «IF (!type.implements.empty)»
104          extends
105          «FOR type : type.implements SEPARATOR ","»
106              «type.importedName»
107          «ENDFOR»
108      « ENDIF»
109      '''
110
111     /**
112      * Template method which generates inner classes inside this interface.
113      *
114      * @return string with the source code for inner classes in JAVA format
115      */
116     def private generateInnerClasses() '''
117         «IF !enclosedGeneratedTypes.empty»
118             «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
119                 «generateInnerClass(innerClass)»
120             «ENDFOR»
121         «ENDIF»
122     '''
123
124     /**
125      * Template method which generates JAVA enum type.
126      *
127      * @return string with inner enum source code in JAVA format
128      */
129     def private generateEnums() '''
130         «IF !enums.empty»
131             «FOR e : enums SEPARATOR "\n"»
132                 «val enumTemplate = new EnumTemplate(javaType.getEnclosedType(e.identifier), e)»
133                 «enumTemplate.generateAsInnerClass»
134             «ENDFOR»
135         «ENDIF»
136     '''
137
138     /**
139      * Template method wich generates JAVA constants.
140      *
141      * @return string with constants in JAVA format
142      */
143     def private generateConstants() '''
144         «IF !consts.empty»
145             «FOR c : consts»
146                 «IF !c.name.startsWith(TypeConstants.PATTERN_CONSTANT_NAME)»
147                     «emitConstant(c)»
148                 «ENDIF»
149             «ENDFOR»
150         «ENDIF»
151     '''
152
153     /**
154      * Template method which generates the declaration of the methods.
155      *
156      * @return string with the declaration of methods source code in JAVA format
157      */
158     def private generateMethods() '''
159         «IF !methods.empty»
160             «FOR m : methods SEPARATOR "\n"»
161                 «IF m.isDefault»
162                     «generateDefaultMethod(m)»
163                 «ELSEIF m.parameters.empty && m.name.isGetterMethodName»
164                     «generateAccessorMethod(m)»
165                 «ELSE»
166                     «generateMethod(m)»
167                 «ENDIF»
168             «ENDFOR»
169         «ENDIF»
170     '''
171
172     def private generateDefaultMethod(MethodSignature method) {
173         if (method.name.isNonnullMethodName) {
174             generateNonnullMethod(method)
175         } else {
176             switch method.name {
177                 case DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME : generateDefaultImplementedInterface
178             }
179         }
180     }
181
182     def private generateMethod(MethodSignature method) '''
183         «method.comment.asJavadoc»
184         «method.annotations.generateAnnotations»
185         «method.returnType.importedName» «method.name»(«method.parameters.generateParameters»);
186     '''
187
188     def private generateAccessorMethod(MethodSignature method) '''
189         «val ret = method.returnType»
190         «formatDataForJavaDoc(method, "@return " + asCode(ret.fullyQualifiedName) + " " + asCode(propertyNameFromGetter(method)) + ", or " + asCode("null") + " if not present")»
191         «method.annotations.generateAnnotations»
192         «nullableType(ret)» «method.name»();
193     '''
194
195     def private generateDefaultImplementedInterface() '''
196         @«OVERRIDE.importedName»
197         default «CLASS.importedName»<«type.fullyQualifiedName»> «DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME»() {
198             return «type.fullyQualifiedName».class;
199         }
200     '''
201
202     def private generateNonnullMethod(MethodSignature method) '''
203         «val ret = method.returnType»
204         «val name = method.name»
205         «formatDataForJavaDoc(method, "@return " + asCode(ret.fullyQualifiedName) + " " + asCode(propertyNameFromGetter(method)) + ", or an empty list if it is not present")»
206         «method.annotations.generateAnnotations»
207         default «ret.importedNonNull» «name»() {
208             return «CODEHELPERS.importedName».nonnull(«getGetterMethodForNonnull(name)»());
209         }
210     '''
211
212     def private String nullableType(Type type) {
213         if (type.isObject) {
214             return type.importedNullable
215         }
216         return type.importedName
217     }
218
219     def private static boolean isObject(Type type) {
220         // The return type has a package, so it's not a primitive type
221         return !type.getPackageName().isEmpty()
222     }
223 }