1 package org.opendaylight.controller.sal.java.api.generator;
3 import java.lang.reflect.Method;
4 import java.util.ArrayList;
5 import java.util.LinkedHashMap;
6 import java.util.LinkedHashSet;
11 import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
12 import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
13 import org.opendaylight.controller.sal.binding.model.api.MethodSignature;
14 import org.opendaylight.controller.sal.binding.model.api.ParameterizedType;
15 import org.opendaylight.controller.sal.binding.model.api.Type;
16 import org.opendaylight.controller.yang.binding.Augmentable;
18 public class BuilderClassDescriptor {
20 private static final String GET_PREFIX = "get";
21 private static final String JAVA_UTIL = "java.util";
22 private static final String HASH_MAP = "HashMap";
23 private static final String MAP = "Map";
24 private static final String GET_AUGMENTATION_METHOD_NAME = "getAugmentation";
26 private final GeneratedType genType;
27 private Map<String, String> imports;
28 private final String packageName;
29 private final String className;
30 private final Set<MethodDeclaration> methods;
31 private final Set<FieldDeclaration> fields;
32 private final List<String> importsNames;
33 private FieldDeclaration augmentField;
35 class TypeDeclaration {
37 private final static String JAVA_LANG_PREFIX = "java.lang";
38 private final String name;
39 private final TypeDeclaration[] generics;
41 public TypeDeclaration(String pkg, String name, TypeDeclaration... generics) {
42 this.name = removeJavaLangPkgName(getRightTypeName(pkg, name));
43 if (generics != null && generics.length > 0) {
44 this.generics = generics;
50 public TypeDeclaration(final Type type) {
52 throw new IllegalArgumentException("Type cannot be NULL");
55 this.name = removeJavaLangPkgName(getRightTypeName(type.getPackageName(), type.getName()));
56 TypeDeclaration[] generics = null;
57 if (type instanceof ParameterizedType) {
58 final ParameterizedType pType = (ParameterizedType) type;
59 final Type[] actualTypeArguments = pType.getActualTypeArguments();
60 generics = new TypeDeclaration[actualTypeArguments.length];
61 for (int i = 0; i < actualTypeArguments.length; i++) {
62 generics[i] = new TypeDeclaration(actualTypeArguments[i].getPackageName(),
63 actualTypeArguments[i].getName());
66 if (generics != null && generics.length > 0) {
67 this.generics = generics;
73 private String removeJavaLangPkgName(final String typeName) {
74 if (typeName.startsWith(JAVA_LANG_PREFIX)) {
75 return typeName.substring(typeName.lastIndexOf(Constants.DOT) + 1);
80 private String getRightTypeName(final String pkg, final String name) {
82 throw new IllegalArgumentException("Name cannot be NULL!");
85 if (imports == null) {
88 final String pkgFromImports = imports.get(name);
89 if (pkgFromImports == null || pkgFromImports.equals(pkg)) {
92 return (pkg == null ? "" : pkg) + Constants.DOT + name;
95 public String getName() {
99 public TypeDeclaration[] getGenerics() {
105 class ParameterDeclaration {
107 private final TypeDeclaration type;
108 private final String name;
110 public ParameterDeclaration(TypeDeclaration type, String name) {
115 public TypeDeclaration getType() {
119 public String getName() {
125 class MethodDeclaration {
127 private final TypeDeclaration returnType;
128 private final String name;
129 private final List<ParameterDeclaration> parameters;
131 public MethodDeclaration(final TypeDeclaration returnType, final String name,
132 final List<ParameterDeclaration> parameters) {
133 this.returnType = returnType;
135 if (parameters != null && !parameters.isEmpty()) {
136 this.parameters = parameters;
138 this.parameters = null;
142 public TypeDeclaration getReturnType() {
146 public String getName() {
150 public List<ParameterDeclaration> getParameters() {
156 class FieldDeclaration extends ParameterDeclaration {
158 public FieldDeclaration(final TypeDeclaration type, final String name) {
164 public BuilderClassDescriptor(final GeneratedType genType) {
165 if (genType == null) {
166 throw new IllegalArgumentException("Generated type reference cannot be NULL!");
168 this.genType = genType;
169 this.imports = GeneratorUtil.createImports(genType);
170 addToImports(genType.getPackageName(), genType.getName());
171 packageName = genType.getPackageName();
172 className = genType.getName();
173 methods = createMethods();
174 fields = createFieldsFromMethods();
175 importsNames = createImportsNames();
178 private Set<MethodDeclaration> createMethods() {
179 final Set<MethodDeclaration> methods = new LinkedHashSet<>();
180 storeMethodsOfIfc(methods, genType);
181 storeMethodsOfImplementedIfcs(methods, genType.getImplements());
185 private void storeMethodsOfIfc(final Set<MethodDeclaration> methodStorage, final GeneratedType ifc) {
186 for (MethodSignature methodSignature : ifc.getMethodDefinitions()) {
187 final List<ParameterDeclaration> parameterDeclarations = getParameterDeclarationsFrom(methodSignature
189 methodStorage.add(new MethodDeclaration(new TypeDeclaration(methodSignature.getReturnType()),
190 methodSignature.getName(), parameterDeclarations));
192 if (ifc.getEnclosedTypes() != null && !ifc.getEnclosedTypes().isEmpty()) {
193 addToImports(ifc.getPackageName(), ifc.getName() + ".*");
197 private List<ParameterDeclaration> getParameterDeclarationsFrom(final List<MethodSignature.Parameter> parameters) {
198 final List<ParameterDeclaration> parameterDeclarations = new ArrayList<>();
199 for (MethodSignature.Parameter mp : parameters) {
200 parameterDeclarations.add(new ParameterDeclaration(new TypeDeclaration(mp.getType()), mp.getName()));
202 return parameterDeclarations;
205 private void storeMethodsOfImplementedIfcs(final Set<MethodDeclaration> methodStorage,
206 final List<Type> implementedIfcs) {
207 if (implementedIfcs == null || implementedIfcs.isEmpty()) {
210 for (Type implementedIfc : implementedIfcs) {
211 if ((implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))) {
212 final GeneratedType ifc = ((GeneratedType) implementedIfc);
213 storeMethodsOfIfc(methodStorage, ifc);
214 storeMethodsOfImplementedIfcs(methodStorage, ifc.getImplements());
215 } else if (implementedIfc.getFullyQualifiedName().equals(Augmentable.class.getName())) {
216 for (Method m : Augmentable.class.getMethods()) {
217 if (m.getName().equals(GET_AUGMENTATION_METHOD_NAME)) {
218 addToImports(JAVA_UTIL, HASH_MAP);
219 addToImports(JAVA_UTIL, MAP);
220 java.lang.reflect.Type returnType = m.getReturnType();
221 final String fullyQualifiedName = ((Class<?>) returnType).getName();
222 addToImports(getPackageFrom(fullyQualifiedName), getNameFrom(fullyQualifiedName));
223 TypeDeclaration augmentMethodType = new TypeDeclaration(getPackageFrom(fullyQualifiedName),
224 getNameFrom(fullyQualifiedName), new TypeDeclaration(genType));
225 augmentField = createFieldFromGetMethod(new MethodDeclaration(augmentMethodType, m.getName(),
233 private void addToImports(final String pkg, final String name) {
234 if (imports == null) {
235 imports = new LinkedHashMap<>();
237 if (imports.get(name) == null) {
238 imports.put(name, pkg);
242 private String getPackageFrom(final String fullyQualifiedName) {
243 final int lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT);
244 return lastDotIndex == -1 ? "" : fullyQualifiedName.substring(0, lastDotIndex);
247 private String getNameFrom(final String fullyQualifiedName) {
248 final int lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT);
249 return lastDotIndex == -1 ? fullyQualifiedName : fullyQualifiedName.substring(lastDotIndex + 1);
252 private Set<FieldDeclaration> createFieldsFromMethods() {
253 final Set<FieldDeclaration> result = new LinkedHashSet<>();
255 if (methods == null || methods.isEmpty()) {
259 for (MethodDeclaration m : methods) {
260 final FieldDeclaration createdField = createFieldFromGetMethod(m);
261 if (createdField != null) {
262 result.add(createdField);
268 private FieldDeclaration createFieldFromGetMethod(final MethodDeclaration method) {
269 if (method == null || method.getName() == null || method.getName().isEmpty()) {
271 } else if (method.getName().startsWith(GET_PREFIX)) {
272 final String fieldNameFromMethod = method.getName().substring(GET_PREFIX.length());
273 final String fieldName = Character.toLowerCase(fieldNameFromMethod.charAt(0))
274 + fieldNameFromMethod.substring(1);
275 return new FieldDeclaration(method.getReturnType(), fieldName);
280 private List<String> createImportsNames() {
281 final List<String> result = new ArrayList<>();
283 if (imports == null || imports.isEmpty()) {
287 for (Map.Entry<String, String> entry : imports.entrySet()) {
288 final String typeName = entry.getKey();
289 final String packageName = entry.getValue();
290 result.add(packageName + Constants.DOT + typeName);
295 public String getPackageName() {
300 * @return list of imports or empty list
302 public List<String> getImportsNames() {
306 public String getClassName() {
311 * @return set of methods or empty set
313 public Set<FieldDeclaration> getFields() {
318 * @return set of methods or empty set
320 public Set<MethodDeclaration> getMethods() {
325 * @return declaration of augment field or NULL
327 public FieldDeclaration getAugmentField() {