Implemented support for generating YangModuleInfo implementation. 02/4602/6
authorMartin Vitez <mvitez@cisco.com>
Tue, 14 Jan 2014 13:50:47 +0000 (14:50 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Sun, 26 Jan 2014 20:58:40 +0000 (20:58 +0000)
Change-Id: I6f1bc55b15490100522349e1121c758a6dc18976
Signed-off-by: Martin Vitez <mvitez@cisco.com>
15 files changed:
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtilTest.java
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/GeneratorJavaFile.java
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/YangModuleInfoTemplate.xtend [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/maven/sal/api/gen/plugin/CodeGeneratorImpl.java
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/YangModuleInfo.java
yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java
yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessor.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/Module.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/SourceStreamAware.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/ModuleBuilder.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserListenerImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/CopyUtils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/NamedFileInputStream.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserListenerUtils.java

index aa1c0c21952321e1817ebca7a283c4138a2ee032..4f458c0c7e1765b56816130ccb796161921f0e39 100644 (file)
@@ -93,7 +93,7 @@ public class BindingGeneratorUtilTest {
                 subPackageNameForTypeDefinition);
 
         // test of exception part of the method moduleNamespaceToPackageName()
-        ModuleBuilder moduleBuilder = new ModuleBuilder("module-withut-revision");
+        ModuleBuilder moduleBuilder = new ModuleBuilder("module-withut-revision", null);
         Module moduleWithoutRevision = moduleBuilder.build();
         boolean passedSuccesfully = false;
         try {
index d6556157562fa89f1a5d7d939e17dac26f53fab3..4692694716a25b5cdf854da0cc338fcdeab880cf 100644 (file)
@@ -187,6 +187,39 @@ public final class GeneratorJavaFile {
         return null;
     }
 
+    private File generateStringToJavaFile(final File parentDir, final String generatedCode, String packageName,
+            final CodeGenerator generator) throws IOException {
+        if (parentDir == null) {
+            LOG.warn("Parent Directory not specified, files will be generated "
+                    + "accordingly to generated Type package path.");
+        }
+        if (generator == null) {
+            LOG.error("Cannot generate Type into Java File because " + "Code Generator instance is NULL!");
+            throw new IllegalArgumentException("Code Generator Cannot be NULL!");
+        }
+        final File packageDir = packageToDirectory(parentDir, packageName);
+
+        if (!packageDir.exists()) {
+            packageDir.mkdirs();
+        }
+
+        if (generatedCode.isEmpty()) {
+            throw new IllegalStateException("Generated code should not be empty!");
+        }
+        final File file = new File(packageDir, "YangModuleInfoImpl.java");
+        try (final OutputStream stream = buildContext.newFileOutputStream(file)) {
+            try (final Writer fw = new OutputStreamWriter(stream)) {
+                try (final BufferedWriter bw = new BufferedWriter(fw)) {
+                    bw.write(generatedCode);
+                }
+            } catch (IOException e) {
+                LOG.error("Failed to write generate output into {}", file.getPath(), e);
+                throw e;
+            }
+        }
+        return file;
+    }
+
     /**
      * Creates the package directory path as concatenation of
      * <code>parentDirectory</code> and parsed <code>packageName</code>. The
@@ -200,7 +233,7 @@ public final class GeneratorJavaFile {
      * @return <code>File</code> object which refers to the new directory for
      *         package <code>packageName</code>
      */
-    private File packageToDirectory(final File parentDirectory, final String packageName) {
+    public static File packageToDirectory(final File parentDirectory, final String packageName) {
         if (packageName == null) {
             throw new IllegalArgumentException("Package Name cannot be NULL!");
         }
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();
+    }
+
+}
index a273c6b8b729c66d048f795c8304d77dcd90b816..2267712a3d19c9cf05795aacf26c3e53cca97f9e 100644 (file)
@@ -7,8 +7,12 @@
  */
 package org.opendaylight.yangtools.maven.sal.api.gen.plugin;
 
+import java.io.BufferedWriter;
 import java.io.File;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
@@ -17,10 +21,12 @@ import java.util.Set;
 
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
 import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.sal.java.api.generator.YangModuleInfoTemplate;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang2sources.spi.BuildContextAware;
@@ -60,7 +66,13 @@ public final class CodeGeneratorImpl implements CodeGenerator, BuildContextAware
         if (persistentSourcesDir == null) {
             persistentSourcesDir = new File(projectBaseDir, "src" + FS + "main" + FS + "java");
         }
-        return generator.generateToFile(outputBaseDir, persistentSourcesDir);
+
+        List<File> result = generator.generateToFile(outputBaseDir, persistentSourcesDir);
+        for (Module module : yangModules) {
+            // TODO: add YangModuleInfo class
+            result.add(generateYangModuleInfo(outputBaseDir, module, context));
+        }
+        return result;
     }
 
     @Override
@@ -89,4 +101,29 @@ public final class CodeGeneratorImpl implements CodeGenerator, BuildContextAware
         this.buildContext = Preconditions.checkNotNull(buildContext);
     }
 
+    private File generateYangModuleInfo(File outputBaseDir, Module module, SchemaContext ctx) {
+        final YangModuleInfoTemplate template = new YangModuleInfoTemplate(module, ctx);
+        String generatedCode = template.generate();
+        if (generatedCode.isEmpty()) {
+            throw new IllegalStateException("Generated code should not be empty!");
+        }
+
+        final File packageDir = GeneratorJavaFile.packageToDirectory(outputBaseDir, BindingGeneratorUtil.moduleNamespaceToPackageName(module));
+
+        final File file = new File(packageDir, "$YangModuleInfoImpl.java");
+        try (final OutputStream stream = buildContext.newFileOutputStream(file)) {
+            try (final Writer fw = new OutputStreamWriter(stream)) {
+                try (final BufferedWriter bw = new BufferedWriter(fw)) {
+                    bw.write(generatedCode);
+                }
+            } catch (Exception e) {
+                // TODO handle exception
+            }
+        } catch (Exception e) {
+            // TODO handle exception
+        }
+        return file;
+
+    }
+
 }
index 90dc06b33c2dbabe84548cee37f41c1e902359c1..1e772f851e5bd41651a80cf7a4d7b685655452d1 100644 (file)
@@ -16,27 +16,28 @@ public interface YangModuleInfo {
 
     /**
      * Returns yang module name
-     * 
+     *
      * @return
      */
     String getName();
-    
+
     /**
-     * 
+     *
      * Returns revision of yang module.
-     * 
+     *
      * @return
      */
     String getRevision();
-    
+
     /**
      * Returns XML namespace associated to the YANG module
-     * 
+     *
      * @return XML namespace associated to the YANG module.
      */
     String getNamespace();
-    
+
     InputStream getModuleSourceStream() throws IOException;
-    
+
     ImmutableSet<YangModuleInfo> getImportedModules();
+
 }
index f930b2c0c342dea8c4cd4a4e53fe94c54cd654c5..b1dee91efec763483ea461f7fdd0f23cea2a631d 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.yangtools.yang2sources.plugin;
 
 import java.io.Closeable;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FilenameFilter;
 import java.io.IOException;
@@ -31,6 +30,7 @@ import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
@@ -100,20 +100,6 @@ final class Util {
         return result;
     }
 
-    static class NamedFileInputStream extends FileInputStream {
-        private final File file;
-
-        NamedFileInputStream(File file) throws FileNotFoundException {
-            super(file);
-            this.file = file;
-        }
-
-        @Override
-        public String toString() {
-            return getClass().getSimpleName() + "{" + file + "}";
-        }
-    }
-
     private static void toCache(final File rootDir, final Collection<File> yangFiles) {
         cache.put(rootDir, yangFiles);
     }
@@ -216,7 +202,7 @@ final class Util {
                             }
                         });
                         for (File yangFile : yangFiles) {
-                            yangsFromDependencies.add(new NamedFileInputStream(yangFile));
+                            yangsFromDependencies.add(new NamedFileInputStream(yangFile, YangToSourcesProcessor.META_INF_YANG_STRING + File.separator + yangFile.getName()));
                         }
                     }
 
index 321896ef3ea76a0138bb67b342da33c0338df77c..9efe633ffafc57c6f39b604e807fcd1a25c410ad 100644 (file)
@@ -27,9 +27,9 @@ import org.apache.maven.project.MavenProject;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
 import org.opendaylight.yangtools.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
 import org.opendaylight.yangtools.yang2sources.plugin.Util.ContextHolder;
-import org.opendaylight.yangtools.yang2sources.plugin.Util.NamedFileInputStream;
 import org.opendaylight.yangtools.yang2sources.plugin.Util.YangsInZipsResult;
 import org.opendaylight.yangtools.yang2sources.spi.BuildContextAware;
 import org.opendaylight.yangtools.yang2sources.spi.CodeGenerator;
@@ -109,7 +109,7 @@ class YangToSourcesProcessor {
                log.info(Util.message("No input files found", LOG_PREFIX));
                return null;
             }
-            
+
             /*
              * Check if any of the listed files changed. If no changes occurred,
              * simply return null, which indicates and of execution.
@@ -129,7 +129,7 @@ class YangToSourcesProcessor {
 
             final List<InputStream> yangsInProject = new ArrayList<>();
             for (final File f : yangFilesInProject) {
-                yangsInProject.add(new NamedFileInputStream(f));
+                yangsInProject.add(new NamedFileInputStream(f, META_INF_YANG_STRING + File.separator + f.getName()));
             }
 
             List<InputStream> all = new ArrayList<>(yangsInProject);
index 3d5cdee20592022588cd10d36a3036f356838ecb..c236409403b639223f10360294b71567bafef41c 100644 (file)
@@ -57,7 +57,7 @@ import java.util.Set;
     </code>
  */
 
-public interface Module extends DataNodeContainer, YangNode {
+public interface Module extends DataNodeContainer, YangNode, SourceStreamAware {
 
     /**
      * Returns the namespace of the module which is specified as argument of
diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/SourceStreamAware.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/SourceStreamAware.java
new file mode 100644 (file)
index 0000000..4ed6617
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * 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.yang.model.api;
+
+public interface SourceStreamAware {
+
+    String getModuleSourcePath();
+
+}
index 9ff2faba1db50a8603afcd39ff0ef5286265f5ea..b7a25760c72374dfa4962d19d5602051d2309bd8 100644 (file)
@@ -27,6 +27,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder {
 
     private final ModuleImpl instance;
     private final String name;
+    private final String sourcePath;
     private final SchemaPath schemaPath;
     private URI namespace;
     private String prefix;
@@ -79,27 +80,28 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder {
 
     private final List<ListSchemaNodeBuilder> allLists = new ArrayList<ListSchemaNodeBuilder>();
 
-    public ModuleBuilder(final String name) {
-        this(name, false);
+    public ModuleBuilder(final String name, final String sourcePath) {
+        this(name, false, sourcePath);
     }
 
-    public ModuleBuilder(final String name, final boolean submodule) {
+    public ModuleBuilder(final String name, final boolean submodule, final String sourcePath) {
         super(name, 0, null);
         this.name = name;
+        this.sourcePath = sourcePath;
         schemaPath = new SchemaPath(Collections.<QName> emptyList(), true);
-        instance = new ModuleImpl(name);
         this.submodule = submodule;
+        instance = new ModuleImpl(name, sourcePath);
         actualPath.push(this);
     }
 
     public ModuleBuilder(Module base) {
         super(base.getName(), 0, null);
         this.name = base.getName();
+        this.sourcePath = base.getModuleSourcePath();
         schemaPath = new SchemaPath(Collections.<QName> emptyList(), true);
-        instance = new ModuleImpl(base.getName());
         submodule = false;
+        instance = new ModuleImpl(base.getName(), base.getModuleSourcePath());
         actualPath.push(this);
-
         namespace = base.getNamespace();
         prefix = base.getPrefix();
         revision = base.getRevision();
@@ -208,6 +210,10 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder {
         return instance;
     }
 
+    public String getModuleSourcePath() {
+        return sourcePath;
+    }
+
     @Override
     public void setParent(Builder parent) {
         throw new YangParseException(name, 0, "Can not set parent to module");
@@ -882,6 +888,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder {
     private final class ModuleImpl implements Module {
         private URI namespace;
         private final String name;
+        private final String sourcePath;
         private Date revision;
         private String prefix;
         private String yangVersion;
@@ -903,8 +910,14 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder {
         private final Set<IdentitySchemaNode> identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
         private final List<UnknownSchemaNode> unknownNodes = new ArrayList<>();
 
-        private ModuleImpl(String name) {
+        private ModuleImpl(String name, String sourcePath) {
             this.name = name;
+            this.sourcePath = sourcePath;
+        }
+
+        @Override
+        public String getModuleSourcePath() {
+            return sourcePath;
         }
 
         @Override
index 648bc121e1ea19ab4786f66ef3cfe49d7b7154f2..e0510aeabd2450d593c50b80b621a6fd658ca714 100644 (file)
@@ -45,6 +45,7 @@ import org.opendaylight.yangtools.yang.parser.util.Comparators;
 import org.opendaylight.yangtools.yang.parser.util.GroupingSort;
 import org.opendaylight.yangtools.yang.parser.util.GroupingUtils;
 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
+import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
 import org.opendaylight.yangtools.yang.parser.util.ParserUtils;
 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
 import org.opendaylight.yangtools.yang.validator.YangModelBasicValidator;
@@ -262,7 +263,13 @@ public final class YangParserImpl implements YangModelParser {
 
         YangParserListenerImpl yangModelParser;
         for (Map.Entry<InputStream, ParseTree> entry : trees.entrySet()) {
-            yangModelParser = new YangParserListenerImpl();
+            InputStream is = entry.getKey();
+            String path = null;
+            if (is instanceof NamedFileInputStream) {
+                NamedFileInputStream nis = (NamedFileInputStream)is;
+                path = nis.getFileDestination();
+            }
+            yangModelParser = new YangParserListenerImpl(path);
             walker.walk(yangModelParser, entry.getValue());
             ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
 
index a90982e0e659ff49aea3dda6780cf8ca8e230c26..f186860c63ee51c5aa7c6277793dc966f5f033e4 100644 (file)
@@ -62,6 +62,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
     private static final Logger LOGGER = LoggerFactory.getLogger(YangParserListenerImpl.class);
     private static final String AUGMENT_STR = "augment";
 
+    private final String sourcePath;
     private ModuleBuilder moduleBuilder;
     private String moduleName;
     private URI namespace;
@@ -79,6 +80,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         return actualPath.peek().pop();
     }
 
+    public YangParserListenerImpl(String sourcePath) {
+        this.sourcePath = sourcePath;
+    }
+
     @Override
     public void enterModule_stmt(YangParser.Module_stmtContext ctx) {
         moduleName = stringFromNode(ctx);
@@ -86,7 +91,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         enterLog("module", moduleName, 0);
         actualPath.push(new Stack<QName>());
 
-        moduleBuilder = new ModuleBuilder(moduleName);
+        moduleBuilder = new ModuleBuilder(moduleName, sourcePath);
 
         String description = null;
         String reference = null;
@@ -118,7 +123,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         enterLog("submodule", moduleName, 0);
         actualPath.push(new Stack<QName>());
 
-        moduleBuilder = new ModuleBuilder(moduleName, true);
+        moduleBuilder = new ModuleBuilder(moduleName, true, sourcePath);
 
         String description = null;
         String reference = null;
index 91a04e875233c03de93fe7c5d90c4076c2b80f44..462aaa7f0e7f65d20c14370cb96822e9b9b5ecf1 100644 (file)
@@ -428,6 +428,8 @@ public final class CopyUtils {
         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
             c.addUnknownNodeBuilder((copy(un, c, updateQName)));
         }
+        c.setExtensionBuilder(old.getExtensionBuilder());
+        c.setExtensionDefinition(old.getExtensionDefinition());
 
         return c;
     }
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/NamedFileInputStream.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/NamedFileInputStream.java
new file mode 100644 (file)
index 0000000..c2d1d24
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.yang.parser.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+public class NamedFileInputStream extends FileInputStream {
+    private final String fileDestination;
+
+    public NamedFileInputStream(File file, String fileDestination) throws FileNotFoundException {
+        super(file);
+        this.fileDestination = fileDestination;
+    }
+
+    public String getFileDestination() {
+        return fileDestination;
+    }
+
+}
index 206e8f7ee5cd35bf6deac3e0f432b5bf0559e202..ec26b4483a1f7e42b8f7b93989fe34fc40109a6e 100644 (file)
@@ -298,8 +298,8 @@ public final class ParserListenerUtils {
     /**
      * Create java.util.List of key node names.
      *
-     * @param keyDefinition
-     *            key definition as string
+     * @param ctx
+     *            Key_stmtContext context
      * @return YANG list key as java.util.List of key node names
      */
     public static List<String> createListKey(final Key_stmtContext ctx) {