verifyCorrectLog(v);
}
+ @Test
+ public void testFindResourceOnCp() throws VerificationException {
+ Verifier v1 = new Verifier(new File("src/test/resources/GenerateTest1/").getAbsolutePath());
+ v1.executeGoal("package");
+ v1.assertFilePresent("target/external-resources/testfile1.yang");
+ v1.assertFilePresent("target/external-resources/testfile2.yang");
+ v1.assertFilePresent("target/external-resources/testfile3.yang");
+
+ Verifier v2 = YangToSourcesPluginTest.setUp("GenerateTest2/",
+ false);
+ v2.executeGoal("package");
+ }
+
}
--- /dev/null
+<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>
+ <artifactId>generator-test1</artifactId>
+ <version>0.5-SNAPSHOT</version>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5-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>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+module types1 {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ import types2 {
+ prefix "data";
+ revision-date 2013-02-27;
+ }
+
+ import types3 {
+ prefix "t3";
+ revision-date 2013-02-27;
+ }
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+
+ revision "2013-02-27" {
+ 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;
+ }
+ }
+
+}
--- /dev/null
+module types2 {
+ yang-version 1;
+ namespace "urn:simple.types.data.demo";
+ prefix "t2";
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+
+ description "This is types-data test description";
+
+ revision "2013-02-27" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+ typedef my-base-int32-type {
+ type int32 {
+ range "2..20";
+ }
+ }
+
+ typedef my-type1 {
+ type my-base-int32-type {
+ range "11..max";
+ }
+ units "mile";
+ default "11";
+ }
+
+ typedef my-custom-string {
+ type string {
+ pattern "[a-k]*";
+ length "5..11";
+ }
+ }
+
+ typedef my-string-type {
+ type my-custom-string {
+ length "5..10";
+ }
+ }
+
+ typedef my-string-type2 {
+ type my-string-type {
+ pattern "[b-u]*";
+ }
+ }
+
+ typedef my-string-type-ext {
+ type my-string-type2 {
+ pattern "[e-z]*";
+ }
+ }
+
+ typedef my-int-type {
+ type int32 {
+ range "10..20";
+ }
+ }
+
+ typedef my-int-type2 {
+ type my-int-type {
+ range "12..18";
+ }
+ }
+
+ typedef my-int-type-ext {
+ type my-int-type2 {
+ range "14..16";
+ }
+ }
+
+ typedef my-decimal-type {
+ type decimal64 {
+ fraction-digits 6;
+ }
+ }
+
+ typedef my-decimal-type-ext {
+ type decimal64 {
+ fraction-digits 5;
+ }
+ }
+
+ typedef my-union {
+ type union {
+ type int16 {
+ range "1..100";
+ }
+ type int32;
+ }
+ }
+
+ typedef my-union-ext {
+ type my-union;
+ }
+
+ typedef nested-union1 {
+ type nested-union2;
+ }
+
+ typedef nested-union2 {
+ type union {
+ type my-union-ext;
+ type string;
+ }
+ }
+
+ leaf if-name {
+ type leafref {
+ path "/interface/name";
+ }
+ }
+
+ leaf name {
+ type string;
+ }
+
+ leaf nested-type-leaf {
+ type my-type1;
+ }
+
+ extension c-define {
+ description
+ "Takes as argument a name string.
+ Makes the code generator use the given name in the
+ #define.";
+ argument "name" {
+ yin-element "true";
+ }
+ }
+
+ container system {
+ leaf user {
+ type string;
+ }
+ }
+
+ grouping target {
+ leaf address {
+ type string;
+ description "Target IP address";
+ }
+ container port {
+ description "Target port container";
+ }
+ }
+
+ container peer {
+ container destination {
+ uses target {
+ refine address {
+ default "1.2.3.4";
+ }
+ refine port {
+ must "must-condition" {
+ error-message "An error message test";
+ error-app-tag "An error app tag test";
+ }
+ }
+ }
+ }
+ }
+
+ container interfaces {
+ list ifEntry {
+ key "ifIndex";
+
+ leaf ifIndex {
+ type uint32;
+ units minutes;
+ }
+
+ leaf ifMtu {
+ type int32;
+ }
+ }
+ }
+
+}
--- /dev/null
+module types3 {
+ yang-version 1;
+ namespace "urn:simple.container.demo.test";
+ prefix "t3";
+
+ 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";
+ }
+
+ 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.";
+ }
+ }
+ }
+
+}
--- /dev/null
+<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>
+ <artifactId>generator-test2</artifactId>
+ <version>0.5-SNAPSHOT</version>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>generator-test1</artifactId>
+ <version>0.5-SNAPSHOT</version>
+ <scope>system</scope>
+ <systemPath>${project.basedir}/../GenerateTest1/target/generator-test1-0.5-SNAPSHOT.jar</systemPath>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5-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>yang-maven-plugin-spi</artifactId>
+ <version>0.5-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
File file = new File(rootDir);
if(!file.exists()) {
- throw new FileNotFoundException();
+ throw new FileNotFoundException(rootDir);
}
Collection<File> yangFiles = FileUtils.listFiles(new File(rootDir),
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
@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/yangs/";
+ private static final String INPUT_RESOURCE_DIR = "META-INF/yang/";
private static final String OUTPUT_RESOURCE_DIR = "/target/external-resources/";
/**
if (yangFiles.isEmpty()) {
getLog().warn(
- Util.message("No %s file found in %s", LOG_PREFIX,
- Util.YANG_SUFFIX, yangFilesRootDir));
+ Util.message(
+ "No %s file found in %s or in dependencies",
+ LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir));
return null;
}
yangFiles.addAll(getFilesFromYangRoot());
// load files from dependencies
- yangFiles.addAll(getFilesFromDependencies());
-
+ Collection<File> filesFromDependencies = getFilesFromDependencies();
+ yangFiles.addAll(filesFromDependencies);
for (ResourceProviderArg resourceProvider : resourceProviders) {
try {
File rootDir = new File(yangFilesRootDir);
try {
- if(!rootDir.isAbsolute()) {
- yangFilesLoaded = Util.listFiles(project.getBasedir().getAbsolutePath() + yangFilesRootDir);
- } else {
+ if (rootDir.isAbsolute()) {
yangFilesLoaded = Util.listFiles(yangFilesRootDir);
+ } else {
+ String path = project.getBasedir().getAbsolutePath()
+ + File.separator + yangFilesRootDir;
+ yangFilesLoaded = Util.listFiles(path);
}
-
- } catch(FileNotFoundException e) {
- getLog().warn("Directory '" + yangFilesRootDir + "' does not exists.");
+ } 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) {
+ for (File yangFile : yangFilesLoaded) {
InputStream is = new FileInputStream(yangFile);
- yangFiles.add(createFileFromStream(is, project.getBasedir().getAbsolutePath() + OUTPUT_RESOURCE_DIR + yangFile.getName()));
+ yangFiles.add(createFileFromStream(is,
+ project.getBasedir().getAbsolutePath()
+ + OUTPUT_RESOURCE_DIR + yangFile.getName()));
resources.add(is);
}
- } catch(IOException e) {
+ } catch (IOException e) {
getLog().warn("Exception while loading yang files.", e);
}
return yangFiles;
continue;
}
InputStream entryStream = zip.getInputStream(entry);
- String newEntryName = entryName.substring(INPUT_RESOURCE_DIR.length());
- File f = createFileFromStream(entryStream, project.getBasedir().getAbsolutePath() + OUTPUT_RESOURCE_DIR + newEntryName);
+ 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);
return yangFiles;
}
- private File createFileFromStream(InputStream is, String absoluteName) throws IOException {
+ private File createFileFromStream(InputStream is, String absoluteName)
+ throws IOException {
File f = new File(absoluteName);
- if(!f.exists()) {
+ if (!f.exists()) {
f.getParentFile().mkdirs();
}
f.createNewFile();
ZipEntry entry = entries.nextElement();
String entryName = entry.getName();
- if(entryName.startsWith(INPUT_RESOURCE_DIR)) {
- if(entry.isDirectory()) {
+ if (entryName.startsWith(INPUT_RESOURCE_DIR)) {
+ if (entry.isDirectory()) {
continue;
}
if (!Util.acceptedFilter(entryName, filter)) {
try {
resource.close();
} catch (IOException e) {
- getLog().warn("Failed to close resources: "+ resource, e);
+ getLog().warn("Failed to close resources: " + resource, e);
}
}
}