Add BitsTypeObject
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / ClassTemplate.xtend
index 89443c26948b341d9bdfee6a19bad665e998cf6b..df7be75af6500637be2a86e50251c07440370c4a 100644 (file)
@@ -23,13 +23,13 @@ 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.BOOLEAN
+import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.BITS_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.ImmutableSet
 import com.google.common.collect.Lists
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
 import java.util.ArrayList
@@ -45,11 +45,14 @@ import org.opendaylight.mdsal.binding.model.api.Constant
 import org.opendaylight.mdsal.binding.model.api.Enumeration
 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName
 import org.opendaylight.mdsal.binding.model.api.Restrictions
 import org.opendaylight.mdsal.binding.model.api.Type
 import org.opendaylight.mdsal.binding.model.ri.TypeConstants
+import org.opendaylight.mdsal.binding.model.ri.Types
 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.
@@ -67,6 +70,15 @@ class ClassTemplate extends BaseTemplate {
         UINT16_TYPE,
         UINT32_TYPE,
         UINT64_TYPE)
+    /**
+     * {@code java.lang.Boolean} as a JavaTypeName.
+     */
+    static val BOOLEAN = JavaTypeName.create(Boolean)
+
+    /**
+     * {@code com.google.common.collect.ImmutableSet} as a JavaTypeName.
+     */
+    static val IMMUTABLE_SET = JavaTypeName.create(ImmutableSet)
 
     protected val List<GeneratedProperty> properties
     protected val List<GeneratedProperty> finalProperties
@@ -174,8 +186,8 @@ class ClassTemplate extends BaseTemplate {
 
             «propertyMethods»
 
-            «IF genTO.isBitsType»
-                «generateGetValueForBitsTypeDef»
+            «IF isBitsTypeObject»
+                «validNamesAndValues»
             «ENDIF»
 
             «generateHashCode»
@@ -187,7 +199,7 @@ class ClassTemplate extends BaseTemplate {
 
     '''
 
-    def private propertyMethods() {
+    def protected propertyMethods() {
         if (properties.empty) {
             return ""
         }
@@ -203,6 +215,19 @@ class ClassTemplate extends BaseTemplate {
         return false
     }
 
+    def private isBitsTypeObject() {
+        var wlk = genTO
+        while (wlk !== null) {
+            for (impl : wlk.implements) {
+                if (BITS_TYPE_OBJECT.identifier.equals(impl.identifier)) {
+                    return true
+                }
+            }
+            wlk = wlk.superType
+        }
+        return false
+    }
+
     def private defaultProperties() '''
         «FOR field : properties SEPARATOR "\n"»
             «field.getterMethod»
@@ -219,20 +244,29 @@ class ClassTemplate extends BaseTemplate {
         }
     '''
 
-    /**
-     * Template method which generates the method <code>getValue()</code> for typedef,
-     * which base type is BitsDefinition.
-     *
-     * @return string with the <code>getValue()</code> method definition in JAVA format
-     */
-    def protected generateGetValueForBitsTypeDef() '''
+    def private validNamesAndValues() {
+        for (c : consts) {
+            if (TypeConstants.VALID_NAMES_NAME.equals(c.name)) {
+                return validNamesAndValues(c.value as BitsTypeDefinition)
+            }
+        }
+        return ""
+    }
 
-        public boolean[] getValue() {
-            return new boolean[]{
-            «FOR property: genTO.properties SEPARATOR ','»
-                 «property.fieldName»
-            «ENDFOR»
-            };
+    def private validNamesAndValues(BitsTypeDefinition typedef) '''
+
+        @«OVERRIDE.importedName»
+        public «IMMUTABLE_SET.importedName»<«STRING.importedName»> validNames() {
+            return «TypeConstants.VALID_NAMES_NAME»;
+        }
+
+        @«OVERRIDE.importedName»
+        public boolean[] values() {
+            return new boolean[] {
+                    «FOR bit : typedef.bits SEPARATOR ','»
+                        «BindingMapping.getPropertyName(bit.name).getterMethodName»()
+                    «ENDFOR»
+                };
         }
     '''
 
@@ -429,7 +463,7 @@ class ClassTemplate extends BaseTemplate {
         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»
         );
     '''
@@ -514,6 +548,11 @@ class ClassTemplate extends BaseTemplate {
                         private static final String[] «Constants.MEMBER_REGEX_LIST» = { «
                         FOR v : cValue.values SEPARATOR ", "»"«v.escapeJava»"«ENDFOR» };
                     «ENDIF»
+                «ELSEIF TypeConstants.VALID_NAMES_NAME.equals(c.name)»
+                    «val cValue = c.value as BitsTypeDefinition»
+                    «val immutableSet = IMMUTABLE_SET.importedName»
+                    protected static final «immutableSet»<«STRING.importedName»> «TypeConstants.VALID_NAMES_NAME» = «immutableSet».of(«
+                    FOR bit : cValue.bits SEPARATOR ", "»"«bit.name»"«ENDFOR»);
                 «ELSE»
                     «emitConstant(c)»
                 «ENDIF»
@@ -544,7 +583,8 @@ class ClassTemplate extends BaseTemplate {
      * @return string with the <code>hashCode()</code> method definition in JAVA format
      */
     def protected generateHashCode() {
-        val size = genTO.hashCodeIdentifiers.size
+        val props = genTO.hashCodeIdentifiers
+        val size = props.size
         if (size == 0) {
             return ""
         }
@@ -554,17 +594,30 @@ class ClassTemplate extends BaseTemplate {
                 «IF size != 1»
                     final int prime = 31;
                     int result = 1;
-                    «FOR property : genTO.hashCodeIdentifier
-                        result = prime * result + «property.importedUtilClass».hashCode(«property.fieldName»);
+                    «FOR property : prop
+                        result = prime * result + «property.importedHashCodeUtilClass».hashCode(«property.fieldName»);
                     «ENDFOR»
                     return result;
                 «ELSE»
-                    return «CODEHELPERS.importedName».wrapperHashCode(«genTO.hashCodeIdentifiers.get(0).fieldName»);
+                    «val prop = props.get(0)»
+                    «IF prop.returnType.equals(Types.primitiveBooleanType())»
+                        return «BOOLEAN.importedName».hashCode(«prop.fieldName»);
+                    «ELSE»
+                        return «CODEHELPERS.importedName».wrapperHashCode(«prop.fieldName»);
+                    «ENDIF»
                 «ENDIF»
             }
         '''
     }
 
+    def private importedHashCodeUtilClass(GeneratedProperty prop) {
+        val propType = prop.returnType
+        if (propType.equals(Types.primitiveBooleanType)) {
+            return BOOLEAN.importedName
+        }
+        return propType.importedUtilClass
+    }
+
     /**
      * Template method which generates the method <code>equals()</code>.
      *
@@ -573,21 +626,17 @@ 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;
-                «FOR property : genTO.equalsIdentifiers»
-                    «val fieldName = property.fieldName»
-                    if (!«property.importedUtilClass».equals(«fieldName», other.«fieldName»)) {
-                        return false;
-                    }
-                «ENDFOR»
-                return true;
+            public final boolean equals(«OBJECT.importedName» obj) {
+                return this == obj || obj instanceof «type.name» other
+                    «FOR property : genTO.equalsIdentifiers»
+                        «val fieldName = property.fieldName»
+                        «val type = property.returnType»
+                        «IF type.equals(Types.primitiveBooleanType)»
+                            && «fieldName» == other.«fieldName»«
+                        »«ELSE»
+                            && «type.importedUtilClass».equals(«fieldName», other.«fieldName»)«
+                        »«ENDIF»«
+                    »«ENDFOR»;
             }
         «ENDIF»
     '''
@@ -598,13 +647,20 @@ class ClassTemplate extends BaseTemplate {
             public «STRING.importedName» toString() {
                 final var helper = «MOREOBJECTS.importedName».toStringHelper(«type.importedName».class);
                 «FOR property : properties»
-                    «CODEHELPERS.importedName».appendValue(helper, "«property.name»", «property.fieldName»);
+                    «CODEHELPERS.importedName».«property.valueAppender»(helper, "«property.name»", «property.fieldName»);
                 «ENDFOR»
                 return helper.toString();
             }
         «ENDIF»
     '''
 
+    def private valueAppender(GeneratedProperty prop) {
+        if (prop.returnType.equals(Types.primitiveBooleanType())) {
+            return "appendBit"
+        }
+        return "appendValue"
+    }
+
     def GeneratedProperty getPropByName(String name) {
         for (GeneratedProperty prop : allProperties) {
             if (prop.name.equals(name)) {