Yang-maven-plugin refactored + fixed bugs. 06/406/6
authorMaros Marsalek <mmarsale@cisco.com>
Thu, 30 May 2013 09:49:22 +0000 (11:49 +0200)
committerMartin Vitez <mvitez@cisco.com>
Wed, 5 Jun 2013 12:59:29 +0000 (14:59 +0200)
Removed resourceProviders argument(unused).
Other arguments marked as optional.
Added argument to set whether use yang files from dependencies or not.
Added packaging of yang files from project to META-INF.
Added additionalConfiguration argument for code generators.

Yang-maven-plugin SPI, ResourceProvider interface removed since
it was unused. Code generator interface improved.

YangParserImpl API changed to provide a map<File, Module>. Users will
know which module belongs to which file and can utilize this information
when parsing yang files from multiple sources. Yang-maven-plugin needs
this information since it parses yang files from project as well as its
dependencies.

Change-Id: I15c53df59c4104793e023ad3686b031ce0ba8cd3
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
33 files changed:
opendaylight/sal/yang-prototype/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/controller/maven/sal/api/gen/plugin/CodeGeneratorImpl.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/java/org/opendaylight/controller/yang2sources/plugin/it/YangToSourcesPluginTest.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/AdditionalConfig/pom.xml [moved from opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoGenerators_resources/pom.xml with 57% similarity]
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct_resources/pom.xml [deleted file]
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile1.yang
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile3.yang
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/yang/private.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Generator/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/MissingYangInDep/pom.xml [moved from opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/UnknownGenerator_resources/pom.xml with 78% similarity]
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/MissingYangInDep/yang/private.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoGenerators/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoOutputDir/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoYangFiles/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/UnknownGenerator/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/YangRootNotExist/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/ConfigArg.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/Util.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesMojo.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesProcessor.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/GenerateSourcesTest.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/UtilTest.java
opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/resources/mock.yang
opendaylight/sal/yang-prototype/code-generator/maven-yang/pom.xml
opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/CodeGenerator.java
opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/ResourceGenerator.java [deleted file]
opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/CodeGeneratorTestImpl.java
opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/ResourceProviderTestImpl.java [deleted file]
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-api/src/main/java/org/opendaylight/controller/yang/model/parser/api/YangModelParser.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java
opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TestUtils.java

index d1b80b3..1876c68 100644 (file)
@@ -12,8 +12,10 @@ import java.io.IOException;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
+import org.apache.maven.plugin.logging.Log;
 import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
 import org.opendaylight.controller.sal.binding.generator.impl.BindingGeneratorImpl;
 import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
@@ -28,7 +30,8 @@ public class CodeGeneratorImpl implements CodeGenerator {
 
     @Override
     public Collection<File> generateSources(SchemaContext context,
-            File outputBaseDir, Set<Module> yangModules) throws IOException {
+            File outputBaseDir, Set<Module> yangModules, File projectBaseDir)
+            throws IOException {
 
         final BindingGenerator bindingGenerator = new BindingGeneratorImpl();
         final List<Type> types = bindingGenerator.generateTypes(context);
@@ -41,11 +44,25 @@ public class CodeGeneratorImpl implements CodeGenerator {
                 typesToGenerate.add((GeneratedType) type);
             }
 
-
         }
 
-        final GeneratorJavaFile generator = new GeneratorJavaFile(typesToGenerate, tosToGenerate);
-        return generator.generateToFile(outputBaseDir);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(
+                typesToGenerate, tosToGenerate);
+
+        return generator.generateToFile(outputBaseDir.getPath().startsWith(
+                projectBaseDir.getPath()) ? outputBaseDir : new File(
+                projectBaseDir, outputBaseDir.getPath()));
+    }
+
+    @Override
+    public void setLog(Log log) {
+        // use maven logging if necessary
+
+    }
+
+    @Override
+    public void setAdditionalConfig(Map<String, String> additionalConfiguration) {
+        // no additional config utilized
     }
 
 }
index 267e35a..e77ec6c 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.controller.yang2sources.plugin.it;
 
 import static org.junit.Assert.*;
-import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.junit.matchers.JUnitMatchers.*;
 
 import java.io.File;
 
@@ -18,16 +18,18 @@ import org.junit.Test;
 
 public class YangToSourcesPluginTest {
 
+    // TODO Test yang files in transitive dependencies
+
     @Test
     public void testYangRootNotExist() {
         try {
             setUp("YangRootNotExist/", false);
         } catch (VerificationException e) {
             assertVerificationException(e,
-                    "[ERROR] yang-to-sources: Unable to parse yang files from unknown");
+                    "[ERROR] yang-to-sources: Unable to parse yang files from ");
             assertVerificationException(
                     e,
-                    "Caused by: org.apache.maven.plugin.MojoExecutionException: yang-to-sources: Unable to parse yang files from unknown");
+                    "Caused by: org.apache.maven.plugin.MojoExecutionException: yang-to-sources: Unable to parse yang files from ");
             return;
         }
 
@@ -38,16 +40,34 @@ public class YangToSourcesPluginTest {
     public void testCorrect() throws VerificationException {
         Verifier v = setUp("Correct/", false);
         verifyCorrectLog(v);
+    }
+
+    @Test
+    public void testAdditionalConfiguration() throws VerificationException {
+        Verifier v = setUp("AdditionalConfig/", false);
+        v.verifyTextInLog("[INFO] yang-to-sources: Additional configuration picked up for : org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl: {nm1=abcd=a.b.c.d, nm2=abcd2=a.b.c.d.2}");
+        v.verifyTextInLog("[INFO] yang-to-sources: Additional configuration picked up for : org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl: {c1=config}");
+    }
+
+    @Test
+    public void testMissingYangInDep() throws VerificationException {
+        try {
+            setUp("MissingYangInDep/", false);
+        } catch (VerificationException e) {
+            assertVerificationException(
+                    e,
+                    "org.opendaylight.controller.yang.parser.util.YangValidationException: Not existing module imported:unknownDep:2013-02-27 by:private:2013-02-27");
+            return;
+        }
 
+        fail("Verification exception should have been thrown");
     }
 
     static void verifyCorrectLog(Verifier v) throws VerificationException {
         v.verifyErrorFreeLog();
-        v.verifyTextInLog("[INFO] yang-to-sources: yang files parsed from");
+        v.verifyTextInLog("[INFO] yang-to-sources: YANG files parsed from");
         v.verifyTextInLog("[INFO] yang-to-sources: Code generator instantiated from org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl");
         v.verifyTextInLog("[INFO] yang-to-sources: Sources generated by org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl: null");
-        v.verifyTextInLog("[INFO] yang-to-sources: Resource provider instantiated from org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl");
-        v.verifyTextInLog("[INFO] yang-to-sources: Resource provider org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl call successful");
     }
 
     @Test
@@ -70,7 +90,7 @@ public class YangToSourcesPluginTest {
     @Test
     public void testNoYangFiles() throws VerificationException {
         Verifier v = setUp("NoYangFiles/", false);
-        v.verifyTextInLog("[WARNING] yang-to-sources: No yang file found in ");
+        v.verifyTextInLog("[INFO] yang-to-sources: YANG files parsed from []");
         v.verifyTextInLog("[INFO] yang-to-sources: Code generator instantiated from org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl");
         v.verifyTextInLog("[INFO] yang-to-sources: Sources generated by org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl: null");
     }
@@ -90,43 +110,29 @@ public class YangToSourcesPluginTest {
         return verifier;
     }
 
-    @Test
-    public void testNoGeneratorsResources() throws VerificationException {
-        Verifier v = YangToSourcesPluginTest.setUp("NoGenerators_resources/",
-                false);
-        v.verifyErrorFreeLog();
-        v.verifyTextInLog("[WARNING] yang-to-sources: No resource provider classes provided");
-    }
-
-    @Test
-    public void testUnknownGeneratorResources() throws VerificationException {
-        Verifier v = YangToSourcesPluginTest.setUp(
-                "UnknownGenerator_resources/", true);
-        v.verifyTextInLog("[ERROR] yang-to-sources: Unable to provide resources with unknown resource provider");
-        v.verifyTextInLog("java.lang.ClassNotFoundException: unknown");
-        v.verifyTextInLog("[INFO] yang-to-sources: Resource provider instantiated from org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl");
-        v.verifyTextInLog("[INFO] yang-to-sources: Resource provider org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl call successful");
-        v.verifyTextInLog("[ERROR] yang-to-sources: One or more code resource provider failed, including failed list(resourceProviderClass=exception) {unknown=java.lang.ClassNotFoundException}");
-    }
-
     @Test
     public void testNoOutputDir() throws VerificationException {
-        Verifier v = YangToSourcesPluginTest.setUp("NoOutputDir/",
-                false);
+        Verifier v = YangToSourcesPluginTest.setUp("NoOutputDir/", false);
         verifyCorrectLog(v);
     }
 
     @Test
     public void testFindResourceOnCp() throws VerificationException {
-        Verifier v1 = new Verifier(new File("src/test/resources/GenerateTest1/").getAbsolutePath());
+        Verifier v1 = new Verifier(
+                new File("src/test/resources/GenerateTest1/").getAbsolutePath());
+        v1.executeGoal("clean");
         v1.executeGoal("package");
-        v1.assertFilePresent("target/external-resources/testfile1.yang");
-        v1.assertFilePresent("target/external-resources/testfile2.yang");
-        v1.assertFilePresent("target/external-resources/testfile3.yang");
+        v1.assertFilePresent("target/classes/META-INF/yang/testfile1.yang");
+        v1.assertFilePresent("target/classes/META-INF/yang/testfile2.yang");
+        v1.assertFilePresent("target/classes/META-INF/yang/testfile3.yang");
 
-        Verifier v2 = YangToSourcesPluginTest.setUp("GenerateTest2/",
-                false);
+        Verifier v2 = YangToSourcesPluginTest.setUp("GenerateTest2/", false);
+        v2.executeGoal("clean");
         v2.executeGoal("package");
+        v2.assertFilePresent("target/classes/META-INF/yang/private.yang");
+        v2.assertFileNotPresent("target/classes/META-INF/yang/testfile1.yang");
+        v2.assertFileNotPresent("target/classes/META-INF/yang/testfile2.yang");
+        v2.assertFileNotPresent("target/classes/META-INF/yang/testfile3.yang");
     }
 
 }
@@ -2,12 +2,18 @@
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.5.1-SNAPSHOT</version>
-
+    <groupId>org.opendaylight.controller</groupId>
+    <version>0.5.1-SNAPSHOT</version>
     <artifactId>test</artifactId>
 
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-maven-plugin-spi</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
     <build>
         <plugins>
             <plugin>
                         </goals>
                         <configuration>
                             <yangFilesRootDir>../files</yangFilesRootDir>
-                                                       <codeGenerators>
+                            <inspectDependencies>false</inspectDependencies>
+                            <codeGenerators>
                                 <generator>
                                     <codeGeneratorClass>
                                         org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
                                     </codeGeneratorClass>
-                                    <outputBaseDir>
-                                        outDir/
-                                    </outputBaseDir>
+                                    <additionalConfiguration>
+                                        <nm1>abcd=a.b.c.d</nm1>
+                                        <nm2>abcd2=a.b.c.d.2</nm2>
+                                    </additionalConfiguration>
+                                </generator>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+                                    </codeGeneratorClass>
+                                    <additionalConfiguration>
+                                        <c1>config</c1>
+                                    </additionalConfiguration>
                                 </generator>
                             </codeGenerators>
-                            <resourceProviders>
-                            </resourceProviders>
                         </configuration>
                     </execution>
                 </executions>
-                               <dependencies>
+
+                <dependencies>
                     <dependency>
                         <groupId>org.opendaylight.controller</groupId>
                         <artifactId>yang-maven-plugin-spi</artifactId>
@@ -47,4 +62,4 @@
             </plugin>
         </plugins>
     </build>
-</project>
\ No newline at end of file
+</project>
index 353416d..ce9389f 100644 (file)
@@ -1,62 +1,53 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-       <modelVersion>4.0.0</modelVersion>
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
 
-        <groupId>org.opendaylight.controller</groupId>
-               <version>0.5.1-SNAPSHOT</version>
-       <artifactId>test</artifactId>
+    <groupId>org.opendaylight.controller</groupId>
+    <version>0.5.1-SNAPSHOT</version>
+    <artifactId>test</artifactId>
 
-       <dependencies>
-               <dependency>
-                       <groupId>org.opendaylight.controller</groupId>
-                       <artifactId>yang-maven-plugin-spi</artifactId>
-                       <version>0.5.1-SNAPSHOT</version>
-               </dependency>
-       </dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-maven-plugin-spi</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
 
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.opendaylight.controller</groupId>
-                               <artifactId>yang-maven-plugin</artifactId>
-                               <version>0.5.1-SNAPSHOT</version>
-                               <executions>
-                                       <execution>
-                                               <goals>
-                                                       <goal>generate-sources</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <yangFilesRootDir>../files</yangFilesRootDir>
-                                                       <codeGenerators>
-                                                               <generator>
-                                                                       <codeGeneratorClass>
-                                                                               org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
-                                                                       </codeGeneratorClass>
-                                                               </generator>
-                                                       </codeGenerators>
-                                                       <resourceProviders>
-                                                               <provider>
-                                                                       <resourceProviderClass>
-                                                                               org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
-                                                                       </resourceProviderClass>
-                                                                       <outputBaseDir>
-                                                                               outDir/
-                                                                       </outputBaseDir>
-                                                               </provider>
-                                                       </resourceProviders>
-                                               </configuration>
-                                       </execution>
-                               </executions>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.controller</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <version>0.5.1-SNAPSHOT</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <yangFilesRootDir>../files</yangFilesRootDir>
+                            <inspectDependencies>false</inspectDependencies>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+                                    </codeGeneratorClass>
+                                </generator>
+                            </codeGenerators>
+                        </configuration>
+                    </execution>
+                </executions>
 
-                               <dependencies>
-                                       <dependency>
-                                               <groupId>org.opendaylight.controller</groupId>
-                                               <artifactId>yang-maven-plugin-spi</artifactId>
-                                               <version>0.5.1-SNAPSHOT</version>
-                                               <type>test-jar</type>
-                                       </dependency>
-                               </dependencies>
-                       </plugin>
-               </plugins>
-       </build>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.controller</groupId>
+                        <artifactId>yang-maven-plugin-spi</artifactId>
+                        <version>0.5.1-SNAPSHOT</version>
+                        <type>test-jar</type>
+                    </dependency>
+                </dependencies>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct_resources/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct_resources/pom.xml
deleted file mode 100644 (file)
index 356f1c6..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.5.1-SNAPSHOT</version>
-
-    <artifactId>test</artifactId>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.opendaylight.controller</groupId>
-                <artifactId>yang-maven-plugin</artifactId>
-                <version>0.5.1-SNAPSHOT</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>generate-sources</goal>
-                        </goals>
-                        <configuration>
-                            <yangFilesRootDir>../files</yangFilesRootDir>
-                            <resourceProviders>
-                                <provider>
-                                    <resourceProviderClass>
-                                        org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
-                                    </resourceProviderClass>
-                                    <outputBaseDir>
-                                        outDir/
-                                    </outputBaseDir>
-                                </provider>
-                            </resourceProviders>
-                        </configuration>
-                    </execution>
-                </executions>
-
-                <dependencies>
-                    <dependency>
-                        <groupId>org.opendaylight.controller</groupId>
-                        <artifactId>yang-maven-plugin-spi</artifactId>
-                        <version>0.5.1-SNAPSHOT</version>
-                        <type>test-jar</type>
-                    </dependency>
-                </dependencies>
-            </plugin>
-        </plugins>
-    </build>
-</project>
\ No newline at end of file
index fdef8ad..e1591b5 100644 (file)
@@ -1,51 +1,45 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-       <modelVersion>4.0.0</modelVersion>
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
 
-       <groupId>org.opendaylight.controller</groupId>
-       <artifactId>generator-test1</artifactId>
-       <version>0.5.1-SNAPSHOT</version>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>generator-test1</artifactId>
+    <version>0.5.1-SNAPSHOT</version>
 
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.opendaylight.controller</groupId>
-                               <artifactId>yang-maven-plugin</artifactId>
-                               <version>0.5.1-SNAPSHOT</version>
-                               <executions>
-                                       <execution>
-                                               <goals>
-                                                       <goal>generate-sources</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <yangFilesRootDir>src/main/resources</yangFilesRootDir>
-                                                       <codeGenerators>
-                                                               <generator>
-                                                                       <codeGeneratorClass>
-                                                                               org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
-                                                                       </codeGeneratorClass>
-                                                               </generator>
-                                                       </codeGenerators>
-                                                       <resourceProviders>
-                                                               <provider>
-                                                                       <resourceProviderClass>
-                                                                               org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
-                                                                       </resourceProviderClass>
-                                                               </provider>
-                                                       </resourceProviders>
-                                               </configuration>
-                                       </execution>
-                               </executions>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.controller</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <version>0.5.1-SNAPSHOT</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <yangFilesRootDir>${basedir}/src/main/resources</yangFilesRootDir>
+                            <inspectDependencies>false</inspectDependencies>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+                                    </codeGeneratorClass>
+                                </generator>
+                            </codeGenerators>
+                        </configuration>
+                    </execution>
+                </executions>
 
-                               <dependencies>
-                                       <dependency>
-                                               <groupId>org.opendaylight.controller</groupId>
-                                               <artifactId>yang-maven-plugin-spi</artifactId>
-                                               <version>0.5.1-SNAPSHOT</version>
-                                               <type>test-jar</type>
-                                       </dependency>
-                               </dependencies>
-                       </plugin>
-               </plugins>
-       </build>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.controller</groupId>
+                        <artifactId>yang-maven-plugin-spi</artifactId>
+                        <version>0.5.1-SNAPSHOT</version>
+                        <type>test-jar</type>
+                    </dependency>
+                </dependencies>
+            </plugin>
+        </plugins>
+    </build>
 </project>
index 2f43553..5bf7ece 100644 (file)
@@ -20,99 +20,4 @@ module types1 {
         reference " WILL BE DEFINED LATER";
     }
 
-    leaf testleaf {
-        type data:my-type1 {
-            range "min..max";
-        }
-    }
-
-    leaf test-string-leaf {
-        type data:my-string-type-ext;
-    }
-
-    leaf leaf-with-length {
-       type data:my-string-type {
-               length "7..max";
-       }
-    }
-
-    leaf test-int-leaf {
-        type data:my-int-type-ext;
-    }
-
-    leaf test-decimal-leaf {
-        type data:my-decimal-type {
-            fraction-digits 4;
-        }
-    }
-
-    leaf test-decimal-leaf2 {
-        type data:my-decimal-type-ext;
-    }
-
-    container ext {
-        data:c-define "MY_INTERFACES";
-    }
-
-    leaf union-leaf {
-       type data:my-union-ext;
-    }
-
-    deviation /data:system/data:user {
-        deviate add {
-            default "admin"; // new users are 'admin' by default
-            config "true";
-        }
-    }
-
-    leaf nested-union-leaf {
-       type data:nested-union1;
-    }
-
-    leaf custom-union-leaf {
-        type t3:union1;
-    }
-
-    container transfer {
-        choice how {
-            default interval;
-            case interval {
-                leaf interval {
-                    type uint16;
-                    default 30;
-                    units minutes;
-                }
-            }
-            case daily {
-                leaf daily {
-                    type empty;
-                }
-                leaf time-of-day {
-                    type string;
-                    units 24-hour-clock;
-                    default 1am;
-                }
-            }
-            case manual {
-                leaf manual {
-                    type empty;
-                }
-            }
-        }
-    }
-
-    anyxml data {
-        description
-          "Copy of the source datastore subset that matched
-           the filter criteria (if any).  An empty data container
-           indicates that the request did not produce any results.";
-    }
-
-    augment "/data:interfaces/data:ifEntry/t3:augment-holder" {
-        when "if:ifType='ds0'";
-        leaf ds0ChannelNumber {
-            type string;
-        }
-    }
-
 }
index b203124..8e5b86a 100644 (file)
@@ -15,127 +15,4 @@ module types3 {
         reference " WILL BE DEFINED LATER";
     }
 
-    typedef union1 {
-        type union2;
-    }
-
-    typedef union2 {
-        type union {
-            type int32;
-            type data:nested-union2;
-        }
-    }
-
-    augment "/data:interfaces/data:ifEntry" {
-        when "if:ifType='ds0'";
-        container augment-holder {
-            description "Description for augment holder";
-        }
-    }
-    
-    augment "/data:interfaces/data:ifEntry" {
-        when "if:ifType='ds2'";
-        container augment-holder2 {
-            description "Description for augment holder";
-        }
-    }
-
-    container network {
-        mnt:mountpoint point {
-               mnt:target-ref target;
-        }
-        
-           description "network-description";
-           reference "network-reference";
-           status obsolete;
-           config true;
-           presence "some presence text";
-    }
-
-    feature local-storage {
-        description
-            "This feature means the device supports local
-             storage (memory, flash or disk) that can be used to
-             store syslog messages.";
-    }
-    
-    extension c-define {
-        description
-            "Takes as argument a name string.
-             Makes the code generator use the given name in the
-             #define.";
-        argument "name";
-    }
-    
-    notification event {
-        leaf event-class {
-            type string;
-        }
-        anyxml reporting-entity;
-        leaf severity {
-            type string;
-        }
-    }
-    
-    rpc get-config {
-        description
-          "Retrieve all or part of a specified configuration.";
-
-        reference "RFC 6241, Section 7.1";
-
-        input {
-            container source {
-                description
-                  "Particular configuration to retrieve.";
-
-                choice config-source {
-                    mandatory true;
-                    description
-                      "The configuration to retrieve.";
-                    case a {
-                        leaf candidate {
-                            if-feature candidate;
-                            type empty;
-                            description
-                              "The candidate configuration is the config source.";
-                        }
-                    }
-                    case b {
-                        leaf running {
-                            type empty;
-                            description
-                              "The running configuration is the config source.";
-                        }
-                    }
-                    case c {
-                        leaf startup {
-                            if-feature startup;
-                            type empty;
-                            description
-                              "The startup configuration is the config source.
-                               This is optional-to-implement on the server because
-                               not all servers will support filtering for this
-                               datastore.";
-                        }
-                    }
-                }
-            }
-
-            anyxml filter {
-                description
-                  "Subtree or XPath filter to use.";
-                   nc:get-filter-element-attributes;
-            }
-        }
-
-        output {
-            anyxml data {
-                description
-                  "Copy of the source datastore subset that matched
-                   the filter criteria (if any).  An empty data container
-                   indicates that the request did not produce any results.";
-            }
-        }
-    }
-
 }
index 2fcbd62..b608637 100644 (file)
@@ -1,68 +1,69 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-       <modelVersion>4.0.0</modelVersion>
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
 
-       <groupId>org.opendaylight.controller</groupId>
-       <version>0.5.1-SNAPSHOT</version>
-       <artifactId>generator-test2</artifactId>
-       
+    <groupId>org.opendaylight.controller</groupId>
+    <version>0.5.1-SNAPSHOT</version>
+    <artifactId>generator-test2</artifactId>
 
-       <dependencies>
-               <dependency>
-                       <groupId>org.opendaylight.controller</groupId>
-                       <artifactId>generator-test1</artifactId>
-                       <version>0.5.1-SNAPSHOT</version>
-                       <scope>system</scope>
-                       <systemPath>${project.basedir}/../GenerateTest1/target/generator-test1-0.5.1-SNAPSHOT.jar</systemPath>
-               </dependency>
-       </dependencies>
 
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.opendaylight.controller</groupId>
-                               <artifactId>yang-maven-plugin</artifactId>
-                               <version>0.5.1-SNAPSHOT</version>
-                               <executions>
-                                       <execution>
-                                               <goals>
-                                                       <goal>generate-sources</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <yangFilesRootDir>${project.basedir}</yangFilesRootDir>
-                                                       <codeGenerators>
-                                                               <generator>
-                                                                       <codeGeneratorClass>
-                                                                               org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
-                                                                       </codeGeneratorClass>
-                                                                       <outputBaseDir>
-                                                                               outDir/
-                                                                       </outputBaseDir>
-                                                               </generator>
-                                                       </codeGenerators>
-                                                       <resourceProviders>
-                                                               <provider>
-                                                                       <resourceProviderClass>
-                                                                               org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
-                                                                       </resourceProviderClass>
-                                                                       <outputBaseDir>
-                                                                               outDir/
-                                                                       </outputBaseDir>
-                                                               </provider>
-                                                       </resourceProviders>
-                                               </configuration>
-                                       </execution>
-                               </executions>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>generator-test1</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/../GenerateTest1/target/generator-test1-0.5.1-SNAPSHOT.jar</systemPath>
+        </dependency>
+    </dependencies>
 
-                               <dependencies>
-                                       <dependency>
-                                               <groupId>org.opendaylight.controller</groupId>
-                                               <artifactId>yang-maven-plugin-spi</artifactId>
-                                               <version>0.5.1-SNAPSHOT</version>
-                                               <type>test-jar</type>
-                                       </dependency>
-                               </dependencies>
-                       </plugin>
-               </plugins>
-       </build>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.controller</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <version>0.5.1-SNAPSHOT</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <yangFilesRootDir>${project.basedir}/yang</yangFilesRootDir>
+                            <inspectDependencies>true</inspectDependencies>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+                                    </codeGeneratorClass>
+                                    <outputBaseDir>
+                                        outDir/
+                                    </outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <resourceProviders>
+                                <provider>
+                                    <resourceProviderClass>
+                                        org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
+                                    </resourceProviderClass>
+                                    <outputBaseDir>
+                                        outDir/
+                                    </outputBaseDir>
+                                </provider>
+                            </resourceProviders>
+                        </configuration>
+                    </execution>
+                </executions>
+
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.controller</groupId>
+                        <artifactId>yang-maven-plugin-spi</artifactId>
+                        <version>0.5.1-SNAPSHOT</version>
+                        <type>test-jar</type>
+                    </dependency>
+                </dependencies>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/yang/private.yang b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/yang/private.yang
new file mode 100644 (file)
index 0000000..db346ca
--- /dev/null
@@ -0,0 +1,19 @@
+module private {
+    yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "p";
+
+    import types2 {
+        prefix "data";
+        revision-date 2013-02-27;
+    }
+
+    organization "opendaylight";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-02-27" {
+        reference " WILL BE DEFINED LATER";
+    }
+    
+
+}
index 5581882..c64a857 100644 (file)
@@ -21,6 +21,7 @@
                         </goals>
                         <configuration>
                             <yangFilesRootDir>../files</yangFilesRootDir>
+                            <inspectDependencies>false</inspectDependencies>
                             <codeGenerators>
                                 <generator>
                                     <codeGeneratorClass>
                                     </outputBaseDir>
                                 </generator>
                             </codeGenerators>
-                            <resourceProviders>
-                                <provider>
-                                    <resourceProviderClass>
-                                        org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
-                                    </resourceProviderClass>
-                                    <outputBaseDir>
-                                        outDir/
-                                    </outputBaseDir>
-                                </provider>
-                            </resourceProviders>
                         </configuration>
                     </execution>
                 </executions>
@@ -2,10 +2,10 @@
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.5.1-SNAPSHOT</version>
+    <groupId>org.opendaylight.controller</groupId>
+    <version>0.5.1-SNAPSHOT</version>
+    <artifactId>generator-test2</artifactId>
 
-    <artifactId>test</artifactId>
 
     <build>
         <plugins>
@@ -19,8 +19,9 @@
                             <goal>generate-sources</goal>
                         </goals>
                         <configuration>
-                            <yangFilesRootDir>../files</yangFilesRootDir>
-                                                       <codeGenerators>
+                            <yangFilesRootDir>${project.basedir}/yang</yangFilesRootDir>
+                            <inspectDependencies>true</inspectDependencies>
+                            <codeGenerators>
                                 <generator>
                                     <codeGeneratorClass>
                                         org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
                                         outDir/
                                     </outputBaseDir>
                                 </provider>
-                                <provider>
-                                    <resourceProviderClass>
-                                        unknown
-                                    </resourceProviderClass>
-                                    <outputBaseDir>
-                                        outDir/
-                                    </outputBaseDir>
-                                </provider>
                             </resourceProviders>
                         </configuration>
                     </execution>
@@ -63,4 +56,4 @@
             </plugin>
         </plugins>
     </build>
-</project>
\ No newline at end of file
+</project>
diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/MissingYangInDep/yang/private.yang b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/MissingYangInDep/yang/private.yang
new file mode 100644 (file)
index 0000000..8d7227b
--- /dev/null
@@ -0,0 +1,19 @@
+module private {
+    yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "p";
+
+    import unknownDep {
+        prefix "data";
+        revision-date 2013-02-27;
+    }
+
+    organization "opendaylight";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-02-27" {
+        reference " WILL BE DEFINED LATER";
+    }
+    
+
+}
index 7d3291a..9a43e89 100644 (file)
@@ -19,6 +19,7 @@
                         </goals>
                         <configuration>
                             <yangFilesRootDir>../files</yangFilesRootDir>
+                            <inspectDependencies>false</inspectDependencies>
                             <codeGenerators>
                             </codeGenerators>
                             <resourceProviders>
index 00ddbdd..54bace0 100644 (file)
@@ -2,8 +2,8 @@
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.5.1-SNAPSHOT</version>
+    <groupId>org.opendaylight.controller</groupId>
+    <version>0.5.1-SNAPSHOT</version>
 
     <artifactId>test</artifactId>
 
@@ -20,6 +20,7 @@
                         </goals>
                         <configuration>
                             <yangFilesRootDir>../files</yangFilesRootDir>
+                            <inspectDependencies>false</inspectDependencies>
                             <codeGenerators>
                                 <generator>
                                     <codeGeneratorClass>
                                     </codeGeneratorClass>
                                 </generator>
                             </codeGenerators>
-                            <resourceProviders>
-                                <provider>
-                                    <resourceProviderClass>
-                                        org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
-                                    </resourceProviderClass>
-                                </provider>
-                            </resourceProviders>
                         </configuration>
                     </execution>
                 </executions>
index 1fc7ab3..b2eeb6f 100644 (file)
@@ -2,8 +2,8 @@
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.5.1-SNAPSHOT</version>
+    <groupId>org.opendaylight.controller</groupId>
+    <version>0.5.1-SNAPSHOT</version>
 
     <artifactId>test</artifactId>
 
@@ -20,6 +20,7 @@
                         </goals>
                         <configuration>
                             <yangFilesRootDir>${basedir}</yangFilesRootDir>
+                            <inspectDependencies>false</inspectDependencies>
                             <codeGenerators>
                                 <generator>
                                     <codeGeneratorClass>
                                     </outputBaseDir>
                                 </generator>
                             </codeGenerators>
-                                                       <resourceProviders>
-                                <provider>
-                                    <resourceProviderClass>
-                                        org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
-                                    </resourceProviderClass>
-                                    <outputBaseDir>
-                                        outDir/
-                                    </outputBaseDir>
-                                </provider>
-                            </resourceProviders>
                         </configuration>
                     </execution>
                 </executions>
index 15f4322..96a75b9 100644 (file)
@@ -2,8 +2,8 @@
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.5.1-SNAPSHOT</version>
+    <groupId>org.opendaylight.controller</groupId>
+    <version>0.5.1-SNAPSHOT</version>
 
     <artifactId>test</artifactId>
 
@@ -20,6 +20,7 @@
                         </goals>
                         <configuration>
                             <yangFilesRootDir>../files</yangFilesRootDir>
+                            <inspectDependencies>false</inspectDependencies>
                             <codeGenerators>
                                 <generator>
                                     <codeGeneratorClass>
                                     </outputBaseDir>
                                 </generator>
                             </codeGenerators>
-                                                       <resourceProviders>
-                                <provider>
-                                    <resourceProviderClass>
-                                        org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
-                                    </resourceProviderClass>
-                                    <outputBaseDir>
-                                        outDir/
-                                    </outputBaseDir>
-                                </provider>
-                            </resourceProviders>
                         </configuration>
                     </execution>
                 </executions>
index 9986438..09df6ab 100644 (file)
@@ -2,8 +2,8 @@
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-        <groupId>org.opendaylight.controller</groupId>
-        <version>0.5.1-SNAPSHOT</version>
+    <groupId>org.opendaylight.controller</groupId>
+    <version>0.5.1-SNAPSHOT</version>
 
     <artifactId>test</artifactId>
 
@@ -20,6 +20,7 @@
                         </goals>
                         <configuration>
                             <yangFilesRootDir>unknown</yangFilesRootDir>
+                            <inspectDependencies>false</inspectDependencies>
                             <codeGenerators>
                                 <generator>
                                     <codeGeneratorClass>
                                     </outputBaseDir>
                                 </generator>
                             </codeGenerators>
-                                                       <resourceProviders>
-                                <provider>
-                                    <resourceProviderClass>
-                                        org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
-                                    </resourceProviderClass>
-                                    <outputBaseDir>
-                                        outDir/
-                                    </outputBaseDir>
-                                </provider>
-                            </resourceProviders>
                         </configuration>
                     </execution>
                 </executions>
index 0ce985d..aaf7080 100644 (file)
@@ -8,77 +8,53 @@
 package org.opendaylight.controller.yang2sources.plugin;
 
 import java.io.File;
+import java.util.Map;
+
+import org.apache.maven.project.MavenProject;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
 
 /**
  * Base complex configuration arguments
  */
 public abstract class ConfigArg {
-    public static final String CODE_GEN_DEFAULT_DIR = "code-generator-files/";
-    public static final String RESOURCE_GEN_DEFAULT_DIR = "resource-generator-files/";
-
-    protected File outputBaseDir;
 
-    public ConfigArg(File outputBaseDir) {
-        this.outputBaseDir = outputBaseDir;
-    }
+    private final File outputBaseDir;
 
-    public ConfigArg() {
+    public ConfigArg(String outputBaseDir) {
+        this.outputBaseDir = new File(outputBaseDir);
     }
 
-    public File getOutputBaseDir() {
-        return outputBaseDir;
+    public File getOutputBaseDir(MavenProject project) {
+        if (outputBaseDir.isAbsolute()) {
+            return outputBaseDir;
+        } else {
+            return new File(project.getBasedir(), outputBaseDir.getPath());
+        }
     }
 
     public abstract void check();
 
-    /**
-     * Configuration argument for resource generator class and output directory.
-     */
-    public static final class ResourceProviderArg extends ConfigArg {
-        private String resourceProviderClass;
-
-        public ResourceProviderArg() {
-        }
-
-        public ResourceProviderArg(String resourceProviderClass) {
-            this(resourceProviderClass, new File(RESOURCE_GEN_DEFAULT_DIR));
-        }
-
-        public ResourceProviderArg(String resourceProviderClass,
-                File outputBaseDir) {
-            super(outputBaseDir);
-            this.resourceProviderClass = resourceProviderClass;
-        }
-
-        @Override
-        public void check() {
-            Preconditions
-                    .checkNotNull(resourceProviderClass,
-                            "resourceProviderClass for ResourceProvider cannot be null");
-        }
-
-        public String getResourceProviderClass() {
-            return resourceProviderClass;
-        }
-    }
-
     /**
      * Configuration argument for code generator class and output directory.
      */
     public static final class CodeGeneratorArg extends ConfigArg {
+        private static final String CODE_GEN_DEFAULT_DIR = "target"
+                + File.separator + "generated-sources";
         private String codeGeneratorClass;
 
+        private Map<String, String> additionalConfiguration = Maps.newHashMap();
+
         public CodeGeneratorArg() {
-            super(new File(CODE_GEN_DEFAULT_DIR));
+            super(CODE_GEN_DEFAULT_DIR);
         }
 
         public CodeGeneratorArg(String codeGeneratorClass) {
-            this(codeGeneratorClass, new File(CODE_GEN_DEFAULT_DIR));
+            this(codeGeneratorClass, CODE_GEN_DEFAULT_DIR);
         }
 
-        public CodeGeneratorArg(String codeGeneratorClass, File outputBaseDir) {
+        public CodeGeneratorArg(String codeGeneratorClass, String outputBaseDir) {
             super(outputBaseDir);
             this.codeGeneratorClass = codeGeneratorClass;
         }
@@ -92,5 +68,9 @@ public abstract class ConfigArg {
         public String getCodeGeneratorClass() {
             return codeGeneratorClass;
         }
+
+        public Map<String, String> getAdditionalConfiguration() {
+            return additionalConfiguration;
+        }
     }
-}
\ No newline at end of file
+}
index acde15e..653c0bf 100644 (file)
@@ -10,19 +10,14 @@ package org.opendaylight.controller.yang2sources.plugin;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Enumeration;
 import java.util.List;
 import java.util.Map;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.maven.artifact.DependencyResolutionRequiredException;
+import org.apache.maven.artifact.Artifact;
 import org.apache.maven.project.MavenProject;
 
 import com.google.common.base.Function;
@@ -38,41 +33,56 @@ final class Util {
     // phase Second: yang files are copied as resources during
     // generate-resources phase. This cache ensures that yang files are listed
     // only once.
-    private static Map<String, Collection<File>> cache = Maps
+    private static Map<File, Collection<File>> cache = Maps
             .newHashMapWithExpectedSize(10);
 
     /**
      * List files recursively and return as array of String paths. Use cache of
      * size 1.
      */
-    static Collection<File> listFiles(String rootDir) throws FileNotFoundException {
-        if (cache.get(rootDir) != null)
-            return cache.get(rootDir);
+    static Collection<File> listFiles(File root) throws FileNotFoundException {
+        if (cache.get(root) != null)
+            return cache.get(root);
 
-        File file = new File(rootDir);
-        if(!file.exists()) {
-            throw new FileNotFoundException(rootDir);
+        if (!root.exists()) {
+            throw new FileNotFoundException(root.toString());
         }
 
-        Collection<File> yangFiles = FileUtils.listFiles(new File(rootDir),
+        Collection<File> yangFiles = FileUtils.listFiles(root,
                 new String[] { YANG_SUFFIX }, true);
 
-        toCache(rootDir, yangFiles);
+        toCache(root, yangFiles);
         return yangFiles;
     }
 
-    static List<InputStream> listFilesAsStream(String rootDir) throws FileNotFoundException {
+    static List<InputStream> listFilesAsStream(File rootDir)
+            throws FileNotFoundException {
         List<InputStream> is = new ArrayList<InputStream>();
 
         Collection<File> files = listFiles(rootDir);
-        for(File f : files) {
-            is.add(new FileInputStream(f));
+        for (File f : files) {
+            is.add(new NamedFileInputStream(f));
         }
 
         return is;
     }
 
-    static String[] listFilesAsArrayOfPaths(String rootDir) throws FileNotFoundException {
+    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 + "}";
+        }
+    }
+
+    static String[] listFilesAsArrayOfPaths(File rootDir)
+            throws FileNotFoundException {
         String[] filesArray = new String[] {};
         Collection<File> yangFiles = listFiles(rootDir);
 
@@ -88,7 +98,7 @@ final class Util {
                 }).toArray(filesArray);
     }
 
-    private static void toCache(final String rootDir,
+    private static void toCache(final File rootDir,
             final Collection<File> yangFiles) {
         cache.put(rootDir, yangFiles);
     }
@@ -127,18 +137,13 @@ final class Util {
         return String.format("%s %s", logPrefix, innerMessage);
     }
 
-    public static List<File> getClassPath(MavenProject project)
-            throws DependencyResolutionRequiredException {
+    public static List<File> getClassPath(MavenProject project) {
         List<File> dependencies = Lists.newArrayList();
-        try {
-            for (Object element : project.getCompileClasspathElements()) {
-                File asFile = new File((String) element);
-                if (isJar(asFile)) {
-                    dependencies.add(asFile);
-                }
+        for (Artifact element : project.getArtifacts()) {
+            File asFile = element.getFile();
+            if (isJar(asFile) || asFile.isDirectory()) {
+                dependencies.add(asFile);
             }
-        } catch (DependencyResolutionRequiredException e) {
-            throw e;
         }
         return dependencies;
     }
@@ -150,28 +155,9 @@ final class Util {
                 : false;
     }
 
-    public static Collection<File> getFilesFromClasspath(
-            List<File> jarsOnClasspath, List<String> classPathFilter)
-            throws ZipException, IOException {
-        List<File> yangs = Lists.newArrayList();
-
-        for (File file : jarsOnClasspath) {
-            ZipFile zip = new ZipFile(file);
-            Enumeration<? extends ZipEntry> entries = zip.entries();
-            while (entries.hasMoreElements()) {
-                ZipEntry entry = entries.nextElement();
-                if (entry.getName().endsWith(YANG_SUFFIX)) {
-                    InputStream stream = zip.getInputStream(entry);
-                }
-            }
-        }
-
-        return yangs;
-    }
-
     public static boolean acceptedFilter(String name, List<String> filter) {
-        for(String f : filter) {
-            if(name.endsWith(f)) {
+        for (String f : filter) {
+            if (name.endsWith(f)) {
                 return true;
             }
         }
index f8117c0..7dbd856 100644 (file)
@@ -7,26 +7,11 @@
  */
 package org.opendaylight.controller.yang2sources.plugin;
 
-import java.io.Closeable;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Arrays;
 import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
 
-import org.apache.commons.io.IOUtils;
-import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
@@ -35,19 +20,11 @@ import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
-import org.opendaylight.controller.yang.model.api.Module;
 import org.opendaylight.controller.yang.model.api.SchemaContext;
-import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
-import org.opendaylight.controller.yang.parser.impl.YangParserImpl;
 import org.opendaylight.controller.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
-import org.opendaylight.controller.yang2sources.plugin.ConfigArg.ResourceProviderArg;
 import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
-import org.opendaylight.controller.yang2sources.spi.ResourceGenerator;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.io.Files;
 
 /**
  * Generate sources from yang files using user provided set of
@@ -64,9 +41,6 @@ import com.google.common.io.Files;
  */
 @Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true)
 public final class YangToSourcesMojo extends AbstractMojo {
-    private static final String LOG_PREFIX = "yang-to-sources:";
-    private static final String INPUT_RESOURCE_DIR = "META-INF/yang/";
-    private static final String OUTPUT_RESOURCE_DIR = "/target/external-resources/";
 
     /**
      * Classes implementing {@link CodeGenerator} interface. An instance will be
@@ -74,397 +48,57 @@ public final class YangToSourcesMojo extends AbstractMojo {
      * CodeGenerator#generateSources(SchemaContext, File, Set<String>
      * yangModulesNames)} will be called on every instance.
      */
-    @Parameter(required = true)
+    @Parameter(required = false)
     private CodeGeneratorArg[] codeGenerators;
 
     /**
      * Source directory that will be recursively searched for yang files (ending
      * with .yang suffix).
      */
-    @Parameter(required = true)
-    private String yangFilesRootDir;
-
-    /**
-     * Classes implementing {@link ResourceGenerator} interface. An instance
-     * will be created out of every class using default constructor. Method
-     * {@link ResourceGenerator#generateResourceFiles(Collection, File)} will be
-     * called on every instance.
-     */
-    @Parameter(required = true)
-    private ResourceProviderArg[] resourceProviders;
+    @Parameter(required = false)
+    private String yangFilesRootDir; // defaults to ${basedir}/src/main/yang
 
     @Parameter(property = "project", required = true, readonly = true)
     protected MavenProject project;
 
-    private transient final YangModelParser parser;
+    @Parameter(property = "inspectDependencies", required = true, readonly = true)
+    private boolean inspectDependencies;
+
+    public YangToSourcesMojo() {
+
+    }
 
     @VisibleForTesting
-    YangToSourcesMojo(ResourceProviderArg[] resourceProviderArgs,
-            CodeGeneratorArg[] codeGeneratorArgs, YangModelParser parser,
+    YangToSourcesMojo(CodeGeneratorArg[] codeGeneratorArgs,
             String yangFilesRootDir) {
-        super();
-        this.resourceProviders = resourceProviderArgs;
         this.codeGenerators = codeGeneratorArgs;
         this.yangFilesRootDir = yangFilesRootDir;
-        this.parser = parser;
-    }
-
-    public YangToSourcesMojo() {
-        super();
-        parser = new YangParserImpl();
     }
 
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
-        ContextHolder context = processYang();
-        generateSources(context);
-        generateResources();
-
-        closeResources();
-    }
-
-    /**
-     * Generate {@link SchemaContext} with {@link YangModelParserImpl}
-     */
-    private ContextHolder processYang() throws MojoExecutionException {
-        try {
-            List<InputStream> yangFiles = Util
-                    .listFilesAsStream(yangFilesRootDir);
-            Set<Module> yangModules = parser
-                    .parseYangModelsFromStreams(yangFiles);
-
-            List<InputStream> yangFilesFromDependencies = getFilesFromDependenciesAsStream();
-            Set<Module> yangModulesFromDependencies = parser
-                    .parseYangModelsFromStreams(yangFilesFromDependencies);
-
-            Set<Module> parsedYang = new HashSet<Module>(yangModules);
-            parsedYang.addAll(yangModulesFromDependencies);
-
-            if (yangFiles.isEmpty() && yangFilesFromDependencies.isEmpty()) {
-                getLog().warn(
-                        Util.message(
-                                "No %s file found in %s or in dependencies",
-                                LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir));
-                Set<Module> modules = Collections.emptySet();
-                return new ContextHolder(null, modules);
-            }
-
-            SchemaContext resolveSchemaContext = parser
-                    .resolveSchemaContext(parsedYang);
-            getLog().info(
-                    Util.message("%s files parsed from %s", LOG_PREFIX,
-                            Util.YANG_SUFFIX, yangFiles));
-            return new ContextHolder(resolveSchemaContext, yangModules);
-
-            // MojoExecutionException is thrown since execution cannot continue
-        } catch (Exception e) {
-            String message = Util.message("Unable to parse %s files from %s",
-                    LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir);
-            getLog().error(message, e);
-            throw new MojoExecutionException(message, e);
-        }
-    }
-
-    private void generateResources() throws MojoExecutionException,
-            MojoFailureException {
-        if (resourceProviders.length == 0) {
-            getLog().warn(
-                    Util.message("No resource provider classes provided",
-                            LOG_PREFIX));
-            return;
-        }
-
-        Resource res = new Resource();
-        String baseDirName = project.getBasedir().getAbsolutePath();
-        res.setDirectory(baseDirName + OUTPUT_RESOURCE_DIR);
-        res.setTargetPath(INPUT_RESOURCE_DIR);
-        project.addResource(res);
-
-        Map<String, String> thrown = Maps.newHashMap();
-
-        Collection<File> yangFiles = new ArrayList<File>();
-
-        // load files from yang root
-        yangFiles.addAll(getFilesFromYangRoot());
-
-        // load files from dependencies
-        Collection<File> filesFromDependencies = getFilesFromDependencies();
-        yangFiles.addAll(filesFromDependencies);
-
-        for (ResourceProviderArg resourceProvider : resourceProviders) {
-            try {
-                provideResourcesWithOneProvider(yangFiles, resourceProvider);
-            } catch (Exception e) {
-                // try other generators, exception will be thrown after
-                getLog().error(
-                        Util.message(
-                                "Unable to provide resources with %s resource provider",
-                                LOG_PREFIX,
-                                resourceProvider.getResourceProviderClass()), e);
-                thrown.put(resourceProvider.getResourceProviderClass(), e
-                        .getClass().getCanonicalName());
-            }
-        }
-
-        if (!thrown.isEmpty()) {
-            String message = Util
-                    .message(
-                            "One or more code resource provider failed, including failed list(resourceProviderClass=exception) %s",
-                            LOG_PREFIX, thrown.toString());
-            getLog().error(message);
-            throw new MojoFailureException(message);
-        }
-    }
-
-    private Collection<File> getFilesFromYangRoot() {
-        Collection<File> yangFilesLoaded = null;
-
-        File rootDir = new File(yangFilesRootDir);
-        try {
-            if (rootDir.isAbsolute()) {
-                yangFilesLoaded = Util.listFiles(yangFilesRootDir);
+        List<CodeGeneratorArg> codeGeneratorArgs;
+        if (codeGenerators == null) {
+            codeGeneratorArgs = Collections.emptyList();
+        } else {
+            codeGeneratorArgs = Arrays.asList(codeGenerators);
+        }
+
+        // defaults to ${basedir}/src/main/yang
+        File yangFilesRootFile;
+        if (yangFilesRootDir == null) {
+            yangFilesRootFile = new File(project.getBasedir(), "src"
+                    + File.separator + "main" + File.separator + "yang");
+        } else {
+            File file = new File(yangFilesRootDir);
+            if (file.isAbsolute()) {
+                yangFilesRootFile = file;
             } else {
-                String path = project.getBasedir().getAbsolutePath()
-                        + File.separator + yangFilesRootDir;
-                yangFilesLoaded = Util.listFiles(path);
+                yangFilesRootFile = new File(project.getBasedir(),
+                        file.getPath());
             }
-        } catch (FileNotFoundException e) {
-            getLog().warn(
-                    "yangFilesRootDir[" + rootDir.getAbsolutePath()
-                            + "] does not exists.");
-            yangFilesLoaded = new ArrayList<File>();
         }
-
-        Collection<File> yangFiles = new ArrayList<File>(yangFilesLoaded);
-
-        try {
-            for (File yangFile : yangFilesLoaded) {
-                InputStream is = new FileInputStream(yangFile);
-                yangFiles.add(createFileFromStream(is,
-                        project.getBasedir().getAbsolutePath()
-                                + OUTPUT_RESOURCE_DIR + yangFile.getName()));
-                resources.add(is);
-            }
-        } catch (IOException e) {
-            getLog().warn("Exception while loading yang files.", e);
-        }
-        return yangFiles;
-    }
-
-    private Collection<File> getFilesFromDependencies() {
-        Collection<File> yangFiles = new ArrayList<File>();
-
-        try {
-            List<File> filesOnCp = Util.getClassPath(project);
-            List<String> filter = Lists.newArrayList(".yang");
-            for (File file : filesOnCp) {
-                ZipFile zip = new ZipFile(file);
-                Enumeration<? extends ZipEntry> entries = zip.entries();
-
-                while (entries.hasMoreElements()) {
-                    ZipEntry entry = entries.nextElement();
-                    String entryName = entry.getName();
-                    if (entryName.startsWith(INPUT_RESOURCE_DIR)) {
-                        if (entry.isDirectory()) {
-                            continue;
-                        }
-                        if (!Util.acceptedFilter(entryName, filter)) {
-                            continue;
-                        }
-                        InputStream entryStream = zip.getInputStream(entry);
-                        String newEntryName = entryName
-                                .substring(INPUT_RESOURCE_DIR.length());
-                        File tmp = Files.createTempDir();
-                        File f = createFileFromStream(entryStream,
-                                tmp.getAbsolutePath() + newEntryName);
-                        yangFiles.add(f);
-
-                        resources.add(entryStream);
-                    }
-                }
-
-                resources.add(zip);
-            }
-        } catch (Exception e) {
-            getLog().warn("Exception while loading external yang files.", e);
-        }
-        return yangFiles;
-    }
-
-    private File createFileFromStream(InputStream is, String absoluteName)
-            throws IOException {
-        File f = new File(absoluteName);
-        if (!f.exists()) {
-            f.getParentFile().mkdirs();
-        }
-        f.createNewFile();
-
-        FileOutputStream fos = new FileOutputStream(f);
-        IOUtils.copy(is, fos);
-        return f;
+        new YangToSourcesProcessor(getLog(), yangFilesRootFile,
+                codeGeneratorArgs, project, inspectDependencies).execute();
     }
-
-    /**
-     * Instantiate provider from class and call required method
-     */
-    private void provideResourcesWithOneProvider(Collection<File> yangFiles,
-            ResourceProviderArg resourceProvider)
-            throws ClassNotFoundException, InstantiationException,
-            IllegalAccessException {
-
-        resourceProvider.check();
-
-        ResourceGenerator g = Util.getInstance(
-                resourceProvider.getResourceProviderClass(),
-                ResourceGenerator.class);
-        getLog().info(
-                Util.message("Resource provider instantiated from %s",
-                        LOG_PREFIX, resourceProvider.getResourceProviderClass()));
-
-        g.generateResourceFiles(yangFiles, resourceProvider.getOutputBaseDir());
-        getLog().info(
-                Util.message("Resource provider %s call successful",
-                        LOG_PREFIX, resourceProvider.getResourceProviderClass()));
-    }
-
-    /**
-     * Call generate on every generator from plugin configuration
-     */
-    private void generateSources(ContextHolder context)
-            throws MojoFailureException {
-        if (codeGenerators.length == 0) {
-            getLog().warn(
-                    Util.message("No code generators provided", LOG_PREFIX));
-            return;
-        }
-
-        Map<String, String> thrown = Maps.newHashMap();
-        for (CodeGeneratorArg codeGenerator : codeGenerators) {
-            try {
-                generateSourcesWithOneGenerator(context, codeGenerator);
-            } catch (Exception e) {
-                // try other generators, exception will be thrown after
-                getLog().error(
-                        Util.message(
-                                "Unable to generate sources with %s generator",
-                                LOG_PREFIX,
-                                codeGenerator.getCodeGeneratorClass()), e);
-                thrown.put(codeGenerator.getCodeGeneratorClass(), e.getClass()
-                        .getCanonicalName());
-            }
-        }
-
-        if (!thrown.isEmpty()) {
-            String message = Util
-                    .message(
-                            "One or more code generators failed, including failed list(generatorClass=exception) %s",
-                            LOG_PREFIX, thrown.toString());
-            getLog().error(message);
-            throw new MojoFailureException(message);
-        }
-    }
-
-    /**
-     * Instantiate generator from class and call required method
-     */
-    private void generateSourcesWithOneGenerator(ContextHolder context,
-            CodeGeneratorArg codeGeneratorCfg) throws ClassNotFoundException,
-            InstantiationException, IllegalAccessException, IOException {
-
-        codeGeneratorCfg.check();
-
-        CodeGenerator g = Util.getInstance(
-                codeGeneratorCfg.getCodeGeneratorClass(), CodeGenerator.class);
-        getLog().info(
-                Util.message("Code generator instantiated from %s", LOG_PREFIX,
-                        codeGeneratorCfg.getCodeGeneratorClass()));
-
-        File outputDir = codeGeneratorCfg.getOutputBaseDir();
-        if (project != null && outputDir != null) {
-            project.addCompileSourceRoot(outputDir.getPath());
-        }
-        Collection<File> generated = g.generateSources(context.getContext(),
-                outputDir, context.getYangModules());
-        getLog().info(
-                Util.message("Sources generated by %s: %s", LOG_PREFIX,
-                        codeGeneratorCfg.getCodeGeneratorClass(), generated));
-    }
-
-    /**
-     * Collection of resources which should be closed after use.
-     */
-    private final List<Closeable> resources = new ArrayList<Closeable>();
-
-    /**
-     * Search for yang files in dependent projects.
-     *
-     * @return files found as List of InputStream
-     */
-    private List<InputStream> getFilesFromDependenciesAsStream() {
-        final List<InputStream> yangsFromDependencies = new ArrayList<InputStream>();
-        try {
-            List<File> filesOnCp = Util.getClassPath(project);
-
-            List<String> filter = Lists.newArrayList(".yang");
-            for (File file : filesOnCp) {
-                ZipFile zip = new ZipFile(file);
-                Enumeration<? extends ZipEntry> entries = zip.entries();
-                while (entries.hasMoreElements()) {
-                    ZipEntry entry = entries.nextElement();
-                    String entryName = entry.getName();
-
-                    if (entryName.startsWith(INPUT_RESOURCE_DIR)) {
-                        if (entry.isDirectory()) {
-                            continue;
-                        }
-                        if (!Util.acceptedFilter(entryName, filter)) {
-                            continue;
-                        }
-
-                        InputStream entryStream = zip.getInputStream(entry);
-                        yangsFromDependencies.add(entryStream);
-                        resources.add(entryStream);
-                    }
-
-                }
-                resources.add(zip);
-            }
-        } catch (Exception e) {
-            getLog().warn("Exception while searching yangs in dependencies", e);
-        }
-        return yangsFromDependencies;
-    }
-
-    /**
-     * Internal utility method for closing open resources.
-     */
-    private void closeResources() {
-        for (Closeable resource : resources) {
-            try {
-                resource.close();
-            } catch (IOException e) {
-                getLog().warn("Failed to close resources: " + resource, e);
-            }
-        }
-    }
-
-    private class ContextHolder {
-        private final SchemaContext context;
-        private final Set<Module> yangModules;
-
-        private ContextHolder(SchemaContext context,
-                Set<Module> yangModules) {
-            this.context = context;
-            this.yangModules = yangModules;
-        }
-
-        public SchemaContext getContext() {
-            return context;
-        }
-
-        public Set<Module> getYangModules() {
-            return yangModules;
-        }
-    }
-
 }
diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesProcessor.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesProcessor.java
new file mode 100644 (file)
index 0000000..be92af0
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * 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.controller.yang2sources.plugin;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.FileUtils;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.parser.impl.YangParserImpl;
+import org.opendaylight.controller.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
+import org.opendaylight.controller.yang2sources.plugin.Util.NamedFileInputStream;
+import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
+
+import com.google.common.collect.Maps;
+
+class YangToSourcesProcessor {
+    private static final String LOG_PREFIX = "yang-to-sources:";
+    private static final String META_INF_YANG_STRING = "META-INF"
+            + File.separator + "yang";
+    private static final File META_INF_YANG_DIR = new File(META_INF_YANG_STRING);
+
+    private final Log log;
+    private final File yangFilesRootDir;
+    private final List<CodeGeneratorArg> codeGenerators;
+    private final MavenProject project;
+    private final boolean inspectDependencies;
+
+    YangToSourcesProcessor(Log log, File yangFilesRootDir,
+            List<CodeGeneratorArg> codeGenerators, MavenProject project,
+            boolean inspectDependencies) {
+        this.log = checkNotNull(log, "log");
+        this.yangFilesRootDir = checkNotNull(yangFilesRootDir,
+                "yangFilesRootDir");
+        this.codeGenerators = Collections.unmodifiableList(checkNotNull(
+                codeGenerators, "codeGenerators"));
+        this.project = checkNotNull(project, "project");
+        this.inspectDependencies = inspectDependencies;
+    }
+
+    private static <T> T checkNotNull(T obj, String paramName) {
+        if (obj == null)
+            throw new NullPointerException("Parameter '" + paramName
+                    + "' is null");
+        return obj;
+    }
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        ContextHolder context = processYang();
+        generateSources(context);
+        addYangsToMETA_INF();
+    }
+
+    private ContextHolder processYang() throws MojoExecutionException {
+        YangParserImpl parser = new YangParserImpl();
+        List<Closeable> closeables = new ArrayList<>();
+        log.info(Util.message("Inspecting %s", LOG_PREFIX, yangFilesRootDir));
+        try {
+            List<InputStream> yangsInProject = Util
+                    .listFilesAsStream(yangFilesRootDir);
+            List<InputStream> all = new ArrayList<>(yangsInProject);
+            closeables.addAll(yangsInProject);
+            Map<InputStream, Module> allYangModules;
+            Set<Module> projectYangModules;
+            try {
+                if (inspectDependencies) {
+                    YangsInZipsResult dependentYangResult = findYangFilesInDependenciesAsStream();
+                    Closeable dependentYangResult1 = dependentYangResult;
+                    closeables.add(dependentYangResult1);
+                    all.addAll(dependentYangResult.yangStreams);
+                }
+
+                allYangModules = parser.parseYangModelsFromStreamsMapped(all);
+
+                projectYangModules = new HashSet<>();
+                for (InputStream inProject : yangsInProject) {
+                    projectYangModules.add(allYangModules.get(inProject));
+                }
+
+            } finally {
+                for (AutoCloseable closeable : closeables) {
+                    closeable.close();
+                }
+            }
+
+            Set<Module> parsedAllYangModules = new HashSet<>(
+                    allYangModules.values());
+            SchemaContext resolveSchemaContext = parser
+                    .resolveSchemaContext(parsedAllYangModules);
+            log.info(Util.message("%s files parsed from %s", LOG_PREFIX,
+                    Util.YANG_SUFFIX.toUpperCase(), yangsInProject));
+            return new ContextHolder(resolveSchemaContext, projectYangModules);
+
+            // MojoExecutionException is thrown since execution cannot continue
+        } catch (Exception e) {
+            String message = Util.message("Unable to parse %s files from %s",
+                    LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir);
+            log.error(message, e);
+            throw new MojoExecutionException(message, e);
+        }
+    }
+
+    private void addYangsToMETA_INF() throws MojoFailureException {
+        Resource res = new Resource();
+
+        File targetYangDir = new File(project.getBasedir(), "target"
+                + File.separator + "yang");
+        res.setDirectory(targetYangDir.getPath());
+
+        res.setTargetPath(META_INF_YANG_DIR.getPath());
+        try {
+            FileUtils.copyDirectory(yangFilesRootDir, targetYangDir);
+        } catch (IOException e) {
+            throw new MojoFailureException(e.getMessage(), e);
+        }
+        project.addResource(res);
+    }
+
+    /**
+     * Call generate on every generator from plugin configuration
+     */
+    private void generateSources(ContextHolder context)
+            throws MojoFailureException {
+        if (codeGenerators.size() == 0) {
+            log.warn(Util.message("No code generators provided", LOG_PREFIX));
+            return;
+        }
+
+        Map<String, String> thrown = Maps.newHashMap();
+        for (CodeGeneratorArg codeGenerator : codeGenerators) {
+            try {
+                generateSourcesWithOneGenerator(context, codeGenerator);
+            } catch (Exception e) {
+                // try other generators, exception will be thrown after
+                log.error(Util.message(
+                        "Unable to generate sources with %s generator",
+                        LOG_PREFIX, codeGenerator.getCodeGeneratorClass()), e);
+                thrown.put(codeGenerator.getCodeGeneratorClass(), e.getClass()
+                        .getCanonicalName());
+            }
+        }
+
+        if (!thrown.isEmpty()) {
+            String message = Util
+                    .message(
+                            "One or more code generators failed, including failed list(generatorClass=exception) %s",
+                            LOG_PREFIX, thrown.toString());
+            log.error(message);
+            throw new MojoFailureException(message);
+        }
+    }
+
+    /**
+     * Instantiate generator from class and call required method
+     */
+    private void generateSourcesWithOneGenerator(ContextHolder context,
+            CodeGeneratorArg codeGeneratorCfg) throws ClassNotFoundException,
+            InstantiationException, IllegalAccessException, IOException {
+
+        codeGeneratorCfg.check();
+
+        CodeGenerator g = Util.getInstance(
+                codeGeneratorCfg.getCodeGeneratorClass(), CodeGenerator.class);
+        log.info(Util.message("Code generator instantiated from %s",
+                LOG_PREFIX, codeGeneratorCfg.getCodeGeneratorClass()));
+
+        File outputDir = codeGeneratorCfg.getOutputBaseDir(project);
+
+        log.info(Util.message("Sources will be generated to %s", LOG_PREFIX,
+                outputDir));
+        log.info(Util.message("Project root dir is %s", LOG_PREFIX,
+                project.getBasedir()));
+        log.info(Util.message(
+                "Additional configuration picked up for : %s: %s", LOG_PREFIX,
+                codeGeneratorCfg.getCodeGeneratorClass(),
+                codeGeneratorCfg.getAdditionalConfiguration()));
+        project.addCompileSourceRoot(outputDir.getAbsolutePath());
+        g.setLog(log);
+        g.setAdditionalConfig(codeGeneratorCfg.getAdditionalConfiguration());
+        Collection<File> generated = g.generateSources(context.getContext(),
+                outputDir, context.getYangModules(), project.getBasedir());
+        log.info(Util.message("Sources generated by %s: %s", LOG_PREFIX,
+                codeGeneratorCfg.getCodeGeneratorClass(), generated));
+    }
+
+    private class YangsInZipsResult implements Closeable {
+        private final List<InputStream> yangStreams;
+        private final List<Closeable> zipInputStreams;
+
+        private YangsInZipsResult(List<InputStream> yangStreams,
+                List<Closeable> zipInputStreams) {
+            this.yangStreams = yangStreams;
+            this.zipInputStreams = zipInputStreams;
+        }
+
+        @Override
+        public void close() throws IOException {
+            for (InputStream is : yangStreams) {
+                is.close();
+            }
+            for (Closeable is : zipInputStreams) {
+                is.close();
+            }
+        }
+    }
+
+    private YangsInZipsResult findYangFilesInDependenciesAsStream()
+            throws MojoFailureException {
+        List<InputStream> yangsFromDependencies = new ArrayList<>();
+        List<Closeable> zips = new ArrayList<>();
+        try {
+            List<File> filesOnCp = Util.getClassPath(project);
+            log.info(Util.message(
+                    "Searching for yang files in following dependencies: %s",
+                    LOG_PREFIX, filesOnCp));
+
+            for (File file : filesOnCp) {
+                List<String> foundFilesForReporting = new ArrayList<>();
+                // is it jar file or directory?
+                if (file.isDirectory()) {
+                    File yangDir = new File(file, META_INF_YANG_STRING);
+                    if (yangDir.exists() && yangDir.isDirectory()) {
+                        File[] yangFiles = yangDir
+                                .listFiles(new FilenameFilter() {
+                                    @Override
+                                    public boolean accept(File dir, String name) {
+                                        return name.endsWith(".yang")
+                                                && new File(dir, name).isFile();
+                                    }
+                                });
+                        for (File yangFile : yangFiles) {
+                            yangsFromDependencies.add(new NamedFileInputStream(
+                                    yangFile));
+                        }
+                    }
+
+                } else {
+                    ZipFile zip = new ZipFile(file);
+                    zips.add(zip);
+
+                    Enumeration<? extends ZipEntry> entries = zip.entries();
+                    while (entries.hasMoreElements()) {
+                        ZipEntry entry = entries.nextElement();
+                        String entryName = entry.getName();
+
+                        if (entryName.startsWith(META_INF_YANG_STRING)) {
+                            if (entry.isDirectory() == false
+                                    && entryName.endsWith(".yang")) {
+                                foundFilesForReporting.add(entryName);
+                                // This will be closed after all strams are
+                                // parsed.
+                                InputStream entryStream = zip
+                                        .getInputStream(entry);
+                                yangsFromDependencies.add(entryStream);
+                            }
+                        }
+                    }
+                }
+                if (foundFilesForReporting.size() > 0) {
+                    log.info(Util.message("Found %d yang files in %s: %s",
+                            LOG_PREFIX, foundFilesForReporting.size(), file,
+                            foundFilesForReporting));
+                }
+
+            }
+        } catch (Exception e) {
+            throw new MojoFailureException(e.getMessage(), e);
+        }
+        return new YangsInZipsResult(yangsFromDependencies, zips);
+    }
+
+    private class ContextHolder {
+        private final SchemaContext context;
+        private final Set<Module> yangModules;
+
+        private ContextHolder(SchemaContext context, Set<Module> yangModules) {
+            this.context = context;
+            this.yangModules = yangModules;
+        }
+
+        public SchemaContext getContext() {
+            return context;
+        }
+
+        public Set<Module> getYangModules() {
+            return yangModules;
+        }
+    }
+}
index 2ded614..1bfe9d4 100644 (file)
@@ -8,14 +8,17 @@
 package org.opendaylight.controller.yang2sources.plugin;
 
 import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.anyListOf;
-import static org.mockito.Mockito.*;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.doReturn;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.Collection;
+import java.util.Map;
 import java.util.Set;
 
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -23,22 +26,18 @@ import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.yang.model.api.Module;
 import org.opendaylight.controller.yang.model.api.SchemaContext;
-import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
 import org.opendaylight.controller.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
-import org.opendaylight.controller.yang2sources.plugin.ConfigArg.ResourceProviderArg;
 import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
-import org.opendaylight.controller.yang2sources.spi.ResourceGenerator;
 
 import com.google.common.collect.Lists;
 
-@Ignore
 public class GenerateSourcesTest {
 
-    @Mock
-    private YangModelParser parser;
     private String yang;
     private YangToSourcesMojo mojo;
     private File outDir;
+    @Mock
+    private MavenProject project;
 
     @Before
     public void setUp() {
@@ -46,71 +45,50 @@ public class GenerateSourcesTest {
 
         yang = new File(getClass().getResource("/mock.yang").getFile())
                 .getParent();
-        outDir = new File("outputDir");
+        outDir = new File("/outputDir");
         mojo = new YangToSourcesMojo(
-                new ResourceProviderArg[] {
-                        new ResourceProviderArg(ProviderMock.class.getName(),
-                                outDir),
-                        new ResourceProviderArg(ProviderMock2.class.getName(),
-                                outDir) },
                 new CodeGeneratorArg[] { new CodeGeneratorArg(
-                        GeneratorMock.class.getName(), outDir) }, parser, yang);
+                        GeneratorMock.class.getName(), "outputDir") }, yang);
+        doReturn(new File("")).when(project).getBasedir();
+        mojo.project = project;
     }
 
+    @Ignore
     @Test
     public void test() throws Exception {
         mojo.execute();
-        verify(parser, times(1)).parseYangModels(anyListOf(File.class));
         assertThat(GeneratorMock.called, is(1));
         assertThat(GeneratorMock.outputDir, is(outDir));
-    }
-
-    @Test
-    public void testRes() throws Exception {
-        mojo.execute();
-        assertThat(ProviderMock.called, is(1));
-        assertThat(ProviderMock2.called, is(1));
-        assertThat(ProviderMock2.baseDir, is(outDir));
-        assertThat(ProviderMock.baseDir, is(outDir));
+        assertNotNull(GeneratorMock.log);
+        assertTrue(GeneratorMock.additionalCfg.isEmpty());
     }
 
     public static class GeneratorMock implements CodeGenerator {
 
         private static int called = 0;
         private static File outputDir;
+        private static Log log;
+        private static Map<String, String> additionalCfg;
 
         @Override
         public Collection<File> generateSources(SchemaContext context,
-                File baseDir, Set<Module> yangModules) {
+                File outputBaseDir, Set<Module> currentModules,
+                File projectBaseDir) throws IOException {
             called++;
-            outputDir = baseDir;
+            outputDir = outputBaseDir;
             return Lists.newArrayList();
         }
-    }
-
-    public static class ProviderMock implements ResourceGenerator {
-
-        private static int called = 0;
-        private static File baseDir;
 
         @Override
-        public void generateResourceFiles(Collection<File> resources,
-                File outputDir) {
-            called++;
-            baseDir = outputDir;
+        public void setLog(Log log) {
+            this.log = log;
         }
-    }
-
-    public static class ProviderMock2 implements ResourceGenerator {
-
-        private static int called = 0;
-        private static File baseDir;
 
         @Override
-        public void generateResourceFiles(Collection<File> resources,
-                File outputDir) {
-            called++;
-            baseDir = outputDir;
+        public void setAdditionalConfig(
+                Map<String, String> additionalConfiguration) {
+            this.additionalCfg = additionalConfiguration;
         }
     }
+
 }
index 75e50f0..96a4d57 100644 (file)
@@ -7,13 +7,13 @@
  */
 package org.opendaylight.controller.yang2sources.plugin;
 
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
 
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.Collection;
 
-import org.junit.Test;
+import static org.junit.Assert.assertTrue;
 
 public class UtilTest {
 
@@ -21,8 +21,8 @@ public class UtilTest {
     public void testCache() throws FileNotFoundException {
         String yang = new File(getClass().getResource("/mock.yang").getFile())
                 .getParent();
-        Collection<File> files = Util.listFiles(yang);
-        Collection<File> files2 = Util.listFiles(yang);
+        Collection<File> files = Util.listFiles(new File(yang));
+        Collection<File> files2 = Util.listFiles(new File(yang));
         assertTrue(files == files2);
     }
 
index ca7a320..9c4475c 100644 (file)
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>yang-model-api</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <version>3.0.5</version>
+        </dependency>
     </dependencies>
 
     <build>
index 14bcccc..df33d4c 100644 (file)
@@ -10,8 +10,10 @@ package org.opendaylight.controller.yang2sources.spi;
 import java.io.File;
 import java.io.IOException;
 import java.util.Collection;
+import java.util.Map;
 import java.util.Set;
 
+import org.apache.maven.plugin.logging.Log;
 import org.opendaylight.controller.yang.model.api.Module;
 import org.opendaylight.controller.yang.model.api.SchemaContext;
 
@@ -29,11 +31,18 @@ public interface CodeGenerator {
      * @param outputBaseDir
      *            expected output directory for generated sources configured by
      *            user
-     * @param yangModules
+     * @param currentModules
      *            yang modules parsed from yangFilesRootDir
+     * @param log
+     *            maven logger
      * @return collection of files that were generated from schema context
      * @throws IOException
      */
     Collection<File> generateSources(SchemaContext context, File outputBaseDir,
-            Set<Module> yangModules) throws IOException;
+            Set<Module> currentModules, File projectBaseDir)
+            throws IOException;
+
+    void setLog(Log log);
+
+    void setAdditionalConfig(Map<String, String> additionalConfiguration);
 }
diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/ResourceGenerator.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/ResourceGenerator.java
deleted file mode 100644 (file)
index 2638dc3..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.controller.yang2sources.spi;
-
-import java.io.File;
-import java.util.Collection;
-
-/**
- * Classes implementing this interface can be submitted to maven-yang-plugin's
- * generate-resources goal.
- */
-public interface ResourceGenerator {
-
-    /**
-     * Generate resources (e.g. copy files into resources folder) from provided
-     * list of yang files
-     * 
-     * @param resources
-     *            list of parsed yang files
-     * @param outputBaseDir
-     *            expected output directory for resources configured by user
-     */
-    void generateResourceFiles(Collection<File> resources, File outputBaseDir);
-}
index 6049627..172a2f2 100644 (file)
@@ -9,8 +9,10 @@ package org.opendaylight.controller.yang2sources.spi;
 
 import java.io.File;
 import java.util.Collection;
+import java.util.Map;
 import java.util.Set;
 
+import org.apache.maven.plugin.logging.Log;
 import org.opendaylight.controller.yang.model.api.Module;
 import org.opendaylight.controller.yang.model.api.SchemaContext;
 
@@ -18,9 +20,20 @@ public class CodeGeneratorTestImpl implements CodeGenerator {
 
     @Override
     public Collection<File> generateSources(SchemaContext context,
-            File outputBaseDir, Set<Module> yangModules) {
+            File outputBaseDir, Set<Module> currentModuleBuilders,
+            File projectMainDir) {
         // no-op
         return null;
     }
 
+    @Override
+    public void setLog(Log log) {
+        // no-op
+    }
+
+    @Override
+    public void setAdditionalConfig(Map<String, String> additionalConfiguration) {
+        // no-op
+    }
+
 }
diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/ResourceProviderTestImpl.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/ResourceProviderTestImpl.java
deleted file mode 100644 (file)
index dc52184..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.controller.yang2sources.spi;
-
-import java.io.File;
-import java.util.Collection;
-
-public class ResourceProviderTestImpl implements ResourceGenerator {
-
-    @Override
-    public void generateResourceFiles(Collection<File> resources,
-            File outputBaseDir) {
-        // no-op
-    }
-
-}
index 953cd43..842bb43 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.yang.model.parser.api;
 import java.io.File;
 import java.io.InputStream;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.opendaylight.controller.yang.model.api.Module;
@@ -33,9 +34,22 @@ public interface YangModelParser {
      *            yang files to parse
      * @return Set of Yang Modules
      */
-    public Set<Module> parseYangModels(final List<File> yangFiles);
-    
-    public Set<Module> parseYangModelsFromStreams(
+    Set<Module> parseYangModels(final List<File> yangFiles);
+
+    /**
+     * Equivalent to {@link #parseYangModels(List)} that returns parsed modules
+     * mapped to Files from which they were parsed.
+     *
+     * @param yangFiles
+     *            yang files to parse
+     * @return Map of Yang Modules
+     */
+    Map<File, Module> parseYangModelsMapped(final List<File> yangFiles);
+
+    Set<Module> parseYangModelsFromStreams(
+            final List<InputStream> yangModelStreams);
+
+    Map<InputStream, Module> parseYangModelsFromStreamsMapped(
             final List<InputStream> yangModelStreams);
 
     /**
@@ -50,5 +64,5 @@ public interface YangModelParser {
      *            Set of Yang Modules
      * @return Schema Context instance constructed from whole Set of Modules.
      */
-    public SchemaContext resolveSchemaContext(final Set<Module> modules);
+    SchemaContext resolveSchemaContext(final Set<Module> modules);
 }
index ac2b533..25af3eb 100644 (file)
@@ -19,9 +19,9 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.TreeMap;
@@ -81,35 +81,80 @@ import org.opendaylight.controller.yang.validator.YangModelBasicValidator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
 public final class YangParserImpl implements YangModelParser {
 
     private static final Logger logger = LoggerFactory
             .getLogger(YangParserImpl.class);
 
     @Override
-    public Set<Module> parseYangModels(final List<File> yangFiles) {
+    public Map<File, Module> parseYangModelsMapped(List<File> yangFiles) {
         if (yangFiles != null) {
-            final List<InputStream> inputStreams = new ArrayList<InputStream>();
+            final Map<InputStream, File> inputStreams = Maps.newHashMap();
 
             for (final File yangFile : yangFiles) {
                 try {
-                    inputStreams.add(new FileInputStream(yangFile));
+                    inputStreams.put(new FileInputStream(yangFile), yangFile);
                 } catch (FileNotFoundException e) {
                     logger.warn("Exception while reading yang file: "
                             + yangFile.getName(), e);
                 }
             }
-            final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(inputStreams);
-            return build(modules);
+
+            Map<ModuleBuilder, InputStream> builderToStreamMap = Maps
+                    .newHashMap();
+
+            final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
+                    Lists.newArrayList(inputStreams.keySet()),
+                    builderToStreamMap);
+            // return new LinkedHashSet<Module>(build(modules).values());
+
+            Map<File, Module> retVal = Maps.newLinkedHashMap();
+            Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
+
+            for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap
+                    .entrySet()) {
+                retVal.put(inputStreams.get(builderToStreamMap
+                        .get(builderToModule.getKey())), builderToModule
+                        .getValue());
+            }
+
+            return retVal;
         }
-        return Collections.emptySet();
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Set<Module> parseYangModels(final List<File> yangFiles) {
+        return Sets.newLinkedHashSet(parseYangModelsMapped(yangFiles).values());
     }
 
     @Override
     public Set<Module> parseYangModelsFromStreams(
             final List<InputStream> yangModelStreams) {
-        final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(yangModelStreams);
-        return build(modules);
+        return Sets.newHashSet(parseYangModelsFromStreamsMapped(
+                yangModelStreams).values());
+    }
+
+    @Override
+    public Map<InputStream, Module> parseYangModelsFromStreamsMapped(
+            final List<InputStream> yangModelStreams) {
+        Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
+
+        final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
+                yangModelStreams, builderToStreamMap);
+        Map<InputStream, Module> retVal = Maps.newLinkedHashMap();
+        Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
+
+        for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap
+                .entrySet()) {
+            retVal.put(builderToStreamMap.get(builderToModule.getKey()),
+                    builderToModule.getValue());
+        }
+        return retVal;
     }
 
     @Override
@@ -117,13 +162,11 @@ public final class YangParserImpl implements YangModelParser {
         return new SchemaContextImpl(modules);
     }
 
-    private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(
-            final List<InputStream> yangFileStreams) {
-        // Linked Hash Map MUST be used because Linked Hash Map preserves ORDER
-        // of items stored in map.
-        final Map<String, TreeMap<Date, ModuleBuilder>> modules = new LinkedHashMap<String, TreeMap<Date, ModuleBuilder>>();
+    private ModuleBuilder[] parseModuleBuilders(List<InputStream> inputStreams,
+            Map<ModuleBuilder, InputStream> streamToBuilderMap) {
+
         final ParseTreeWalker walker = new ParseTreeWalker();
-        final List<ParseTree> trees = parseStreams(yangFileStreams);
+        final List<ParseTree> trees = parseStreams(inputStreams);
         final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
 
         // validate yang
@@ -133,8 +176,25 @@ public final class YangParserImpl implements YangModelParser {
         for (int i = 0; i < trees.size(); i++) {
             yangModelParser = new YangParserListenerImpl();
             walker.walk(yangModelParser, trees.get(i));
-            builders[i] = yangModelParser.getModuleBuilder();
+            ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
+
+            // We expect the order of trees and streams has to be the same
+            streamToBuilderMap.put(moduleBuilder, inputStreams.get(i));
+            builders[i] = moduleBuilder;
         }
+        return builders;
+    }
+
+    private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(
+            final List<InputStream> yangFileStreams,
+            Map<ModuleBuilder, InputStream> streamToBuilderMap) {
+
+        final ModuleBuilder[] builders = parseModuleBuilders(yangFileStreams,
+                streamToBuilderMap);
+
+        // Linked Hash Map MUST be used because Linked Hash Map preserves ORDER
+        // of items stored in map.
+        final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> modules = new LinkedHashMap<String, TreeMap<Date, ModuleBuilder>>();
 
         // module dependency graph sorted
         List<ModuleBuilder> sorted = ModuleDependencySort.sort(builders);
@@ -178,7 +238,7 @@ public final class YangParserImpl implements YangModelParser {
         return result;
     }
 
-    private Set<Module> build(
+    private Map<ModuleBuilder, Module> build(
             final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
         // fix unresolved nodes
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
@@ -192,10 +252,10 @@ public final class YangParserImpl implements YangModelParser {
         resolveAugments(modules);
 
         // build
-        // LinkedHashSet MUST be used otherwise the Set will not maintain
+        // LinkedHashMap MUST be used otherwise the values will not maintain
         // order!
-        // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html
-        final Set<Module> result = new LinkedHashSet<Module>();
+        // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html
+        final Map<ModuleBuilder, Module> result = new LinkedHashMap<ModuleBuilder, Module>();
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
                 .entrySet()) {
             final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
@@ -204,7 +264,7 @@ public final class YangParserImpl implements YangModelParser {
                 final ModuleBuilder moduleBuilder = childEntry.getValue();
                 final Module module = moduleBuilder.build();
                 modulesByRevision.put(childEntry.getKey(), module);
-                result.add(module);
+                result.put(moduleBuilder, module);
             }
         }
         return result;
@@ -739,7 +799,7 @@ public final class YangParserImpl implements YangModelParser {
                     if (currentQName.getLocalName().equals(
                             lastAugmentPathElement.getLocalName())) {
 
-                        if(currentParent instanceof ChoiceBuilder) {
+                        if (currentParent instanceof ChoiceBuilder) {
                             ParserUtils.fillAugmentTarget(augmentBuilder,
                                     (ChoiceBuilder) currentParent);
                         } else {
index 3d9df34..d14c542 100644 (file)
@@ -18,6 +18,7 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -54,7 +55,8 @@ final class TestUtils {
         for(String path : pathToYangFile) {
             input.add(TestUtils.class.getResourceAsStream(path));
         }
-        Set<Module> modules = parser.parseYangModelsFromStreams(input);
+        Set<Module> modules = new HashSet<Module>(
+                parser.parseYangModelsFromStreams(input));
         for(InputStream stream : input) {
             stream.close();
         }
@@ -65,7 +67,8 @@ final class TestUtils {
         YangModelParser parser = new YangParserImpl();
         InputStream stream = TestUtils.class.getResourceAsStream(pathToYangFile);
         List<InputStream> input = Collections.singletonList(stream);
-        Set<Module> modules = parser.parseYangModelsFromStreams(input);
+        Set<Module> modules = new HashSet<Module>(
+                parser.parseYangModelsFromStreams(input));
         stream.close();
         return modules.iterator().next();
     }