Cleanup equals() template
[controller.git] / opendaylight / config / yang-jmx-generator-plugin / src / main / java / org / opendaylight / controller / config / yangjmxgenerator / plugin / ftl / TemplateFactory.java
index 53ab4ef335973029568f0820968c830d59112f17..294520b36389992edb75af3e0121c7232728496d 100644 (file)
@@ -11,7 +11,6 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -23,7 +22,7 @@ import org.opendaylight.controller.config.api.IdentityAttributeRef;
 import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
 import org.opendaylight.controller.config.api.runtime.RuntimeBean;
-import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.AbstractModule;
 import org.opendaylight.controller.config.yangjmxgenerator.AbstractEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
@@ -48,9 +47,9 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Meth
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.MethodDefinition;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField;
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
-import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
 
 public class TemplateFactory {
 
@@ -59,12 +58,12 @@ public class TemplateFactory {
      * bean as value that should be persisted from this instance.
      */
     public static Map<String, FtlTemplate> getTOAndMXInterfaceFtlFiles(
-            RuntimeBeanEntry entry) {
+            final RuntimeBeanEntry entry) {
         Map<String, FtlTemplate> result = new HashMap<>();
         { // create GeneralInterfaceFtlFile for runtime MXBean. Attributes will
           // be transformed to getter methods
             String mxBeanTypeName = entry.getJavaNameOfRuntimeMXBean();
-            List<String> extendedInterfaces = Arrays.asList(RuntimeBean.class
+            List<String> extendedInterfaces = Collections.singletonList(RuntimeBean.class
                     .getCanonicalName());
             List<MethodDeclaration> methods = new ArrayList<>();
 
@@ -84,7 +83,7 @@ public class TemplateFactory {
                 // convert JavaAttribute parameters into fields
                 List<Field> fields = new ArrayList<>();
                 for (JavaAttribute ja : rpc.getParameters()) {
-                    Field field = new Field(Collections.<String> emptyList(),
+                    Field field = new Field(Collections.emptyList(),
                             ja.getType().getFullyQualifiedName(),
                             ja.getLowerCaseCammelCase(), ja.getNullableDefaultWrappedForCode());
                     fields.add(field);
@@ -109,7 +108,7 @@ public class TemplateFactory {
     }
 
     // FIXME: put into Type.toString
-    static String serializeType(Type type, boolean addWildcards) {
+    static String serializeType(final Type type, final boolean addWildcards) {
         if (type instanceof ParameterizedType){
             ParameterizedType parameterizedType = (ParameterizedType) type;
             StringBuilder sb = new StringBuilder();
@@ -131,11 +130,11 @@ public class TemplateFactory {
         }
     }
 
-    static String serializeType(Type type) {
+    static String serializeType(final Type type) {
         return serializeType(type, false);
     }
 
-    private static String getReturnType(AttributeIfc attributeIfc) {
+    private static String getReturnType(final AttributeIfc attributeIfc) {
         String returnType;
         if (attributeIfc instanceof TypedAttribute) {
             Type type = ((TypedAttribute) attributeIfc).getType();
@@ -151,7 +150,7 @@ public class TemplateFactory {
     }
 
     public static GeneralInterfaceTemplate serviceInterfaceFromSie(
-            ServiceInterfaceEntry sie) {
+            final ServiceInterfaceEntry sie) {
 
         List<String> extendedInterfaces = Lists
                 .newArrayList(AbstractServiceInterface.class.getCanonicalName());
@@ -177,10 +176,9 @@ public class TemplateFactory {
     }
 
     public static AbstractFactoryTemplate abstractFactoryTemplateFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         AbstractFactoryAttributesProcessor attrProcessor = new AbstractFactoryAttributesProcessor();
-        attrProcessor.processAttributes(mbe.getAttributes(),
-                mbe.getPackageName());
+        attrProcessor.processAttributes(mbe.getAttributes());
 
 
 
@@ -191,12 +189,11 @@ public class TemplateFactory {
     }
 
     public static AbstractModuleTemplate abstractModuleTemplateFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         AbstractModuleAttributesProcessor attrProcessor = new AbstractModuleAttributesProcessor(mbe.getAttributes());
 
         List<ModuleField> moduleFields = attrProcessor.getModuleFields();
         List<String> implementedIfcs = Lists.newArrayList(
-                Module.class.getCanonicalName(),
                 mbe.getFullyQualifiedName(mbe.getMXBeanInterfaceName()));
 
         for (String implementedService : mbe.getProvidedServices().keySet()) {
@@ -206,7 +203,7 @@ public class TemplateFactory {
         boolean generateRuntime = false;
         String registratorFullyQualifiedName = null;
         if (mbe.getRuntimeBeans() != null
-                && mbe.getRuntimeBeans().isEmpty() == false) {
+                && !mbe.getRuntimeBeans().isEmpty()) {
             generateRuntime = true;
             RuntimeBeanEntry rootEntry = RuntimeRegistratorFtlTemplate
                     .findRoot(mbe.getRuntimeBeans());
@@ -218,9 +215,11 @@ public class TemplateFactory {
                     .getCanonicalName());
         }
 
+        List<String> extendedClasses = Collections.singletonList(AbstractModule.class.getCanonicalName() + "<" + mbe.getAbstractModuleName() + ">");
+
         AbstractModuleTemplate abstractModuleTemplate = new AbstractModuleTemplate(
                 getHeaderFromEntry(mbe), mbe.getPackageName(),
-                mbe.getAbstractModuleName(), implementedIfcs, moduleFields,
+                mbe.getAbstractModuleName(), extendedClasses, implementedIfcs, moduleFields,
                 attrProcessor.getMethods(), generateRuntime,
                 registratorFullyQualifiedName);
 
@@ -233,7 +232,7 @@ public class TemplateFactory {
     }
 
     public static StubFactoryTemplate stubFactoryTemplateFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         return new StubFactoryTemplate(getHeaderFromEntry(mbe),
                 mbe.getPackageName(), mbe.getStubFactoryName(),
                 mbe.getFullyQualifiedName(mbe.getAbstractFactoryName())
@@ -241,7 +240,7 @@ public class TemplateFactory {
     }
 
     public static GeneralInterfaceTemplate mXBeanInterfaceTemplateFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         MXBeanInterfaceAttributesProcessor attrProcessor = new MXBeanInterfaceAttributesProcessor();
         attrProcessor.processAttributes(mbe.getAttributes());
         GeneralInterfaceTemplate ifcTemplate = new GeneralInterfaceTemplate(
@@ -253,7 +252,7 @@ public class TemplateFactory {
     }
 
     public static Map<String, GeneralClassTemplate> tOsFromMbe(
-            ModuleMXBeanEntry mbe) {
+            final ModuleMXBeanEntry mbe) {
         Map<String, GeneralClassTemplate> retVal = Maps.newHashMap();
         TOAttributesProcessor processor = new TOAttributesProcessor();
         processor.processAttributes(mbe.getAttributes());
@@ -274,7 +273,7 @@ public class TemplateFactory {
     }
 
     public static Map<String, GeneralClassTemplate> tOsFromRbe(
-            RuntimeBeanEntry rbe) {
+            final RuntimeBeanEntry rbe) {
         Map<String, GeneralClassTemplate> retVal = Maps.newHashMap();
         TOAttributesProcessor processor = new TOAttributesProcessor();
         Map<String, AttributeIfc> yangPropertiesToTypesMap = Maps.newHashMap(rbe.getYangPropertiesToTypesMap());
@@ -293,7 +292,7 @@ public class TemplateFactory {
                 continue;
             }
 
-            Preconditions.checkState(yangPropertiesToTypesMap.containsKey(returnType.getAttributeYangName()) == false,
+            Preconditions.checkState(!yangPropertiesToTypesMap.containsKey(returnType.getAttributeYangName()),
                     "Duplicate TO %s for %s", returnType.getAttributeYangName(), rbe);
             yangPropertiesToTypesMap.put(returnType.getAttributeYangName(), returnType);
         }
@@ -315,7 +314,7 @@ public class TemplateFactory {
         return retVal;
     }
 
-    private static Header getHeaderFromEntry(AbstractEntry mbe) {
+    private static Header getHeaderFromEntry(final AbstractEntry mbe) {
         return new Header(mbe.getYangModuleName(), mbe.getYangModuleLocalname());
     }
 
@@ -325,7 +324,7 @@ public class TemplateFactory {
 
         private final List<TOInternal> tos = Lists.newArrayList();
 
-        void processAttributes(Map<String, AttributeIfc> attributes) {
+        void processAttributes(final Map<String, AttributeIfc> attributes) {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
                 AttributeIfc attributeIfc = attrEntry.getValue();
                 if (attributeIfc instanceof TOAttribute) {
@@ -341,7 +340,7 @@ public class TemplateFactory {
             }
         }
 
-        private void createTOInternal(TOAttribute toAttribute) {
+        private void createTOInternal(final TOAttribute toAttribute) {
 
             Map<String, AttributeIfc> attrs = toAttribute.getCapitalizedPropertiesToTypesMap();
             // recursive processing of TO's attributes
@@ -359,12 +358,12 @@ public class TemplateFactory {
             private List<Field> fields;
             private List<MethodDefinition> methods;
 
-            public TOInternal(Type type, Map<String, AttributeIfc> attrs) {
+            public TOInternal(final Type type, final Map<String, AttributeIfc> attrs) {
                 this(type.getFullyQualifiedName(), type.getName(), attrs, type.getPackageName());
             }
 
-            public TOInternal(String fullyQualifiedName, String name,
-                    Map<String, AttributeIfc> attrs, String packageName) {
+            public TOInternal(final String fullyQualifiedName, final String name,
+                    final Map<String, AttributeIfc> attrs, final String packageName) {
                 this.fullyQualifiedName = fullyQualifiedName;
                 this.name = name;
                 processAttrs(attrs, packageName);
@@ -373,7 +372,7 @@ public class TemplateFactory {
             private final static String dependencyResolverVarName = "dependencyResolver";
             private final static String dependencyResolverInjectMethodName = "injectDependencyResolver";
 
-            private void processAttrs(Map<String, AttributeIfc> attrs, String packageName) {
+            private void processAttrs(final Map<String, AttributeIfc> attrs, final String packageName) {
                 fields = Lists.newArrayList();
                 methods = Lists.newArrayList();
 
@@ -385,8 +384,7 @@ public class TemplateFactory {
 
                 for (Entry<String, AttributeIfc> attrEntry : attrs.entrySet()) {
                     String innerName = attrEntry.getKey();
-                    String varName = BindingGeneratorUtil
-                            .parseToValidParamName(attrEntry.getKey());
+                    String varName = BindingMapping.getPropertyName(attrEntry.getKey());
 
                     String fullyQualifiedName, nullableDefault = null;
                     if (attrEntry.getValue() instanceof TypedAttribute) {
@@ -424,6 +422,43 @@ public class TemplateFactory {
                     methods.add(setter);
                 }
 
+                // Add hashCode
+                final MethodDefinition hashCode = getHash(attrs);
+                methods.add(hashCode);
+
+                // Add equals
+                final MethodDefinition equals = getEquals(attrs);
+                methods.add(equals);
+            }
+
+            private MethodDefinition getEquals(final Map<String, AttributeIfc> attrs) {
+                final StringBuilder equalsBodyBuilder = new StringBuilder(
+                        "        if (this == o) { return true; }\n" +
+                        "        if (o == null || getClass() != o.getClass()) { return false; }\n");
+                equalsBodyBuilder.append(String.format(
+                        "        final %s that = (%s) o;\n", name, name));
+                for (AttributeIfc s : attrs.values()) {
+                    equalsBodyBuilder.append(String.format(
+                            "        if (!java.util.Objects.equals(%1$s, that.%1$s)) {\n" +
+                            "            return false;\n" +
+                            "        }\n\n", s.getLowerCaseCammelCase()));
+                }
+                equalsBodyBuilder.append(
+                        "       return true;\n");
+                return new MethodDefinition("boolean", "equals", Collections.singletonList(new Field("Object", "o")),
+                        Collections.singletonList(new Annotation("Override", Collections.<Parameter>emptyList())), equalsBodyBuilder.toString());
+            }
+
+            private static MethodDefinition getHash(final Map<String, AttributeIfc> attrs) {
+                final StringBuilder hashBodyBuilder = new StringBuilder(
+                        "        return java.util.Objects.hash(");
+                for (AttributeIfc s : attrs.values()) {
+                    hashBodyBuilder.append(s.getLowerCaseCammelCase());
+                    hashBodyBuilder.append(", ");
+                }
+                hashBodyBuilder.replace(hashBodyBuilder.length() - 2, hashBodyBuilder.length(), ");\n");
+                return new MethodDefinition("int", "hashCode", Collections.<Field>emptyList(),
+                        Collections.singletonList(new Annotation("Override", Collections.<Parameter>emptyList())), hashBodyBuilder.toString());
             }
 
             String getType() {
@@ -448,7 +483,7 @@ public class TemplateFactory {
     private static class MXBeanInterfaceAttributesProcessor {
         private final List<MethodDeclaration> methods = Lists.newArrayList();
 
-        void processAttributes(Map<String, AttributeIfc> attributes) {
+        void processAttributes(final Map<String, AttributeIfc> attributes) {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
                 String returnType;
                 AttributeIfc attributeIfc = attrEntry.getValue();
@@ -472,8 +507,7 @@ public class TemplateFactory {
                 MethodDeclaration getter = new MethodDeclaration(returnType,
                         getterName, Collections.<Field> emptyList());
 
-                String varName = BindingGeneratorUtil
-                        .parseToValidParamName(attrEntry.getKey());
+                String varName = BindingMapping.getPropertyName(attrEntry.getKey());
                 String setterName = "set"
                         + attributeIfc.getUpperCaseCammelCase();
                 MethodDeclaration setter = new MethodDeclaration("void",
@@ -518,24 +552,19 @@ public class TemplateFactory {
 
         private final List<Field> fields = Lists.newArrayList();
 
-        void processAttributes(Map<String, AttributeIfc> attributes,
-                String packageName) {
-            for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
-                String type;
-                String nullableDefaultWrapped = null;
-                AttributeIfc attributeIfc = attrEntry.getValue();
-
+        void processAttributes(final Map<String, AttributeIfc> attributes) {
+            for (AttributeIfc attributeIfc : attributes.values()) {
                 if (attributeIfc instanceof TypedAttribute) {
                     TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
-                    type = serializeType(typedAttribute.getType());
+                    String type = serializeType(typedAttribute.getType());
+
+                    fields.add(new Field(type, attributeIfc
+                            .getUpperCaseCammelCase(), null));
                 } else {
                     throw new UnsupportedOperationException(
                             "Attribute not supported: "
                                     + attributeIfc.getClass());
                 }
-
-                fields.add(new Field(type, attributeIfc
-                        .getUpperCaseCammelCase(), nullableDefaultWrapped));
             }
         }
 
@@ -549,7 +578,7 @@ public class TemplateFactory {
             private final List<ModuleField> moduleFields;
             private final List<MethodDefinition> methods;
 
-            private Holder(List<ModuleField> moduleFields, List<MethodDefinition> methods) {
+            private Holder(final List<ModuleField> moduleFields, final List<MethodDefinition> methods) {
                 this.moduleFields = Collections.unmodifiableList(moduleFields);
                 this.methods = Collections.unmodifiableList(methods);
             }
@@ -558,11 +587,11 @@ public class TemplateFactory {
         private final Holder holder;
 
 
-        private AbstractModuleAttributesProcessor(Map<String, AttributeIfc> attributes) {
+        private AbstractModuleAttributesProcessor(final Map<String, AttributeIfc> attributes) {
             this.holder = processAttributes(attributes);
         }
 
-        private static Holder processAttributes(Map<String, AttributeIfc> attributes) {
+        private static Holder processAttributes(final Map<String, AttributeIfc> attributes) {
             List<ModuleField> moduleFields = new ArrayList<>();
             List<MethodDefinition> methods = new ArrayList<>();
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
@@ -606,8 +635,7 @@ public class TemplateFactory {
                     }
                 }
 
-                String varName = BindingGeneratorUtil
-                        .parseToValidParamName(attrEntry.getKey());
+                String varName = BindingMapping.getPropertyName(attrEntry.getKey());
 
                 ModuleField field;
                 if (isIdentity) {
@@ -662,8 +690,8 @@ public class TemplateFactory {
 
                 String setterBody = "this." + varName + " = " + varName + ";";
                 if (isListOfDependencies) {
-                    String nullCheck = String.format("if (%s == null) throw new IllegalArgumentException(\"Null not supported\");%n",
-                            varName);
+                    String nullCheck = String.format("if (%s == null) {\n%s = new java.util.ArrayList<>(); \n}%n",
+                            varName, varName);
                     setterBody = nullCheck + setterBody;
                 }
                 MethodDefinition setter = new MethodDefinition("void",
@@ -688,7 +716,7 @@ public class TemplateFactory {
     }
 
 
-    private static boolean needsDepResolver(AttributeIfc value) {
+    private static boolean needsDepResolver(final AttributeIfc value) {
         if(value instanceof TOAttribute) {
             return true;
         }
@@ -700,7 +728,7 @@ public class TemplateFactory {
         return false;
     }
 
-    private static String getInnerTypeFromIdentity(Type type) {
+    private static String getInnerTypeFromIdentity(final Type type) {
         Preconditions.checkArgument(type instanceof ParameterizedType);
         Type[] args = ((ParameterizedType) type).getActualTypeArguments();
         Preconditions.checkArgument(args.length ==1);