70ea929bc3aef6ba2a9056440dcbee1bfda917b4
[yangtools.git] / code-generator / binding-java-api-generator / src / main / java / org / opendaylight / yangtools / sal / java / api / generator / InterfaceTemplate.xtend
1 package org.opendaylight.yangtools.sal.java.api.generator
2
3 import java.util.List
4 import java.util.Map
5 import org.opendaylight.yangtools.binding.generator.util.TypeConstants
6 import org.opendaylight.yangtools.sal.binding.model.api.Constant
7 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
8 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
9 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
10 import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
11 import org.opendaylight.yangtools.sal.binding.model.api.Type
12 import java.util.LinkedHashMap
13 /**
14  * Template for generating JAVA interfaces. 
15  */
16 class InterfaceTemplate {
17     
18     /**
19      * Generated type which is transformed to interface JAVA file.
20      */
21     val GeneratedType genType
22     
23     /**
24      * Map of imports for this <code>genTO</code>.
25      */
26     val Map<String, String> imports
27     
28     /**
29      * List of constant instances which are generated as JAVA public static final attributes.
30      */
31     val List<Constant> consts
32     
33     /**
34      * List of method signatures which are generated as method declarations.
35      */
36     val List<MethodSignature> methods
37     
38     /**
39      * List of enumeration which are generated as JAVA enum type.
40      */
41     val List<Enumeration> enums
42     
43     /**
44      * List of generated types which are enclosed inside <code>genType</code>
45      */
46     val List<GeneratedType> enclosedGeneratedTypes
47     
48     /**
49      * Creates the instance of this class which is used for generating the interface file source 
50      * code from <code>genType</code>.
51      * 
52      * @throws IllegalArgumentException if <code>genType</code> equals <code>null</code>
53      */
54     new(GeneratedType genType) {
55         if (genType == null) {
56             throw new IllegalArgumentException("Generated type reference cannot be NULL!")
57         }
58         
59         this.genType = genType
60         imports = GeneratorUtil.createImports(genType)
61         consts = genType.constantDefinitions
62         methods = genType.methodDefinitions
63         enums = genType.enumerations
64         enclosedGeneratedTypes = genType.enclosedTypes
65     }
66     
67     /**
68      * Generates the source code for interface with package name, imports and interface body.
69      * 
70      * @return string with the code for the interface file in JAVA format
71      */
72     def String generate() {
73         val body = generateBody
74         val pkgAndImports = generatePkgAndImports
75         return pkgAndImports.toString + body.toString
76     }
77     
78     /**
79      * Template method which generate the whole body of the interface.
80      * 
81      * @return string with code for interface body in JAVA format
82      */
83     def private generateBody() '''
84         «genType.comment.generateComment»
85         «generateIfcDeclaration» {
86         
87             «generateInnerClasses»
88         
89             «generateEnums»
90         
91             «generateConstants»
92         
93             «generateMethods»
94         
95         }
96         
97     '''
98     
99     /**
100      * Template method which generates JAVA comment.
101      * 
102      * @param comment 
103      * string with the comment for whole JAVA interface
104      * @return string with comment in JAVA format
105      */
106     def private generateComment(String comment) '''
107         «IF comment != null && !comment.empty»
108             /*
109             «comment»
110             */
111         «ENDIF»
112     '''
113     
114     /**
115      * Template method which generates the interface name declaration.
116      * 
117      * @return string with the code for the interface declaration in JAVA format
118      */
119     def private generateIfcDeclaration() '''
120         public interface «genType.name»«
121         IF (!genType.implements.empty)»«
122             " extends "»«
123             FOR type : genType.implements SEPARATOR ", "»«
124                 type.resolveName»«
125             ENDFOR»«
126         ENDIF
127     »'''
128     
129     /**
130      * Template method which generates inner classes inside this interface.
131      * 
132      * @return string with the source code for inner classes in JAVA format
133      */
134     def private generateInnerClasses() '''
135         «IF !enclosedGeneratedTypes.empty»
136             «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
137                 «IF (innerClass instanceof GeneratedTransferObject)»
138                     «val classTemplate = new ClassTemplate(innerClass as GeneratedTransferObject)»
139                     «classTemplate.generateAsInnerClass»
140                     
141                 «ENDIF»
142             «ENDFOR»
143         «ENDIF»
144     '''
145
146     /**
147      * Template method which generates JAVA enum type.
148      * 
149      * @return string with inner enum source code in JAVA format
150      */    
151     def private generateEnums() '''
152         «IF !enums.empty»
153             «FOR e : enums SEPARATOR "\n"»
154                 «val enumTemplate = new EnumTemplate(e)»
155                 «enumTemplate.generateAsInnerClass»
156             «ENDFOR»
157         «ENDIF»
158     '''
159     
160     /**
161      * Template method wich generates JAVA constants.
162      * 
163      * @return string with constants in JAVA format 
164      */    
165     def private generateConstants() '''
166         «IF !consts.empty»
167             «FOR c : consts»
168                 «IF c.name != TypeConstants.PATTERN_CONSTANT_NAME»
169                     public static final «c.type.resolveName» «c.name» = «c.value»;
170                 «ENDIF»
171             «ENDFOR»
172         «ENDIF»
173     '''
174
175     /**
176      * Template method which generates the declaration of the methods.
177      * 
178      * @return string with the declaration of methods source code in JAVA format 
179      */    
180     def private generateMethods() '''
181         «IF !methods.empty»
182             «FOR m : methods SEPARATOR "\n"»
183                 «m.comment.generateComment»
184                 «m.returnType.resolveName» «m.name»(«m.parameters.generateParameters»);
185             «ENDFOR»
186         «ENDIF»
187     '''
188     
189     /**
190      * Template method which generates method parameters with their types from <code>parameters</code>.
191      * 
192      * @param parameters
193      * list of parameter instances which are transformed to the method parameters
194      * @return string with the list of the method parameters with their types in JAVA format
195      */
196     def private generateParameters(List<MethodSignature.Parameter> parameters) '''«
197         IF !parameters.empty»«
198             FOR parameter : parameters SEPARATOR ", "»«
199                 parameter.type.resolveName» «parameter.name»«
200             ENDFOR»«
201         ENDIF
202     »'''
203     
204
205     /**
206      * Template method which generates the map of all the required imports for and imports 
207      * from extended type (and recursivelly so on).
208      * 
209      * @return map which maps type name to package name   
210      */
211     def private Map<String, String> resolveImports() {
212         val innerTypeImports = GeneratorUtil.createChildImports(genType)
213         val Map<String, String> resolvedImports = new LinkedHashMap
214         for (Map.Entry<String, String> entry : imports.entrySet() + innerTypeImports.entrySet) {
215             val typeName = entry.getKey();
216             val packageName = entry.getValue();
217             if (packageName != genType.packageName && packageName != genType.fullyQualifiedName) {
218                 resolvedImports.put(typeName, packageName);
219             }
220         }
221         return resolvedImports
222     }
223     
224     /**
225      * Template method which generate package name line and import lines.
226      * 
227      * @result string with package and import lines in JAVA format
228      */    
229     def private generatePkgAndImports() '''
230         package «genType.packageName»;
231         
232         
233         «IF !imports.empty»
234             «FOR entry : resolveImports.entrySet»
235                 import «entry.value».«entry.key»;
236             «ENDFOR»
237         «ENDIF»
238         
239     '''    
240     
241     /**
242      * Adds package to imports if it is necessary and returns necessary type name (with or without package name)
243      *  
244      * @param type JAVA <code>Type</code> 
245      * @return string with the type name (with or without package name)
246      */      
247     def private resolveName(Type type) {
248         GeneratorUtil.putTypeIntoImports(genType, type, imports);
249         GeneratorUtil.getExplicitType(genType, type, imports)
250     }
251     
252 }