Fix checkstyle in mdsal-binding2-java-api-generator
[mdsal.git] / binding2 / mdsal-binding2-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / javav2 / java / api / generator / renderers / BuilderRenderer.java
old mode 100644 (file)
new mode 100755 (executable)
index d81280d..ac4d63f
@@ -8,6 +8,7 @@
 
 package org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers;
 
+import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.typeForClass;
 import static org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.DOT;
 import static org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.getPropertyList;
 import static org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.toFirstLower;
@@ -16,12 +17,14 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ClassToInstanceMap;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSortedSet;
+
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -29,54 +32,74 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.regex.Pattern;
+
 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes;
 import org.opendaylight.mdsal.binding.javav2.generator.util.ReferencedTypeImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.builderConstructorHelperTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.builderTemplate;
+import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.constantsTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.AlphabeticallyTypeMemberComparator;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTypeForBuilder;
 import org.opendaylight.mdsal.binding.javav2.model.api.MethodSignature;
 import org.opendaylight.mdsal.binding.javav2.model.api.ParameterizedType;
 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
+import org.opendaylight.mdsal.binding.javav2.spec.base.IdentifiableItem;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Item;
 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.CodeHelpers;
 import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentable;
 import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentation;
 import org.opendaylight.mdsal.binding.javav2.spec.structural.AugmentationHolder;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.common.QName;
 
 public class BuilderRenderer extends BaseRenderer {
 
     /**
-     * Set of class attributes (fields) which are derived from the getter methods names
+     * Set of class attributes (fields) which are derived from the getter methods names.
      */
     private final Set<GeneratedProperty> properties;
 
     /**
-     * Set of name from properties
+     * Set of name from properties.
      */
     private final Map<GeneratedProperty, String> importedNamesForProperties = new HashMap<>();
 
     /**
-     * list of all imported names for template
-     */
-    private final Map<String, String> importedNames = new HashMap<>();
-
-    /**
-     * Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME
+     * Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME.
      */
     private GeneratedProperty augmentField;
 
+    boolean instantiable = false;
+
     public BuilderRenderer(final GeneratedType type) {
         super(type);
         this.properties = propertiesFromMethods(createMethods());
         putToImportMap(Builder.class.getSimpleName(), Builder.class.getPackage().getName());
+        putToImportMap(type.getName(), type.getPackageName());
+    }
+
+    @Override
+    protected String packageDefinition() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("package ")
+                .append(((GeneratedTypeForBuilder) getType()).getPackageNameForBuilder())
+                .append(";\n\n");
+        return sb.toString();
+    }
+
+    @Override
+    protected boolean hasSamePackage(final String importedTypePackageName) {
+        return ((GeneratedTypeForBuilder) getType()).getPackageNameForBuilder()
+                .equals(importedTypePackageName);
     }
 
     /**
@@ -95,6 +118,9 @@ public class BuilderRenderer extends BaseRenderer {
             if (createdField != null) {
                 result.add(createdField);
                 importedNamesForProperties.put(createdField, importedName(createdField.getReturnType()));
+                if (createdField.getReturnType().equals(typeForClass(List.class))) {
+                    getImportedNames().put("arrayList", importedName(ArrayList.class));
+                }
             }
         }
         return result;
@@ -105,22 +131,23 @@ public class BuilderRenderer extends BaseRenderer {
      *
      * @param method method signature from which is the method name and return type obtained
      * @return generated property instance for the getter <code>method</code>
-     * @throws IllegalArgumentException
-     *  <li>if the <code>method</code> equals <code>null</code></li>
-     *  <li>if the name of the <code>method</code> equals <code>null</code></li>
-     *  <li>if the name of the <code>method</code> is empty</li>
-     *  <li>if the return type of the <code>method</code> equals <code>null</code></li>
+     * @throws IllegalArgumentException <li>if the <code>method</code> equals <code>null</code></li>
+     *                                  <li>if the name of the <code>method</code> equals <code>null</code></li>
+     *                                  <li>if the name of the <code>method</code> is empty</li>
+     *                                  <li>if the return type of the <code>method</code> equals <code>null</code></li>
      */
     private GeneratedProperty propertyFromGetter(final MethodSignature method) {
         Preconditions.checkArgument(method != null, "Method cannot be NULL");
-        Preconditions.checkArgument(!Strings.isNullOrEmpty(method.getName()), "Method name cannot be NULL or empty");
-        Preconditions.checkArgument(method.getReturnType() != null, "Method return type reference cannot be NULL");
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(method.getName()),
+                "Method name cannot be NULL or empty");
+        Preconditions.checkArgument(method.getReturnType() != null,
+                "Method return type reference cannot be NULL");
         final String prefix = Types.BOOLEAN.equals(method.getReturnType()) ? "is" : "get";
         if (method.getName().startsWith(prefix)) {
             final String fieldName = toFirstLower(method.getName().substring(prefix.length()));
-            final GeneratedTOBuilderImpl tmpGenTO = new GeneratedTOBuilderImpl("foo", "foo");
-            tmpGenTO.addProperty(fieldName)
-                    .setReturnType(method.getReturnType());
+            final GeneratedTOBuilderImpl tmpGenTO =
+                    new GeneratedTOBuilderImpl("foo", "foo", true);
+            tmpGenTO.addProperty(fieldName).setReturnType(method.getReturnType());
             return tmpGenTO.toInstance().getProperties().get(0);
         }
         return null;
@@ -147,7 +174,7 @@ public class BuilderRenderer extends BaseRenderer {
      * Adds to the <code>methods</code> set all the methods of the <code>implementedIfcs</code>
      * and recursively their implemented interfaces.
      *
-     * @param methods set of method signatures
+     * @param methods         set of method signatures
      * @param implementedIfcs list of implemented interfaces
      */
     private void collectImplementedMethods(final Set<MethodSignature> methods, List<Type> implementedIfcs) {
@@ -155,7 +182,9 @@ public class BuilderRenderer extends BaseRenderer {
             for (Type implementedIfc : implementedIfcs) {
                 if ((implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))) {
                     final GeneratedType ifc = (GeneratedType) implementedIfc;
-                    methods.addAll(ifc.getMethodDefinitions());
+                    if (implementedIfc instanceof GeneratedTypeForBuilder) {
+                        methods.addAll(ifc.getMethodDefinitions());
+                    }
                     collectImplementedMethods(methods, ifc.getImplements());
                 } else if (Augmentable.class.getName().equals(implementedIfc.getFullyQualifiedName())) {
                     for (Method method : Augmentable.class.getMethods()) {
@@ -163,22 +192,30 @@ public class BuilderRenderer extends BaseRenderer {
                             final String fullyQualifiedName = method.getReturnType().getName();
                             final String aPackage = getPackage(fullyQualifiedName);
                             final String name = getName(fullyQualifiedName);
-                            final GeneratedTOBuilderImpl generatedTOBuilder = new GeneratedTOBuilderImpl(aPackage, name);
-                            final ReferencedTypeImpl referencedType = new ReferencedTypeImpl(aPackage, name, true);
+                            final GeneratedTOBuilderImpl generatedTOBuilder = new GeneratedTOBuilderImpl(aPackage,
+                                    name, true);
+                            final ReferencedTypeImpl referencedType = new ReferencedTypeImpl(aPackage, name,
+                                    true, null);
                             final ReferencedTypeImpl generic = new ReferencedTypeImpl(getType().getPackageName(),
-                                    getType().getName(), true);
-                            final ParameterizedType parametrizedReturnType = Types.parameterizedTypeFor(referencedType, generic);
+                                    getType().getName(), true, null);
+                            final ParameterizedType parametrizedReturnType =
+                                    Types.parameterizedTypeFor(referencedType, generic);
                             generatedTOBuilder.addMethod(method.getName()).setReturnType(parametrizedReturnType);
-                            augmentField = propertyFromGetter(generatedTOBuilder.toInstance().getMethodDefinitions().get(0));
-                            importedNames.put("map", importedName(Map.class));
-                            importedNames.put("hashMap", importedName(HashMap.class));
-                            importedNames.put("class", importedName(Class.class));
+                            augmentField = propertyFromGetter(generatedTOBuilder.toInstance().getMethodDefinitions()
+                                    .get(0));
+                            getImportedNames().put("map", importedName(Map.class));
+                            getImportedNames().put("hashMap", importedName(HashMap.class));
+                            getImportedNames().put("class", importedName(Class.class));
 //                            To do This is for third party, is it needed ?
-                            importedNames.put("augmentationHolder", importedName(AugmentationHolder.class));
-                            importedNames.put("collections", importedName(Collections.class));
-                            importedNames.put("augmentFieldReturnType", importedName(augmentField.getReturnType()));
+                            getImportedNames().put("augmentationHolder", importedName(AugmentationHolder.class));
+                            getImportedNames().put("collections", importedName(Collections.class));
+                            getImportedNames().put("augmentFieldReturnType", importedName(
+                                    augmentField.getReturnType()));
                         }
                     }
+                } else if (Instantiable.class.getName().equals(implementedIfc.getFullyQualifiedName())) {
+                    getImportedNames().put("class", importedName(Class.class));
+                    instantiable = true;
                 }
             }
         }
@@ -196,7 +233,7 @@ public class BuilderRenderer extends BaseRenderer {
     }
 
     /**
-     * Returns the name of tye type from <code>fullyQualifiedName</code>
+     * Returns the name of the type from <code>fullyQualifiedName</code>.
      *
      * @param fullyQualifiedName string with fully qualified type name (package + type)
      * @return string with the name of the type
@@ -209,8 +246,8 @@ public class BuilderRenderer extends BaseRenderer {
     public static Set<Type> getAllIfcs(final Type type) {
         final Set<Type> baseIfcs = new HashSet<>();
         if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
-            for (Type impl : ((GeneratedType)type).getImplements()) {
-                if (impl instanceof GeneratedType && !(((GeneratedType)impl).getMethodDefinitions().isEmpty())) {
+            for (Type impl : ((GeneratedType) type).getImplements()) {
+                if (impl instanceof GeneratedType && !(((GeneratedType) impl).getMethodDefinitions().isEmpty())) {
                     baseIfcs.add(impl);
                 }
                 baseIfcs.addAll(getAllIfcs(impl));
@@ -221,10 +258,13 @@ public class BuilderRenderer extends BaseRenderer {
 
     /**
      * Method is used to find out if given type implements any interface from uses.
+     *
+     * @param type type to inspect
+     * @return has implements from uses-stmt true/false
      */
     public static boolean hasImplementsFromUses(GeneratedType type) {
         for (Type impl : getAllIfcs(type)) {
-            if ((impl instanceof GeneratedType) && !(((GeneratedType)impl).getMethodDefinitions().isEmpty())) {
+            if ((impl instanceof GeneratedType) && !(((GeneratedType) impl).getMethodDefinitions().isEmpty())) {
                 return true;
             }
         }
@@ -242,63 +282,77 @@ public class BuilderRenderer extends BaseRenderer {
     @Override
     protected String body() {
         final String parentTypeForBuilderName;
-        importedNames.put("genType", importedName(getType()));
-        importedNames.put("objects", importedName(Objects.class));
-        importedNames.put("object", importedName(Object.class));
-        importedNames.put("string", importedName(String.class));
-        importedNames.put("stringBuilder", importedName(StringBuilder.class));
-        importedNames.put("treeNode", importedName(TreeNode.class));
-        importedNames.put("instantiable", importedName(Instantiable.class));
-        importedNames.put("item", importedName(Item.class));
+        getImportedNames().put("genType", importedName(getType()));
+        getImportedNames().put("objects", importedName(Objects.class));
+        getImportedNames().put("object", importedName(Object.class));
+        getImportedNames().put("string", importedName(String.class));
+        getImportedNames().put("arrays", importedName(Arrays.class));
+        getImportedNames().put("stringBuilder", importedName(StringBuilder.class));
+        getImportedNames().put("treeNode", importedName(TreeNode.class));
+        getImportedNames().put("instantiable", importedName(Instantiable.class));
+        getImportedNames().put("item", importedName(Item.class));
+        getImportedNames().put("identifiableItem", importedName(IdentifiableItem.class));
+        getImportedNames().put("qname", importedName(QName.class));
+        getImportedNames().put("codeHelpers", importedName(CodeHelpers.class));
+        getImportedNames().put("list", importedName(List.class));
+        getImportedNames().put("immutableList", importedName(ImmutableList.class));
+        getImportedNames().put("pattern", importedName(Pattern.class));
+
         if (getType().getParentType() != null) {
-            importedNames.put("parent", importedName(getType().getParentType()));
-            parentTypeForBuilderName = getType().getParentType().getName();
+            getImportedNames().put("parent", importedName(getType().getParentType()));
+            parentTypeForBuilderName = getType().getParentType().getFullyQualifiedName();
         } else if (getType().getParentTypeForBuilder() != null) {
-            importedNames.put("parentTypeForBuilder", importedName(getType().getParentTypeForBuilder()));
-            parentTypeForBuilderName = getType().getParentTypeForBuilder().getName();
+            getImportedNames().put("parentTypeForBuilder", importedName(getType().getParentTypeForBuilder()));
+            parentTypeForBuilderName = getType().getParentTypeForBuilder().getFullyQualifiedName();
         } else {
             parentTypeForBuilderName = null;
         }
 
         boolean childTreeNode = false;
+        boolean childTreeNodeIdent = false;
+        String keyTypeName = null;
         if (getType().getImplements().contains(BindingTypes.TREE_CHILD_NODE)) {
             childTreeNode = true;
+            if (getType().getImplements().contains(BindingTypes.IDENTIFIABLE)) {
+                childTreeNodeIdent = true;
+                final ParameterizedType pType = (ParameterizedType) getType().getImplements().get(getType()
+                        .getImplements().indexOf(BindingTypes.IDENTIFIABLE));
+                keyTypeName = pType.getActualTypeArguments()[0].getName();
+            }
         }
 
-        importedNames.put("augmentation", importedName(Augmentation.class));
-        importedNames.put("classInstMap", importedName(ClassToInstanceMap.class));
+        getImportedNames().put("augmentation", importedName(Augmentation.class));
+        getImportedNames().put("classInstMap", importedName(ClassToInstanceMap.class));
+
+        final String constants = constantsTemplate.render(getType(), getImportedNames(), this::importedName, false)
+                .body();
 
         // list for generate copy constructor
         final String copyConstructorHelper = generateListForCopyConstructor();
         List<String> getterMethods = new ArrayList<>(Collections2.transform(properties, this::getterMethod));
 
-        return builderTemplate.render(getType(), properties, importedNames, importedNamesForProperties, augmentField,
-            copyConstructorHelper, getterMethods, parentTypeForBuilderName, childTreeNode)
-                .body();
+        return builderTemplate.render(getType(), properties, getImportedNames(), importedNamesForProperties,
+                augmentField,
+                copyConstructorHelper, getterMethods, parentTypeForBuilderName, childTreeNode, childTreeNodeIdent,
+                keyTypeName, instantiable, constants).body();
     }
 
     private String generateListForCopyConstructor() {
         final List allProps = new ArrayList<>(properties);
-        final boolean isList = implementsIfc(getType(), Types.parameterizedTypeFor(Types.typeForClass(Identifiable.class),
-                getType()));
+        final boolean isList = implementsIfc(getType(),
+                Types.parameterizedTypeFor(typeForClass(Identifiable.class), getType()));
         final Type keyType = getKey(getType());
         if (isList && keyType != null) {
             final List<GeneratedProperty> keyProps = ((GeneratedTransferObject) keyType).getProperties();
-            final Comparator<GeneratedProperty> function = (GeneratedProperty p1, GeneratedProperty p2) -> {
-                String name2 = p1.getName();
-                String name3 = p2.getName();
-                return name2.compareTo(name3);
-            };
-            Collections.sort(keyProps, function);
             for (GeneratedProperty keyProp : keyProps) {
                 removeProperty(allProps, keyProp.getName());
             }
             removeProperty(allProps, "key");
-            importedNames.put("keyTypeConstructor", importedName(keyType));
-            return builderConstructorHelperTemplate.render(allProps, keyProps, importedNames, getPropertyList(allProps))
-                    .body();
+            getImportedNames().put("keyTypeConstructor", importedName(keyType));
+            return builderConstructorHelperTemplate.render(allProps, keyProps, getImportedNames(),
+                    getPropertyList(keyProps)).body();
         }
-        return builderConstructorHelperTemplate.render(allProps, null, importedNames, null).body();
+        return builderConstructorHelperTemplate.render(allProps, null, getImportedNames(), null).body();
     }
 
     private Type getKey(final GeneratedType genType) {
@@ -314,10 +368,10 @@ public class BuilderRenderer extends BaseRenderer {
         return type.getImplements().contains(impl);
     }
 
-    private void removeProperty(final Collection<GeneratedProperty> properties, final String name) {
-        for (final GeneratedProperty property : properties) {
+    private void removeProperty(final Collection<GeneratedProperty> props, final String name) {
+        for (final GeneratedProperty property : props) {
             if (name.equals(property.getName())) {
-                properties.remove(property);
+                props.remove(property);
                 break;
             }
         }