From 3556bca9524bd19e738ac0d86c4e8b4d5add0a21 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Thu, 30 May 2013 11:49:22 +0200 Subject: [PATCH] Yang-maven-plugin refactored + fixed bugs. 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. 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 --- .../sal/api/gen/plugin/CodeGeneratorImpl.java | 25 +- .../plugin/it/YangToSourcesPluginTest.java | 74 +-- .../pom.xml | 39 +- .../src/test/resources/Correct/pom.xml | 103 ++--- .../test/resources/Correct_resources/pom.xml | 48 -- .../src/test/resources/GenerateTest1/pom.xml | 86 ++-- .../src/main/resources/testfile1.yang | 95 ---- .../src/main/resources/testfile3.yang | 123 ----- .../src/test/resources/GenerateTest2/pom.xml | 125 ++--- .../resources/GenerateTest2/yang/private.yang | 19 + .../src/test/resources/Generator/pom.xml | 11 +- .../pom.xml | 21 +- .../MissingYangInDep/yang/private.yang | 19 + .../src/test/resources/NoGenerators/pom.xml | 1 + .../src/test/resources/NoOutputDir/pom.xml | 12 +- .../src/test/resources/NoYangFiles/pom.xml | 15 +- .../test/resources/UnknownGenerator/pom.xml | 15 +- .../test/resources/YangRootNotExist/pom.xml | 15 +- .../yang2sources/plugin/ConfigArg.java | 70 +-- .../controller/yang2sources/plugin/Util.java | 88 ++-- .../plugin/YangToSourcesMojo.java | 428 ++---------------- .../plugin/YangToSourcesProcessor.java | 313 +++++++++++++ .../plugin/GenerateSourcesTest.java | 74 ++- .../yang2sources/plugin/UtilTest.java | 8 +- .../src/test/resources/mock.yang | 11 + .../code-generator/maven-yang/pom.xml | 6 + .../yang2sources/spi/CodeGenerator.java | 13 +- .../yang2sources/spi/ResourceGenerator.java | 29 -- .../spi/CodeGeneratorTestImpl.java | 15 +- .../spi/ResourceProviderTestImpl.java | 21 - .../model/parser/api/YangModelParser.java | 22 +- .../yang/parser/impl/YangParserImpl.java | 104 ++++- .../yang/parser/impl/TestUtils.java | 7 +- 33 files changed, 880 insertions(+), 1175 deletions(-) rename opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/{NoGenerators_resources => AdditionalConfig}/pom.xml (57%) delete mode 100644 opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct_resources/pom.xml create mode 100644 opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/yang/private.yang rename opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/{UnknownGenerator_resources => MissingYangInDep}/pom.xml (78%) create mode 100644 opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/MissingYangInDep/yang/private.yang create mode 100644 opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesProcessor.java delete mode 100644 opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/ResourceGenerator.java delete mode 100644 opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/ResourceProviderTestImpl.java diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/controller/maven/sal/api/gen/plugin/CodeGeneratorImpl.java b/opendaylight/sal/yang-prototype/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/controller/maven/sal/api/gen/plugin/CodeGeneratorImpl.java index d1b80b3f12..1876c689c0 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/controller/maven/sal/api/gen/plugin/CodeGeneratorImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/controller/maven/sal/api/gen/plugin/CodeGeneratorImpl.java @@ -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 generateSources(SchemaContext context, - File outputBaseDir, Set yangModules) throws IOException { + File outputBaseDir, Set yangModules, File projectBaseDir) + throws IOException { final BindingGenerator bindingGenerator = new BindingGeneratorImpl(); final List 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 additionalConfiguration) { + // no additional config utilized } } diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/java/org/opendaylight/controller/yang2sources/plugin/it/YangToSourcesPluginTest.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/java/org/opendaylight/controller/yang2sources/plugin/it/YangToSourcesPluginTest.java index 267e35ab60..e77ec6c46b 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/java/org/opendaylight/controller/yang2sources/plugin/it/YangToSourcesPluginTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/java/org/opendaylight/controller/yang2sources/plugin/it/YangToSourcesPluginTest.java @@ -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"); } } diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoGenerators_resources/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/AdditionalConfig/pom.xml similarity index 57% rename from opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoGenerators_resources/pom.xml rename to opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/AdditionalConfig/pom.xml index 90220bae4f..b7baa74338 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoGenerators_resources/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/AdditionalConfig/pom.xml @@ -2,12 +2,18 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - org.opendaylight.controller - 0.5.1-SNAPSHOT - + org.opendaylight.controller + 0.5.1-SNAPSHOT test + + + org.opendaylight.controller + yang-maven-plugin-spi + 0.5.1-SNAPSHOT + + + @@ -21,22 +27,31 @@ ../files - + false + org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl - - outDir/ - + + abcd=a.b.c.d + abcd2=a.b.c.d.2 + + + + + org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl + + + config + - - - + + org.opendaylight.controller yang-maven-plugin-spi @@ -47,4 +62,4 @@ - \ No newline at end of file + diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct/pom.xml index 353416d2ac..ce9389f64b 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct/pom.xml @@ -1,62 +1,53 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - org.opendaylight.controller - 0.5.1-SNAPSHOT - test + org.opendaylight.controller + 0.5.1-SNAPSHOT + test - - - org.opendaylight.controller - yang-maven-plugin-spi - 0.5.1-SNAPSHOT - - + + + org.opendaylight.controller + yang-maven-plugin-spi + 0.5.1-SNAPSHOT + + - - - - org.opendaylight.controller - yang-maven-plugin - 0.5.1-SNAPSHOT - - - - generate-sources - - - ../files - - - - org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl - - - - - - - org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl - - - outDir/ - - - - - - + + + + org.opendaylight.controller + yang-maven-plugin + 0.5.1-SNAPSHOT + + + + generate-sources + + + ../files + false + + + + org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl + + + + + + - - - org.opendaylight.controller - yang-maven-plugin-spi - 0.5.1-SNAPSHOT - test-jar - - - - - + + + org.opendaylight.controller + yang-maven-plugin-spi + 0.5.1-SNAPSHOT + test-jar + + + + + 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 index 356f1c6386..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Correct_resources/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - 4.0.0 - - org.opendaylight.controller - 0.5.1-SNAPSHOT - - test - - - - - org.opendaylight.controller - yang-maven-plugin - 0.5.1-SNAPSHOT - - - - generate-sources - - - ../files - - - - org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl - - - outDir/ - - - - - - - - - - org.opendaylight.controller - yang-maven-plugin-spi - 0.5.1-SNAPSHOT - test-jar - - - - - - \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/pom.xml index fdef8ad595..e1591b5733 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/pom.xml @@ -1,51 +1,45 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - org.opendaylight.controller - generator-test1 - 0.5.1-SNAPSHOT + org.opendaylight.controller + generator-test1 + 0.5.1-SNAPSHOT - - - - org.opendaylight.controller - yang-maven-plugin - 0.5.1-SNAPSHOT - - - - generate-sources - - - src/main/resources - - - - org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl - - - - - - - org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl - - - - - - + + + + org.opendaylight.controller + yang-maven-plugin + 0.5.1-SNAPSHOT + + + + generate-sources + + + ${basedir}/src/main/resources + false + + + + org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl + + + + + + - - - org.opendaylight.controller - yang-maven-plugin-spi - 0.5.1-SNAPSHOT - test-jar - - - - - + + + org.opendaylight.controller + yang-maven-plugin-spi + 0.5.1-SNAPSHOT + test-jar + + + + + diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile1.yang b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile1.yang index 2f4355390b..5bf7ece91b 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile1.yang +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile1.yang @@ -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; - } - } - } diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile3.yang b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile3.yang index b203124a9f..8e5b86a880 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile3.yang +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest1/src/main/resources/testfile3.yang @@ -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."; - } - } - } - } diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/pom.xml index 2fcbd62284..b608637e6b 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/pom.xml @@ -1,68 +1,69 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - org.opendaylight.controller - 0.5.1-SNAPSHOT - generator-test2 - + org.opendaylight.controller + 0.5.1-SNAPSHOT + generator-test2 - - - org.opendaylight.controller - generator-test1 - 0.5.1-SNAPSHOT - system - ${project.basedir}/../GenerateTest1/target/generator-test1-0.5.1-SNAPSHOT.jar - - - - - - org.opendaylight.controller - yang-maven-plugin - 0.5.1-SNAPSHOT - - - - generate-sources - - - ${project.basedir} - - - - org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl - - - outDir/ - - - - - - - org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl - - - outDir/ - - - - - - + + + org.opendaylight.controller + generator-test1 + 0.5.1-SNAPSHOT + system + ${project.basedir}/../GenerateTest1/target/generator-test1-0.5.1-SNAPSHOT.jar + + - - - org.opendaylight.controller - yang-maven-plugin-spi - 0.5.1-SNAPSHOT - test-jar - - - - - + + + + org.opendaylight.controller + yang-maven-plugin + 0.5.1-SNAPSHOT + + + + generate-sources + + + ${project.basedir}/yang + true + + + + org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl + + + outDir/ + + + + + + + org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl + + + outDir/ + + + + + + + + + + org.opendaylight.controller + yang-maven-plugin-spi + 0.5.1-SNAPSHOT + test-jar + + + + + 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 index 0000000000..db346ca487 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/GenerateTest2/yang/private.yang @@ -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"; + } + + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Generator/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Generator/pom.xml index 5581882a31..c64a857c1e 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Generator/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/Generator/pom.xml @@ -21,6 +21,7 @@ ../files + false @@ -31,16 +32,6 @@ - - - - org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl - - - outDir/ - - - diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/UnknownGenerator_resources/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/MissingYangInDep/pom.xml similarity index 78% rename from opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/UnknownGenerator_resources/pom.xml rename to opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/MissingYangInDep/pom.xml index 438ef945f6..1b73c76bb7 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/UnknownGenerator_resources/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/MissingYangInDep/pom.xml @@ -2,10 +2,10 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.opendaylight.controller - 0.5.1-SNAPSHOT + org.opendaylight.controller + 0.5.1-SNAPSHOT + generator-test2 - test @@ -19,8 +19,9 @@ generate-sources - ../files - + ${project.basedir}/yang + true + org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl @@ -39,14 +40,6 @@ outDir/ - - - unknown - - - outDir/ - - @@ -63,4 +56,4 @@ - \ No newline at end of file + 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 index 0000000000..8d7227b08b --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/MissingYangInDep/yang/private.yang @@ -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"; + } + + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoGenerators/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoGenerators/pom.xml index 7d3291a304..9a43e893b5 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoGenerators/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoGenerators/pom.xml @@ -19,6 +19,7 @@ ../files + false diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoOutputDir/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoOutputDir/pom.xml index 00ddbdd344..54bace053c 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoOutputDir/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoOutputDir/pom.xml @@ -2,8 +2,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.opendaylight.controller - 0.5.1-SNAPSHOT + org.opendaylight.controller + 0.5.1-SNAPSHOT test @@ -20,6 +20,7 @@ ../files + false @@ -27,13 +28,6 @@ - - - - org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl - - - diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoYangFiles/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoYangFiles/pom.xml index 1fc7ab34d6..b2eeb6f66a 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoYangFiles/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/NoYangFiles/pom.xml @@ -2,8 +2,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.opendaylight.controller - 0.5.1-SNAPSHOT + org.opendaylight.controller + 0.5.1-SNAPSHOT test @@ -20,6 +20,7 @@ ${basedir} + false @@ -30,16 +31,6 @@ - - - - org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl - - - outDir/ - - - diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/UnknownGenerator/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/UnknownGenerator/pom.xml index 15f4322360..96a75b969c 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/UnknownGenerator/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/UnknownGenerator/pom.xml @@ -2,8 +2,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.opendaylight.controller - 0.5.1-SNAPSHOT + org.opendaylight.controller + 0.5.1-SNAPSHOT test @@ -20,6 +20,7 @@ ../files + false @@ -38,16 +39,6 @@ - - - - org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl - - - outDir/ - - - diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/YangRootNotExist/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/YangRootNotExist/pom.xml index 9986438d0b..09df6ab23d 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/YangRootNotExist/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin-it/src/test/resources/YangRootNotExist/pom.xml @@ -2,8 +2,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.opendaylight.controller - 0.5.1-SNAPSHOT + org.opendaylight.controller + 0.5.1-SNAPSHOT test @@ -20,6 +20,7 @@ unknown + false @@ -30,16 +31,6 @@ - - - - org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl - - - outDir/ - - - diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/ConfigArg.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/ConfigArg.java index 0ce985d334..aaf7080a62 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/ConfigArg.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/ConfigArg.java @@ -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 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 getAdditionalConfiguration() { + return additionalConfiguration; + } } -} \ No newline at end of file +} diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/Util.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/Util.java index acde15ef2a..653c0bff6d 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/Util.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/Util.java @@ -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> cache = Maps + private static Map> cache = Maps .newHashMapWithExpectedSize(10); /** * List files recursively and return as array of String paths. Use cache of * size 1. */ - static Collection listFiles(String rootDir) throws FileNotFoundException { - if (cache.get(rootDir) != null) - return cache.get(rootDir); + static Collection 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 yangFiles = FileUtils.listFiles(new File(rootDir), + Collection yangFiles = FileUtils.listFiles(root, new String[] { YANG_SUFFIX }, true); - toCache(rootDir, yangFiles); + toCache(root, yangFiles); return yangFiles; } - static List listFilesAsStream(String rootDir) throws FileNotFoundException { + static List listFilesAsStream(File rootDir) + throws FileNotFoundException { List is = new ArrayList(); Collection 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 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 yangFiles) { cache.put(rootDir, yangFiles); } @@ -127,18 +137,13 @@ final class Util { return String.format("%s %s", logPrefix, innerMessage); } - public static List getClassPath(MavenProject project) - throws DependencyResolutionRequiredException { + public static List getClassPath(MavenProject project) { List 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 getFilesFromClasspath( - List jarsOnClasspath, List classPathFilter) - throws ZipException, IOException { - List yangs = Lists.newArrayList(); - - for (File file : jarsOnClasspath) { - ZipFile zip = new ZipFile(file); - Enumeration 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 filter) { - for(String f : filter) { - if(name.endsWith(f)) { + for (String f : filter) { + if (name.endsWith(f)) { return true; } } diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesMojo.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesMojo.java index f8117c077e..7dbd856824 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesMojo.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesMojo.java @@ -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 * 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 yangFiles = Util - .listFilesAsStream(yangFilesRootDir); - Set yangModules = parser - .parseYangModelsFromStreams(yangFiles); - - List yangFilesFromDependencies = getFilesFromDependenciesAsStream(); - Set yangModulesFromDependencies = parser - .parseYangModelsFromStreams(yangFilesFromDependencies); - - Set parsedYang = new HashSet(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 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 thrown = Maps.newHashMap(); - - Collection yangFiles = new ArrayList(); - - // load files from yang root - yangFiles.addAll(getFilesFromYangRoot()); - - // load files from dependencies - Collection 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 getFilesFromYangRoot() { - Collection yangFilesLoaded = null; - - File rootDir = new File(yangFilesRootDir); - try { - if (rootDir.isAbsolute()) { - yangFilesLoaded = Util.listFiles(yangFilesRootDir); + List 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(); } - - Collection yangFiles = new ArrayList(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 getFilesFromDependencies() { - Collection yangFiles = new ArrayList(); - - try { - List filesOnCp = Util.getClassPath(project); - List filter = Lists.newArrayList(".yang"); - for (File file : filesOnCp) { - ZipFile zip = new ZipFile(file); - Enumeration 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 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 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 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 resources = new ArrayList(); - - /** - * Search for yang files in dependent projects. - * - * @return files found as List of InputStream - */ - private List getFilesFromDependenciesAsStream() { - final List yangsFromDependencies = new ArrayList(); - try { - List filesOnCp = Util.getClassPath(project); - - List filter = Lists.newArrayList(".yang"); - for (File file : filesOnCp) { - ZipFile zip = new ZipFile(file); - Enumeration 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 yangModules; - - private ContextHolder(SchemaContext context, - Set yangModules) { - this.context = context; - this.yangModules = yangModules; - } - - public SchemaContext getContext() { - return context; - } - - public Set 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 index 0000000000..be92af0126 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesProcessor.java @@ -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 codeGenerators; + private final MavenProject project; + private final boolean inspectDependencies; + + YangToSourcesProcessor(Log log, File yangFilesRootDir, + List 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 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 closeables = new ArrayList<>(); + log.info(Util.message("Inspecting %s", LOG_PREFIX, yangFilesRootDir)); + try { + List yangsInProject = Util + .listFilesAsStream(yangFilesRootDir); + List all = new ArrayList<>(yangsInProject); + closeables.addAll(yangsInProject); + Map allYangModules; + Set 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 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 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 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 yangStreams; + private final List zipInputStreams; + + private YangsInZipsResult(List yangStreams, + List 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 yangsFromDependencies = new ArrayList<>(); + List zips = new ArrayList<>(); + try { + List filesOnCp = Util.getClassPath(project); + log.info(Util.message( + "Searching for yang files in following dependencies: %s", + LOG_PREFIX, filesOnCp)); + + for (File file : filesOnCp) { + List 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 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 yangModules; + + private ContextHolder(SchemaContext context, Set yangModules) { + this.context = context; + this.yangModules = yangModules; + } + + public SchemaContext getContext() { + return context; + } + + public Set getYangModules() { + return yangModules; + } + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/GenerateSourcesTest.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/GenerateSourcesTest.java index 2ded61426b..1bfe9d4d0c 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/GenerateSourcesTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/GenerateSourcesTest.java @@ -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 additionalCfg; @Override public Collection generateSources(SchemaContext context, - File baseDir, Set yangModules) { + File outputBaseDir, Set 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 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 resources, - File outputDir) { - called++; - baseDir = outputDir; + public void setAdditionalConfig( + Map additionalConfiguration) { + this.additionalCfg = additionalConfiguration; } } + } diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/UtilTest.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/UtilTest.java index 75e50f0261..96a4d57a00 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/UtilTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/java/org/opendaylight/controller/yang2sources/plugin/UtilTest.java @@ -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 files = Util.listFiles(yang); - Collection files2 = Util.listFiles(yang); + Collection files = Util.listFiles(new File(yang)); + Collection files2 = Util.listFiles(new File(yang)); assertTrue(files == files2); } diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/resources/mock.yang b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/resources/mock.yang index e69de29bb2..72e4d2c4d8 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/resources/mock.yang +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/test/resources/mock.yang @@ -0,0 +1,11 @@ + module mock { + + namespace "a:b:c"; + prefix "m"; + + revision 2010-09-24 { + description + "Initial revision."; + } + + } diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang/pom.xml b/opendaylight/sal/yang-prototype/code-generator/maven-yang/pom.xml index ca7a320247..9c4475cd40 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang/pom.xml @@ -13,6 +13,12 @@ org.opendaylight.controller yang-model-api + + + org.apache.maven + maven-plugin-api + 3.0.5 + diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/CodeGenerator.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/CodeGenerator.java index 14bcccccaf..df33d4c591 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/CodeGenerator.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/CodeGenerator.java @@ -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 generateSources(SchemaContext context, File outputBaseDir, - Set yangModules) throws IOException; + Set currentModules, File projectBaseDir) + throws IOException; + + void setLog(Log log); + + void setAdditionalConfig(Map 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 index 2638dc33b0..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/main/java/org/opendaylight/controller/yang2sources/spi/ResourceGenerator.java +++ /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 resources, File outputBaseDir); -} diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/CodeGeneratorTestImpl.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/CodeGeneratorTestImpl.java index 60496277b8..172a2f25b6 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/CodeGeneratorTestImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/CodeGeneratorTestImpl.java @@ -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 generateSources(SchemaContext context, - File outputBaseDir, Set yangModules) { + File outputBaseDir, Set currentModuleBuilders, + File projectMainDir) { // no-op return null; } + @Override + public void setLog(Log log) { + // no-op + } + + @Override + public void setAdditionalConfig(Map 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 index dc521841ef..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang/src/test/java/org/opendaylight/controller/yang2sources/spi/ResourceProviderTestImpl.java +++ /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 resources, - File outputBaseDir) { - // no-op - } - -} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-api/src/main/java/org/opendaylight/controller/yang/model/parser/api/YangModelParser.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-api/src/main/java/org/opendaylight/controller/yang/model/parser/api/YangModelParser.java index 953cd436cb..842bb43d79 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-api/src/main/java/org/opendaylight/controller/yang/model/parser/api/YangModelParser.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-api/src/main/java/org/opendaylight/controller/yang/model/parser/api/YangModelParser.java @@ -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 parseYangModels(final List yangFiles); - - public Set parseYangModelsFromStreams( + Set parseYangModels(final List 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 parseYangModelsMapped(final List yangFiles); + + Set parseYangModelsFromStreams( + final List yangModelStreams); + + Map parseYangModelsFromStreamsMapped( final List 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 modules); + SchemaContext resolveSchemaContext(final Set modules); } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java index ac2b5334fb..25af3ebae5 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java @@ -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 parseYangModels(final List yangFiles) { + public Map parseYangModelsMapped(List yangFiles) { if (yangFiles != null) { - final List inputStreams = new ArrayList(); + final Map 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> modules = resolveModuleBuilders(inputStreams); - return build(modules); + + Map builderToStreamMap = Maps + .newHashMap(); + + final Map> modules = resolveModuleBuilders( + Lists.newArrayList(inputStreams.keySet()), + builderToStreamMap); + // return new LinkedHashSet(build(modules).values()); + + Map retVal = Maps.newLinkedHashMap(); + Map builderToModuleMap = build(modules); + + for (Entry builderToModule : builderToModuleMap + .entrySet()) { + retVal.put(inputStreams.get(builderToStreamMap + .get(builderToModule.getKey())), builderToModule + .getValue()); + } + + return retVal; } - return Collections.emptySet(); + return Collections.emptyMap(); + } + + @Override + public Set parseYangModels(final List yangFiles) { + return Sets.newLinkedHashSet(parseYangModelsMapped(yangFiles).values()); } @Override public Set parseYangModelsFromStreams( final List yangModelStreams) { - final Map> modules = resolveModuleBuilders(yangModelStreams); - return build(modules); + return Sets.newHashSet(parseYangModelsFromStreamsMapped( + yangModelStreams).values()); + } + + @Override + public Map parseYangModelsFromStreamsMapped( + final List yangModelStreams) { + Map builderToStreamMap = Maps.newHashMap(); + + final Map> modules = resolveModuleBuilders( + yangModelStreams, builderToStreamMap); + Map retVal = Maps.newLinkedHashMap(); + Map builderToModuleMap = build(modules); + + for (Entry 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> resolveModuleBuilders( - final List yangFileStreams) { - // Linked Hash Map MUST be used because Linked Hash Map preserves ORDER - // of items stored in map. - final Map> modules = new LinkedHashMap>(); + private ModuleBuilder[] parseModuleBuilders(List inputStreams, + Map streamToBuilderMap) { + final ParseTreeWalker walker = new ParseTreeWalker(); - final List trees = parseStreams(yangFileStreams); + final List 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> resolveModuleBuilders( + final List yangFileStreams, + Map 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> modules = new LinkedHashMap>(); // module dependency graph sorted List sorted = ModuleDependencySort.sort(builders); @@ -178,7 +238,7 @@ public final class YangParserImpl implements YangModelParser { return result; } - private Set build( + private Map build( final Map> modules) { // fix unresolved nodes for (Map.Entry> 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 result = new LinkedHashSet(); + // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html + final Map result = new LinkedHashMap(); for (Map.Entry> entry : modules .entrySet()) { final Map modulesByRevision = new HashMap(); @@ -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 { diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TestUtils.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TestUtils.java index 3d9df349e4..d14c54219e 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TestUtils.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TestUtils.java @@ -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 modules = parser.parseYangModelsFromStreams(input); + Set modules = new HashSet( + 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 input = Collections.singletonList(stream); - Set modules = parser.parseYangModelsFromStreams(input); + Set modules = new HashSet( + parser.parseYangModelsFromStreams(input)); stream.close(); return modules.iterator().next(); } -- 2.36.6