Merge "Bug 2818: Updated implementation of parser."
[yangtools.git] / code-generator / binding-java-api-generator / src / main / java / org / opendaylight / yangtools / sal / java / api / generator / YangModuleInfoTemplate.xtend
index 7c19f20a9db35d6b6263b8ce49c7050031fb2b4a..64693702ff05b90f4fcd6f92e0e822385ed09d96 100644 (file)
@@ -20,7 +20,6 @@ import java.util.Map
 import java.util.Set
 import java.util.TreeMap
 
-import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
 import org.opendaylight.yangtools.binding.generator.util.Types
 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
 import org.opendaylight.yangtools.sal.binding.model.api.Type
@@ -30,52 +29,78 @@ import org.opendaylight.yangtools.yang.model.api.Module
 import org.opendaylight.yangtools.yang.model.api.SchemaContext
 
 import com.google.common.collect.ImmutableSet
+import static org.opendaylight.yangtools.yang.binding.BindingMapping.*
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider
+import com.google.common.base.Preconditions
 
 class YangModuleInfoTemplate {
-    val CLASS = "$YangModuleInfoImpl"
 
     val Module module
     val SchemaContext ctx
     val Map<String, String> importMap = new LinkedHashMap()
 
-    new (Module module, SchemaContext ctx) {
-        if (module == null) {
-            throw new IllegalArgumentException("Module reference cannot be NULL!")
-        }
+    @Property
+    val String packageName;
+
+    @Property
+    val String modelBindingProviderName;
+
+    new(Module module, SchemaContext ctx) {
+        Preconditions.checkArgument(module != null, "Module must not be null.");
         this.module = module
         this.ctx = ctx
+        _packageName = getRootPackageName(module.getQNameModule());
+        _modelBindingProviderName = '''«packageName».«MODEL_BINDING_PROVIDER_CLASS_NAME»''';
     }
 
     def String generate() {
-        val String classBody = body().toString
-        '''
-        package «BindingGeneratorUtil.moduleNamespaceToPackageName(module)» ;
+        val body = '''
+            public final class «MODULE_INFO_CLASS_NAME» implements «YangModuleInfo.importedName» {
+
+                private static final «YangModuleInfo.importedName» INSTANCE = new «MODULE_INFO_CLASS_NAME»();
+
+                private final «String.importedName» name = "«module.name»";
+                private final «String.importedName» namespace = "«module.namespace.toString»";
+                «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
+                private final «String.importedName» revision = "«df.format(module.revision)»";
+                private final «String.importedName» resourcePath = "«sourcePath»";
 
-        «imports»
+                private final «Set.importedName»<YangModuleInfo> importedModules;
 
-        «classBody»
+                public static «YangModuleInfo.importedName» getInstance() {
+                    return INSTANCE;
+                }
+
+                «classBody(module, MODULE_INFO_CLASS_NAME)»
+            }
+        '''
+        return '''
+            package «packageName» ;
+            «imports»
+            «body»
         '''.toString
     }
 
-    def body() '''
-        public final class «CLASS» implements «YangModuleInfo.importedName» {
-
-            private static final «YangModuleInfo.importedName» INSTANCE = new «CLASS»();
+    def String generateModelProvider() {
+        '''
+            package «packageName»;
 
-            private final Set<YangModuleInfo> importedModules;
+            public final class «MODEL_BINDING_PROVIDER_CLASS_NAME» implements «YangModelBindingProvider.name» {
 
-            public static «YangModuleInfo.importedName» getInstance() {
-                return INSTANCE;
+                public «YangModuleInfo.name» getModuleInfo() {
+                    return «MODULE_INFO_CLASS_NAME».getInstance();
+                }
             }
+        '''
 
-            «module.classBody»
-        }
-    '''
+    }
 
-    private def CharSequence classBody(Module m) '''
-        private «CLASS»() {
-            «IF m.imports.size != 0»
+    private def CharSequence classBody(Module m, String className) '''
+        private «className»() {
+            «IF !m.imports.empty || !m.submodules.empty»
                 «Set.importedName»<«YangModuleInfo.importedName»> set = new «HashSet.importedName»<>();
+            «ENDIF»
+            «IF !m.imports.empty»
                 «FOR imp : m.imports»
                     «val name = imp.moduleName»
                     «val rev = imp.revision»
@@ -87,48 +112,54 @@ class YangModuleInfoTemplate {
                                 «sorted.put(module.revision, module)»
                             «ENDIF»
                         «ENDFOR»
-                        set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(sorted.lastEntry().value)».«CLASS».getInstance());
+                        set.add(«getRootPackageName(sorted.lastEntry().value.QNameModule)».«MODULE_INFO_CLASS_NAME».getInstance());
                     «ELSE»
-                        set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(ctx.findModuleByName(name, rev))».«CLASS».getInstance());
+                        set.add(«getRootPackageName((ctx.findModuleByName(name, rev).QNameModule))».«MODULE_INFO_CLASS_NAME».getInstance());
                     «ENDIF»
                 «ENDFOR»
-                importedModules = «ImmutableSet.importedName».copyOf(set);
-            «ELSE»
+            «ENDIF»
+            «IF !m.submodules.empty»
+                «FOR submodule : m.submodules»
+                    set.add(«getClassName(submodule.name)»Info.getInstance());
+                «ENDFOR»
+            «ENDIF»
+            «IF m.imports.empty && m.submodules.empty»
                 importedModules = «Collections.importedName».emptySet();
+            «ELSE»
+                importedModules = «ImmutableSet.importedName».copyOf(set);
             «ENDIF»
 
-            «InputStream.importedName» stream = «CLASS».class.getResourceAsStream("«sourcePath»");
+            «InputStream.importedName» stream = «MODULE_INFO_CLASS_NAME».class.getResourceAsStream(resourcePath);
             if (stream == null) {
-                throw new IllegalStateException("Resource «sourcePath» is missing");
+                throw new IllegalStateException("Resource '" + resourcePath + "' is missing");
             }
             try {
                 stream.close();
             } catch («IOException.importedName» e) {
-                // Resource leak, but there is nothing we can do
+            // Resource leak, but there is nothing we can do
             }
         }
 
         @Override
         public «String.importedName» getName() {
-            return "«m.name»";
+            return name;
         }
 
         @Override
         public «String.importedName» getRevision() {
-            «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
-            return "«df.format(m.revision)»";
+            return revision;
         }
 
         @Override
         public «String.importedName» getNamespace() {
-            return "«m.namespace.toString»";
+            return namespace;
         }
 
         @Override
         public «InputStream.importedName» getModuleSourceStream() throws IOException {
-            «InputStream.importedName» stream = «CLASS».class.getResourceAsStream("«sourcePath»");
+            «InputStream.importedName» stream = «MODULE_INFO_CLASS_NAME».class.getResourceAsStream(resourcePath);
             if (stream == null) {
-                throw new «IOException.importedName»("Resource «sourcePath» is missing");
+                throw new «IOException.importedName»("Resource " + resourcePath + " is missing");
             }
             return stream;
         }
@@ -137,21 +168,36 @@ class YangModuleInfoTemplate {
         public «Set.importedName»<«YangModuleInfo.importedName»> getImportedModules() {
             return importedModules;
         }
+
+        @Override
+        public «String.importedName» toString() {
+            «StringBuilder.importedName» sb = new «StringBuilder.importedName»(this.getClass().getCanonicalName());
+            sb.append("[");
+            sb.append("name = " + name);
+            sb.append(", namespace = " + namespace);
+            sb.append(", revision = " + revision);
+            sb.append(", resourcePath = " + resourcePath);
+            sb.append(", imports = " + importedModules);
+            sb.append("]");
+            return sb.toString();
+        }
+
+        «generateSubInfo(m)»
+
     '''
-    
+
     def getSourcePath() {
         return "/" + module.moduleSourcePath.replace(java.io.File.separatorChar, '/')
     }
 
-    private def imports() ''' 
+    private def imports() '''
         «IF !importMap.empty»
             «FOR entry : importMap.entrySet»
-                «IF entry.value != BindingGeneratorUtil.moduleNamespaceToPackageName(module)»
+                «IF entry.value != getRootPackageName(module.QNameModule)»
                     import «entry.value».«entry.key»;
                 «ENDIF»
             «ENDFOR»
         «ENDIF»
-        
     '''
 
     final protected def importedName(Class<?> cls) {
@@ -170,8 +216,7 @@ class YangModuleInfoTemplate {
             importMap.put(typeName, typePackageName);
         }
         if (type instanceof ParameterizedType) {
-            val ParameterizedType paramType = (type as ParameterizedType)
-            val Type[] params = paramType.getActualTypeArguments()
+            val Type[] params = type.getActualTypeArguments()
             if (params != null) {
                 for (Type param : params) {
                     putTypeIntoImports(param);
@@ -212,11 +257,10 @@ class YangModuleInfoTemplate {
 
     final def StringBuilder addActualTypeParameters(StringBuilder builder, Type type) {
         if (type instanceof ParameterizedType) {
-            val ParameterizedType pType = (type as ParameterizedType)
-            val Type[] pTypes = pType.getActualTypeArguments();
-            builder.append("<");
+            val Type[] pTypes = type.getActualTypeArguments();
+            builder.append('<');
             builder.append(getParameters(pTypes));
-            builder.append(">");
+            builder.append('>');
         }
         return builder;
     }
@@ -226,7 +270,7 @@ class YangModuleInfoTemplate {
             return "?";
         }
         val StringBuilder builder = new StringBuilder();
-        
+
         var int i = 0;
         for (pType : pTypes) {
             val Type t = pTypes.get(i)
@@ -252,4 +296,27 @@ class YangModuleInfoTemplate {
         return builder.toString();
     }
 
+    private def generateSubInfo(Module module) '''
+        «FOR submodule : module.submodules»
+            private static final class «getClassName(submodule.name)»Info implements «YangModuleInfo.importedName» {
+
+                private static final «YangModuleInfo.importedName» INSTANCE = new «getClassName(submodule.name)»Info();
+
+                private final «String.importedName» name = "«submodule.name»";
+                private final «String.importedName» namespace = "«submodule.namespace.toString»";
+                «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
+                private final «String.importedName» revision = "«df.format(submodule.revision)»";
+                private final «String.importedName» resourcePath = "/«submodule.moduleSourcePath.replace(java.io.File.separatorChar, '/')»";
+
+                private final «Set.importedName»<YangModuleInfo> importedModules;
+
+                public static «YangModuleInfo.importedName» getInstance() {
+                    return INSTANCE;
+                }
+
+                «classBody(submodule, getClassName(submodule.name + "Info"))»
+            }
+        «ENDFOR»
+    '''
+
 }