Improve class template equals()
[yangtools.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / ClassTemplate.xtend
index fac6cf25c5aed0a114667df8fd07314f01508bbb..8eee22e21131e1401c62fb642149494364ec9922 100644 (file)
@@ -8,37 +8,37 @@
 package org.opendaylight.mdsal.binding.java.api.generator
 
 import static java.util.Objects.requireNonNull
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.BINARY_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.BOOLEAN_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.EMPTY_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.INSTANCE_IDENTIFIER
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.INT16_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.INT32_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.INT64_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.INT8_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.STRING_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.UINT16_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.UINT32_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.UINT64_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BaseYangTypes.UINT8_TYPE
-import static org.opendaylight.mdsal.binding.model.util.BindingTypes.SCALAR_TYPE_OBJECT
-import static org.opendaylight.mdsal.binding.model.util.Types.BOOLEAN
-import static org.opendaylight.mdsal.binding.model.util.Types.STRING;
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.BINARY_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.BOOLEAN_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.DECIMAL64_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.EMPTY_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.INSTANCE_IDENTIFIER
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.INT16_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.INT32_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.INT64_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.INT8_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.STRING_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.UINT16_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.UINT32_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.UINT64_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.UINT8_TYPE
+import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.SCALAR_TYPE_OBJECT
+import static org.opendaylight.mdsal.binding.model.ri.Types.STRING;
 import static extension org.apache.commons.text.StringEscapeUtils.escapeJava
+import static extension org.opendaylight.mdsal.binding.model.ri.BindingTypes.isBitsType
 
 import com.google.common.base.Preconditions
 import com.google.common.collect.ImmutableList
 import com.google.common.collect.Lists
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
-import java.beans.ConstructorProperties
 import java.util.ArrayList
 import java.util.Base64;
+import java.util.Collection
 import java.util.Comparator
 import java.util.List
 import java.util.Map
 import java.util.Set
 import javax.management.ConstructorParameters
-import org.gaul.modernizer_maven_annotations.SuppressModernizer
 import org.opendaylight.mdsal.binding.model.api.ConcreteType
 import org.opendaylight.mdsal.binding.model.api.Constant
 import org.opendaylight.mdsal.binding.model.api.Enumeration
@@ -46,19 +46,18 @@ import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
 import org.opendaylight.mdsal.binding.model.api.Restrictions
 import org.opendaylight.mdsal.binding.model.api.Type
-import org.opendaylight.mdsal.binding.model.util.TypeConstants
+import org.opendaylight.mdsal.binding.model.ri.TypeConstants
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping
 import org.opendaylight.yangtools.yang.common.Empty
-import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
 
 /**
  * Template for generating JAVA class.
  */
-@SuppressModernizer
 class ClassTemplate extends BaseTemplate {
     static val Comparator<GeneratedProperty> PROP_COMPARATOR = Comparator.comparing([prop | prop.name])
     static val VALUEOF_TYPES = Set.of(
         BOOLEAN_TYPE,
+        DECIMAL64_TYPE,
         INT8_TYPE,
         INT16_TYPE,
         INT32_TYPE,
@@ -146,8 +145,11 @@ class ClassTemplate extends BaseTemplate {
      * @return string with class source code in JAVA format
      */
     def protected generateBody(boolean isInnerClass) '''
-        «wrapToDocumentation(formatDataForJavaDoc(type))»
+        «type.formatDataForJavaDoc.wrapToDocumentation»
         «annotationDeclaration»
+        «IF !isInnerClass»
+            «generatedAnnotation»
+        «ENDIF»
         «generateClassDeclaration(isInnerClass)» {
             «suidDeclaration»
             «innerClassesDeclarations»
@@ -171,7 +173,7 @@ class ClassTemplate extends BaseTemplate {
 
             «propertyMethods»
 
-            «IF (genTO.isTypedef() && genTO.getBaseType instanceof BitsTypeDefinition)»
+            «IF genTO.isBitsType»
                 «generateGetValueForBitsTypeDef»
             «ENDIF»
 
@@ -184,7 +186,7 @@ class ClassTemplate extends BaseTemplate {
 
     '''
 
-    def private propertyMethods() {
+    def protected propertyMethods() {
         if (properties.empty) {
             return ""
         }
@@ -212,7 +214,7 @@ class ClassTemplate extends BaseTemplate {
     def private scalarTypeObjectValue(GeneratedProperty field) '''
         @«OVERRIDE.importedName»
         public «field.returnType.importedName» «BindingMapping.SCALAR_TYPE_OBJECT_GET_VALUE_NAME»() {
-            return «field.fieldName»«IF field.returnType.name.endsWith("[]")».clone()«ENDIF»;
+            return «field.fieldName»«field.cloneCall»;
         }
     '''
 
@@ -263,7 +265,7 @@ class ClassTemplate extends BaseTemplate {
         «ENDIF»
     '''
 
-    def private allValuesConstructor() '''
+    def allValuesConstructor() '''
     public «type.name»(«allProperties.asArgumentsDeclaration») {
         «IF !parentProperties.empty»
             super(«parentProperties.asArguments»);
@@ -285,7 +287,6 @@ class ClassTemplate extends BaseTemplate {
 
     def private typedefConstructor() '''
     @«ConstructorParameters.importedName»("«TypeConstants.VALUE_PROP»")
-    @«ConstructorProperties.importedName»("«TypeConstants.VALUE_PROP»")
     public «type.name»(«allProperties.asArgumentsDeclaration») {
         «IF !parentProperties.empty»
             super(«parentProperties.asArguments»);
@@ -302,11 +303,7 @@ class ClassTemplate extends BaseTemplate {
 
         «FOR p : properties»
             «val fieldName = p.fieldName»
-            «IF p.returnType.name.endsWith("[]")»
-                this.«fieldName» = «fieldName».clone();
-            «ELSE»
-                this.«fieldName» = «fieldName»;
-            «ENDIF»
+            this.«fieldName» = «fieldName»«p.cloneCall»;
         «ENDFOR»
     }
     '''
@@ -338,7 +335,7 @@ class ClassTemplate extends BaseTemplate {
 
     def private genPatternEnforcer(String ref) '''
         «FOR c : consts»
-            «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
+            «IF TypeConstants.PATTERN_CONSTANT_NAME.equals(c.name)»
             «CODEHELPERS.importedName».checkPattern(«ref», «Constants.MEMBER_PATTERN_LIST», «Constants.MEMBER_REGEX_LIST»);
             «ENDIF»
         «ENDFOR»
@@ -352,7 +349,7 @@ class ClassTemplate extends BaseTemplate {
         }
     }
 
-    def private generateRestrictions(Type type, String paramName, Type returnType) '''
+    def generateRestrictions(Type type, String paramName, Type returnType) '''
         «val restrictions = type.restrictions»
         «IF restrictions !== null»
             «IF restrictions.lengthConstraint.present || restrictions.rangeConstraint.present»
@@ -413,7 +410,7 @@ class ClassTemplate extends BaseTemplate {
                     return new «genTO.name»(«Base64.importedName».getDecoder().decode(defaultValue));
                 «ELSEIF EMPTY_TYPE.equals(propType)»
                     «Preconditions.importedName».checkArgument(defaultValue.isEmpty(), "Invalid value %s", defaultValue);
-                    return new «genTO.name»(«Empty.importedName».getInstance());
+                    return new «genTO.name»(«Empty.importedName».value());
                 «ELSE»
                     return new «genTO.name»(new «propType.importedName»(defaultValue));
                 «ENDIF»
@@ -426,12 +423,12 @@ class ClassTemplate extends BaseTemplate {
     def protected bitsArgs() '''
         «JU_LIST.importedName»<«STRING.importedName»> properties = «Lists.importedName».newArrayList(«allProperties.propsAsArgs»);
         if (!properties.contains(defaultValue)) {
-            throw new «IllegalArgumentException.importedName»("invalid default parameter");
+            throw new «IAE.importedName»("invalid default parameter");
         }
         int i = 0;
         return new «genTO.name»(
         «FOR prop : allProperties SEPARATOR ","»
-            properties.get(i++).equals(defaultValue) ? «BOOLEAN.importedName».TRUE : null
+            properties.get(i++).equals(defaultValue) ? true : false
         «ENDFOR»
         );
     '''
@@ -503,7 +500,7 @@ class ClassTemplate extends BaseTemplate {
     def protected constantsDeclarations() '''
         «IF !consts.empty»
             «FOR c : consts»
-                «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
+                «IF TypeConstants.PATTERN_CONSTANT_NAME.equals(c.name)»
                     «val cValue = c.value as Map<String, String>»
                     «val jurPatternRef = JUR_PATTERN.importedName»
                     public static final «JU_LIST.importedName»<String> «TypeConstants.PATTERN_CONSTANT_NAME» = «ImmutableList.importedName».of(«
@@ -554,7 +551,11 @@ class ClassTemplate extends BaseTemplate {
             @«OVERRIDE.importedName»
             public int hashCode() {
                 «IF size != 1»
-                    «hashCodeResult(genTO.hashCodeIdentifiers)»
+                    final int prime = 31;
+                    int result = 1;
+                    «FOR property : genTO.hashCodeIdentifiers»
+                        result = prime * result + «property.importedUtilClass».hashCode(«property.fieldName»);
+                    «ENDFOR»
                     return result;
                 «ELSE»
                     return «CODEHELPERS.importedName».wrapperHashCode(«genTO.hashCodeIdentifiers.get(0).fieldName»);
@@ -571,21 +572,25 @@ class ClassTemplate extends BaseTemplate {
     def private generateEquals() '''
         «IF !genTO.equalsIdentifiers.empty»
             @«OVERRIDE.importedName»
-            public final boolean equals(java.lang.Object obj) {
-                if (this == obj) {
-                    return true;
-                }
-                if (!(obj instanceof «type.name»)) {
-                    return false;
-                }
-                final «type.name» other = («type.name») obj;
+            public final boolean equals(«OBJECT.importedName» obj) {
+                return this == obj || obj instanceof «type.name» other
                 «FOR property : genTO.equalsIdentifiers»
                     «val fieldName = property.fieldName»
-                    if (!«property.importedUtilClass».equals(«fieldName», other.«fieldName»)) {
-                        return false;
-                    }
+                        && «property.importedUtilClass».equals(«fieldName», other.«fieldName»)«
+                »«ENDFOR»;
+            }
+        «ENDIF»
+    '''
+
+    def private generateToString(Collection<GeneratedProperty> properties) '''
+        «IF !properties.empty»
+            @«OVERRIDE.importedName»
+            public «STRING.importedName» toString() {
+                final var helper = «MOREOBJECTS.importedName».toStringHelper(«type.importedName».class);
+                «FOR property : properties»
+                    «CODEHELPERS.importedName».appendValue(helper, "«property.name»", «property.fieldName»);
                 «ENDFOR»
-                return true;
+                return helper.toString();
             }
         «ENDIF»
     '''