2 * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers;
11 import static com.google.common.base.Preconditions.checkArgument;
12 import static java.util.Objects.requireNonNull;
14 import com.google.common.collect.ImmutableMap;
16 import java.util.Collection;
17 import java.util.HashMap;
18 import java.util.LinkedList;
19 import java.util.List;
22 import org.eclipse.jdt.annotation.NonNull;
23 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
24 import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil;
25 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty;
26 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
27 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
28 import org.opendaylight.mdsal.binding.javav2.model.api.MethodSignature;
29 import org.opendaylight.mdsal.binding.javav2.model.api.ParameterizedType;
30 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
31 import org.opendaylight.mdsal.binding.javav2.model.api.WildcardType;
35 public abstract class BaseRenderer {
36 private static final String COMMA = ",";
37 private static final String DOT = ".";
39 private final GeneratedType genType;
40 private final Map<String, String> importMap;
42 * list of all imported names for template.
44 private final Map<String, String> importedNames = new HashMap<>();
46 protected BaseRenderer(final GeneratedType type) {
47 this.genType = requireNonNull(type);
48 this.importMap = new HashMap<>();
52 * Implementation needs to call Scala template render() method to generate string body.
53 * @return rendered body
55 protected abstract String body();
57 protected GeneratedType getType() {
61 protected Map<String, String> getImportedNames() {
65 protected String getFromImportMap(@NonNull final String typeName) {
66 return importMap.get(typeName);
69 protected void putToImportMap(@NonNull final String typeName, final String typePackageName) {
70 importMap.put(typeName, typePackageName);
73 protected void putAllToImportMap(@NonNull final Map<String, String> imports) {
74 importMap.putAll(imports);
77 protected Map<String, String> getImportMap() {
78 return ImmutableMap.copyOf(importMap);
82 * Return string with type name for type in the full format or in the short format.
83 * @param intype type to format and add to imports
84 * @return formatted type
86 protected String importedName(final Type intype) {
87 putTypeIntoImports(genType, intype);
88 return getExplicitType(genType, intype);
91 protected String importedName(final Class<?> cls) {
92 return importedName(Types.typeForClass(cls));
96 * Generate package definition for template.
97 * @return package definition for template
99 protected String packageDefinition() {
100 final StringBuilder sb = new StringBuilder();
101 sb.append("package ")
102 .append(genType.getPackageName())
104 return sb.toString();
108 * walks through map of imports.
109 * @return string of imports for template
111 private String imports() {
112 final StringBuilder sb = new StringBuilder();
113 if (!importMap.isEmpty()) {
114 for (Map.Entry<String, String> entry : importMap.entrySet()) {
115 if (!hasSamePackage(entry.getValue())) {
117 .append(entry.getValue())
119 .append(entry.getKey())
124 return sb.toString();
128 * Template method which generates method parameters with their types from <code>parameters</code>.
131 * group of generated property instances which are transformed to the method parameters
132 * @return string with the list of the method parameters with their types in JAVA format
134 protected String asArgumentsDeclaration(final Collection<GeneratedProperty> parameters) {
135 final List<CharSequence> strings = new LinkedList<>();
136 if (parameters.iterator().hasNext()) {
137 for (GeneratedProperty parameter : parameters) {
138 final StringBuilder sb = new StringBuilder();
139 sb.append(importedName(parameter.getReturnType()));
141 sb.append(TextTemplateUtil.fieldName(parameter));
145 return String.join(", ", strings);
149 * Checks if package of generated type and imported type is the same.
150 * @param importedTypePackageName imported types package name
151 * @return equals packages
153 protected boolean hasSamePackage(final String importedTypePackageName) {
154 return genType.getPackageName().equals(importedTypePackageName);
158 * Evaluates if it is necessary to add the package name for type to the map of imports for parentGenType
159 * If it is so the package name is saved to the map imports.
161 * @param parentGenType generated type for which is the map of necessary imports build
162 * @param type JAVA type for which is the necessary of the package import evaluated
164 private void putTypeIntoImports(final GeneratedType parentGenType, final Type type) {
165 checkArgument(parentGenType != null, "Parent Generated Type parameter MUST be specified and cannot be NULL!");
166 checkArgument(type != null, "Type parameter MUST be specified and cannot be NULL!");
167 checkArgument(parentGenType.getPackageName() != null,
168 "Parent Generated Type cannot have Package Name referenced as NULL!");
170 final String typeName = requireNonNull(type.getName());
171 final String typePackageName = requireNonNull(type.getPackageName());
172 final String parentTypeName = requireNonNull(parentGenType.getName());
173 if (typeName.equals(parentTypeName) || typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
176 if (!importMap.containsKey(typeName)) {
177 importMap.put(typeName, typePackageName);
179 if (type instanceof ParameterizedType) {
180 final ParameterizedType paramType = (ParameterizedType) type;
181 final Type[] params = paramType.getActualTypeArguments();
182 if (params != null) {
183 for (Type param : params) {
184 putTypeIntoImports(parentGenType, param);
191 * Builds the string which contains either the full path to the type (package name with type) or only type name
192 * if the package is among imports.
194 * @param parentGenType generated type which contains type
195 * @param type JAVA type for which is the string with type info generated
196 * @return string with type name for type in the full format or in the short format
198 private String getExplicitType(final GeneratedType parentGenType, final Type type) {
199 checkArgument(type != null, "Type parameter MUST be specified and cannot be NULL!");
200 checkArgument(importMap != null, "Imports Map cannot be NULL!");
202 final String typePackageName = requireNonNull(type.getPackageName());
203 final String typeName = requireNonNull(type.getName());
204 final String importedPackageName = importMap.get(typeName);
205 final StringBuilder sb;
206 if (typePackageName.equals(importedPackageName)) {
207 sb = new StringBuilder(typeName);
208 addActualTypeParameters(sb, type, parentGenType);
209 if (sb.toString().equals("Void")) {
213 sb = new StringBuilder();
214 if (!typePackageName.isEmpty()) {
215 sb.append(typePackageName).append(DOT).append(typeName);
217 sb.append(type.getName());
219 if (type.equals(Types.voidType())) {
222 addActualTypeParameters(sb, type, parentGenType);
224 return sb.toString();
228 * Adds actual type parameters from type to builder if type is ParametrizedType.
230 * @param sb string builder which contains type name
231 * @param type JAVA Type for which is the string with type info generated
232 * @param parentGenType generated type which contains type
233 * @return adds actual type parameters to builder
235 private StringBuilder addActualTypeParameters(final StringBuilder sb, final Type type,
236 final GeneratedType parentGenType) {
237 if (type instanceof ParameterizedType) {
238 final ParameterizedType pType = (ParameterizedType) type;
239 final Type[] pTypes = pType.getActualTypeArguments();
241 sb.append(getParameters(parentGenType, pTypes));
247 protected GeneratedProperty findProperty(final GeneratedTransferObject gto, final String name) {
248 for (GeneratedProperty prop : gto.getProperties()) {
249 if (name.equals(prop.getName())) {
253 final GeneratedTransferObject parent = gto.getSuperType();
254 if (parent != null) {
255 return findProperty(parent, name);
261 * Generates the string with all actual type parameters from.
263 * @param parentGenType generated type for which is the JAVA code generated
264 * @param types array of Type instances = actual type parameters
265 * @return string with all actual type parameters from types
267 private String getParameters(final GeneratedType parentGenType, final Type[] types) {
268 if (types == null || types.length == 0) {
271 final StringBuilder sb = new StringBuilder();
272 for (int i = 0; i < types.length; i++) {
273 final Type t = types[i];
275 String separator = COMMA;
276 if (i == types.length - 1) {
281 if (t.equals(Types.voidType())) {
282 sb.append("java.lang.Void")
287 String wildcardParam = "";
288 if (t instanceof WildcardType) {
289 wildcardParam = "? extends ";
292 sb.append(wildcardParam).append(getExplicitType(parentGenType, t)).append(separator);
295 return sb.toString();
299 * Template method which generates method parameters with their types from <code>parameters</code>.
300 * InterfaceTemplate / UnionTemaplate
302 * @param parameters list of parameter instances which are transformed to the method parameters
303 * @return string with the list of the method parameters with their types in JAVA format
305 protected String generateParameters(final List<MethodSignature.Parameter> parameters) {
306 final List<CharSequence> strings = new LinkedList<>();
307 if (!parameters.isEmpty()) {
308 for (MethodSignature.Parameter parameter : parameters) {
309 final StringBuilder sb = new StringBuilder();
310 sb.append(importedName(parameter.getType()));
312 sb.append(parameter.getName());
316 return String.join(", ", strings);
320 * Template method which generates the getter method for field.
322 * @param field generated property with data about field which is generated as the getter method
323 * @return string with the getter method source code in JAVA format
325 protected String getterMethod(final GeneratedProperty field) {
326 final StringBuilder sb = new StringBuilder();
327 final String name = TextTemplateUtil.fieldName(field);
328 final String importedName = requireNonNull(importedName(field.getReturnType()));
330 .append(importedName)
332 .append(TextTemplateUtil.getterMethodName(field))
336 if (!(field.getReturnType() instanceof ParameterizedType)
337 && importedName.contains("[]")) {
338 sb.append(" == null ? null : ")
343 return sb.toString();
348 * @return generated final template
350 public String generateTemplate() {
351 final StringBuilder sb = new StringBuilder();
352 /* sb body must be filled before imports method call */
353 final String templateBody = body();
354 sb.append(packageDefinition())
356 .append(templateBody);
357 return sb.toString();