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