Fix YANG snippet escaping
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / InterfaceTemplate.xtend
index 0d10d69345698d27618ce6d2886f11262c6ee5cc..deb9b6b0a236f1918fb7d19f7d680729e2d15ca5 100644 (file)
@@ -7,20 +7,25 @@
  */
 package org.opendaylight.mdsal.binding.java.api.generator
 
+import static extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME
+import static extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.getGetterMethodForNonnull
+import static extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.isGetterMethodName
+import static extension org.opendaylight.mdsal.binding.spec.naming.BindingMapping.isNonnullMethodName
+
 import java.util.List
 import org.opendaylight.mdsal.binding.model.api.AnnotationType
 import org.opendaylight.mdsal.binding.model.api.Constant
 import org.opendaylight.mdsal.binding.model.api.Enumeration
-import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
 import org.opendaylight.mdsal.binding.model.api.GeneratedType
 import org.opendaylight.mdsal.binding.model.api.MethodSignature
+import org.opendaylight.mdsal.binding.model.api.Type
 import org.opendaylight.mdsal.binding.model.util.TypeConstants
+import org.opendaylight.yangtools.yang.binding.CodeHelpers
 
 /**
  * Template for generating JAVA interfaces.
  */
 class InterfaceTemplate extends BaseTemplate {
-
     /**
      * List of constant instances which are generated as JAVA public static final attributes.
      */
@@ -45,14 +50,10 @@ class InterfaceTemplate extends BaseTemplate {
      * Creates the instance of this class which is used for generating the interface file source
      * code from <code>genType</code>.
      *
-     * @throws IllegalArgumentException if <code>genType</code> equals <code>null</code>
+     * @throws NullPointerException if <code>genType</code> is <code>null</code>
      */
     new(GeneratedType genType) {
         super(genType)
-        if (genType === null) {
-            throw new IllegalArgumentException("Generated type reference cannot be NULL!")
-        }
-
         consts = genType.constantDefinitions
         methods = genType.methodDefinitions
         enums = genType.enumerations
@@ -83,18 +84,10 @@ class InterfaceTemplate extends BaseTemplate {
 
     '''
 
-
     def private generateAnnotations(List<AnnotationType> annotations) '''
         «IF annotations !== null && !annotations.empty»
             «FOR annotation : annotations»
-                @«annotation.importedName»
-                «IF annotation.parameters !== null && !annotation.parameters.empty»
-                (
-                «FOR param : annotation.parameters SEPARATOR ","»
-                    «param.name»=«param.value»
-                «ENDFOR»
-                )
-                «ENDIF»
+                «annotation.generateAnnotation»
             «ENDFOR»
         «ENDIF»
     '''
@@ -122,18 +115,7 @@ class InterfaceTemplate extends BaseTemplate {
     def private generateInnerClasses() '''
         «IF !enclosedGeneratedTypes.empty»
             «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
-                «IF (innerClass instanceof GeneratedTransferObject)»
-                    «IF innerClass.unionType»
-                        «val unionTemplate = new UnionTemplate(innerClass)»
-                        «unionTemplate.generateAsInnerClass»
-                        «addImports(unionTemplate)»
-                    «ELSE»
-                        «val classTemplate = new ClassTemplate(innerClass)»
-                        «classTemplate.generateAsInnerClass»
-                        «addImports(classTemplate)»
-                    «ENDIF»
-
-                «ENDIF»
+                «generateInnerClass(innerClass)»
             «ENDFOR»
         «ENDIF»
     '''
@@ -146,9 +128,8 @@ class InterfaceTemplate extends BaseTemplate {
     def private generateEnums() '''
         «IF !enums.empty»
             «FOR e : enums SEPARATOR "\n"»
-                «val enumTemplate = new EnumTemplate(e)»
+                «val enumTemplate = new EnumTemplate(javaType.getEnclosedType(e.identifier), e)»
                 «enumTemplate.generateAsInnerClass»
-                «addImports(enumTemplate)»
             «ENDFOR»
         «ENDIF»
     '''
@@ -176,17 +157,66 @@ class InterfaceTemplate extends BaseTemplate {
     def private generateMethods() '''
         «IF !methods.empty»
             «FOR m : methods SEPARATOR "\n"»
-                «IF !m.isAccessor»
-                    «m.comment.asJavadoc»
+                «IF m.isDefault»
+                    «generateDefaultMethod(m)»
+                «ELSEIF m.parameters.empty && m.name.isGetterMethodName»
+                    «generateAccessorMethod(m)»
                 «ELSE»
-                    «formatDataForJavaDoc(m, "@return " + asCode(m.returnType.fullyQualifiedName) + " "
-                    + asCode(propertyNameFromGetter(m)) + ", or " + asCode("null") + " if not present")»
+                    «generateMethod(m)»
                 «ENDIF»
-                «m.annotations.generateAnnotations»
-                «m.returnType.importedName» «m.name»(«m.parameters.generateParameters»);
             «ENDFOR»
         «ENDIF»
     '''
 
-}
+    def private generateDefaultMethod(MethodSignature method) {
+        if (method.name.isNonnullMethodName) {
+            generateNonnullMethod(method)
+        } else {
+            switch method.name {
+                case DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME : generateDefaultImplementedInterface
+            }
+        }
+    }
+
+    def private generateMethod(MethodSignature method) '''
+        «method.comment.asJavadoc»
+        «method.annotations.generateAnnotations»
+        «method.returnType.importedName» «method.name»(«method.parameters.generateParameters»);
+    '''
 
+    def private generateAccessorMethod(MethodSignature method) '''
+        «val ret = method.returnType»
+        «formatDataForJavaDoc(method, "@return " + asCode(ret.fullyQualifiedName) + " " + asCode(propertyNameFromGetter(method)) + ", or " + asCode("null") + " if not present")»
+        «method.annotations.generateAnnotations»
+        «nullableType(ret)» «method.name»();
+    '''
+
+    def private generateDefaultImplementedInterface() '''
+        @«Override.importedName»
+        default «Class.importedName»<«type.fullyQualifiedName»> «DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME»() {
+            return «type.fullyQualifiedName».class;
+        }
+    '''
+
+    def private generateNonnullMethod(MethodSignature method) '''
+        «val ret = method.returnType»
+        «val name = method.name»
+        «formatDataForJavaDoc(method, "@return " + asCode(ret.fullyQualifiedName) + " " + asCode(propertyNameFromGetter(method)) + ", or an empty list if it is not present")»
+        «method.annotations.generateAnnotations»
+        default «ret.importedNonNull» «name»() {
+            return «CodeHelpers.importedName».nonnull(«getGetterMethodForNonnull(name)»());
+        }
+    '''
+
+    def private String nullableType(Type type) {
+        if (type.isObject) {
+            return type.importedNullable
+        }
+        return type.importedName
+    }
+
+    def private static boolean isObject(Type type) {
+        // The return type has a package, so it's not a primitive type
+        return !type.getPackageName().isEmpty()
+    }
+}