Generation of java files from templates
[controller.git] / opendaylight / sal / yang-prototype / code-generator / binding-java-api-generator / src / main / java / org / opendaylight / controller / sal / java / api / generator / GeneratorUtil.java
1 /*
2  * Copyright (c) 2013 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.controller.sal.java.api.generator;
9
10 import static org.opendaylight.controller.sal.java.api.generator.Constants.COMMA;
11
12 import java.util.ArrayList;
13 import java.util.LinkedHashMap;
14 import java.util.List;
15 import java.util.Map;
16
17 import org.opendaylight.controller.binding.generator.util.TypeConstants;
18 import org.opendaylight.controller.binding.generator.util.Types;
19 import org.opendaylight.controller.sal.binding.model.api.Constant;
20 import org.opendaylight.controller.sal.binding.model.api.GeneratedProperty;
21 import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
22 import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
23 import org.opendaylight.controller.sal.binding.model.api.MethodSignature;
24 import org.opendaylight.controller.sal.binding.model.api.ParameterizedType;
25 import org.opendaylight.controller.sal.binding.model.api.Type;
26 import org.opendaylight.controller.sal.binding.model.api.WildcardType;
27
28
29 public final class GeneratorUtil {
30
31     private GeneratorUtil() {
32     }
33     
34     public static Map<String, String> createImports(GeneratedType genType) {
35         if (genType == null) {
36             throw new IllegalArgumentException("Generated Type cannot be NULL!");
37         }
38         final Map<String, String> imports = new LinkedHashMap<>();
39         imports.put(genType.getName(), genType.getPackageName());
40         List<GeneratedType> childGeneratedTypes = genType.getEnclosedTypes();
41         if (!childGeneratedTypes.isEmpty()) {
42             for (GeneratedType genTypeChild : childGeneratedTypes) {
43                 imports.putAll(createImports(genTypeChild));
44             }
45         }
46
47         final List<Constant> constants = genType.getConstantDefinitions();
48         final List<MethodSignature> methods = genType.getMethodDefinitions();
49         final List<Type> impl = genType.getImplements();
50
51         // IMPLEMENTATIONS
52         if (impl != null) {
53             for (final Type type : impl) {
54                 putTypeIntoImports(genType, type, imports);
55             }
56         }
57
58         // CONSTANTS
59         if (constants != null) {
60             for (final Constant constant : constants) {
61                 final Type constantType = constant.getType();
62                 putTypeIntoImports(genType, constantType, imports);
63             }
64         }
65
66         // REGULAR EXPRESSION
67         if (genType instanceof GeneratedTransferObject) {
68             if (isConstantInTO(TypeConstants.PATTERN_CONSTANT_NAME, (GeneratedTransferObject) genType)) {
69                 putTypeIntoImports(genType, Types.typeForClass(java.util.regex.Pattern.class), imports);
70                 putTypeIntoImports(genType, Types.typeForClass(java.util.Arrays.class), imports);
71                 putTypeIntoImports(genType, Types.typeForClass(java.util.ArrayList.class), imports);
72             }
73         }
74
75         // METHODS
76         if (methods != null) {
77             for (final MethodSignature method : methods) {
78                 final Type methodReturnType = method.getReturnType();
79                 putTypeIntoImports(genType, methodReturnType, imports);
80                 for (final MethodSignature.Parameter methodParam : method.getParameters()) {
81                     putTypeIntoImports(genType, methodParam.getType(), imports);
82                 }
83             }
84         }
85
86         // PROPERTIES
87         if (genType instanceof GeneratedTransferObject) {
88             final GeneratedTransferObject genTO = (GeneratedTransferObject) genType;
89             final List<GeneratedProperty> properties = genTO.getProperties();
90             if (properties != null) {
91                 for (GeneratedProperty property : properties) {
92                     final Type propertyType = property.getReturnType();
93                     putTypeIntoImports(genType, propertyType, imports);
94                 }
95             }
96         }
97
98         return imports;
99     }
100     
101     public static void putTypeIntoImports(final GeneratedType parentGenType, final Type type,
102             final Map<String, String> imports) {
103         if (parentGenType == null) {
104             throw new IllegalArgumentException("Parent Generated Type parameter MUST be specified and cannot be "
105                     + "NULL!");
106         }
107         if (parentGenType.getName() == null) {
108             throw new IllegalArgumentException("Parent Generated Type name cannot be NULL!");
109         }
110         if (parentGenType.getPackageName() == null) {
111             throw new IllegalArgumentException("Parent Generated Type cannot have Package Name referenced as NULL!");
112         }
113         if (type == null) {
114             throw new IllegalArgumentException("Type parameter MUST be specified and cannot be NULL!");
115         }
116         if (type.getName() == null) {
117             throw new IllegalArgumentException("Type name cannot be NULL!");
118         }
119         if (type.getPackageName() == null) {
120             throw new IllegalArgumentException("Type cannot have Package Name referenced as NULL!");
121         }
122
123         final String typeName = type.getName();
124         final String typePackageName = type.getPackageName();
125         final String parentTypeName = parentGenType.getName();
126         final String parentTypePackageName = parentGenType.getPackageName();
127         if (typeName.equals(parentTypeName) || typePackageName.startsWith("java.lang")
128                 || typePackageName.equals(parentTypePackageName) || typePackageName.isEmpty()) {
129             return;
130         }
131         if (!imports.containsKey(typeName)) {
132             imports.put(typeName, typePackageName);
133         }
134         if (type instanceof ParameterizedType) {
135             final ParameterizedType paramType = (ParameterizedType) type;
136             final Type[] params = paramType.getActualTypeArguments();
137             for (Type param : params) {
138                 putTypeIntoImports(parentGenType, param, imports);
139             }
140         }
141     }
142     
143     public static boolean isConstantInTO(String constName, GeneratedTransferObject genTO) {
144         if (constName == null || genTO == null)
145             throw new IllegalArgumentException();
146         List<Constant> consts = genTO.getConstantDefinitions();
147         for (Constant cons : consts) {
148             if (cons.getName().equals(constName)) {
149                 return true;
150             }
151
152         }
153         return false;
154     }
155     
156     public static Map<String, String> createChildImports(GeneratedType genType) {
157         Map<String, String> childImports = new LinkedHashMap<>();
158         List<GeneratedType> childGeneratedTypes = genType.getEnclosedTypes();
159         if (!childGeneratedTypes.isEmpty()) {
160             for (GeneratedType genTypeChild : childGeneratedTypes) {
161                 createChildImports(genTypeChild);
162                 childImports.put(genTypeChild.getName(), genTypeChild.getPackageName());
163             }
164         }
165         return childImports;
166     }
167
168     public static String getExplicitType(final GeneratedType parentGenType, final Type type, final Map<String, String> imports) {
169         if (type == null) {
170             throw new IllegalArgumentException("Type parameter MUST be specified and cannot be NULL!");
171         }
172         if (type.getName() == null) {
173             throw new IllegalArgumentException("Type name cannot be NULL!");
174         }
175         if (type.getPackageName() == null) {
176             throw new IllegalArgumentException("Type cannot have Package Name referenced as NULL!");
177         }
178         if (imports == null) {
179             throw new IllegalArgumentException("Imports Map cannot be NULL!");
180         }
181
182         final String typePackageName = type.getPackageName();
183         final String typeName = type.getName();
184         final String importedPackageName = imports.get(typeName);
185         if (typePackageName.equals(importedPackageName) || typePackageName.equals(parentGenType.getPackageName())) {
186             final StringBuilder builder = new StringBuilder(type.getName());
187             if (type instanceof ParameterizedType) {
188                 final ParameterizedType pType = (ParameterizedType) type;
189                 final Type[] pTypes = pType.getActualTypeArguments();
190                 builder.append("<");
191                 builder.append(getParameters(parentGenType, pTypes, imports));
192                 builder.append(">");
193             }
194             if (builder.toString().equals("Void")) {
195                 return "void";
196             }
197             return builder.toString();
198         } else {
199             final StringBuilder builder = new StringBuilder();
200             if (typePackageName.startsWith("java.lang")) {
201                 builder.append(type.getName());
202             } else {
203                 if (!typePackageName.isEmpty()) {
204                     builder.append(typePackageName + Constants.DOT + type.getName());
205                 } else {
206                     builder.append(type.getName());
207                 }
208             }
209             if (type.equals(Types.voidType())) {
210                 return "void";
211             }
212             if (type instanceof ParameterizedType) {
213                 final ParameterizedType pType = (ParameterizedType) type;
214                 final Type[] pTypes = pType.getActualTypeArguments();
215                 builder.append("<");
216                 builder.append(getParameters(parentGenType, pTypes, imports));
217                 builder.append(">");
218             }
219             return builder.toString();
220         }
221     }
222     
223     private static String getParameters(final GeneratedType parentGenType, final Type[] pTypes, Map<String, String> availableImports) {
224         final StringBuilder builder = new StringBuilder();
225         for (int i = 0; i < pTypes.length; i++) {
226             final Type t = pTypes[i];
227
228             String separator = COMMA;
229             if (i == (pTypes.length - 1)) {
230                 separator = "";
231             }
232
233             String wildcardParam = "";
234             if (t.equals(Types.voidType())) {
235                 builder.append("java.lang.Void" + separator);
236                 continue;
237             } else {
238
239                 if (t instanceof WildcardType) {
240                     wildcardParam = "? extends ";
241                 }
242
243                 builder.append(wildcardParam + getExplicitType(parentGenType, t, availableImports) + separator);
244             }
245         }
246         return builder.toString();
247     }
248     
249     /**
250      * The method returns reference to highest (top parent) Generated Transfer
251      * Object.
252      * 
253      * @param childTransportObject
254      *            is generated transfer object which can be extended by other
255      *            generated transfer object
256      * @return in first case that <code>childTransportObject</code> isn't
257      *         extended then <code>childTransportObject</code> is returned. In
258      *         second case the method is recursive called until first case.
259      */
260     public static GeneratedTransferObject getTopParrentTransportObject(GeneratedTransferObject childTransportObject) {
261         if (childTransportObject == null) {
262             throw new IllegalArgumentException("Parameter childTransportObject can't be null.");
263         }
264         if (childTransportObject.getExtends() == null) {
265             return childTransportObject;
266         } else {
267             return getTopParrentTransportObject(childTransportObject.getExtends());
268         }
269     }
270     
271     /**
272      * The method selects from input list of properties only those which have
273      * read only attribute set to true.
274      * 
275      * @param properties
276      *            contains list of properties of generated transfer object
277      * @return subset of <code>properties</code> which have read only attribute
278      *         set to true
279      */
280     public static List<GeneratedProperty> resolveReadOnlyPropertiesFromTO(List<GeneratedProperty> properties) {
281         List<GeneratedProperty> readOnlyProperties = new ArrayList<GeneratedProperty>();
282         if (properties != null) {
283             for (final GeneratedProperty property : properties) {
284                 if (property.isReadOnly()) {
285                     readOnlyProperties.add(property);
286                 }
287             }
288         }
289         return readOnlyProperties;
290     }
291     
292     /**
293      * The method returns the list of the properties of all extending generated
294      * transfer object from <code>genTO</code> to highest parent generated
295      * transfer object
296      * 
297      * @param genTO
298      * @return the list of all properties from actual to highest parent
299      *         generated transfer object. In case when extension exists the
300      *         method is recursive called.
301      */
302     public static List<GeneratedProperty> getPropertiesOfAllParents(GeneratedTransferObject genTO) {
303         List<GeneratedProperty> propertiesOfAllParents = new ArrayList<GeneratedProperty>();
304         if (genTO.getExtends() != null) {
305             final List<GeneratedProperty> allPropertiesOfTO = genTO.getExtends().getProperties();
306             List<GeneratedProperty> readOnlyPropertiesOfTO = resolveReadOnlyPropertiesFromTO(allPropertiesOfTO);
307             propertiesOfAllParents.addAll(readOnlyPropertiesOfTO);
308             propertiesOfAllParents.addAll(getPropertiesOfAllParents(genTO.getExtends()));
309         }
310         return propertiesOfAllParents;
311     }
312     
313 }