2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
8 package org.opendaylight.yangtools.sal.java.api.generator;
\r
10 import static org.opendaylight.yangtools.sal.java.api.generator.Constants.COMMA;
\r
12 import java.util.ArrayList;
\r
13 import java.util.LinkedHashMap;
\r
14 import java.util.List;
\r
15 import java.util.Map;
\r
17 import org.opendaylight.yangtools.binding.generator.util.TypeConstants;
\r
18 import org.opendaylight.yangtools.binding.generator.util.Types;
\r
19 import org.opendaylight.yangtools.sal.binding.model.api.Constant;
\r
20 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
\r
21 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
\r
22 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
\r
23 import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
\r
24 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
\r
25 import org.opendaylight.yangtools.sal.binding.model.api.Type;
\r
26 import org.opendaylight.yangtools.sal.binding.model.api.WildcardType;
\r
28 public final class GeneratorUtil {
\r
31 * It doesn't have the sense to create the instances of this class.
\r
33 private GeneratorUtil() {
\r
37 * Returns the map of imports. The map maps the type name to the package
\r
38 * name. To the map are added packages for <code>genType</code> and for all
\r
39 * enclosed types, constants, methods (parameter types, return values),
\r
40 * implemented types.
\r
43 * generated type for which the map of the imports is created
\r
44 * @return map of the necessary imports
\r
45 * @throws IllegalArgumentException
\r
46 * if <code>genType</code> equals <code>null</code>
\r
48 public static Map<String, String> createImports(GeneratedType genType) {
\r
49 if (genType == null) {
\r
50 throw new IllegalArgumentException("Generated Type cannot be NULL!");
\r
52 final Map<String, String> imports = new LinkedHashMap<>();
\r
54 List<GeneratedType> childGeneratedTypes = genType.getEnclosedTypes();
\r
55 if (!childGeneratedTypes.isEmpty()) {
\r
56 for (GeneratedType genTypeChild : childGeneratedTypes) {
\r
57 imports.putAll(createImports(genTypeChild));
\r
61 final List<Constant> constants = genType.getConstantDefinitions();
\r
62 final List<MethodSignature> methods = genType.getMethodDefinitions();
\r
63 final List<Type> impl = genType.getImplements();
\r
67 for (final Type type : impl) {
\r
68 putTypeIntoImports(genType, type, imports);
\r
73 if (constants != null) {
\r
74 for (final Constant constant : constants) {
\r
75 final Type constantType = constant.getType();
\r
76 putTypeIntoImports(genType, constantType, imports);
\r
80 // REGULAR EXPRESSION
\r
81 if (genType instanceof GeneratedTransferObject) {
\r
82 if (isConstantInTO(TypeConstants.PATTERN_CONSTANT_NAME, (GeneratedTransferObject) genType)) {
\r
83 putTypeIntoImports(genType, Types.typeForClass(java.util.regex.Pattern.class), imports);
\r
84 putTypeIntoImports(genType, Types.typeForClass(java.util.Arrays.class), imports);
\r
85 putTypeIntoImports(genType, Types.typeForClass(java.util.ArrayList.class), imports);
\r
90 if (methods != null) {
\r
91 for (final MethodSignature method : methods) {
\r
92 final Type methodReturnType = method.getReturnType();
\r
93 putTypeIntoImports(genType, methodReturnType, imports);
\r
94 for (final MethodSignature.Parameter methodParam : method.getParameters()) {
\r
95 putTypeIntoImports(genType, methodParam.getType(), imports);
\r
101 if (genType instanceof GeneratedTransferObject) {
\r
102 final GeneratedTransferObject genTO = (GeneratedTransferObject) genType;
\r
103 final List<GeneratedProperty> properties = genTO.getProperties();
\r
104 if (properties != null) {
\r
105 for (GeneratedProperty property : properties) {
\r
106 final Type propertyType = property.getReturnType();
\r
107 putTypeIntoImports(genType, propertyType, imports);
\r
116 * Evaluates if it is necessary to add the package name for
\r
117 * <code>type</code> to the map of imports for <code>parentGenType</code>.
\r
118 * If it is so the package name is saved to the map <code>imports</code>.
\r
120 * @param parentGenType
\r
121 * generated type for which is the map of the necessary imports
\r
124 * JAVA <code>Type</code> for which is the necessary of the
\r
125 * package import evaluated
\r
127 * map of the imports for <code>parentGenType</code>
\r
128 * @throws IllegalArgumentException
\r
130 * <li>if the <code>parentGenType</code> equals
\r
131 * <code>null</code></li>
\r
132 * <li>if the name of <code>parentGenType</code> equals
\r
133 * <code>null</code></li>
\r
134 * <li>if the name of the package of <code>parentGenType</code>
\r
135 * equals <code>null</code></li>
\r
136 * <li>if the <code>type</code> equals <code>null</code></li>
\r
137 * <li>if the name of <code>type</code> equals <code>null</code>
\r
139 * <li>if the name of the package of <code>type</code> equals
\r
140 * <code>null</code></li>
\r
143 public static void putTypeIntoImports(final GeneratedType parentGenType, final Type type,
\r
144 final Map<String, String> imports) {
\r
145 if (parentGenType == null) {
\r
146 throw new IllegalArgumentException("Parent Generated Type parameter MUST be specified and cannot be "
\r
149 if (parentGenType.getName() == null) {
\r
150 throw new IllegalArgumentException("Parent Generated Type name cannot be NULL!");
\r
152 if (parentGenType.getPackageName() == null) {
\r
153 throw new IllegalArgumentException("Parent Generated Type cannot have Package Name referenced as NULL!");
\r
155 if (type == null) {
\r
156 throw new IllegalArgumentException("Type parameter MUST be specified and cannot be NULL!");
\r
158 if (type.getName() == null) {
\r
159 throw new IllegalArgumentException("Type name cannot be NULL!");
\r
161 if (type.getPackageName() == null) {
\r
162 throw new IllegalArgumentException("Type cannot have Package Name referenced as NULL!");
\r
165 final String typeName = type.getName();
\r
166 final String typePackageName = type.getPackageName();
\r
167 final String parentTypeName = parentGenType.getName();
\r
168 final String parentTypePackageName = parentGenType.getPackageName();
\r
169 if (typeName.equals(parentTypeName) || typePackageName.startsWith("java.lang")
\r
170 || typePackageName.equals(parentTypePackageName) || typePackageName.isEmpty()) {
\r
173 if (!imports.containsKey(typeName)) {
\r
174 imports.put(typeName, typePackageName);
\r
176 if (type instanceof ParameterizedType) {
\r
177 final ParameterizedType paramType = (ParameterizedType) type;
\r
178 final Type[] params = paramType.getActualTypeArguments();
\r
179 for (Type param : params) {
\r
180 putTypeIntoImports(parentGenType, param, imports);
\r
186 * Checks if the constant with the name <code>constName</code> is in the
\r
187 * list of the constant definition for <code>genTO</code>.
\r
190 * string with the name of constant which is sought
\r
192 * generated transfer object in which is <code>constName</code>
\r
194 * @return boolean value
\r
196 * <li>true - if <code>constName</code> is in the list of the
\r
197 * constant definition for <code>genTO</code></li>
\r
198 * <li>false - in other cases</li>
\r
200 * @throws IllegalArgumentException
\r
202 * <li>if <code>constName</code> equals <code>null</code></li>
\r
203 * <li>if <code>genTO</code> equals <code>null</code></li>
\r
206 public static boolean isConstantInTO(String constName, GeneratedTransferObject genTO) {
\r
207 if (constName == null || genTO == null)
\r
208 throw new IllegalArgumentException();
\r
209 List<Constant> consts = genTO.getConstantDefinitions();
\r
210 for (Constant cons : consts) {
\r
211 if (cons.getName().equals(constName)) {
\r
219 * Creates the map which maps the type name to package name and contains
\r
220 * only package names for enclosed types of <code>genType</code> and
\r
221 * recursivelly their enclosed types.
\r
224 * JAVA <code>Type</code> for which is the map created
\r
225 * @return map of the package names for all the enclosed types and
\r
226 * recursivelly their enclosed types
\r
228 public static Map<String, String> createChildImports(GeneratedType genType) {
\r
229 Map<String, String> childImports = new LinkedHashMap<>();
\r
230 List<GeneratedType> childGeneratedTypes = genType.getEnclosedTypes();
\r
231 if (!childGeneratedTypes.isEmpty()) {
\r
232 for (GeneratedType genTypeChild : childGeneratedTypes) {
\r
233 createChildImports(genTypeChild);
\r
234 childImports.put(genTypeChild.getName(), genTypeChild.getPackageName());
\r
237 return childImports;
\r
241 * Builds the string which contains either the full path to the type
\r
242 * (package name with type) or only type name if the package is among
\r
243 * <code>imports</code>.
\r
245 * @param parentGenType
\r
246 * generated type which contains <code>type</code>
\r
248 * JAVA <code>Type</code> for which is the string with type info
\r
251 * map of necessary imports for <code>parentGenType</code>
\r
252 * @return string with type name for <code>type</code> in the full format or
\r
253 * in the short format
\r
254 * @throws IllegalArgumentException
\r
256 * <li>if the <code>type</code> equals <code>null</code></li>
\r
257 * <li>if the name of the <code>type</code> equals
\r
258 * <code>null</code></li>
\r
259 * <li>if the name of the package of the <code>type</code>
\r
260 * equals <code>null</code></li>
\r
261 * <li>if the <code>imports</code> equals <code>null</code></li>
\r
264 public static String getExplicitType(final GeneratedType parentGenType, final Type type,
\r
265 final Map<String, String> imports) {
\r
266 if (type == null) {
\r
267 throw new IllegalArgumentException("Type parameter MUST be specified and cannot be NULL!");
\r
269 if (type.getName() == null) {
\r
270 throw new IllegalArgumentException("Type name cannot be NULL!");
\r
272 if (type.getPackageName() == null) {
\r
273 throw new IllegalArgumentException("Type cannot have Package Name referenced as NULL!");
\r
275 if (imports == null) {
\r
276 throw new IllegalArgumentException("Imports Map cannot be NULL!");
\r
279 final String typePackageName = type.getPackageName();
\r
280 final String typeName = type.getName();
\r
281 final String importedPackageName = imports.get(typeName);
\r
282 if (typePackageName.equals(importedPackageName) || typePackageName.equals(parentGenType.getPackageName())) {
\r
283 final StringBuilder builder = new StringBuilder(type.getName());
\r
284 if (type instanceof ParameterizedType) {
\r
285 final ParameterizedType pType = (ParameterizedType) type;
\r
286 final Type[] pTypes = pType.getActualTypeArguments();
\r
287 builder.append("<");
\r
288 builder.append(getParameters(parentGenType, pTypes, imports));
\r
289 builder.append(">");
\r
291 if (builder.toString().equals("Void")) {
\r
294 return builder.toString();
\r
296 final StringBuilder builder = new StringBuilder();
\r
297 if (typePackageName.startsWith("java.lang")) {
\r
298 builder.append(type.getName());
\r
300 if (!typePackageName.isEmpty()) {
\r
301 builder.append(typePackageName + Constants.DOT + type.getName());
\r
303 builder.append(type.getName());
\r
306 if (type.equals(Types.voidType())) {
\r
309 if (type instanceof ParameterizedType) {
\r
310 final ParameterizedType pType = (ParameterizedType) type;
\r
311 final Type[] pTypes = pType.getActualTypeArguments();
\r
312 builder.append("<");
\r
313 builder.append(getParameters(parentGenType, pTypes, imports));
\r
314 builder.append(">");
\r
316 return builder.toString();
\r
321 * Generates the string with all actual type parameters from
\r
322 * <code>pTypes</code>
\r
324 * @param parentGenType
\r
325 * generated type for which is the JAVA code generated
\r
327 * array of <code>Type</code> instances = actual type parameters
\r
328 * @param availableImports
\r
329 * map of imports for <code>parentGenType</code>
\r
330 * @return string with all actual type parameters from <code>pTypes</code>
\r
332 private static String getParameters(final GeneratedType parentGenType, final Type[] pTypes,
\r
333 Map<String, String> availableImports) {
\r
334 final StringBuilder builder = new StringBuilder();
\r
335 for (int i = 0; i < pTypes.length; i++) {
\r
336 final Type t = pTypes[i];
\r
338 String separator = COMMA;
\r
339 if (i == (pTypes.length - 1)) {
\r
343 String wildcardParam = "";
\r
344 if (t.equals(Types.voidType())) {
\r
345 builder.append("java.lang.Void" + separator);
\r
349 if (t instanceof WildcardType) {
\r
350 wildcardParam = "? extends ";
\r
353 builder.append(wildcardParam + getExplicitType(parentGenType, t, availableImports) + separator);
\r
356 return builder.toString();
\r
360 * Returns the reference to highest (top parent) Generated Transfer Object.
\r
362 * @param childTransportObject
\r
363 * is generated transfer object which can be extended by other
\r
364 * generated transfer object
\r
365 * @return in first case that <code>childTransportObject</code> isn't
\r
366 * extended then <code>childTransportObject</code> is returned. In
\r
367 * second case the method is recursive called until first case.
\r
368 * @throws IllegalArgumentException
\r
369 * if <code>childTransportObject</code> equals <code>null</code>
\r
371 public static GeneratedTransferObject getTopParrentTransportObject(GeneratedTransferObject childTransportObject) {
\r
372 if (childTransportObject == null) {
\r
373 throw new IllegalArgumentException("Parameter childTransportObject can't be null.");
\r
375 if (childTransportObject.getExtends() == null) {
\r
376 return childTransportObject;
\r
378 return getTopParrentTransportObject(childTransportObject.getExtends());
\r
383 * Selects from input list of properties only those which have read only
\r
384 * attribute set to true.
\r
386 * @param properties
\r
387 * list of properties of generated transfer object
\r
388 * @return subset of <code>properties</code> which have read only attribute
\r
391 public static List<GeneratedProperty> resolveReadOnlyPropertiesFromTO(List<GeneratedProperty> properties) {
\r
392 List<GeneratedProperty> readOnlyProperties = new ArrayList<GeneratedProperty>();
\r
393 if (properties != null) {
\r
394 for (final GeneratedProperty property : properties) {
\r
395 if (property.isReadOnly()) {
\r
396 readOnlyProperties.add(property);
\r
400 return readOnlyProperties;
\r
404 * Returns the list of the read only properties of all extending generated
\r
405 * transfer object from <code>genTO</code> to highest parent generated
\r
409 * generated transfer object for which is the list of read only
\r
410 * properties generated
\r
411 * @return list of all read only properties from actual to highest parent
\r
412 * generated transfer object. In case when extension exists the
\r
413 * method is recursive called.
\r
415 public static List<GeneratedProperty> getPropertiesOfAllParents(GeneratedTransferObject genTO) {
\r
416 List<GeneratedProperty> propertiesOfAllParents = new ArrayList<GeneratedProperty>();
\r
417 if (genTO.getExtends() != null) {
\r
418 final List<GeneratedProperty> allPropertiesOfTO = genTO.getExtends().getProperties();
\r
419 List<GeneratedProperty> readOnlyPropertiesOfTO = resolveReadOnlyPropertiesFromTO(allPropertiesOfTO);
\r
420 propertiesOfAllParents.addAll(readOnlyPropertiesOfTO);
\r
421 propertiesOfAllParents.addAll(getPropertiesOfAllParents(genTO.getExtends()));
\r
423 return propertiesOfAllParents;
\r