Implemented support for generating YangModuleInfo implementation.
[mdsal.git] / code-generator / binding-java-api-generator / src / main / java / org / opendaylight / yangtools / sal / java / api / generator / YangModuleInfoTemplate.xtend
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/YangModuleInfoTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/YangModuleInfoTemplate.xtend
new file mode 100644 (file)
index 0000000..3eaf216
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.sal.java.api.generator
+
+import org.opendaylight.yangtools.yang.model.api.Module
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo
+import java.io.InputStream
+import com.google.common.collect.ImmutableSet
+import java.util.Map
+import java.util.LinkedHashMap
+import org.opendaylight.yangtools.binding.generator.util.Types
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
+import org.opendaylight.yangtools.sal.binding.model.api.WildcardType
+import java.io.IOException
+import java.util.Set
+import java.util.HashSet
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import java.util.Date
+import java.util.TreeMap
+import java.text.DateFormat
+import java.text.SimpleDateFormat
+
+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!")
+        }
+        this.module = module
+        this.ctx = ctx
+    }
+
+    def String generate() {
+        val String classBody = body().toString
+        '''
+        package «BindingGeneratorUtil.moduleNamespaceToPackageName(module)» ;
+
+        «imports»
+
+        «classBody»
+        '''.toString
+    }
+
+    def body() '''
+        public class «CLASS» implements «YangModuleInfo.importedName» {
+
+            private static final «YangModuleInfo.importedName» INSTANCE = new «CLASS»();
+
+            private «CLASS»() {}
+
+            public static «YangModuleInfo.importedName» getInstance() {
+                return INSTANCE;
+            }
+
+            «module.classBody»
+
+        }
+    '''
+
+    private def CharSequence classBody(Module m) '''
+        @Override
+            public «String.importedName» getName() {
+            return "«m.name»";
+        }
+
+        @Override
+        public «String.importedName» getRevision() {
+            «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
+            return "«df.format(m.revision)»";
+        }
+
+        @Override
+        public «String.importedName» getNamespace() {
+            return "«m.namespace.toString»";
+        }
+
+        @Override
+        public «InputStream.importedName» getModuleSourceStream() throws «IOException.importedName» {
+            «val path = m.moduleSourcePath»
+            «IF path == null»
+                return null;
+            «ELSE»
+                return «CLASS».class.getResourceAsStream("«path»");
+            «ENDIF»
+        }
+
+        @Override
+        public «ImmutableSet.importedName»<«YangModuleInfo.importedName»> getImportedModules() {
+            «Set.importedName»<«YangModuleInfo.importedName»> set = new «HashSet.importedName»<>();
+            «FOR imp : m.imports»
+                «val name = imp.moduleName»
+                «val rev = imp.revision»
+                «IF rev == null»
+                    «val Set<Module> modules = ctx.modules»
+                    «val TreeMap<Date, Module> sorted = new TreeMap()»
+                    «FOR module : modules»
+                        «IF module.name.equals(name)»
+                            «sorted.put(module.revision, module)»
+                        «ENDIF»
+                    «ENDFOR»
+                    set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(sorted.lastEntry().value)».«CLASS».getInstance());
+                «ELSE»
+                    set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(ctx.findModuleByName(name, rev))».«CLASS».getInstance());
+                «ENDIF»
+            «ENDFOR»
+            return «ImmutableSet.importedName».copyOf(set);
+        }
+    '''
+
+    private def imports() ''' 
+        «IF !importMap.empty»
+            «FOR entry : importMap.entrySet»
+                «IF entry.value != BindingGeneratorUtil.moduleNamespaceToPackageName(module)»
+                    import «entry.value».«entry.key»;
+                «ENDIF»
+            «ENDFOR»
+        «ENDIF»
+        
+    '''
+
+    final protected def importedName(Class<?> cls) {
+        val Type intype = Types.typeForClass(cls)
+        putTypeIntoImports(intype);
+        getExplicitType(intype)
+    }
+
+    final def void putTypeIntoImports(Type type) {
+        val String typeName = type.getName();
+        val String typePackageName = type.getPackageName();
+        if (typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
+            return;
+        }
+        if (!importMap.containsKey(typeName)) {
+            importMap.put(typeName, typePackageName);
+        }
+        if (type instanceof ParameterizedType) {
+            val ParameterizedType paramType = (type as ParameterizedType)
+            val Type[] params = paramType.getActualTypeArguments()
+            if (params != null) {
+                for (Type param : params) {
+                    putTypeIntoImports(param);
+                }
+            }
+        }
+    }
+
+    final def String getExplicitType(Type type) {
+        val String typePackageName = type.getPackageName();
+        val String typeName = type.getName();
+        val String importedPackageName = importMap.get(typeName);
+        var StringBuilder builder;
+        if (typePackageName.equals(importedPackageName)) {
+            builder = new StringBuilder(type.getName());
+            addActualTypeParameters(builder, type);
+            if (builder.toString().equals("Void")) {
+                return "void";
+            }
+        } else {
+            builder = new StringBuilder();
+            if (typePackageName.startsWith("java.lang")) {
+                builder.append(type.getName());
+            } else {
+                if (!typePackageName.isEmpty()) {
+                    builder.append(typePackageName + Constants.DOT + type.getName());
+                } else {
+                    builder.append(type.getName());
+                }
+            }
+            if (type.equals(Types.voidType())) {
+                return "void";
+            }
+            addActualTypeParameters(builder, type);
+        }
+        return builder.toString();
+    }
+
+    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("<");
+            builder.append(getParameters(pTypes));
+            builder.append(">");
+        }
+        return builder;
+    }
+
+    final def String getParameters(Type[] pTypes) {
+        if (pTypes == null || pTypes.length == 0) {
+            return "?";
+        }
+        val StringBuilder builder = new StringBuilder();
+        
+        var int i = 0;
+        for (pType : pTypes) {
+            val Type t = pTypes.get(i)
+
+            var String separator = ",";
+            if (i == (pTypes.length - 1)) {
+                separator = "";
+            }
+
+            var String wildcardParam = "";
+            if (t.equals(Types.voidType())) {
+                builder.append("java.lang.Void" + separator);
+            } else {
+
+                if (t instanceof WildcardType) {
+                    wildcardParam = "? extends ";
+                }
+
+                builder.append(wildcardParam + getExplicitType(t) + separator);
+                i = i + 1
+            }
+        }
+        return builder.toString();
+    }
+
+}