Moved code-generator/maven-yang -> yang/.
Moved code-generator/maven-yang-plugin -> yang/.
Moved code-generator/maven-yang-plugin-it -> yang/.
Moved code-generator/yang-model-parser-api -> yang/.
Moved code-generator/yang-model-parser-impl -> yang/.
Configured site plugin for project. Fixed some javadocs.
Fixed bug in ParserUtils causing NullPointerException.
Fixed bug in resolving uses statement.
Improved tests.
Change-Id: Ia7567544fbe006f0cf87055c6633c04b5ce2c50e
Signed-off-by: Martin Vitez <mvitez@cisco.com>
--- /dev/null
+log.txt
+/target
--- /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>
+ <parent>
+ <artifactId>yang</artifactId>
+ <groupId>org.opendaylight.controller</groupId>
+ <version>0.5.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>yang-maven-plugin-it</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-verifier</artifactId>
+ <version>1.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>integration-test</goal>
+ <goal>verify</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+/*
+ * 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.it;
+
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.*;
+
+import java.io.File;
+import java.net.URL;
+
+import org.apache.maven.it.VerificationException;
+import org.apache.maven.it.Verifier;
+import org.junit.Test;
+
+public class YangToSourcesPluginTestIT {
+
+ // 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 ");
+ assertVerificationException(
+ e,
+ "Caused by: org.apache.maven.plugin.MojoExecutionException: yang-to-sources: Unable to parse yang files from ");
+ return;
+ }
+
+ fail("Verification exception should have been thrown");
+ }
+
+ @Test
+ 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("[DEBUG] 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("[DEBUG] yang-to-sources: Additional configuration picked up for : org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl: {c1=config}");
+ v.verifyTextInLog(File.separator
+ + "files marked as resources: META-INF/yang");
+ v.verifyTextInLog("target"
+ + File.separator
+ + "generated-resources marked as resources for generator: org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl");
+ }
+
+ @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: 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");
+ }
+
+ @Test
+ public void testNoGenerators() throws VerificationException {
+ Verifier v = setUp("NoGenerators/", false);
+ v.verifyErrorFreeLog();
+ v.verifyTextInLog("[WARNING] yang-to-sources: No code generators provided");
+ }
+
+ @Test
+ public void testUnknownGenerator() throws VerificationException {
+ Verifier v = setUp("UnknownGenerator/", true);
+ v.verifyTextInLog("[ERROR] yang-to-sources: Unable to generate sources with unknown generator");
+ v.verifyTextInLog("java.lang.ClassNotFoundException: unknown");
+ 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("[ERROR] yang-to-sources: One or more code generators failed, including failed list(generatorClass=exception) {unknown=java.lang.ClassNotFoundException}");
+ }
+
+ @Test
+ public void testNoYangFiles() throws VerificationException {
+ Verifier v = setUp("NoYangFiles/", false);
+ 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");
+ }
+
+ static void assertVerificationException(VerificationException e,
+ String string) {
+ assertThat(e.getMessage(), containsString(string));
+ }
+
+ static Verifier setUp(String project, boolean ignoreF)
+ throws VerificationException {
+ final URL path = YangToSourcesPluginTestIT.class.getResource("/"
+ + project + "pom.xml");
+ File parent = new File(path.getPath());
+ Verifier verifier = new Verifier(parent.getParent());
+ if (ignoreF)
+ verifier.addCliOption("-fn");
+ verifier.setMavenDebug(true);
+ verifier.executeGoal("generate-sources");
+ return verifier;
+ }
+
+ @Test
+ public void testNoOutputDir() throws VerificationException {
+ Verifier v = YangToSourcesPluginTestIT.setUp("NoOutputDir/", false);
+ verifyCorrectLog(v);
+ }
+
+ @Test
+ public void testFindResourceOnCp() throws VerificationException {
+ Verifier v1 = new Verifier(new File(getClass().getResource(
+ "/GenerateTest1/pom.xml").getPath()).getParent());
+ v1.executeGoal("clean");
+ v1.executeGoal("package");
+ 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 = YangToSourcesPluginTestIT.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");
+ }
+}
--- /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>
+ <version>0.5.4-SNAPSHOT</version>
+ <artifactId>test</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>../files</yangFilesRootDir>
+ <inspectDependencies>false</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ <additionalConfiguration>
+ <nm1>abcd=a.b.c.d</nm1>
+ <nm2>abcd2=a.b.c.d.2</nm2>
+ </additionalConfiguration>
+ <resourceBaseDir>/target/resourcesGenerated</resourceBaseDir>
+ </generator>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ <additionalConfiguration>
+ <c1>config</c1>
+ </additionalConfiguration>
+ </generator>
+ </codeGenerators>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /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>
+ <version>0.5.4-SNAPSHOT</version>
+ <artifactId>test</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>../files</yangFilesRootDir>
+ <inspectDependencies>false</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ </generator>
+ </codeGenerators>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /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.4-SNAPSHOT</version>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>${basedir}/src/main/resources</yangFilesRootDir>
+ <inspectDependencies>false</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ </generator>
+ </codeGenerators>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-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";
+ }
+
+}
--- /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 {
+ description "new port description updated by refine";
+ }
+ }
+ }
+ }
+
+ 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";
+ }
+
+}
--- /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>
+ <version>0.5.4-SNAPSHOT</version>
+ <artifactId>generator-test2</artifactId>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>generator-test1</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <scope>system</scope>
+ <systemPath>${project.basedir}/../GenerateTest1/target/generator-test1-0.5.4-SNAPSHOT.jar</systemPath>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>${project.basedir}/yang</yangFilesRootDir>
+ <inspectDependencies>true</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ <outputBaseDir>
+ outDir/
+ </outputBaseDir>
+ </generator>
+ </codeGenerators>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+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";
+ }
+
+
+}
--- /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>
+ <parent>
+ <artifactId>binding-generator</artifactId>
+ <groupId>org.opendaylight.controller</groupId>
+ <version>0.5.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>test</artifactId>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>../files</yangFilesRootDir>
+ <inspectDependencies>false</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ <outputBaseDir>
+ outDir/
+ </outputBaseDir>
+ </generator>
+ </codeGenerators>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /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>
+ <version>0.5.4-SNAPSHOT</version>
+ <artifactId>generator-test2</artifactId>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>${project.basedir}/yang</yangFilesRootDir>
+ <inspectDependencies>true</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ <outputBaseDir>
+ outDir/
+ </outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <resourceProviders>
+ <provider>
+ <resourceProviderClass>
+ org.opendaylight.controller.yang2sources.spi.ResourceProviderTestImpl
+ </resourceProviderClass>
+ <outputBaseDir>
+ outDir/
+ </outputBaseDir>
+ </provider>
+ </resourceProviders>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+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";
+ }
+
+
+}
--- /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>
+ <version>0.5.4-SNAPSHOT</version>
+ <artifactId>test</artifactId>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>../files</yangFilesRootDir>
+ <inspectDependencies>false</inspectDependencies>
+ <codeGenerators>
+ </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.4-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /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>
+ <version>0.5.4-SNAPSHOT</version>
+
+ <artifactId>test</artifactId>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>../files</yangFilesRootDir>
+ <inspectDependencies>false</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ </generator>
+ </codeGenerators>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /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>
+ <version>0.5.4-SNAPSHOT</version>
+
+ <artifactId>test</artifactId>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>${basedir}</yangFilesRootDir>
+ <inspectDependencies>false</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ <outputBaseDir>
+ /outDir/
+ </outputBaseDir>
+ </generator>
+ </codeGenerators>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /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>
+ <version>0.5.4-SNAPSHOT</version>
+
+ <artifactId>test</artifactId>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>../files</yangFilesRootDir>
+ <inspectDependencies>false</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ <outputBaseDir>
+ /outDir/
+ </outputBaseDir>
+ </generator>
+ <generator>
+ <codeGeneratorClass>
+ unknown
+ </codeGeneratorClass>
+ <outputBaseDir>
+ /outDir/
+ </outputBaseDir>
+ </generator>
+ </codeGenerators>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /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>
+ <version>0.5.4-SNAPSHOT</version>
+
+ <artifactId>test</artifactId>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>unknown</yangFilesRootDir>
+ <inspectDependencies>false</inspectDependencies>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
+ </codeGeneratorClass>
+ <outputBaseDir>
+ /outDir/
+ </outputBaseDir>
+ </generator>
+ </codeGenerators>
+ </configuration>
+ </execution>
+ </executions>
+ </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";
+ }
+
+}
--- /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";
+ }
+
+}
--- /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";
+ }
+
+}
--- /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>
+ <parent>
+ <artifactId>yang</artifactId>
+ <groupId>org.opendaylight.controller</groupId>
+ <version>0.5.4-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>yang-maven-plugin</artifactId>
+ <packaging>maven-plugin</packaging>
+ <description>
+ This plugin is a wrapper for "yang to source code" generation.
+ It can be configured by a set of third-party code generators and resource providers.
+ For further info see available goals.
+ Sample usage:
+
+ TODO: add sample usage when finished
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>3.0.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>3.0.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-annotations</artifactId>
+ <version>3.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>2.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>yang-model-parser-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.8.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>3.2</version>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>3.2</version>
+ <configuration>
+ <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+ </configuration>
+ <executions>
+ <execution>
+ <id>mojo-descriptor</id>
+ <goals>
+ <goal>descriptor</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
--- /dev/null
+/*
+ * 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.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 {
+
+ private final File outputBaseDir;
+
+ public ConfigArg(String outputBaseDir) {
+ this.outputBaseDir = outputBaseDir == null ? null : new File(outputBaseDir);
+ }
+
+ public File getOutputBaseDir(MavenProject project) {
+ if (outputBaseDir == null) {
+ return null;
+ }
+ if (outputBaseDir.isAbsolute()) {
+ return outputBaseDir;
+ } else {
+ return new File(project.getBasedir(), outputBaseDir.getPath());
+ }
+ }
+
+ public abstract void check();
+
+ /**
+ * Configuration argument for code generator class and output directory.
+ */
+ public static final class CodeGeneratorArg extends ConfigArg {
+ private static final String CODE_GEN_DEFAULT_RESOURCE_DIR = "target" + File.separator + "generated-resources";
+
+ private String codeGeneratorClass;
+ private File resourceBaseDir = new File(CODE_GEN_DEFAULT_RESOURCE_DIR);
+
+ private Map<String, String> additionalConfiguration = Maps.newHashMap();
+
+ public CodeGeneratorArg() {
+ super(null);
+ }
+
+ public CodeGeneratorArg(String codeGeneratorClass) {
+ this(codeGeneratorClass, null);
+ }
+
+ public CodeGeneratorArg(String codeGeneratorClass, String outputBaseDir) {
+ super(outputBaseDir);
+ this.codeGeneratorClass = codeGeneratorClass;
+ }
+
+ public CodeGeneratorArg(String codeGeneratorClass, String outputBaseDir, String resourceBaseDir) {
+ super(outputBaseDir);
+ this.codeGeneratorClass = codeGeneratorClass;
+ this.resourceBaseDir = new File(resourceBaseDir);
+ }
+
+ @Override
+ public void check() {
+ Preconditions.checkNotNull(codeGeneratorClass, "codeGeneratorClass for CodeGenerator cannot be null");
+ }
+
+ public String getCodeGeneratorClass() {
+ return codeGeneratorClass;
+ }
+
+ public File getResourceBaseDir(MavenProject project) {
+ if (resourceBaseDir.isAbsolute()) {
+ return resourceBaseDir;
+ } else {
+ return new File(project.getBasedir(), resourceBaseDir.getPath());
+ }
+ }
+
+ public Map<String, String> getAdditionalConfiguration() {
+ return additionalConfiguration;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+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.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+final class Util {
+ static final String YANG_SUFFIX = "yang";
+
+ // Cache for listed directories and found yang files. Typically yang files
+ // are utilized twice. First: code is generated during generate-sources
+ // 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<File, Collection<File>> cache = Maps
+ .newHashMapWithExpectedSize(10);
+
+ /**
+ * List files recursively and return as array of String paths. Use cache of
+ * size 1.
+ */
+ static Collection<File> listFiles(File root) throws FileNotFoundException {
+ if (cache.get(root) != null)
+ return cache.get(root);
+
+ if (!root.exists()) {
+ throw new FileNotFoundException(root.toString());
+ }
+
+ Collection<File> yangFiles = FileUtils.listFiles(root,
+ new String[] { YANG_SUFFIX }, true);
+
+ toCache(root, yangFiles);
+ return yangFiles;
+ }
+
+ static List<InputStream> listFilesAsStream(File rootDir)
+ throws FileNotFoundException {
+ List<InputStream> is = new ArrayList<InputStream>();
+
+ Collection<File> files = listFiles(rootDir);
+ for (File f : files) {
+ is.add(new NamedFileInputStream(f));
+ }
+
+ return is;
+ }
+
+ static class NamedFileInputStream extends FileInputStream {
+ private final File file;
+
+ NamedFileInputStream(File file) throws FileNotFoundException {
+ super(file);
+ this.file = file;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" + file + "}";
+ }
+ }
+
+ private static void toCache(final File rootDir,
+ final Collection<File> yangFiles) {
+ cache.put(rootDir, yangFiles);
+ }
+
+ /**
+ * Instantiate object from fully qualified class name
+ */
+ static <T> T getInstance(String codeGeneratorClass, Class<T> baseType)
+ throws ClassNotFoundException, InstantiationException,
+ IllegalAccessException {
+ return baseType.cast(resolveClass(codeGeneratorClass, baseType)
+ .newInstance());
+ }
+
+ private static Class<?> resolveClass(String codeGeneratorClass,
+ Class<?> baseType) throws ClassNotFoundException {
+ Class<?> clazz = Class.forName(codeGeneratorClass);
+
+ if (!isImplemented(baseType, clazz))
+ throw new IllegalArgumentException("Code generator " + clazz
+ + " has to implement " + baseType);
+ return clazz;
+ }
+
+ private static boolean isImplemented(Class<?> expectedIface,
+ Class<?> byClazz) {
+ for (Class<?> iface : byClazz.getInterfaces()) {
+ if (iface.equals(expectedIface))
+ return true;
+ }
+ return false;
+ }
+
+ static String message(String message, String logPrefix, Object... args) {
+ String innerMessage = String.format(message, args);
+ return String.format("%s %s", logPrefix, innerMessage);
+ }
+
+ static List<File> getClassPath(MavenProject project) {
+ List<File> dependencies = Lists.newArrayList();
+ for (Artifact element : project.getArtifacts()) {
+ File asFile = element.getFile();
+ if (isJar(asFile) || asFile.isDirectory()) {
+ dependencies.add(asFile);
+ }
+ }
+ return dependencies;
+ }
+
+ private static final String JAR_SUFFIX = ".jar";
+
+ private static boolean isJar(File element) {
+ return (element.isFile() && element.getName().endsWith(JAR_SUFFIX)) ? true
+ : false;
+ }
+
+ static <T> T checkNotNull(T obj, String paramName) {
+ return Preconditions.checkNotNull(obj, "Parameter " + paramName
+ + " is null");
+ }
+
+ final static class YangsInZipsResult implements Closeable {
+ final List<InputStream> yangStreams;
+ private final List<Closeable> zipInputStreams;
+
+ private YangsInZipsResult(List<InputStream> yangStreams,
+ List<Closeable> zipInputStreams) {
+ this.yangStreams = yangStreams;
+ this.zipInputStreams = zipInputStreams;
+ }
+
+ @Override
+ public void close() throws IOException {
+ for (InputStream is : yangStreams) {
+ is.close();
+ }
+ for (Closeable is : zipInputStreams) {
+ is.close();
+ }
+ }
+ }
+
+ static YangsInZipsResult findYangFilesInDependenciesAsStream(Log log,
+ MavenProject project)
+ throws MojoFailureException {
+ List<InputStream> yangsFromDependencies = new ArrayList<>();
+ List<Closeable> zips = new ArrayList<>();
+ try {
+ List<File> filesOnCp = Util.getClassPath(project);
+ log.info(Util.message(
+ "Searching for yang files in following dependencies: %s",
+ YangToSourcesProcessor.LOG_PREFIX, filesOnCp));
+
+ for (File file : filesOnCp) {
+ List<String> foundFilesForReporting = new ArrayList<>();
+ // is it jar file or directory?
+ if (file.isDirectory()) {
+ File yangDir = new File(file,
+ YangToSourcesProcessor.META_INF_YANG_STRING);
+ if (yangDir.exists() && yangDir.isDirectory()) {
+ File[] yangFiles = yangDir
+ .listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".yang")
+ && new File(dir, name).isFile();
+ }
+ });
+ for (File yangFile : yangFiles) {
+ yangsFromDependencies.add(new NamedFileInputStream(
+ yangFile));
+ }
+ }
+
+ } else {
+ ZipFile zip = new ZipFile(file);
+ zips.add(zip);
+
+ Enumeration<? extends ZipEntry> entries = zip.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ String entryName = entry.getName();
+
+ if (entryName
+ .startsWith(YangToSourcesProcessor.META_INF_YANG_STRING_JAR)) {
+ 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",
+ YangToSourcesProcessor.LOG_PREFIX,
+ foundFilesForReporting.size(), file,
+ foundFilesForReporting));
+ }
+
+ }
+ } catch (Exception e) {
+ throw new MojoFailureException(e.getMessage(), e);
+ }
+ return new YangsInZipsResult(yangsFromDependencies, zips);
+ }
+
+ final static class ContextHolder {
+ private final SchemaContext context;
+ private final Set<Module> yangModules;
+
+ ContextHolder(SchemaContext context, Set<Module> yangModules) {
+ this.context = context;
+ this.yangModules = yangModules;
+ }
+
+ SchemaContext getContext() {
+ return context;
+ }
+
+ Set<Module> getYangModules() {
+ return yangModules;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+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.SchemaContext;
+import org.opendaylight.controller.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
+import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Generate sources from yang files using user provided set of
+ * {@link CodeGenerator}s. Steps of this process:
+ * <ol>
+ * <li>List yang files from {@link #yangFilesRootDir}</li>
+ * <li>Process yang files using {@link YangModelParserImpl}</li>
+ * <li>For each {@link CodeGenerator} from {@link #codeGenerators}:</li>
+ * <ol>
+ * <li>Instantiate using default constructor</li>
+ * <li>Call {@link CodeGenerator#generateSources(SchemaContext, File)}</li>
+ * </ol>
+ * </ol>
+ */
+@Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true)
+public final class YangToSourcesMojo extends AbstractMojo {
+
+ /**
+ * Classes implementing {@link CodeGenerator} interface. An instance will be
+ * created out of every class using default constructor. Method {@link
+ * CodeGenerator#generateSources(SchemaContext, File, Set<String>
+ * yangModulesNames)} will be called on every instance.
+ */
+ @Parameter(required = false)
+ private CodeGeneratorArg[] codeGenerators;
+
+ /**
+ * Source directory that will be recursively searched for yang files (ending
+ * with .yang suffix).
+ */
+ @Parameter(required = false)
+ private String yangFilesRootDir; // defaults to ${basedir}/src/main/yang
+
+ @Parameter(property = "project", required = true, readonly = true)
+ protected MavenProject project;
+
+ @Parameter(property = "inspectDependencies", required = true, readonly = true)
+ private boolean inspectDependencies;
+
+ private YangToSourcesProcessor yangToSourcesProcessor;
+
+ public YangToSourcesMojo() {
+
+ }
+
+ @VisibleForTesting
+ YangToSourcesMojo(YangToSourcesProcessor processor) {
+ this.yangToSourcesProcessor = processor;
+ }
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ if (yangToSourcesProcessor == null) {
+ List<CodeGeneratorArg> codeGeneratorArgs = processCodeGenerators(codeGenerators);
+
+ // defaults to ${basedir}/src/main/yang
+ File yangFilesRootFile = processYangFilesRootDir(yangFilesRootDir,
+ project.getBasedir());
+
+ yangToSourcesProcessor = new YangToSourcesProcessor(getLog(),
+ yangFilesRootFile, codeGeneratorArgs, project,
+ inspectDependencies);
+ }
+ yangToSourcesProcessor.execute();
+ }
+
+ private static List<CodeGeneratorArg> processCodeGenerators(
+ CodeGeneratorArg[] codeGenerators) {
+ List<CodeGeneratorArg> codeGeneratorArgs;
+ if (codeGenerators == null) {
+ codeGeneratorArgs = Collections.emptyList();
+ } else {
+ codeGeneratorArgs = Arrays.asList(codeGenerators);
+ }
+ return codeGeneratorArgs;
+ }
+
+ private static File processYangFilesRootDir(String yangFilesRootDir,
+ File baseDir) {
+ File yangFilesRootFile;
+ if (yangFilesRootDir == null) {
+ yangFilesRootFile = new File(baseDir, "src" + File.separator
+ + "main" + File.separator + "yang");
+ } else {
+ File file = new File(yangFilesRootDir);
+ if (file.isAbsolute()) {
+ yangFilesRootFile = file;
+ } else {
+ yangFilesRootFile = new File(baseDir, file.getPath());
+ }
+ }
+ return yangFilesRootFile;
+ }
+}
--- /dev/null
+/*
+ * 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.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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.ContextHolder;
+import org.opendaylight.controller.yang2sources.plugin.Util.YangsInZipsResult;
+import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Maps;
+
+class YangToSourcesProcessor {
+ static final String LOG_PREFIX = "yang-to-sources:";
+ static final String META_INF_YANG_STRING = "META-INF" + File.separator
+ + "yang";
+ static final String META_INF_YANG_STRING_JAR = "META-INF" + "/" + "yang";
+ static final File META_INF_YANG_DIR = new File(META_INF_YANG_STRING);
+
+ private final Log log;
+ private final File yangFilesRootDir;
+ private final List<CodeGeneratorArg> codeGenerators;
+ private final MavenProject project;
+ private final boolean inspectDependencies;
+ private YangProvider yangProvider;
+
+ @VisibleForTesting
+ YangToSourcesProcessor(Log log, File yangFilesRootDir,
+ List<CodeGeneratorArg> codeGenerators, MavenProject project,
+ boolean inspectDependencies, YangProvider yangProvider) {
+ this.log = Util.checkNotNull(log, "log");
+ this.yangFilesRootDir = Util.checkNotNull(yangFilesRootDir,
+ "yangFilesRootDir");
+ this.codeGenerators = Collections.unmodifiableList(Util.checkNotNull(
+ codeGenerators, "codeGenerators"));
+ this.project = Util.checkNotNull(project, "project");
+ this.inspectDependencies = inspectDependencies;
+ this.yangProvider = yangProvider;
+ }
+
+ YangToSourcesProcessor(Log log, File yangFilesRootDir,
+ List<CodeGeneratorArg> codeGenerators, MavenProject project,
+ boolean inspectDependencies) {
+ this(log, yangFilesRootDir, codeGenerators, project,
+ inspectDependencies, new YangProvider());
+ }
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ ContextHolder context = processYang();
+ generateSources(context);
+ yangProvider.addYangsToMETA_INF(log, project, yangFilesRootDir);
+ }
+
+ private ContextHolder processYang() throws MojoExecutionException {
+ YangParserImpl parser = new YangParserImpl();
+ List<Closeable> closeables = new ArrayList<>();
+ log.info(Util.message("Inspecting %s", LOG_PREFIX, yangFilesRootDir));
+ try {
+ List<InputStream> yangsInProject = Util
+ .listFilesAsStream(yangFilesRootDir);
+ List<InputStream> all = new ArrayList<>(yangsInProject);
+ closeables.addAll(yangsInProject);
+ Map<InputStream, Module> allYangModules;
+ Set<Module> projectYangModules;
+ try {
+ if (inspectDependencies) {
+ YangsInZipsResult dependentYangResult = Util
+ .findYangFilesInDependenciesAsStream(log, project);
+ Closeable dependentYangResult1 = dependentYangResult;
+ closeables.add(dependentYangResult1);
+ all.addAll(dependentYangResult.yangStreams);
+ }
+
+ allYangModules = parser.parseYangModelsFromStreamsMapped(all);
+
+ projectYangModules = new HashSet<>();
+ for (InputStream inProject : yangsInProject) {
+ projectYangModules.add(allYangModules.get(inProject));
+ }
+
+ } finally {
+ for (AutoCloseable closeable : closeables) {
+ closeable.close();
+ }
+ }
+
+ Set<Module> parsedAllYangModules = new HashSet<>(
+ allYangModules.values());
+ SchemaContext resolveSchemaContext = parser
+ .resolveSchemaContext(parsedAllYangModules);
+ log.info(Util.message("%s files parsed from %s", LOG_PREFIX,
+ Util.YANG_SUFFIX.toUpperCase(), yangsInProject));
+ return new ContextHolder(resolveSchemaContext, projectYangModules);
+
+ // MojoExecutionException is thrown since execution cannot continue
+ } catch (Exception e) {
+ String message = Util.message("Unable to parse %s files from %s",
+ LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir);
+ log.error(message, e);
+ throw new MojoExecutionException(message, e);
+ }
+ }
+
+ static class YangProvider {
+
+ private static final String yangResourceDir = "target" + File.separator
+ + "yang";
+
+ void addYangsToMETA_INF(Log log, MavenProject project,
+ File yangFilesRootDir) throws MojoFailureException {
+ File targetYangDir = new File(project.getBasedir(), yangResourceDir);
+
+ try {
+ FileUtils.copyDirectory(yangFilesRootDir, targetYangDir);
+ } catch (IOException e) {
+ String message = "Unable to copy yang files into resource folder";
+ log.warn(message, e);
+ throw new MojoFailureException(message, e);
+ }
+
+ setResource(targetYangDir, META_INF_YANG_STRING_JAR, project);
+
+ log.debug(Util.message(
+ "Yang files from: %s marked as resources: %s", LOG_PREFIX,
+ yangFilesRootDir, META_INF_YANG_STRING_JAR));
+ }
+
+ private static void setResource(File targetYangDir, String targetPath,
+ MavenProject project) {
+ Resource res = new Resource();
+ res.setDirectory(targetYangDir.getPath());
+ if (targetPath != null)
+ res.setTargetPath(targetPath);
+ project.addResource(res);
+ }
+ }
+
+ /**
+ * Call generate on every generator from plugin configuration
+ */
+ private void generateSources(ContextHolder context)
+ throws MojoFailureException {
+ if (codeGenerators.size() == 0) {
+ log.warn(Util.message("No code generators provided", LOG_PREFIX));
+ return;
+ }
+
+ Map<String, String> thrown = Maps.newHashMap();
+ for (CodeGeneratorArg codeGenerator : codeGenerators) {
+ try {
+ generateSourcesWithOneGenerator(context, codeGenerator);
+ } catch (Exception e) {
+ // try other generators, exception will be thrown after
+ log.error(Util.message(
+ "Unable to generate sources with %s generator",
+ LOG_PREFIX, codeGenerator.getCodeGeneratorClass()), e);
+ thrown.put(codeGenerator.getCodeGeneratorClass(), e.getClass()
+ .getCanonicalName());
+ }
+ }
+
+ if (!thrown.isEmpty()) {
+ String message = Util
+ .message(
+ "One or more code generators failed, including failed list(generatorClass=exception) %s",
+ LOG_PREFIX, thrown.toString());
+ log.error(message);
+ throw new MojoFailureException(message);
+ }
+ }
+
+ /**
+ * Instantiate generator from class and call required method
+ */
+ private void generateSourcesWithOneGenerator(ContextHolder context,
+ CodeGeneratorArg codeGeneratorCfg) throws ClassNotFoundException,
+ InstantiationException, IllegalAccessException, IOException {
+
+ codeGeneratorCfg.check();
+
+ CodeGenerator g = Util.getInstance(
+ codeGeneratorCfg.getCodeGeneratorClass(), CodeGenerator.class);
+ log.info(Util.message("Code generator instantiated from %s",
+ LOG_PREFIX, codeGeneratorCfg.getCodeGeneratorClass()));
+
+ File outputDir = codeGeneratorCfg.getOutputBaseDir(project);
+
+ log.info(Util.message("Sources will be generated to %s", LOG_PREFIX,
+ outputDir));
+ log.debug(Util.message("Project root dir is %s", LOG_PREFIX,
+ project.getBasedir()));
+ log.debug(Util.message(
+ "Additional configuration picked up for : %s: %s", LOG_PREFIX,
+ codeGeneratorCfg.getCodeGeneratorClass(),
+ codeGeneratorCfg.getAdditionalConfiguration()));
+
+ if(outputDir != null) {
+ project.addCompileSourceRoot(outputDir.getAbsolutePath());
+ }
+ g.setLog(log);
+ g.setMavenProject(project);
+ g.setAdditionalConfig(codeGeneratorCfg.getAdditionalConfiguration());
+ File resourceBaseDir = codeGeneratorCfg.getResourceBaseDir(project);
+
+ YangProvider.setResource(resourceBaseDir, null, project);
+ g.setResourceBaseDir(resourceBaseDir);
+ log.debug(Util.message(
+ "Folder: %s marked as resources for generator: %s", LOG_PREFIX,
+ resourceBaseDir, codeGeneratorCfg.getCodeGeneratorClass()));
+
+ Collection<File> generated = g.generateSources(context.getContext(),
+ outputDir, context.getYangModules());
+
+ log.info(Util.message("Sources generated by %s: %s", LOG_PREFIX,
+ codeGeneratorCfg.getCodeGeneratorClass(), generated));
+ }
+
+}
--- /dev/null
+/*
+ * 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 static org.hamcrest.core.Is.*;
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+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.MojoFailureException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.junit.Before;
+import org.junit.Test;
+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.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
+import org.opendaylight.controller.yang2sources.plugin.YangToSourcesProcessor.YangProvider;
+import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
+
+import com.google.common.collect.Lists;
+
+public class GenerateSourcesTest {
+
+ private String yang;
+ private YangToSourcesMojo mojo;
+ private File outDir;
+ @Mock
+ private MavenProject project;
+
+ @Before
+ public void setUp() throws MojoFailureException {
+ MockitoAnnotations.initMocks(this);
+
+ yang = new File(getClass().getResource("/yang/mock.yang").getFile())
+ .getParent();
+ outDir = new File("/outputDir");
+ YangProvider mock = mock(YangProvider.class);
+ doNothing().when(mock).addYangsToMETA_INF(any(Log.class),
+ any(MavenProject.class), any(File.class));
+
+ YangToSourcesProcessor processor = new YangToSourcesProcessor(
+ mock(Log.class), new File(yang),
+ Lists.newArrayList(new CodeGeneratorArg(GeneratorMock.class
+ .getName(), "outputDir")), project, false,
+ mock);
+ mojo = new YangToSourcesMojo(processor);
+ doReturn(new File("")).when(project).getBasedir();
+ mojo.project = project;
+ }
+
+ @Test
+ public void test() throws Exception {
+ mojo.execute();
+ assertThat(GeneratorMock.called, is(1));
+ assertThat(GeneratorMock.outputDir, is(outDir));
+ assertThat(GeneratorMock.project, is(project));
+ assertNotNull(GeneratorMock.log);
+ assertTrue(GeneratorMock.additionalCfg.isEmpty());
+ assertThat(GeneratorMock.resourceBaseDir.toString(),
+ containsString("target" + File.separator
+ + "generated-resources"));
+ }
+
+ public static class GeneratorMock implements CodeGenerator {
+
+ private static int called = 0;
+ private static File outputDir;
+ private static Log log;
+ private static Map<String, String> additionalCfg;
+ private static File resourceBaseDir;
+ private static MavenProject project;
+
+ @Override
+ public Collection<File> generateSources(SchemaContext context,
+ File outputBaseDir, Set<Module> currentModules)
+ throws IOException {
+ called++;
+ outputDir = outputBaseDir;
+ return Lists.newArrayList();
+ }
+
+ @Override
+ public void setLog(Log log) {
+ GeneratorMock.log = log;
+ }
+
+ @Override
+ public void setAdditionalConfig(
+ Map<String, String> additionalConfiguration) {
+ GeneratorMock.additionalCfg = additionalConfiguration;
+ }
+
+ @Override
+ public void setResourceBaseDir(File resourceBaseDir) {
+ GeneratorMock.resourceBaseDir = resourceBaseDir;
+
+ }
+
+ @Override
+ public void setMavenProject(MavenProject project) {
+ GeneratorMock.project = project;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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 static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Collection;
+
+import org.junit.Test;
+
+public class UtilTest {
+
+ @Test
+ public void testCache() throws FileNotFoundException {
+ String yang = new File(getClass().getResource("/yang/mock.yang")
+ .getFile())
+ .getParent();
+ Collection<File> files = Util.listFiles(new File(yang));
+ Collection<File> files2 = Util.listFiles(new File(yang));
+ assertTrue(files == files2);
+ }
+
+}
--- /dev/null
+ module mock {
+
+ namespace "a:b:c";
+ prefix "m";
+
+ revision 2010-09-24 {
+ description
+ "Initial revision.";
+ }
+
+ }
--- /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">
+
+ <parent>
+ <artifactId>yang</artifactId>
+ <groupId>org.opendaylight.controller</groupId>
+ <version>0.5.4-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>yang-maven-plugin-spi</artifactId>
+ <name>${project.artifactId}</name>
+ <description>${project.artifactId}</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-model-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>3.0.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>3.0.5</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
--- /dev/null
+/*
+ * 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.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.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+
+/**
+ * Classes implementing this interface can be submitted to maven-yang-plugin's
+ * generate-sources goal.
+ */
+public interface CodeGenerator {
+
+ /**
+ * Generate sources from provided {@link SchemaContext}
+ *
+ * @param context
+ * parsed from yang files
+ * @param outputBaseDir
+ * expected output directory for generated sources configured by
+ * user
+ * @param currentModules
+ * yang modules parsed from yangFilesRootDir
+ * @return collection of files that were generated from schema context
+ * @throws IOException
+ */
+ Collection<File> generateSources(SchemaContext context, File outputBaseDir, Set<Module> currentModules)
+ throws IOException;
+
+ /**
+ * Utilize maven logging if necessary
+ *
+ * @param log
+ */
+ void setLog(Log log);
+
+ /**
+ * Provided map contains all configuration that was set in pom for code
+ * generator in additionalConfiguration tag
+ *
+ * @param additionalConfiguration
+ */
+ void setAdditionalConfig(Map<String, String> additionalConfiguration);
+
+ /**
+ * Provided folder is marked as resources and its content will be packaged
+ * in resulting jar. Feel free to add necessary resources
+ *
+ * @param resourceBaseDir
+ */
+ void setResourceBaseDir(File resourceBaseDir);
+
+ /**
+ * Provided maven project object. Any additional information about current
+ * maven project can be accessed from it.
+ *
+ * @param project
+ */
+ void setMavenProject(MavenProject project);
+}
--- /dev/null
+/*
+ * 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;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+
+public class CodeGeneratorTestImpl implements CodeGenerator {
+
+ private Log log;
+
+ @Override
+ public Collection<File> generateSources(SchemaContext context,
+ File outputBaseDir, Set<Module> currentModuleBuilders) {
+ if (log != null) {
+ log.debug(getClass().getCanonicalName()
+ + " generateSources:context: " + context);
+ log.debug(getClass().getCanonicalName()
+ + " generateSources:outputBaseDir: " + outputBaseDir);
+ log.debug(getClass().getCanonicalName()
+ + " generateSources:currentModuleBuilders: "
+ + currentModuleBuilders);
+
+ }
+ return null;
+ }
+
+ @Override
+ public void setLog(Log log) {
+ this.log = log;
+ }
+
+ @Override
+ public void setAdditionalConfig(Map<String, String> additionalConfiguration) {
+ if (log != null)
+ log.debug(getClass().getCanonicalName() + " additionalConfig: "
+ + additionalConfiguration);
+ }
+
+
+ @Override
+ public void setResourceBaseDir(File resourceBaseDir) {
+ if (log != null)
+ log.debug(getClass().getCanonicalName() + " resourceBaseDir: "
+ + resourceBaseDir);
+ }
+
+ @Override
+ public void setMavenProject(MavenProject project) {
+ if (log != null)
+ log.debug(getClass().getCanonicalName() + " maven project: "
+ + project);
+ }
+
+}
<module>yang-common</module>
<module>yang-data-api</module>
<module>yang-data-util</module>
- <module>yang-data-impl</module>
+ <module>yang-data-impl</module>
<module>yang-model-api</module>
<module>yang-model-util</module>
<module>yang-binding</module>
<module>yang-ext</module>
- <module>../code-generator/yang-model-parser-api</module>
- <module>../code-generator/yang-model-parser-impl</module>
- <module>../code-generator/maven-yang</module>
- <module>../code-generator/maven-yang-plugin</module>
- <module>../code-generator/maven-yang-plugin-it</module>
+ <module>yang-model-parser-api</module>
+ <module>yang-model-parser-impl</module>
+ <module>maven-yang</module>
+ <module>maven-yang-plugin</module>
+ <module>maven-yang-plugin-it</module>
</modules>
<dependencyManagement>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
- <version>2.8.1</version>
<configuration>
<stylesheet>maven</stylesheet>
</configuration>
</plugin>
</plugins>
</build>
+
<reporting>
<plugins>
<plugin>
</plugin>
</plugins>
</reporting>
+
</project>
--- /dev/null
+<project name="${project.name}">
+
+ <skin>
+ <groupId>org.apache.maven.skins</groupId>
+ <artifactId>maven-fluido-skin</artifactId>
+ <version>1.3.0</version>
+ </skin>
+
+ <body>
+ <menu ref="parent"/>
+ <menu ref="modules"/>
+ <menu ref="reports"/>
+ </body>
+
+</project>
+
-<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">\r
- <modelVersion>4.0.0</modelVersion>\r
- <parent>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>yang</artifactId>\r
- <version>0.5.4-SNAPSHOT</version>\r
- </parent>\r
- <artifactId>yang-binding</artifactId>\r
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+\r
+ <parent>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang</artifactId>\r
+ <version>0.5.4-SNAPSHOT</version>\r
+ </parent>\r
+\r
+ <modelVersion>4.0.0</modelVersion>\r
+ <artifactId>yang-binding</artifactId>\r
+ <name>${project.artifactId}</name>\r
+ <description>Java binding for YANG</description>\r
+\r
</project>\r
-<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">\r
- <modelVersion>4.0.0</modelVersion>\r
- <parent>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>yang</artifactId>\r
- <version>0.5.4-SNAPSHOT</version>\r
- </parent>\r
- <artifactId>yang-common</artifactId>\r
- <dependencies>\r
- <dependency>\r
- <groupId>org.slf4j</groupId>\r
- <artifactId>slf4j-api</artifactId>\r
- <version>${slf4j.version}</version>\r
- </dependency>\r
- </dependencies>\r
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+\r
+ <parent>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang</artifactId>\r
+ <version>0.5.4-SNAPSHOT</version>\r
+ </parent>\r
+\r
+ <modelVersion>4.0.0</modelVersion>\r
+ <artifactId>yang-common</artifactId>\r
+ <name>${project.artifactId}</name>\r
+ <description>${project.artifactId}</description>\r
+\r
+ <dependencies>\r
+ <dependency>\r
+ <groupId>org.slf4j</groupId>\r
+ <artifactId>slf4j-api</artifactId>\r
+ </dependency>\r
+ </dependencies>\r
+\r
</project>\r
+\r
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
- <modelVersion>4.0.0</modelVersion>\r
+\r
<parent>\r
<groupId>org.opendaylight.controller</groupId>\r
<artifactId>yang</artifactId>\r
<version>0.5.4-SNAPSHOT</version>\r
</parent>\r
+\r
+ <modelVersion>4.0.0</modelVersion>\r
<artifactId>yang-data-api</artifactId>\r
+ <name>${project.artifactId}</name>\r
+ <description>${project.artifactId}</description>\r
\r
<dependencies>\r
<dependency>\r
<artifactId>yang-common</artifactId>\r
</dependency>\r
</dependencies>\r
-</project>
\ No newline at end of file
+\r
+</project>\r
-<project xmlns="http://maven.apache.org/POM/4.0.0"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
- <modelVersion>4.0.0</modelVersion>\r
+\r
<parent>\r
<groupId>org.opendaylight.controller</groupId>\r
<artifactId>yang</artifactId>\r
<version>0.5.4-SNAPSHOT</version>\r
</parent>\r
+\r
+ <modelVersion>4.0.0</modelVersion>\r
<artifactId>yang-data-impl</artifactId>\r
+ <name>${project.artifactId}</name>\r
+ <description>${project.artifactId}</description>\r
\r
<properties>\r
<groovy.version>2.1.6</groovy.version>\r
</plugins>\r
</build>\r
\r
-\r
<dependencies>\r
<dependency>\r
<groupId>org.opendaylight.controller</groupId>\r
<scope>test</scope>\r
</dependency>\r
</dependencies>\r
+\r
</project>\r
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
- <modelVersion>4.0.0</modelVersion>\r
+\r
<parent>\r
<groupId>org.opendaylight.controller</groupId>\r
<artifactId>yang</artifactId>\r
<version>0.5.4-SNAPSHOT</version>\r
</parent>\r
+\r
+ <modelVersion>4.0.0</modelVersion>\r
<artifactId>yang-data-util</artifactId>\r
+ <name>${project.artifactId}</name>\r
+ <description>${project.artifactId}</description>\r
+\r
<dependencies>\r
<dependency>\r
<groupId>org.opendaylight.controller</groupId>\r
<artifactId>yang-data-api</artifactId>\r
</dependency>\r
</dependencies>\r
-</project>
\ No newline at end of file
+\r
+</project>\r
<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>
+
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>yang</artifactId>
<version>0.5.4-SNAPSHOT</version>
</parent>
+
+ <modelVersion>4.0.0</modelVersion>
<artifactId>yang-ext</artifactId>
<version>2013.09.07-SNAPSHOT</version>
+ <name>${project.artifactId}</name>
+ <description>${project.artifactId}</description>
<build>
<plugins>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
- <modelVersion>4.0.0</modelVersion>\r
+\r
<parent>\r
<groupId>org.opendaylight.controller</groupId>\r
<artifactId>yang</artifactId>\r
<version>0.5.4-SNAPSHOT</version>\r
</parent>\r
+\r
+ <modelVersion>4.0.0</modelVersion>\r
<artifactId>yang-model-api</artifactId>\r
+ <name>${project.artifactId}</name>\r
+ <description>${project.artifactId}</description>\r
+\r
<dependencies>\r
<dependency>\r
<groupId>org.opendaylight.controller</groupId>\r
<artifactId>yang-common</artifactId>\r
</dependency>\r
</dependencies>\r
+\r
</project>\r
import org.opendaylight.controller.yang.model.api.TypeDefinition;
-public interface DecimalTypeDefinition extends
- TypeDefinition<DecimalTypeDefinition> {
+public interface DecimalTypeDefinition extends TypeDefinition<DecimalTypeDefinition> {
List<RangeConstraint> getRangeStatements();
/**
* Returns integer between 1 and 18 inclusively. <br>
* <br>
- *
+ *
* The "fraction-digits" statement controls the size of the minimum
* difference between values of a decimal64 type, by restricting the value
* space to numbers that are expressible as "i x 10^-n" where n is the
* fraction-digits argument.
- *
- * @return
+ *
+ * @return number of fraction digits
*/
Integer getFractionDigits();
}
--- /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">
+
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang</artifactId>
+ <version>0.5.4-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>yang-model-parser-api</artifactId>
+ <name>${project.artifactId}</name>
+ <description>YANG parser API</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-model-api</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+/*
+ * 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.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;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.api.type.UnknownTypeDefinition;
+
+/**
+ * Yang Model Parser interface is designed for parsing yang models and convert
+ * the information to Data Schema Tree.
+ *
+ */
+public interface YangModelParser {
+
+ /**
+ * Parse one or more Yang model files and return the definitions of Yang
+ * modules defined in *.yang files; <br>
+ * This method SHOULD be used if user need to parse multiple yang models
+ * that are referenced either through import or include statements.
+ *
+ * @param yangFiles
+ * yang files to parse
+ * @return Set of Yang Modules
+ */
+ Set<Module> parseYangModels(final List<File> yangFiles);
+
+ /**
+ * Parse one or more Yang model files and return the definitions of Yang
+ * modules defined in *.yang files. <br>
+ * This method SHOULD be used if user has already parsed context and need to
+ * parse additinal yang models which can have dependencies on models in this
+ * context.
+ *
+ * @param yangFiles
+ * yang files to parse
+ * @param context
+ * SchemaContext containing already parsed yang models
+ * @return Set of Yang Modules
+ */
+ Set<Module> parseYangModels(final List<File> yangFiles, final SchemaContext context);
+
+ /**
+ * Equivalent to {@link #parseYangModels(List)} that returns parsed modules
+ * mapped to Files from which they were parsed.
+ *
+ * @param yangFiles
+ * yang files to parse
+ * @return Map of Yang Modules
+ */
+ Map<File, Module> parseYangModelsMapped(final List<File> yangFiles);
+
+ /**
+ * Parse one or more Yang model streams and return the definitions of Yang
+ * modules defined in *.yang files; <br>
+ * This method SHOULD be used if user need to parse multiple yang models
+ * that are referenced either through import or include statements.
+ *
+ * @param yangModelStreams
+ * yang streams to parse
+ * @return Set of Yang Modules
+ */
+ Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams);
+
+ /**
+ * Parse one or more Yang model streams and return the definitions of Yang
+ * modules defined in *.yang files. <br>
+ * This method SHOULD be used if user has already parsed context and need to
+ * parse additinal yang models which can have dependencies on models in this
+ * context.
+ *
+ * @param yangModelStreams
+ * yang streams to parse
+ * @param context
+ * SchemaContext containing already parsed yang models
+ * @return Set of Yang Modules
+ */
+ Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams, final SchemaContext context);
+
+ /**
+ * Equivalent to {@link #parseYangModels(List)} that returns parsed modules
+ * mapped to IputStreams from which they were parsed.
+ *
+ * @param yangModelStreams
+ * yang streams to parse
+ * @return Map of Yang Modules
+ */
+ Map<InputStream, Module> parseYangModelsFromStreamsMapped(final List<InputStream> yangModelStreams);
+
+ /**
+ * Creates {@link SchemaContext} from specified Modules. The modules SHOULD
+ * not contain any unresolved Schema Nodes or Type Definitions. By
+ * unresolved Schema Nodes or Type Definitions we mean that the Module
+ * should not contain ANY Schema Nodes that contains
+ * {@link UnknownTypeDefinition} and all dependencies although via import or
+ * include definitions are resolved.
+ *
+ * @param modules
+ * Set of Yang Modules
+ * @return Schema Context instance constructed from whole Set of Modules.
+ */
+ SchemaContext resolveSchemaContext(final Set<Module> modules);
+}
--- /dev/null
+/*
+ * 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.yang.model.parser.api;
\ No newline at end of file
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+\r
+ <parent>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang</artifactId>\r
+ <version>0.5.4-SNAPSHOT</version>\r
+ </parent>\r
+\r
+ <modelVersion>4.0.0</modelVersion>\r
+ <artifactId>yang-model-parser-impl</artifactId>\r
+ <name>${project.artifactId}</name>\r
+ <description>YANG parser</description>\r
+\r
+ <dependencies>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang-common</artifactId>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang-model-api</artifactId>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang-model-parser-api</artifactId>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang-model-util</artifactId>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.antlr</groupId>\r
+ <artifactId>antlr4</artifactId>\r
+ <version>4.0</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.slf4j</groupId>\r
+ <artifactId>slf4j-simple</artifactId>\r
+ <version>1.7.2</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.mockito</groupId>\r
+ <artifactId>mockito-all</artifactId>\r
+ <version>1.8.4</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>com.google.guava</groupId>\r
+ <artifactId>guava</artifactId>\r
+ <version>14.0.1</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>junit</groupId>\r
+ <artifactId>junit</artifactId>\r
+ </dependency>\r
+ </dependencies>\r
+\r
+ <build>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.antlr</groupId>\r
+ <artifactId>antlr4-maven-plugin</artifactId>\r
+ <version>4.0</version>\r
+ <executions>\r
+ <execution>\r
+ <goals>\r
+ <goal>antlr4</goal>\r
+ </goals>\r
+ </execution>\r
+ </executions>\r
+ <configuration>\r
+ <sourceDirectory>src/main/antlr</sourceDirectory>\r
+ <outputDirectory>target/generated-sources/parser/org/opendaylight/controller/antlrv4/code/gen</outputDirectory>\r
+ <visitor>true</visitor>\r
+ <listener>true</listener>\r
+ </configuration>\r
+ </plugin>\r
+ <plugin>\r
+ <groupId>org.codehaus.mojo</groupId>\r
+ <artifactId>build-helper-maven-plugin</artifactId>\r
+ <version>1.7</version>\r
+ <executions>\r
+ <execution>\r
+ <phase>generate-sources</phase>\r
+ <goals>\r
+ <goal>add-source</goal>\r
+ </goals>\r
+ <configuration>\r
+ <sources>\r
+ <source>target/generated-sources/parser</source>\r
+ </sources>\r
+ </configuration>\r
+ </execution>\r
+ </executions>\r
+ </plugin>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-javadoc-plugin</artifactId>\r
+ <configuration>\r
+ <excludePackageNames>\r
+ *.opendaylight.controller.antlrv4.code.gen\r
+ </excludePackageNames>\r
+ </configuration>\r
+ </plugin>\r
+ </plugins>\r
+ <pluginManagement>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.eclipse.m2e</groupId>\r
+ <artifactId>lifecycle-mapping</artifactId>\r
+ <version>1.0.0</version>\r
+ <configuration>\r
+ <lifecycleMappingMetadata>\r
+ <pluginExecutions>\r
+ <pluginExecution>\r
+ <pluginExecutionFilter>\r
+ <groupId>org.antlr</groupId>\r
+ <artifactId>antlr4-maven-plugin</artifactId>\r
+ <versionRange>[4.0,)</versionRange>\r
+ <goals>\r
+ <goal>antlr4</goal>\r
+ </goals>\r
+ </pluginExecutionFilter>\r
+ <action>\r
+ <execute></execute>\r
+ </action>\r
+ </pluginExecution>\r
+ </pluginExecutions>\r
+ </lifecycleMappingMetadata>\r
+ </configuration>\r
+ </plugin>\r
+ </plugins>\r
+ </pluginManagement>\r
+ </build>\r
+</project>\r
--- /dev/null
+lexer grammar YangLexer;
+
+@header {
+package org.opendaylight.controller.antlrv4.code.gen;
+}
+
+tokens{
+ SEMICOLON,
+ LEFT_BRACE,
+ RIGHT_BRACE
+}
+
+
+PLUS : '+'-> pushMode(VALUE_MODE);
+WS : [ \n\r\t] -> skip;
+LINE_COMMENT : ('//' (~( '\r' | '\n' )*)) -> skip;
+
+START_BLOCK_COMMENT : '/*' ->pushMode(BLOCK_COMMENT_MODE), skip ;
+
+
+SEMICOLON : ';' ->type(SEMICOLON);
+LEFT_BRACE : '{' ->type(LEFT_BRACE);
+RIGHT_BRACE : '}' ->type(RIGHT_BRACE);
+
+YIN_ELEMENT_KEYWORD : 'yin-element'-> pushMode(VALUE_MODE);
+YANG_VERSION_KEYWORD: 'yang-version'-> pushMode(VALUE_MODE);
+WHEN_KEYWORD : 'when'-> pushMode(VALUE_MODE);
+VALUE_KEYWORD : 'value'-> pushMode(VALUE_MODE);
+USES_KEYWORD : 'uses'-> pushMode(VALUE_MODE);
+UNITS_KEYWORD : 'units'-> pushMode(VALUE_MODE);
+UNIQUE_KEYWORD : 'unique'-> pushMode(VALUE_MODE);
+TYPEDEF_KEYWORD : 'typedef'-> pushMode(VALUE_MODE);
+TYPE_KEYWORD : 'type'-> pushMode(VALUE_MODE);
+SUBMODULE_KEYWORD : 'submodule'-> pushMode(VALUE_MODE);
+STATUS_KEYWORD : 'status'-> pushMode(VALUE_MODE);
+RPC_KEYWORD : 'rpc'-> pushMode(VALUE_MODE);
+REVISION_DATE_KEYWORD : 'revision-date'-> pushMode(VALUE_MODE);
+REVISION_KEYWORD : 'revision'-> pushMode(VALUE_MODE);
+REQUIRE_INSTANCE_KEYWORD : 'require-instance'-> pushMode(VALUE_MODE);
+REFINE_KEYWORD : 'refine'-> pushMode(VALUE_MODE);
+REFERENCE_KEYWORD : 'reference'-> pushMode(VALUE_MODE);
+RANGE_KEYWORD : 'range'-> pushMode(VALUE_MODE);
+PRESENCE_KEYWORD : 'presence'-> pushMode(VALUE_MODE);
+PREFIX_KEYWORD : 'prefix'-> pushMode(VALUE_MODE);
+POSITION_KEYWORD : 'position'-> pushMode(VALUE_MODE);
+PATTERN_KEYWORD : 'pattern'-> pushMode(VALUE_MODE);
+PATH_KEYWORD : 'path'-> pushMode(VALUE_MODE);
+OUTPUT_KEYWORD : 'output';
+ORGANIZATION_KEYWORD: 'organization'-> pushMode(VALUE_MODE);
+ORDERED_BY_KEYWORD : 'ordered-by'-> pushMode(VALUE_MODE);
+NOTIFICATION_KEYWORD: 'notification'-> pushMode(VALUE_MODE);
+NAMESPACE_KEYWORD : 'namespace'-> pushMode(VALUE_MODE);
+MUST_KEYWORD : 'must'-> pushMode(VALUE_MODE);
+MODULE_KEYWORD : 'module'-> pushMode(VALUE_MODE);
+MIN_ELEMENTS_KEYWORD : 'min-elements'-> pushMode(VALUE_MODE);
+MAX_ELEMENTS_KEYWORD : 'max-elements'-> pushMode(VALUE_MODE);
+MANDATORY_KEYWORD : 'mandatory'-> pushMode(VALUE_MODE);
+LIST_KEYWORD : 'list'-> pushMode(VALUE_MODE);
+LENGTH_KEYWORD : 'length'-> pushMode(VALUE_MODE);
+LEAF_LIST_KEYWORD : 'leaf-list'-> pushMode(VALUE_MODE);
+LEAF_KEYWORD : 'leaf'-> pushMode(VALUE_MODE);
+KEY_KEYWORD : 'key'-> pushMode(VALUE_MODE);
+INPUT_KEYWORD : 'input';
+INCLUDE_KEYWORD : 'include'-> pushMode(VALUE_MODE);
+IMPORT_KEYWORD : 'import'-> pushMode(VALUE_MODE);
+IF_FEATURE_KEYWORD : 'if-feature'-> pushMode(VALUE_MODE);
+IDENTITY_KEYWORD : 'identity'-> pushMode(VALUE_MODE);
+GROUPING_KEYWORD : 'grouping'-> pushMode(VALUE_MODE);
+FRACTION_DIGITS_KEYWORD : 'fraction-digits'-> pushMode(VALUE_MODE);
+FEATURE_KEYWORD : 'feature'-> pushMode(VALUE_MODE);
+DEVIATE_KEYWORD : 'deviate'-> pushMode(VALUE_MODE);
+DEVIATION_KEYWORD : 'deviation'-> pushMode(VALUE_MODE);
+EXTENSION_KEYWORD : 'extension'-> pushMode(VALUE_MODE);
+ERROR_MESSAGE_KEYWORD : 'error-message'-> pushMode(VALUE_MODE);
+ERROR_APP_TAG_KEYWORD : 'error-app-tag'-> pushMode(VALUE_MODE);
+ENUM_KEYWORD : 'enum'-> pushMode(VALUE_MODE);
+DESCRIPTION_KEYWORD : 'description'-> pushMode(VALUE_MODE);
+DEFAULT_KEYWORD : 'default'-> pushMode(VALUE_MODE);
+CONTAINER_KEYWORD : 'container'-> pushMode(VALUE_MODE);
+CONTACT_KEYWORD : 'contact'-> pushMode(VALUE_MODE);
+CONFIG_KEYWORD : 'config'-> pushMode(VALUE_MODE);
+CHOICE_KEYWORD: 'choice'-> pushMode(VALUE_MODE);
+CASE_KEYWORD : 'case'-> pushMode(VALUE_MODE);
+BIT_KEYWORD : 'bit'-> pushMode(VALUE_MODE);
+BELONGS_TO_KEYWORD : 'belongs-to'-> pushMode(VALUE_MODE);
+BASE_KEYWORD : 'base'-> pushMode(VALUE_MODE);
+AUGMENT_KEYWORD : 'augment'-> pushMode(VALUE_MODE);
+ARGUMENT_KEYWORD : 'argument'-> pushMode(VALUE_MODE);
+ANYXML_KEYWORD : 'anyxml'-> pushMode(VALUE_MODE);
+
+IDENTIFIER : [/.a-zA-Z_0-9\-][a-zA-Z0-9_\-.:]* -> pushMode(VALUE_MODE);
+
+mode VALUE_MODE;
+
+fragment ESC : '\\' (["\\/bfnrt] | UNICODE) ;
+fragment UNICODE : 'u' HEX HEX HEX HEX ;
+fragment HEX : [0-9a-fA-F] ;
+
+END_IDENTIFIER_SEMICOLON : ';' -> type(SEMICOLON),popMode;
+END_IDENTIFIER_LEFT_BRACE : '{' ->type(LEFT_BRACE), popMode;
+
+fragment SUB_STRING : ('"' (ESC | ~["])*'"') | ('\'' (ESC | ~['])*'\'') ;
+
+STRING: (SUB_STRING | (~( '\r' | '\n' | ' ' | ';' | '{' )+)) ->popMode;// IDENTIFIER ;
+S : [ \n\r\t] -> skip;
+
+mode BLOCK_COMMENT_MODE;
+END_BLOCK_COMMENT : '*/' -> popMode,skip;
+BLOCK_COMMENT : . ->more,skip;
\ No newline at end of file
--- /dev/null
+parser grammar YangParser;
+
+@header {
+package org.opendaylight.controller.antlrv4.code.gen;
+}
+
+options{
+ tokenVocab=YangLexer;
+
+}
+
+
+yang : module_stmt | submodule_stmt ;
+
+string : STRING (PLUS STRING)*;
+
+identifier_stmt : IDENTIFIER string? stmtend;
+
+stmtend : (SEMICOLON) | (LEFT_BRACE identifier_stmt? RIGHT_BRACE);
+deviate_replace_stmt : DEVIATE_KEYWORD string /* REPLACE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |type_stmt | units_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
+deviate_delete_stmt : DEVIATE_KEYWORD string /* DELETE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt )* RIGHT_BRACE));
+deviate_add_stmt : DEVIATE_KEYWORD string /*ADD_KEYWORD*/ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
+deviate_not_supported_stmt : DEVIATE_KEYWORD string /*NOT_SUPPORTED_KEYWORD*/ (SEMICOLON | (LEFT_BRACE identifier_stmt? RIGHT_BRACE));
+deviation_stmt : DEVIATION_KEYWORD string LEFT_BRACE (identifier_stmt |description_stmt | reference_stmt | deviate_not_supported_stmt | deviate_add_stmt | deviate_replace_stmt | deviate_delete_stmt)+ RIGHT_BRACE;
+notification_stmt : NOTIFICATION_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |if_feature_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt )* RIGHT_BRACE));
+output_stmt : OUTPUT_KEYWORD LEFT_BRACE (identifier_stmt |typedef_stmt | grouping_stmt | data_def_stmt )+ RIGHT_BRACE;
+input_stmt : INPUT_KEYWORD LEFT_BRACE (identifier_stmt |typedef_stmt | grouping_stmt | data_def_stmt )+ RIGHT_BRACE;
+rpc_stmt : RPC_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |if_feature_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | input_stmt | output_stmt )* RIGHT_BRACE));
+when_stmt : WHEN_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |description_stmt | reference_stmt )* RIGHT_BRACE));
+
+augment_stmt : AUGMENT_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt | case_stmt)+ RIGHT_BRACE;
+uses_augment_stmt : AUGMENT_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt | case_stmt)+ RIGHT_BRACE;
+refine_anyxml_stmts : (identifier_stmt |must_stmt | config_stmt | mandatory_stmt | description_stmt | reference_stmt )*;
+refine_case_stmts : (identifier_stmt |description_stmt | reference_stmt )*;
+refine_choice_stmts : (identifier_stmt |default_stmt | config_stmt | mandatory_stmt | description_stmt | reference_stmt )*;
+refine_list_stmts : (identifier_stmt |must_stmt | config_stmt | min_elements_stmt | max_elements_stmt | description_stmt | reference_stmt )*;
+refine_leaf_list_stmts : (identifier_stmt |must_stmt | config_stmt | min_elements_stmt | max_elements_stmt | description_stmt | reference_stmt )*;
+refine_leaf_stmts : (identifier_stmt |must_stmt | default_stmt | config_stmt | mandatory_stmt | description_stmt | reference_stmt )*;
+refine_container_stmts : (identifier_stmt |must_stmt | presence_stmt | config_stmt | description_stmt | reference_stmt )*;
+refine_pom : (refine_container_stmts | refine_leaf_stmts | refine_leaf_list_stmts | refine_list_stmts | refine_choice_stmts | refine_case_stmts | refine_anyxml_stmts);
+refine_stmt : REFINE_KEYWORD string (SEMICOLON | (LEFT_BRACE (refine_pom) RIGHT_BRACE));
+uses_stmt : USES_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | refine_stmt | uses_augment_stmt )* RIGHT_BRACE));
+anyxml_stmt : ANYXML_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | must_stmt | config_stmt | mandatory_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+case_stmt : CASE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt )* RIGHT_BRACE));
+short_case_stmt : container_stmt | leaf_stmt | leaf_list_stmt | list_stmt | anyxml_stmt;
+choice_stmt : CHOICE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | default_stmt | config_stmt | mandatory_stmt | status_stmt | description_stmt | reference_stmt | short_case_stmt | case_stmt)* RIGHT_BRACE));
+unique_stmt : UNIQUE_KEYWORD string stmtend;
+key_stmt : KEY_KEYWORD string stmtend;
+list_stmt : LIST_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | must_stmt | key_stmt | unique_stmt | config_stmt | min_elements_stmt | max_elements_stmt | ordered_by_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt )+ RIGHT_BRACE;
+leaf_list_stmt : LEAF_LIST_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | type_stmt | units_stmt | must_stmt | config_stmt | min_elements_stmt | max_elements_stmt | ordered_by_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE;
+leaf_stmt : LEAF_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | type_stmt | units_stmt | must_stmt | default_stmt | config_stmt | mandatory_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE;
+container_stmt : CONTAINER_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | when_stmt | if_feature_stmt | must_stmt | presence_stmt | config_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt )* RIGHT_BRACE));
+grouping_stmt : GROUPING_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt )* RIGHT_BRACE));
+value_stmt : VALUE_KEYWORD string stmtend;
+max_value_arg : /*UNBOUNDED_KEYWORD |*/ string;
+min_value_arg : /*UNBOUNDED_KEYWORD |*/ string;
+max_elements_stmt : MAX_ELEMENTS_KEYWORD max_value_arg stmtend;
+min_elements_stmt : MIN_ELEMENTS_KEYWORD min_value_arg stmtend;
+error_app_tag_stmt : ERROR_APP_TAG_KEYWORD string stmtend;
+error_message_stmt : ERROR_MESSAGE_KEYWORD string stmtend;
+must_stmt : MUST_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+ordered_by_arg : string; /*USER_KEYWORD | SYSTEM_KEYWORD;*/
+ordered_by_stmt : ORDERED_BY_KEYWORD ordered_by_arg stmtend;
+presence_stmt : PRESENCE_KEYWORD string stmtend;
+mandatory_arg :string; // TRUE_KEYWORD | FALSE_KEYWORD;
+mandatory_stmt : MANDATORY_KEYWORD mandatory_arg stmtend;
+config_arg : string; // TRUE_KEYWORD | FALSE_KEYWORD;
+config_stmt : CONFIG_KEYWORD config_arg stmtend;
+status_arg : string; /*CURRENT_KEYWORD | OBSOLETE_KEYWORD | DEPRECATED_KEYWORD; */
+status_stmt : STATUS_KEYWORD status_arg stmtend;
+position_stmt : POSITION_KEYWORD string stmtend;
+bit_stmt : BIT_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |position_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+bits_specification : bit_stmt (bit_stmt | identifier_stmt)*;
+union_specification : type_stmt (identifier_stmt | type_stmt )+;
+identityref_specification : base_stmt ;
+instance_identifier_specification : (require_instance_stmt )?;
+require_instance_arg :string; // TRUE_KEYWORD | FALSE_KEYWORD;
+require_instance_stmt : REQUIRE_INSTANCE_KEYWORD require_instance_arg stmtend;
+path_stmt : PATH_KEYWORD string stmtend;
+leafref_specification : path_stmt;
+enum_stmt : ENUM_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |value_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+enum_specification : enum_stmt (identifier_stmt | enum_stmt )*;
+default_stmt : DEFAULT_KEYWORD string stmtend;
+pattern_stmt : PATTERN_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+length_stmt : LENGTH_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+string_restrictions : (length_stmt | pattern_stmt )*;
+fraction_digits_stmt : FRACTION_DIGITS_KEYWORD string stmtend;
+decimal64_specification : (numerical_restrictions? (identifier_stmt)* fraction_digits_stmt | fraction_digits_stmt (identifier_stmt)* numerical_restrictions?);
+range_stmt : RANGE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+numerical_restrictions : range_stmt ;
+type_body_stmts : (identifier_stmt)* (numerical_restrictions | decimal64_specification | string_restrictions | enum_specification | leafref_specification | identityref_specification | instance_identifier_specification | bits_specification | union_specification) (identifier_stmt)*;
+type_stmt : TYPE_KEYWORD string (SEMICOLON | (LEFT_BRACE type_body_stmts RIGHT_BRACE));
+typedef_stmt : TYPEDEF_KEYWORD string LEFT_BRACE (identifier_stmt | type_stmt | units_stmt | default_stmt | status_stmt | description_stmt | reference_stmt )+ RIGHT_BRACE;
+if_feature_stmt : IF_FEATURE_KEYWORD string stmtend;
+feature_stmt : FEATURE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+base_stmt : BASE_KEYWORD string stmtend;
+identity_stmt : IDENTITY_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | base_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+yin_element_arg : string; // TRUE_KEYWORD | FALSE_KEYWORD;
+yin_element_stmt : YIN_ELEMENT_KEYWORD yin_element_arg stmtend;
+argument_stmt : ARGUMENT_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt)? (yin_element_stmt )? (identifier_stmt)* RIGHT_BRACE));
+extension_stmt : EXTENSION_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | argument_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+revision_date_stmt : REVISION_DATE_KEYWORD string stmtend;
+revision_stmt : REVISION_KEYWORD string (SEMICOLON | (LEFT_BRACE (description_stmt )? (reference_stmt )? RIGHT_BRACE));
+units_stmt : UNITS_KEYWORD string stmtend;
+reference_stmt : REFERENCE_KEYWORD string stmtend;
+description_stmt : DESCRIPTION_KEYWORD string stmtend;
+contact_stmt : CONTACT_KEYWORD string stmtend;
+organization_stmt : ORGANIZATION_KEYWORD string stmtend;
+belongs_to_stmt : BELONGS_TO_KEYWORD string LEFT_BRACE prefix_stmt RIGHT_BRACE;
+prefix_stmt : PREFIX_KEYWORD string stmtend;
+namespace_stmt : NAMESPACE_KEYWORD string stmtend;
+include_stmt : INCLUDE_KEYWORD string (SEMICOLON | (LEFT_BRACE (revision_date_stmt )? RIGHT_BRACE));
+import_stmt : IMPORT_KEYWORD string LEFT_BRACE prefix_stmt (revision_date_stmt )? RIGHT_BRACE;
+yang_version_stmt : YANG_VERSION_KEYWORD string stmtend;
+data_def_stmt : container_stmt | leaf_stmt | leaf_list_stmt | list_stmt | choice_stmt | anyxml_stmt | uses_stmt;
+body_stmts : (( identifier_stmt| extension_stmt | feature_stmt | identity_stmt | typedef_stmt | grouping_stmt | data_def_stmt | augment_stmt | rpc_stmt | notification_stmt | deviation_stmt) )*;
+revision_stmts : (revision_stmt )*;
+linkage_stmts : (import_stmt | include_stmt )*;
+meta_stmts : (organization_stmt | contact_stmt | description_stmt | reference_stmt )*;
+submodule_header_stmts : (yang_version_stmt | belongs_to_stmt)+ ;
+module_header_stmts : (yang_version_stmt | namespace_stmt | prefix_stmt)+ ;
+submodule_stmt : SUBMODULE_KEYWORD string LEFT_BRACE submodule_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
+module_stmt : MODULE_KEYWORD string LEFT_BRACE module_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
+
+/**
+ * Basic implementation of Builder.
+ */
+public abstract class AbstractBuilder implements Builder {
+ protected String moduleName;
+ protected final int line;
+ protected Builder parent;
+
+ protected List<UnknownSchemaNode> unknownNodes;
+ protected final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
+
+ protected AbstractBuilder(final String moduleName, final int line) {
+ this.moduleName = moduleName;
+ this.line = line;
+ }
+
+ @Override
+ public String getModuleName() {
+ return moduleName;
+ }
+
+ @Override
+ public void setModuleName(final String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ @Override
+ public int getLine() {
+ return line;
+ }
+
+ @Override
+ public Builder getParent() {
+ return parent;
+ }
+
+ @Override
+ public void setParent(final Builder parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public List<UnknownSchemaNodeBuilder> getUnknownNodeBuilders() {
+ return addedUnknownNodes;
+ }
+
+ @Override
+ public void addUnknownNodeBuilder(UnknownSchemaNodeBuilder unknownNode) {
+ addedUnknownNodes.add(unknownNode);
+ }
+
+ public void setUnknownNodes(List<UnknownSchemaNode> unknownNodes) {
+ this.unknownNodes = unknownNodes;
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+/**
+ * Basic implementation of DataNodeContainerBuilder.
+ */
+public abstract class AbstractDataNodeContainerBuilder extends AbstractBuilder implements DataNodeContainerBuilder {
+ protected final QName qname;
+
+ protected Set<DataSchemaNode> childNodes;
+ protected final Set<DataSchemaNodeBuilder> addedChildNodes = new HashSet<DataSchemaNodeBuilder>();
+
+ protected Set<GroupingDefinition> groupings;
+ protected final Set<GroupingBuilder> addedGroupings = new HashSet<GroupingBuilder>();
+
+ protected AbstractDataNodeContainerBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line);
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ if (childNodes == null) {
+ return Collections.emptySet();
+ }
+ return childNodes;
+ }
+
+ public void setChildNodes(Set<DataSchemaNode> childNodes) {
+ this.childNodes = childNodes;
+ }
+
+ @Override
+ public Set<DataSchemaNodeBuilder> getChildNodeBuilders() {
+ return addedChildNodes;
+ }
+
+ @Override
+ public DataSchemaNodeBuilder getDataChildByName(final String name) {
+ for (DataSchemaNodeBuilder child : addedChildNodes) {
+ if (child.getQName().getLocalName().equals(name)) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void addChildNode(DataSchemaNodeBuilder child) {
+ String childName = child.getQName().getLocalName();
+ for (DataSchemaNodeBuilder addedChildNode : addedChildNodes) {
+ if (addedChildNode.getQName().getLocalName().equals(childName)) {
+ throw new YangParseException(child.getModuleName(), child.getLine(), "Can not add '" + child + "' to '"
+ + this + "' in module '" + moduleName + "': node with same name already declared at line "
+ + addedChildNode.getLine());
+ }
+ }
+ addedChildNodes.add(child);
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ if (groupings == null) {
+ return Collections.emptySet();
+ }
+ return groupings;
+ }
+
+ public void setGroupings(final Set<GroupingDefinition> groupings) {
+ this.groupings = groupings;
+ }
+
+ public Set<GroupingBuilder> getGroupingBuilders() {
+ return addedGroupings;
+ }
+
+ @Override
+ public void addGrouping(GroupingBuilder grouping) {
+ String groupingName = grouping.getQName().getLocalName();
+ for (GroupingBuilder addedGrouping : addedGroupings) {
+ if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
+ throw new YangParseException(grouping.getModuleName(), grouping.getLine(), "Can not add '" + grouping
+ + "': grouping with same name already declared in module '" + moduleName + "' at line "
+ + addedGrouping.getLine());
+ }
+ }
+ addedGroupings.add(grouping);
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.parser.builder.api;\r
+\r
+import java.util.List;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.model.api.SchemaPath;\r
+import org.opendaylight.controller.yang.model.api.Status;\r
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;\r
+\r
+/**\r
+ * Basic implementation of SchemaNodeBuilder.\r
+ */\r
+public abstract class AbstractSchemaNodeBuilder extends AbstractBuilder implements SchemaNodeBuilder {\r
+ protected final QName qname;\r
+ protected SchemaPath schemaPath;\r
+ protected String description;\r
+ protected String reference;\r
+ protected Status status = Status.CURRENT;\r
+ protected List<UnknownSchemaNode> unknownNodes;\r
+\r
+ protected AbstractSchemaNodeBuilder(final String moduleName, final int line, final QName qname) {\r
+ super(moduleName, line);\r
+ this.qname = qname;\r
+ }\r
+\r
+ public QName getQName() {\r
+ return qname;\r
+ }\r
+\r
+ @Override\r
+ public SchemaPath getPath() {\r
+ return schemaPath;\r
+ }\r
+\r
+ @Override\r
+ public void setPath(SchemaPath schemaPath) {\r
+ this.schemaPath = schemaPath;\r
+ }\r
+\r
+ @Override\r
+ public String getDescription() {\r
+ return description;\r
+ }\r
+\r
+ @Override\r
+ public void setDescription(String description) {\r
+ this.description = description;\r
+ }\r
+\r
+ @Override\r
+ public String getReference() {\r
+ return reference;\r
+ }\r
+\r
+ @Override\r
+ public void setReference(String reference) {\r
+ this.reference = reference;\r
+ }\r
+\r
+ @Override\r
+ public Status getStatus() {\r
+ return status;\r
+ }\r
+\r
+ @Override\r
+ public void setStatus(Status status) {\r
+ if (status != null) {\r
+ this.status = status;\r
+ }\r
+ }\r
+\r
+ public void setUnknownNodes(List<UnknownSchemaNode> unknownNodes) {\r
+ this.unknownNodes = unknownNodes;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+
+/**
+ * Basic implementation for TypeAwareBuilder builders.
+ */
+public abstract class AbstractTypeAwareBuilder extends AbstractBuilder implements TypeAwareBuilder {
+ protected final QName qname;
+ protected TypeDefinition<?> type;
+ protected TypeDefinitionBuilder typedef;
+
+ public AbstractTypeAwareBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line);
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public TypeDefinition<?> getType() {
+ return type;
+ }
+
+ @Override
+ public TypeDefinitionBuilder getTypedef() {
+ return typedef;
+ }
+
+ @Override
+ public void setType(TypeDefinition<?> type) {
+ this.type = type;
+ this.typedef = null;
+ }
+
+ @Override
+ public void setTypedef(TypeDefinitionBuilder typedef) {
+ this.typedef = typedef;
+ this.type = null;
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+
+/**
+ * Interface for builders of 'augment' statement.
+ */
+public interface AugmentationSchemaBuilder extends DataNodeContainerBuilder {
+
+ String getWhenCondition();
+
+ void addWhenCondition(String whenCondition);
+
+ void setDescription(String description);
+
+ void setReference(String reference);
+
+ void setStatus(Status status);
+
+ String getTargetPathAsString();
+
+ SchemaPath getTargetPath();
+
+ void setTargetPath(SchemaPath path);
+
+ AugmentationSchema build();
+
+ boolean isResolved();
+
+ void setResolved(boolean resolved);
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+/**
+ * Interface for builders of those nodes, which can be augmentation targets.
+ */
+public interface AugmentationTargetBuilder {
+
+ /**
+ * Add augment, which points to this node.
+ *
+ * @param augment
+ * augment which points to this node
+ */
+ void addAugmentation(AugmentationSchemaBuilder augment);
+
+ /**
+ * Build again already built data node.
+ *
+ * In general, when Builder.build is called first time, it creates YANG data
+ * model node instance. With every other call it just return this instance
+ * without checking for properties change. This method causes that builder
+ * object process again all its properties and return an updated instance of
+ * YANG data node.
+ */
+ void rebuild();
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import java.util.List;
+
+import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
+
+/**
+ * Parent interface for all builder interfaces.
+ */
+public interface Builder {
+
+ /**
+ * Get name of module in which this node is declared.
+ *
+ * @return module name
+ */
+ String getModuleName();
+
+ /**
+ * Set name of module in which this node is declared.
+ *
+ * @param moduleName
+ */
+ void setModuleName(String moduleName);
+
+ /**
+ * Get current line in yang file.
+ *
+ * @return current line in yang file
+ */
+ int getLine();
+
+ /**
+ * Get parent node of this node.
+ *
+ * @return parent node builder or null if this is top level node
+ */
+ Builder getParent();
+
+ /**
+ * Set parent of this node.
+ *
+ * @param parent
+ * parent node builder
+ */
+ void setParent(Builder parent);
+
+ /**
+ * Add unknown node to this builder.
+ *
+ * @param unknownNode
+ */
+ void addUnknownNodeBuilder(UnknownSchemaNodeBuilder unknownNode);
+
+ /**
+ * Get builders of unknown nodes defined in this node.
+ *
+ * @return collection of UnknownSchemaNodeBuilder objects
+ */
+ List<UnknownSchemaNodeBuilder> getUnknownNodeBuilders();
+
+ /**
+ * Build YANG data model node.
+ *
+ * This method should create an instance of YANG data model node. After
+ * creating an instance, this instance should be returned for each call
+ * without repeating build process.
+ *
+ * @return YANG data model node
+ */
+ Object build();
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import java.util.Set;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+
+/**
+ * Interface for all yang data-node containers [augment, case, container,
+ * grouping, list, module, notification].
+ */
+public interface DataNodeContainerBuilder extends Builder {
+
+ /**
+ * Get qname of this node.
+ *
+ * @return QName of this node
+ */
+ QName getQName();
+
+ /**
+ * Get schema path of this node.
+ *
+ * @return SchemaPath of this node
+ */
+ SchemaPath getPath();
+
+ /**
+ * Get already built child nodes.
+ *
+ * @return collection of child nodes
+ */
+ Set<DataSchemaNode> getChildNodes();
+
+ /**
+ * Get builders of child nodes.
+ *
+ * @return collection child nodes builders
+ */
+ Set<DataSchemaNodeBuilder> getChildNodeBuilders();
+
+ /**
+ * Get child node by name.
+ *
+ * @param name
+ * name of child to seek
+ * @return child node with given name if present, null otherwise
+ */
+ DataSchemaNodeBuilder getDataChildByName(String name);
+
+ /**
+ * Add builder of child node to this node.
+ *
+ * @param childNode
+ */
+ void addChildNode(DataSchemaNodeBuilder childNode);
+
+ /**
+ * Get already built groupings defined in this node.
+ *
+ * @return collection of GroupingDefinition objects
+ */
+ Set<GroupingDefinition> getGroupings();
+
+ /**
+ * Get builders of groupings defined in this node.
+ *
+ * @return collection of grouping builders
+ */
+ Set<GroupingBuilder> getGroupingBuilders();
+
+ /**
+ * Add builder of grouping statement to this node.
+ *
+ * @param groupingBuilder
+ */
+ void addGrouping(GroupingBuilder groupingBuilder);
+
+ /**
+ * Add builder of uses statement to this node.
+ *
+ * @param usesBuilder
+ */
+ void addUsesNode(UsesNodeBuilder usesBuilder);
+
+ /**
+ * Get builders of typedef statement defined in this node.
+ *
+ * @return
+ */
+ Set<TypeDefinitionBuilder> getTypeDefinitionBuilders();
+
+ /**
+ * Add typedef builder to this node.
+ *
+ * @param typedefBuilder
+ */
+ void addTypedef(TypeDefinitionBuilder typedefBuilder);
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.impl.ConstraintsBuilder;
+
+/**
+ * Interface for all yang data-schema nodes [anyxml, case, container, grouping,
+ * list, module, notification].
+ */
+public interface DataSchemaNodeBuilder extends SchemaNodeBuilder {
+
+ /**
+ * Build DataSchemaNode object from this builder.
+ */
+ DataSchemaNode build();
+
+ /**
+ *
+ * @return true, if this node is added by augmentation, false otherwise
+ */
+ boolean isAugmenting();
+
+ /**
+ * Set if this node is added by augmentation.
+ *
+ * @param augmenting
+ */
+ void setAugmenting(boolean augmenting);
+
+ /**
+ * Get value of config statement.
+ *
+ * @return value of config statement
+ */
+ Boolean isConfiguration();
+
+ /**
+ * Set config statement.
+ *
+ * @param config
+ */
+ void setConfiguration(Boolean config);
+
+ /**
+ * Get constraints of this builder.
+ *
+ * @return constraints of this builder
+ */
+ ConstraintsBuilder getConstraints();
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import java.util.Set;
+
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+
+/**
+ * Interface for builders of 'grouping' statement.
+ */
+public interface GroupingBuilder extends DataNodeContainerBuilder, SchemaNodeBuilder, GroupingMember {
+
+ /**
+ * Build GroupingDefinition object from this builder.
+ */
+ GroupingDefinition build();
+
+ /**
+ * Get uses statement defined in this builder
+ *
+ * @return collection of builders of uses statements
+ */
+ Set<UsesNodeBuilder> getUses();
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+/**
+ * Marker interface for nodes which can be defined in grouping statement.
+ * [anyxml, choice, container, grouping, leaf, leaf-list, list, typedef, uses]
+ */
+public interface GroupingMember extends Builder {
+
+ /**
+ *
+ * @return true, if this node is added by uses statement, false otherwise
+ */
+ boolean isAddedByUses();
+
+ /**
+ * Set if this node is added by uses.
+ *
+ * @param addedByUses
+ */
+ void setAddedByUses(boolean addedByUses);
+
+}
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.parser.builder.api;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.model.api.SchemaNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaPath;\r
+import org.opendaylight.controller.yang.model.api.Status;\r
+\r
+/**\r
+ * Interface for all builders of SchemaNode nodes.\r
+ */\r
+public interface SchemaNodeBuilder extends Builder {\r
+\r
+ /**\r
+ * Get qname of this node.\r
+ *\r
+ * @return QName of this node\r
+ */\r
+ QName getQName();\r
+\r
+ /**\r
+ * Get schema path of this node.\r
+ *\r
+ * @return SchemaPath of this node\r
+ */\r
+ SchemaPath getPath();\r
+\r
+ /**\r
+ * Set schema path to this node.\r
+ *\r
+ * @param schemaPath\r
+ */\r
+ void setPath(SchemaPath schemaPath);\r
+\r
+ /**\r
+ * Get description of this node.\r
+ *\r
+ * @return description statement\r
+ */\r
+ String getDescription();\r
+\r
+ /**\r
+ * Set description to this node.\r
+ *\r
+ * @param description\r
+ */\r
+ void setDescription(String description);\r
+\r
+ /**\r
+ * Get reference of this node.\r
+ *\r
+ * @return reference statement\r
+ */\r
+ String getReference();\r
+\r
+ /**\r
+ * Set reference to this node.\r
+ *\r
+ * @param reference\r
+ */\r
+ void setReference(String reference);\r
+\r
+ /**\r
+ * Get status of this node.\r
+ *\r
+ * @return status statement\r
+ */\r
+ Status getStatus();\r
+\r
+ /**\r
+ * Set status to this node.\r
+ *\r
+ * @param status\r
+ */\r
+ void setStatus(Status status);\r
+\r
+ /**\r
+ * Build SchemaNode object from this builder.\r
+ */\r
+ SchemaNode build();\r
+\r
+}\r
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+
+/**
+ * Builders of all nodes, which can have 'type' statement must implement this
+ * interface. [typedef, type, leaf, leaf-list, deviate]
+ */
+public interface TypeAwareBuilder extends Builder {
+
+ /**
+ * Get qname of this node.
+ *
+ * @return QName of this node
+ */
+ QName getQName();
+
+ /**
+ * Get schema path of this node.
+ *
+ * @return SchemaPath of this node
+ */
+ SchemaPath getPath();
+
+ /**
+ * Get resolved type of this node.
+ *
+ * @return type of this node if it is already resolved, null otherwise
+ */
+ TypeDefinition<?> getType();
+
+ /**
+ * Get builder of type of this node.
+ *
+ * @return builder of type of this node or null of this builder has already
+ * resolved type
+ */
+ TypeDefinitionBuilder getTypedef();
+
+ /**
+ * Set resolved type to this node.
+ *
+ * @param type
+ * type to set
+ */
+ void setType(TypeDefinition<?> type);
+
+ /**
+ * Set builder of type to this node.
+ *
+ * @param typedef
+ * builder of type to set
+ */
+ void setTypedef(TypeDefinitionBuilder typedef);
+
+}
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.parser.builder.api;\r
+\r
+import java.util.List;\r
+\r
+import org.opendaylight.controller.yang.model.api.TypeDefinition;\r
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;\r
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;\r
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;\r
+\r
+/**\r
+ * Interface for builders of 'typedef' statement.\r
+ */\r
+public interface TypeDefinitionBuilder extends TypeAwareBuilder, SchemaNodeBuilder, GroupingMember {\r
+\r
+ TypeDefinition<?> build();\r
+\r
+ List<RangeConstraint> getRanges();\r
+\r
+ void setRanges(List<RangeConstraint> ranges);\r
+\r
+ List<LengthConstraint> getLengths();\r
+\r
+ void setLengths(List<LengthConstraint> lengths);\r
+\r
+ List<PatternConstraint> getPatterns();\r
+\r
+ void setPatterns(List<PatternConstraint> patterns);\r
+\r
+ Integer getFractionDigits();\r
+\r
+ void setFractionDigits(Integer fractionDigits);\r
+\r
+ List<UnknownSchemaNode> getUnknownNodes();\r
+\r
+ Object getDefaultValue();\r
+\r
+ void setDefaultValue(Object defaultValue);\r
+\r
+ String getUnits();\r
+\r
+ void setUnits(String units);\r
+\r
+}\r
--- /dev/null
+/*
+ * 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.yang.parser.builder.api;
+
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.util.RefineHolder;
+
+/**
+ * Interface for builders of 'uses' statement.
+ */
+public interface UsesNodeBuilder extends GroupingMember, Builder {
+
+ DataNodeContainerBuilder getParent();
+
+ String getGroupingName();
+
+ SchemaPath getGroupingPath();
+
+ void setGroupingPath(SchemaPath groupingPath);
+
+ Set<AugmentationSchemaBuilder> getAugmentations();
+
+ void addAugment(AugmentationSchemaBuilder builder);
+
+ boolean isAugmenting();
+
+ void setAugmenting(boolean augmenting);
+
+ List<RefineHolder> getRefines();
+
+ List<SchemaNodeBuilder> getRefineNodes();
+
+ void addRefine(RefineHolder refine);
+
+ void addRefineNode(SchemaNodeBuilder refineNode);
+
+ UsesNode build();
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+
+public final class AnyXmlBuilder extends AbstractSchemaNodeBuilder implements DataSchemaNodeBuilder, GroupingMember {
+ private boolean built;
+ private final AnyXmlSchemaNodeImpl instance;
+ private final ConstraintsBuilder constraints;
+
+ private Boolean configuration;
+ private boolean augmenting;
+ private boolean addedByUses;
+
+ public AnyXmlBuilder(final String moduleName, final int line, final QName qname, final SchemaPath schemaPath) {
+ super(moduleName, line, qname);
+ this.schemaPath = schemaPath;
+ instance = new AnyXmlSchemaNodeImpl(qname);
+ constraints = new ConstraintsBuilder(moduleName, line);
+ }
+
+ public AnyXmlBuilder(final AnyXmlBuilder builder) {
+ super(builder.getModuleName(), builder.getLine(), builder.getQName());
+ parent = builder.getParent();
+ instance = new AnyXmlSchemaNodeImpl(qname);
+ constraints = builder.getConstraints();
+ schemaPath = builder.getPath();
+ unknownNodes = builder.unknownNodes;
+ addedUnknownNodes.addAll(builder.getUnknownNodes());
+ description = builder.getDescription();
+ reference = builder.getReference();
+ status = builder.getStatus();
+ configuration = builder.isConfiguration();
+ augmenting = builder.isAugmenting();
+ addedByUses = builder.isAddedByUses();
+ }
+
+ @Override
+ public AnyXmlSchemaNode build() {
+ if (!built) {
+ instance.setPath(schemaPath);
+ instance.setConstraints(constraints.build());
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setConfiguration(configuration);
+ instance.setAugmenting(augmenting);
+ instance.setAddedByUses(addedByUses);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ built = true;
+ }
+ return instance;
+ }
+
+ @Override
+ public ConstraintsBuilder getConstraints() {
+ return constraints;
+ }
+
+ public List<UnknownSchemaNodeBuilder> getUnknownNodes() {
+ return addedUnknownNodes;
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ @Override
+ public void setAugmenting(final boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public Boolean isConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ public void setConfiguration(final Boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ AnyXmlBuilder other = (AnyXmlBuilder) obj;
+ if (schemaPath == null) {
+ if (other.schemaPath != null) {
+ return false;
+ }
+ } else if (!schemaPath.equals(other.schemaPath)) {
+ return false;
+ }
+ if (parent == null) {
+ if (other.parent != null) {
+ return false;
+ }
+ } else if (!parent.equals(other.parent)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "anyxml " + qname.getLocalName();
+ }
+
+ private final class AnyXmlSchemaNodeImpl implements AnyXmlSchemaNode {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private boolean configuration;
+ private ConstraintDefinition constraintsDef;
+ private boolean augmenting;
+ private boolean addedByUses;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private AnyXmlSchemaNodeImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(final SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ private void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ private void setAddedByUses(boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public boolean isConfiguration() {
+ return configuration;
+ }
+
+ private void setConfiguration(boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintDefinition getConstraints() {
+ return constraintsDef;
+ }
+
+ private void setConstraints(ConstraintDefinition constraintsDef) {
+ this.constraintsDef = constraintsDef;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ AnyXmlSchemaNodeImpl other = (AnyXmlSchemaNodeImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(AnyXmlSchemaNodeImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("qname=" + qname);
+ sb.append(", path=" + path);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+import org.opendaylight.controller.yang.parser.util.ParserListenerUtils;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+public final class AugmentationSchemaBuilderImpl extends AbstractDataNodeContainerBuilder implements
+ AugmentationSchemaBuilder {
+ private boolean built;
+ private final AugmentationSchemaImpl instance;
+
+ private String whenCondition;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+
+ private final String augmentTargetStr;
+ private SchemaPath dirtyAugmentTarget;
+ private SchemaPath finalAugmentTarget;
+
+ private final Set<UsesNodeBuilder> usesNodes = new HashSet<UsesNodeBuilder>();
+ private boolean resolved;
+
+ AugmentationSchemaBuilderImpl(final String moduleName, final int line, final String augmentTargetStr) {
+ super(moduleName, line, null);
+ this.augmentTargetStr = augmentTargetStr;
+ final SchemaPath targetPath = ParserListenerUtils.parseAugmentPath(augmentTargetStr);
+ dirtyAugmentTarget = targetPath;
+ instance = new AugmentationSchemaImpl(targetPath);
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<GroupingBuilder> getGroupingBuilders() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void addGrouping(GroupingBuilder grouping) {
+ throw new YangParseException(moduleName, line, "augment can not contains grouping statement");
+ }
+
+ @Override
+ public void addUsesNode(UsesNodeBuilder usesBuilder) {
+ usesNodes.add(usesBuilder);
+ }
+
+ /**
+ * Always returns null.
+ */
+ @Override
+ public SchemaPath getPath() {
+ return null;
+ }
+
+ @Override
+ public AugmentationSchema build() {
+ if (!built) {
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setTargetPath(finalAugmentTarget);
+
+ RevisionAwareXPath whenStmt;
+ if (whenCondition == null) {
+ whenStmt = null;
+ } else {
+ whenStmt = new RevisionAwareXPathImpl(whenCondition, false);
+ }
+ instance.setWhenCondition(whenStmt);
+
+ // CHILD NODES
+ final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
+ for (DataSchemaNodeBuilder node : addedChildNodes) {
+ childs.put(node.getQName(), node.build());
+ }
+ instance.setChildNodes(childs);
+
+ // USES
+ final Set<UsesNode> usesNodeDefinitions = new HashSet<UsesNode>();
+ for (UsesNodeBuilder builder : usesNodes) {
+ usesNodeDefinitions.add(builder.build());
+ }
+ instance.setUses(usesNodeDefinitions);
+
+ // UNKNOWN NODES
+ List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ built = true;
+ }
+ return instance;
+ }
+
+ @Override
+ public boolean isResolved() {
+ return resolved;
+ }
+
+ @Override
+ public void setResolved(boolean resolved) {
+ this.resolved = resolved;
+ }
+
+ public String getWhenCondition() {
+ return whenCondition;
+ }
+
+ public void addWhenCondition(String whenCondition) {
+ this.whenCondition = whenCondition;
+ }
+
+ @Override
+ public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void addTypedef(TypeDefinitionBuilder type) {
+ throw new YangParseException(moduleName, line, "Augmentation can not contains typedef statement.");
+ }
+
+ @Override
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public SchemaPath getTargetPath() {
+ return dirtyAugmentTarget;
+ }
+
+ @Override
+ public void setTargetPath(SchemaPath path) {
+ this.finalAugmentTarget = path;
+ }
+
+ @Override
+ public String getTargetPathAsString() {
+ return augmentTargetStr;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 17;
+ int result = 1;
+ result = prime * result + ((augmentTargetStr == null) ? 0 : augmentTargetStr.hashCode());
+ result = prime * result + ((whenCondition == null) ? 0 : whenCondition.hashCode());
+ result = prime * result + ((childNodes == null) ? 0 : childNodes.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ AugmentationSchemaBuilderImpl other = (AugmentationSchemaBuilderImpl) obj;
+ if (augmentTargetStr == null) {
+ if (other.augmentTargetStr != null) {
+ return false;
+ }
+ } else if (!augmentTargetStr.equals(other.augmentTargetStr)) {
+ return false;
+ }
+ if (whenCondition == null) {
+ if (other.whenCondition != null) {
+ return false;
+ }
+ } else if (!whenCondition.equals(other.whenCondition)) {
+ return false;
+ }
+ if (childNodes == null) {
+ if (other.childNodes != null) {
+ return false;
+ }
+ } else if (!childNodes.equals(other.childNodes)) {
+ return false;
+ }
+ return true;
+ }
+
+ public String toString() {
+ return "augment " + augmentTargetStr;
+ }
+
+ private final class AugmentationSchemaImpl implements AugmentationSchema {
+ private SchemaPath targetPath;
+ private RevisionAwareXPath whenCondition;
+ private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
+ private Set<UsesNode> uses = Collections.emptySet();
+ private String description;
+ private String reference;
+ private Status status;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private AugmentationSchemaImpl(SchemaPath targetPath) {
+ this.targetPath = targetPath;
+ }
+
+ @Override
+ public SchemaPath getTargetPath() {
+ return targetPath;
+ }
+
+ private void setTargetPath(SchemaPath path) {
+ this.targetPath = path;
+ }
+
+ @Override
+ public RevisionAwareXPath getWhenCondition() {
+ return whenCondition;
+ }
+
+ private void setWhenCondition(RevisionAwareXPath whenCondition) {
+ this.whenCondition = whenCondition;
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ final Set<DataSchemaNode> result = new TreeSet<DataSchemaNode>(Comparators.SCHEMA_NODE_COMP);
+ result.addAll(childNodes.values());
+ return result;
+ }
+
+ private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
+ if (childNodes != null) {
+ this.childNodes = childNodes;
+ }
+ }
+
+ /**
+ * Always returns an empty set, because augment can not contains
+ * grouping statement.
+ */
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return uses;
+ }
+
+ private void setUses(Set<UsesNode> uses) {
+ if (uses != null) {
+ this.uses = uses;
+ }
+ }
+
+ /**
+ * Always returns an empty set, because augment can not contains type
+ * definitions.
+ */
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
+ if (unknownSchemaNodes != null) {
+ this.unknownNodes = unknownSchemaNodes;
+ }
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(QName name) {
+ return childNodes.get(name);
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(String name) {
+ DataSchemaNode result = null;
+ for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
+ if (entry.getKey().getLocalName().equals(name)) {
+ result = entry.getValue();
+ break;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 17;
+ int result = 1;
+ result = prime * result + ((targetPath == null) ? 0 : targetPath.hashCode());
+ result = prime * result + ((whenCondition == null) ? 0 : whenCondition.hashCode());
+ result = prime * result + ((childNodes == null) ? 0 : childNodes.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ AugmentationSchemaImpl other = (AugmentationSchemaImpl) obj;
+ if (targetPath == null) {
+ if (other.targetPath != null) {
+ return false;
+ }
+ } else if (!targetPath.equals(other.targetPath)) {
+ return false;
+ }
+ if (whenCondition == null) {
+ if (other.whenCondition != null) {
+ return false;
+ }
+ } else if (!whenCondition.equals(other.whenCondition)) {
+ return false;
+ }
+ if (childNodes == null) {
+ if (other.childNodes != null) {
+ return false;
+ }
+ } else if (!childNodes.equals(other.childNodes)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(AugmentationSchemaImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("targetPath=" + targetPath);
+ sb.append(", when=" + whenCondition);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+import org.opendaylight.controller.yang.parser.util.ParserUtils;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements DataSchemaNodeBuilder,
+ AugmentationTargetBuilder, GroupingMember {
+ private boolean isBuilt;
+ private final ChoiceNodeImpl instance;
+ // DataSchemaNode args
+ private boolean augmenting;
+ private boolean addedByUses;
+ private Boolean configuration;
+ private final ConstraintsBuilder constraints;
+ // AugmentationTarget args
+ private final Set<AugmentationSchemaBuilder> addedAugmentations = new HashSet<AugmentationSchemaBuilder>();
+ // ChoiceNode args
+ private Set<ChoiceCaseNode> cases;
+ private final Set<ChoiceCaseBuilder> addedCases = new HashSet<ChoiceCaseBuilder>();
+ private String defaultCase;
+
+ public ChoiceBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ instance = new ChoiceNodeImpl(qname);
+ constraints = new ConstraintsBuilder(moduleName, line);
+ }
+
+ public ChoiceBuilder(ChoiceBuilder b) {
+ super(b.getModuleName(), b.getLine(), b.getQName());
+ parent = b.getParent();
+ instance = new ChoiceNodeImpl(qname);
+ constraints = b.getConstraints();
+ schemaPath = b.getPath();
+ description = b.getDescription();
+ reference = b.getReference();
+ status = b.getStatus();
+ unknownNodes = b.unknownNodes;
+ addedUnknownNodes.addAll(b.getUnknownNodes());
+ augmenting = b.isAugmenting();
+ addedByUses = b.isAddedByUses();
+ configuration = b.isConfiguration();
+ addedAugmentations.addAll(b.getAugmentations());
+ cases = b.cases;
+ addedCases.addAll(b.getCases());
+ defaultCase = b.getDefaultCase();
+ }
+
+ @Override
+ public ChoiceNode build() {
+ if (!isBuilt) {
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setAugmenting(augmenting);
+ instance.setAddedByUses(addedByUses);
+ instance.setConfiguration(configuration);
+ instance.setConstraints(constraints.build());
+ instance.setDefaultCase(defaultCase);
+
+ // CASES
+ if (cases == null) {
+ cases = new TreeSet<ChoiceCaseNode>(Comparators.SCHEMA_NODE_COMP);
+ for (ChoiceCaseBuilder caseBuilder : addedCases) {
+ cases.add(caseBuilder.build());
+ }
+ }
+ instance.setCases(cases);
+
+ // AUGMENTATIONS
+ final Set<AugmentationSchema> augmentations = new HashSet<AugmentationSchema>();
+ for (AugmentationSchemaBuilder builder : addedAugmentations) {
+ augmentations.add(builder.build());
+ }
+ instance.setAvailableAugmentations(augmentations);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+ return instance;
+ }
+
+ @Override
+ public void rebuild() {
+ isBuilt = false;
+ build();
+ }
+
+ public Set<ChoiceCaseBuilder> getCases() {
+ return addedCases;
+ }
+
+ /**
+ * Add case node to this choice.
+ *
+ * If node is not declared with 'case' keyword, create new case builder and
+ * make this node child of newly created case.
+ *
+ * @param caseNode
+ * case node
+ */
+ public void addCase(DataSchemaNodeBuilder caseNode) {
+ QName caseQName = caseNode.getQName();
+ String caseName = caseQName.getLocalName();
+ for (ChoiceCaseBuilder addedCase : addedCases) {
+ if (addedCase.getQName().getLocalName().equals(caseName)) {
+ throw new YangParseException(caseNode.getModuleName(), caseNode.getLine(), "Can not add '" + caseNode
+ + "' to node '" + qname.getLocalName() + "' in module '" + moduleName
+ + "': case with same name already declared at line " + addedCase.getLine());
+ }
+ }
+
+ if (caseNode instanceof ChoiceCaseBuilder) {
+ addedCases.add((ChoiceCaseBuilder) caseNode);
+ } else {
+ ChoiceCaseBuilder caseBuilder = new ChoiceCaseBuilder(caseNode.getModuleName(), caseNode.getLine(),
+ caseQName);
+ if (caseNode.isAugmenting()) {
+ // if node is added by augmentation, set case builder augmenting
+ // as true and node augmenting as false
+ caseBuilder.setAugmenting(true);
+ caseNode.setAugmenting(false);
+ }
+ caseBuilder.setPath(caseNode.getPath());
+ SchemaPath newPath = ParserUtils.createSchemaPath(caseNode.getPath(), caseQName.getLocalName(),
+ caseQName.getNamespace(), caseQName.getRevision(), caseQName.getPrefix());
+ caseNode.setPath(newPath);
+ caseBuilder.addChildNode(caseNode);
+ addedCases.add(caseBuilder);
+ }
+ }
+
+ public void setCases(Set<ChoiceCaseNode> cases) {
+ this.cases = cases;
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ @Override
+ public void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ public Boolean isConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ public void setConfiguration(Boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintsBuilder getConstraints() {
+ return constraints;
+ }
+
+ public Set<AugmentationSchemaBuilder> getAugmentations() {
+ return addedAugmentations;
+ }
+
+ @Override
+ public void addAugmentation(AugmentationSchemaBuilder augment) {
+ addedAugmentations.add(augment);
+ }
+
+ public List<UnknownSchemaNodeBuilder> getUnknownNodes() {
+ return addedUnknownNodes;
+ }
+
+ public String getDefaultCase() {
+ return defaultCase;
+ }
+
+ public void setDefaultCase(String defaultCase) {
+ this.defaultCase = defaultCase;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ChoiceBuilder other = (ChoiceBuilder) obj;
+ if (schemaPath == null) {
+ if (other.schemaPath != null) {
+ return false;
+ }
+ } else if (!schemaPath.equals(other.schemaPath)) {
+ return false;
+ }
+ if (parent == null) {
+ if (other.parent != null) {
+ return false;
+ }
+ } else if (!parent.equals(other.parent)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "choice " + qname.getLocalName();
+ }
+
+ public final class ChoiceNodeImpl implements ChoiceNode {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private boolean augmenting;
+ private boolean addedByUses;
+ private boolean configuration;
+ private ConstraintDefinition constraints;
+ private Set<ChoiceCaseNode> cases = Collections.emptySet();
+ private Set<AugmentationSchema> augmentations = Collections.emptySet();
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+ private String defaultCase;
+
+ private ChoiceNodeImpl(QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ private void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ private void setAddedByUses(boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public boolean isConfiguration() {
+ return configuration;
+ }
+
+ private void setConfiguration(boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintDefinition getConstraints() {
+ return constraints;
+ }
+
+ private void setConstraints(ConstraintDefinition constraints) {
+ this.constraints = constraints;
+ }
+
+ @Override
+ public Set<AugmentationSchema> getAvailableAugmentations() {
+ return augmentations;
+ }
+
+ private void setAvailableAugmentations(Set<AugmentationSchema> availableAugmentations) {
+ if (availableAugmentations != null) {
+ this.augmentations = availableAugmentations;
+ }
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
+ if (unknownSchemaNodes != null) {
+ this.unknownNodes = unknownSchemaNodes;
+ }
+ }
+
+ @Override
+ public Set<ChoiceCaseNode> getCases() {
+ return cases;
+ }
+
+ @Override
+ public ChoiceCaseNode getCaseNodeByName(final QName name) {
+ if (name == null) {
+ throw new IllegalArgumentException("Choice Case QName cannot be NULL!");
+ }
+ for (final ChoiceCaseNode caseNode : cases) {
+ if (caseNode != null) {
+ if (name.equals(caseNode.getQName())) {
+ return caseNode;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public ChoiceCaseNode getCaseNodeByName(final String name) {
+ if (name == null) {
+ throw new IllegalArgumentException("Choice Case string Name cannot be NULL!");
+ }
+ for (final ChoiceCaseNode caseNode : cases) {
+ if (caseNode != null && (caseNode.getQName() != null)) {
+ if (name.equals(caseNode.getQName().getLocalName())) {
+ return caseNode;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void setCases(Set<ChoiceCaseNode> cases) {
+ if (cases != null) {
+ this.cases = cases;
+ }
+ }
+
+ @Override
+ public String getDefaultCase() {
+ return defaultCase;
+ }
+
+ private void setDefaultCase(String defaultCase) {
+ this.defaultCase = defaultCase;
+ }
+
+ public ChoiceBuilder toBuilder() {
+ return ChoiceBuilder.this;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ChoiceNodeImpl other = (ChoiceNodeImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(ChoiceNodeImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("qname=" + qname);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+public final class ChoiceCaseBuilder extends AbstractDataNodeContainerBuilder implements DataSchemaNodeBuilder,
+ AugmentationTargetBuilder {
+ private boolean isBuilt;
+ private final ChoiceCaseNodeImpl instance;
+ // SchemaNode args
+ private SchemaPath schemaPath;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ // DataSchemaNode args
+ private boolean augmenting;
+ private final ConstraintsBuilder constraints;
+ // DataNodeContainer args
+ private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
+ // AugmentationTarget args
+ private final Set<AugmentationSchemaBuilder> addedAugmentations = new HashSet<AugmentationSchemaBuilder>();
+
+ ChoiceCaseBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ instance = new ChoiceCaseNodeImpl(qname);
+ constraints = new ConstraintsBuilder(moduleName, line);
+ }
+
+ @Override
+ public ChoiceCaseNode build() {
+ if (!isBuilt) {
+ instance.setConstraints(constraints.build());
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setAugmenting(augmenting);
+
+ // CHILD NODES
+ final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
+ for (DataSchemaNodeBuilder node : addedChildNodes) {
+ childs.put(node.getQName(), node.build());
+ }
+ instance.setChildNodes(childs);
+
+ // USES
+ final Set<UsesNode> uses = new HashSet<UsesNode>();
+ for (UsesNodeBuilder builder : addedUsesNodes) {
+ uses.add(builder.build());
+ }
+ instance.setUses(uses);
+
+ // UNKNOWN NODES
+ final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ // AUGMENTATIONS
+ final Set<AugmentationSchema> augmentations = new HashSet<AugmentationSchema>();
+ for (AugmentationSchemaBuilder builder : addedAugmentations) {
+ augmentations.add(builder.build());
+ }
+ instance.setAvailableAugmentations(augmentations);
+
+ isBuilt = true;
+ }
+
+ return instance;
+ }
+
+ @Override
+ public void rebuild() {
+ isBuilt = false;
+ build();
+ }
+
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public void setPath(final SchemaPath schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ @Override
+ public void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ public Set<UsesNodeBuilder> getUsesNodes() {
+ return addedUsesNodes;
+ }
+
+ @Override
+ public void addUsesNode(UsesNodeBuilder usesNodeBuilder) {
+ addedUsesNodes.add(usesNodeBuilder);
+ }
+
+ @Override
+ public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void addTypedef(TypeDefinitionBuilder typedefBuilder) {
+ throw new YangParseException(moduleName, line, "Can not add type definition to choice case.");
+ }
+
+ @Override
+ public Boolean isConfiguration() {
+ return false;
+ }
+
+ @Override
+ public void setConfiguration(final Boolean configuration) {
+ throw new YangParseException(moduleName, line, "Can not add config statement to choice case.");
+ }
+
+ @Override
+ public ConstraintsBuilder getConstraints() {
+ return constraints;
+ }
+
+ @Override
+ public void addAugmentation(AugmentationSchemaBuilder augment) {
+ addedAugmentations.add(augment);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ChoiceCaseBuilder other = (ChoiceCaseBuilder) obj;
+ if (schemaPath == null) {
+ if (other.schemaPath != null) {
+ return false;
+ }
+ } else if (!schemaPath.equals(other.schemaPath)) {
+ return false;
+ }
+ if (parent == null) {
+ if (other.parent != null) {
+ return false;
+ }
+ } else if (!parent.equals(other.parent)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "case " + getQName().getLocalName();
+ }
+
+ public final class ChoiceCaseNodeImpl implements ChoiceCaseNode {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private boolean augmenting;
+ private ConstraintDefinition constraints;
+ private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
+ private Set<AugmentationSchema> augmentations = Collections.emptySet();
+ private Set<UsesNode> uses = Collections.emptySet();
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private ChoiceCaseNodeImpl(QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public boolean isConfiguration() {
+ return false;
+ }
+
+ @Override
+ public ConstraintDefinition getConstraints() {
+ return constraints;
+ }
+
+ private void setConstraints(ConstraintDefinition constraints) {
+ this.constraints = constraints;
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ private void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return false;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ /**
+ * Always returns an empty set, because case node can not contains type
+ * definitions.
+ */
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ return new HashSet<DataSchemaNode>(childNodes.values());
+ }
+
+ private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
+ if (childNodes != null) {
+ this.childNodes = childNodes;
+ }
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(QName name) {
+ return childNodes.get(name);
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(String name) {
+ DataSchemaNode result = null;
+ for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
+ if (entry.getKey().getLocalName().equals(name)) {
+ result = entry.getValue();
+ break;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return uses;
+ }
+
+ private void setUses(Set<UsesNode> uses) {
+ if (uses != null) {
+ this.uses = uses;
+ }
+ }
+
+ @Override
+ public Set<AugmentationSchema> getAvailableAugmentations() {
+ return augmentations;
+ }
+
+ private void setAvailableAugmentations(Set<AugmentationSchema> augmentations) {
+ if (augmentations != null) {
+ this.augmentations = augmentations;
+ }
+ }
+
+ public ChoiceCaseBuilder toBuilder() {
+ return ChoiceCaseBuilder.this;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ChoiceCaseNodeImpl other = (ChoiceCaseNodeImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(ChoiceCaseNodeImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("qname=" + qname);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.MustDefinition;
+import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractBuilder;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+public final class ConstraintsBuilder extends AbstractBuilder {
+ private final ConstraintDefinitionImpl instance;
+ private final Set<MustDefinition> mustDefinitions;
+ private String whenCondition;
+ private boolean mandatory;
+ private Integer min;
+ private Integer max;
+
+ ConstraintsBuilder(final String moduleName, final int line) {
+ super(moduleName, line);
+ instance = new ConstraintDefinitionImpl();
+ mustDefinitions = new HashSet<MustDefinition>();
+ }
+
+ @Override
+ public ConstraintDefinition build() {
+ RevisionAwareXPath whenStmt;
+ if (whenCondition == null) {
+ whenStmt = null;
+ } else {
+ whenStmt = new RevisionAwareXPathImpl(whenCondition, false);
+ }
+ instance.setWhenCondition(whenStmt);
+ instance.setMustConstraints(mustDefinitions);
+ instance.setMandatory(mandatory);
+ instance.setMinElements(min);
+ instance.setMaxElements(max);
+ return instance;
+ }
+
+ @Override
+ public void addUnknownNodeBuilder(UnknownSchemaNodeBuilder unknownNode) {
+ throw new YangParseException(moduleName, line, "Can not add unknown node to constraints.");
+ }
+
+ @Override
+ public List<UnknownSchemaNodeBuilder> getUnknownNodeBuilders() {
+ return Collections.emptyList();
+ }
+
+ public Integer getMinElements() {
+ return min;
+ }
+
+ public void setMinElements(Integer minElements) {
+ this.min = minElements;
+ }
+
+ public Integer getMaxElements() {
+ return max;
+ }
+
+ public void setMaxElements(Integer maxElements) {
+ this.max = maxElements;
+ }
+
+ public Set<MustDefinition> getMustDefinitions() {
+ return mustDefinitions;
+ }
+
+ public void addMustDefinition(MustDefinition must) {
+ mustDefinitions.add(must);
+ }
+
+ public String getWhenCondition() {
+ return whenCondition;
+ }
+
+ public void addWhenCondition(String whenCondition) {
+ this.whenCondition = whenCondition;
+ }
+
+ public boolean isMandatory() {
+ return mandatory;
+ }
+
+ public void setMandatory(boolean mandatory) {
+ this.mandatory = mandatory;
+ }
+
+ private final class ConstraintDefinitionImpl implements ConstraintDefinition {
+ private RevisionAwareXPath whenCondition;
+ private Set<MustDefinition> mustConstraints;
+ private boolean mandatory;
+ private Integer minElements;
+ private Integer maxElements;
+
+ @Override
+ public RevisionAwareXPath getWhenCondition() {
+ return whenCondition;
+ }
+
+ private void setWhenCondition(RevisionAwareXPath whenCondition) {
+ this.whenCondition = whenCondition;
+ }
+
+ @Override
+ public Set<MustDefinition> getMustConstraints() {
+ if (mustConstraints == null) {
+ return Collections.emptySet();
+ } else {
+ return mustConstraints;
+ }
+ }
+
+ private void setMustConstraints(Set<MustDefinition> mustConstraints) {
+ if (mustConstraints != null) {
+ this.mustConstraints = mustConstraints;
+ }
+ }
+
+ @Override
+ public boolean isMandatory() {
+ return mandatory;
+ }
+
+ private void setMandatory(boolean mandatory) {
+ this.mandatory = mandatory;
+ }
+
+ @Override
+ public Integer getMinElements() {
+ return minElements;
+ }
+
+ private void setMinElements(Integer minElements) {
+ this.minElements = minElements;
+ }
+
+ @Override
+ public Integer getMaxElements() {
+ return maxElements;
+ }
+
+ private void setMaxElements(Integer maxElements) {
+ this.maxElements = maxElements;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((whenCondition == null) ? 0 : whenCondition.hashCode());
+ result = prime * result + ((mustConstraints == null) ? 0 : mustConstraints.hashCode());
+ result = prime * result + ((minElements == null) ? 0 : minElements.hashCode());
+ result = prime * result + ((maxElements == null) ? 0 : maxElements.hashCode());
+ result = prime * result + (mandatory ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ConstraintDefinitionImpl other = (ConstraintDefinitionImpl) obj;
+ if (whenCondition == null) {
+ if (other.whenCondition != null) {
+ return false;
+ }
+ } else if (!whenCondition.equals(other.whenCondition)) {
+ return false;
+ }
+ if (mustConstraints == null) {
+ if (other.mustConstraints != null) {
+ return false;
+ }
+ } else if (!mustConstraints.equals(other.mustConstraints)) {
+ return false;
+ }
+ if (mandatory != other.mandatory) {
+ return false;
+ }
+ if (minElements == null) {
+ if (other.minElements != null) {
+ return false;
+ }
+ } else if (!minElements.equals(other.minElements)) {
+ return false;
+ }
+ if (maxElements == null) {
+ if (other.maxElements != null) {
+ return false;
+ }
+ } else if (!maxElements.equals(other.maxElements)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(ConstraintDefinitionImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("whenCondition=" + whenCondition);
+ sb.append(", mustConstraints=" + mustConstraints);
+ sb.append(", mandatory=" + mandatory);
+ sb.append(", minElements=" + minElements);
+ sb.append(", maxElements=" + maxElements);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerBuilder implements
+ AugmentationTargetBuilder, DataSchemaNodeBuilder, GroupingMember {
+ private boolean isBuilt;
+ private final ContainerSchemaNodeImpl instance;
+
+ // SchemaNode args
+ private SchemaPath schemaPath;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ // DataSchemaNode args
+ private boolean augmenting;
+ private boolean addedByUses;
+ private Boolean configuration;
+ private final ConstraintsBuilder constraints;
+ // DataNodeContainer args
+ private Set<TypeDefinition<?>> typedefs;
+ private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
+ private Set<UsesNode> usesNodes;
+ private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
+ // AugmentationTarget args
+ private Set<AugmentationSchema> augmentations;
+ private final Set<AugmentationSchemaBuilder> addedAugmentations = new HashSet<AugmentationSchemaBuilder>();
+ // ContainerSchemaNode args
+ private boolean presence;
+
+ public ContainerSchemaNodeBuilder(final String moduleName, final int line, final QName qname,
+ final SchemaPath schemaPath) {
+ super(moduleName, line, qname);
+ this.schemaPath = schemaPath;
+ instance = new ContainerSchemaNodeImpl(qname);
+ constraints = new ConstraintsBuilder(moduleName, line);
+ }
+
+ public ContainerSchemaNodeBuilder(final ContainerSchemaNodeBuilder b) {
+ super(b.getModuleName(), b.getLine(), b.getQName());
+ instance = new ContainerSchemaNodeImpl(b.getQName());
+ constraints = b.getConstraints();
+ schemaPath = b.getPath();
+ description = b.getDescription();
+ reference = b.getReference();
+ status = b.getStatus();
+ presence = b.isPresence();
+ augmenting = b.isAugmenting();
+ addedByUses = b.isAddedByUses();
+ configuration = b.isConfiguration();
+ childNodes = b.getChildNodes();
+ addedChildNodes.addAll(b.getChildNodeBuilders());
+ groupings = b.getGroupings();
+ addedGroupings.addAll(b.getGroupingBuilders());
+ typedefs = b.typedefs;
+ addedTypedefs.addAll(b.getTypeDefinitionBuilders());
+ usesNodes = b.usesNodes;
+ addedUsesNodes.addAll(b.getUsesNodes());
+ augmentations = b.augmentations;
+ addedAugmentations.addAll(b.getAugmentations());
+ unknownNodes = b.unknownNodes;
+ addedUnknownNodes.addAll(b.getUnknownNodeBuilders());
+ }
+
+ @Override
+ public ContainerSchemaNode build() {
+ if (!isBuilt) {
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setPresenceContainer(presence);
+ instance.setAugmenting(augmenting);
+ instance.setAddedByUses(addedByUses);
+
+ // if this builder represents rpc input or output, it can has
+ // configuration value set to null
+ if (configuration == null) {
+ configuration = false;
+ }
+ instance.setConfiguration(configuration);
+
+ // CHILD NODES
+ final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
+ if (childNodes == null || childNodes.isEmpty()) {
+ for (DataSchemaNodeBuilder node : addedChildNodes) {
+ childs.put(node.getQName(), node.build());
+ }
+ } else {
+ for (DataSchemaNode node : childNodes) {
+ childs.put(node.getQName(), node);
+ }
+ }
+ instance.setChildNodes(childs);
+
+ // GROUPINGS
+ if (groupings == null) {
+ groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
+ for (GroupingBuilder builder : addedGroupings) {
+ groupings.add(builder.build());
+ }
+ }
+ instance.setGroupings(groupings);
+
+ // TYPEDEFS
+ if (typedefs == null) {
+ typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
+ for (TypeDefinitionBuilder entry : addedTypedefs) {
+ typedefs.add(entry.build());
+ }
+ }
+ instance.setTypeDefinitions(typedefs);
+
+ // USES
+ if (usesNodes == null) {
+ usesNodes = new HashSet<UsesNode>();
+ for (UsesNodeBuilder builder : addedUsesNodes) {
+ usesNodes.add(builder.build());
+ }
+ }
+ instance.setUses(usesNodes);
+
+ // AUGMENTATIONS
+ if (augmentations == null) {
+ augmentations = new HashSet<AugmentationSchema>();
+ for (AugmentationSchemaBuilder builder : addedAugmentations) {
+ augmentations.add(builder.build());
+ }
+ }
+ instance.setAvailableAugmentations(augmentations);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ instance.setConstraints(constraints.build());
+ instance.setAvailableAugmentations(augmentations);
+
+ isBuilt = true;
+ }
+ return instance;
+ }
+
+ @Override
+ public void rebuild() {
+ isBuilt = false;
+ build();
+ }
+
+ @Override
+ public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
+ return addedTypedefs;
+ }
+
+ @Override
+ public void addTypedef(final TypeDefinitionBuilder type) {
+ String typeName = type.getQName().getLocalName();
+ for (TypeDefinitionBuilder addedTypedef : addedTypedefs) {
+ throw new YangParseException(moduleName, type.getLine(), "Can not add typedef '" + typeName
+ + "': typedef with same name already declared at line " + addedTypedef.getLine());
+ }
+ addedTypedefs.add(type);
+ }
+
+ public void setTypedefs(final Set<TypeDefinition<?>> typedefs) {
+ this.typedefs = typedefs;
+ }
+
+ public Set<AugmentationSchemaBuilder> getAugmentations() {
+ return addedAugmentations;
+ }
+
+ @Override
+ public void addAugmentation(AugmentationSchemaBuilder augment) {
+ addedAugmentations.add(augment);
+ }
+
+ public void setAugmentations(final Set<AugmentationSchema> augmentations) {
+ this.augmentations = augmentations;
+ }
+
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public void setPath(final SchemaPath schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ @Override
+ public void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public Boolean isConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ public void setConfiguration(Boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintsBuilder getConstraints() {
+ return constraints;
+ }
+
+ public Set<UsesNodeBuilder> getUsesNodes() {
+ return addedUsesNodes;
+ }
+
+ @Override
+ public void addUsesNode(UsesNodeBuilder usesNodeBuilder) {
+ addedUsesNodes.add(usesNodeBuilder);
+ }
+
+ public void setUsesnodes(final Set<UsesNode> usesNodes) {
+ this.usesNodes = usesNodes;
+ }
+
+ public boolean isPresence() {
+ return presence;
+ }
+
+ public void setPresence(boolean presence) {
+ this.presence = presence;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ContainerSchemaNodeBuilder other = (ContainerSchemaNodeBuilder) obj;
+ if (schemaPath == null) {
+ if (other.schemaPath != null) {
+ return false;
+ }
+ } else if (!schemaPath.equals(other.schemaPath)) {
+ return false;
+ }
+ if (parent == null) {
+ if (other.parent != null) {
+ return false;
+ }
+ } else if (!parent.equals(other.parent)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "container " + qname.getLocalName();
+ }
+
+ public final class ContainerSchemaNodeImpl implements ContainerSchemaNode {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private boolean augmenting;
+ private boolean addedByUses;
+ private boolean configuration;
+ private ConstraintDefinition constraints;
+ private Set<AugmentationSchema> augmentations = Collections.emptySet();
+ private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
+ private Set<GroupingDefinition> groupings = Collections.emptySet();
+ private Set<TypeDefinition<?>> typeDefinitions = Collections.emptySet();
+ private Set<UsesNode> uses = Collections.emptySet();
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+ private boolean presence;
+
+ private ContainerSchemaNodeImpl(QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ private void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ private void setAddedByUses(boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public boolean isConfiguration() {
+ return configuration;
+ }
+
+ private void setConfiguration(boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintDefinition getConstraints() {
+ return constraints;
+ }
+
+ private void setConstraints(ConstraintDefinition constraints) {
+ this.constraints = constraints;
+ }
+
+ @Override
+ public Set<AugmentationSchema> getAvailableAugmentations() {
+ return augmentations;
+ }
+
+ private void setAvailableAugmentations(Set<AugmentationSchema> augmentations) {
+ if (augmentations != null) {
+ this.augmentations = augmentations;
+ }
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ return new HashSet<DataSchemaNode>(childNodes.values());
+ }
+
+ private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
+ if (childNodes != null) {
+ this.childNodes = childNodes;
+ }
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return groupings;
+ }
+
+ private void setGroupings(Set<GroupingDefinition> groupings) {
+ if (groupings != null) {
+ this.groupings = groupings;
+ }
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(QName name) {
+ return childNodes.get(name);
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(String name) {
+ DataSchemaNode result = null;
+ for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
+ if (entry.getKey().getLocalName().equals(name)) {
+ result = entry.getValue();
+ break;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return uses;
+ }
+
+ private void setUses(Set<UsesNode> uses) {
+ if (uses != null) {
+ this.uses = uses;
+ }
+ }
+
+ @Override
+ public boolean isPresenceContainer() {
+ return presence;
+ }
+
+ private void setPresenceContainer(boolean presence) {
+ this.presence = presence;
+ }
+
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return typeDefinitions;
+ }
+
+ private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
+ if (typeDefinitions != null) {
+ this.typeDefinitions = typeDefinitions;
+ }
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
+ if (unknownSchemaNodes != null) {
+ this.unknownNodes = unknownSchemaNodes;
+ }
+ }
+
+ public ContainerSchemaNodeBuilder toBuilder() {
+ return ContainerSchemaNodeBuilder.this;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ContainerSchemaNodeImpl other = (ContainerSchemaNodeImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(ContainerSchemaNodeImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("qname=" + qname);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.model.api.Deviation;
+import org.opendaylight.controller.yang.model.api.Deviation.Deviate;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+import org.opendaylight.controller.yang.parser.util.ParserListenerUtils;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+public final class DeviationBuilder extends AbstractBuilder {
+ private final String targetPathStr;
+ private boolean isBuilt;
+ private final DeviationImpl instance;
+
+ private SchemaPath targetPath;
+ private String reference;
+ private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
+
+ DeviationBuilder(final String moduleName, final int line, final String targetPathStr) {
+ super(moduleName, line);
+ if (!targetPathStr.startsWith("/")) {
+ throw new YangParseException(moduleName, line,
+ "Deviation argument string must be an absolute schema node identifier.");
+ }
+ this.targetPathStr = targetPathStr;
+ this.targetPath = ParserListenerUtils.parseAugmentPath(targetPathStr);
+ instance = new DeviationImpl();
+ }
+
+ @Override
+ public Deviation build() {
+ if (targetPath == null) {
+ throw new YangParseException(moduleName, line, "Unresolved deviation target");
+ }
+
+ if (!isBuilt) {
+ instance.setTargetPath(targetPath);
+ instance.setReference(reference);
+
+ // UNKNOWN NODES
+ List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+
+ return instance;
+ }
+
+ public SchemaPath getTargetPath() {
+ return targetPath;
+ }
+
+ public void setTargetPath(final SchemaPath targetPath) {
+ this.targetPath = targetPath;
+ }
+
+ public void setDeviate(final String deviate) {
+ if ("not-supported".equals(deviate)) {
+ instance.setDeviate(Deviate.NOT_SUPPORTED);
+ } else if ("add".equals(deviate)) {
+ instance.setDeviate(Deviate.ADD);
+ } else if ("replace".equals(deviate)) {
+ instance.setDeviate(Deviate.REPLACE);
+ } else if ("delete".equals(deviate)) {
+ instance.setDeviate(Deviate.DELETE);
+ } else {
+ throw new YangParseException(moduleName, line, "Unsupported type of 'deviate' statement: " + deviate);
+ }
+ }
+
+ public void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public String toString() {
+ return "deviation " + targetPathStr;
+ }
+
+ private final class DeviationImpl implements Deviation {
+ private SchemaPath targetPath;
+ private Deviate deviate;
+ private String reference;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private DeviationImpl() {
+ }
+
+ @Override
+ public SchemaPath getTargetPath() {
+ return targetPath;
+ }
+
+ private void setTargetPath(final SchemaPath targetPath) {
+ this.targetPath = targetPath;
+ }
+
+ @Override
+ public Deviate getDeviate() {
+ return deviate;
+ }
+
+ private void setDeviate(final Deviate deviate) {
+ this.deviate = deviate;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
+ if (unknownSchemaNodes != null) {
+ this.unknownNodes = unknownSchemaNodes;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((targetPath == null) ? 0 : targetPath.hashCode());
+ result = prime * result + ((deviate == null) ? 0 : deviate.hashCode());
+ result = prime * result + ((reference == null) ? 0 : reference.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ DeviationImpl other = (DeviationImpl) obj;
+ if (targetPath == null) {
+ if (other.targetPath != null) {
+ return false;
+ }
+ } else if (!targetPath.equals(other.targetPath)) {
+ return false;
+ }
+ if (deviate == null) {
+ if (other.deviate != null) {
+ return false;
+ }
+ } else if (!deviate.equals(other.deviate)) {
+ return false;
+ }
+ if (reference == null) {
+ if (other.reference != null) {
+ return false;
+ }
+ } else if (!reference.equals(other.reference)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(DeviationImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("targetPath=" + targetPath);
+ sb.append(", deviate=" + deviate);
+ sb.append(", reference=" + reference);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+
+public final class ExtensionBuilder extends AbstractSchemaNodeBuilder {
+ private boolean isBuilt;
+ private final ExtensionDefinitionImpl instance;
+
+ ExtensionBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ instance = new ExtensionDefinitionImpl(qname);
+ }
+
+ @Override
+ public ExtensionDefinition build() {
+ if (!isBuilt) {
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder un : addedUnknownNodes) {
+ unknownNodes.add(un.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+
+ return instance;
+ }
+
+ public void setYinElement(boolean yin) {
+ instance.setYinElement(yin);
+ }
+
+ public void setArgument(String argument) {
+ instance.setArgument(argument);
+ }
+
+ @Override
+ public String toString() {
+ return "extension " + qname.getLocalName();
+ }
+
+ private final class ExtensionDefinitionImpl implements ExtensionDefinition {
+ private final QName qname;
+ private String argument;
+ private SchemaPath schemaPath;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+ private boolean yin;
+
+ private ExtensionDefinitionImpl(QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ private void setPath(SchemaPath schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public String getArgument() {
+ return argument;
+ }
+
+ private void setArgument(String argument) {
+ this.argument = argument;
+ }
+
+ @Override
+ public boolean isYinElement() {
+ return yin;
+ }
+
+ private void setYinElement(boolean yin) {
+ this.yin = yin;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ExtensionDefinitionImpl other = (ExtensionDefinitionImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (schemaPath == null) {
+ if (other.schemaPath != null) {
+ return false;
+ }
+ } else if (!schemaPath.equals(other.schemaPath)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(ExtensionDefinitionImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("argument=" + argument);
+ sb.append(", qname=" + qname);
+ sb.append(", schemaPath=" + schemaPath);
+ sb.append(", extensionSchemaNodes=" + unknownNodes);
+ sb.append(", yin=" + yin);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.FeatureDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+
+public final class FeatureBuilder extends AbstractSchemaNodeBuilder {
+ private boolean isBuilt;
+ private final FeatureDefinitionImpl instance;
+
+ FeatureBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ instance = new FeatureDefinitionImpl(qname);
+ }
+
+ @Override
+ public FeatureDefinitionImpl build() {
+ if (!isBuilt) {
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+ return instance;
+ }
+
+ @Override
+ public String toString() {
+ return "feature " + qname.getLocalName();
+ }
+
+ private final class FeatureDefinitionImpl implements FeatureDefinition {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private FeatureDefinitionImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(final SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(final List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ FeatureDefinitionImpl other = (FeatureDefinitionImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(FeatureDefinitionImpl.class.getSimpleName());
+ sb.append("[name=" + qname + "]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+public final class GroupingBuilderImpl extends AbstractDataNodeContainerBuilder implements GroupingBuilder {
+ private boolean isBuilt;
+ private final GroupingDefinitionImpl instance;
+ private SchemaPath schemaPath;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private boolean addedByUses;
+
+ private Set<TypeDefinition<?>> typedefs;
+ private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
+
+ private Set<UsesNode> usesNodes;
+ private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
+
+ public GroupingBuilderImpl(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ instance = new GroupingDefinitionImpl(qname);
+ }
+
+ public GroupingBuilderImpl(GroupingBuilder builder) {
+ super(builder.getModuleName(), builder.getLine(), builder.getQName());
+ parent = builder.getParent();
+ instance = new GroupingDefinitionImpl(qname);
+ schemaPath = builder.getPath();
+ description = builder.getDescription();
+ reference = builder.getReference();
+ status = builder.getStatus();
+ addedByUses = builder.isAddedByUses();
+ childNodes = builder.getChildNodes();
+ addedChildNodes.addAll(builder.getChildNodeBuilders());
+ groupings = builder.getGroupings();
+ addedGroupings.addAll(builder.getGroupingBuilders());
+ addedUsesNodes.addAll(builder.getUses());
+ addedUnknownNodes.addAll(builder.getUnknownNodeBuilders());
+ }
+
+ @Override
+ public GroupingDefinition build() {
+ if (!isBuilt) {
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setAddedByUses(addedByUses);
+
+ // CHILD NODES
+ final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
+ if (childNodes == null || childNodes.isEmpty()) {
+ for (DataSchemaNodeBuilder node : addedChildNodes) {
+ childs.put(node.getQName(), node.build());
+ }
+ } else {
+ for (DataSchemaNode node : childNodes) {
+ childs.put(node.getQName(), node);
+ }
+ }
+ instance.setChildNodes(childs);
+
+ // GROUPINGS
+ if (groupings == null) {
+ groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
+ for (GroupingBuilder builder : addedGroupings) {
+ groupings.add(builder.build());
+ }
+ }
+ instance.setGroupings(groupings);
+
+ // TYPEDEFS
+ if (typedefs == null) {
+ typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
+ for (TypeDefinitionBuilder entry : addedTypedefs) {
+ typedefs.add(entry.build());
+ }
+ }
+ instance.setTypeDefinitions(typedefs);
+
+ // USES
+ if (usesNodes == null) {
+ usesNodes = new HashSet<UsesNode>();
+ for (UsesNodeBuilder builder : addedUsesNodes) {
+ usesNodes.add(builder.build());
+ }
+ }
+ instance.setUses(usesNodes);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+
+ return instance;
+ }
+
+
+ @Override
+ public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
+ return addedTypedefs;
+ }
+
+ @Override
+ public void addTypedef(final TypeDefinitionBuilder type) {
+ String typeName = type.getQName().getLocalName();
+ for (TypeDefinitionBuilder addedTypedef : addedTypedefs) {
+ throw new YangParseException(moduleName, type.getLine(), "Can not add typedef '" + typeName
+ + "': typedef with same name already declared at line " + addedTypedef.getLine());
+ }
+ addedTypedefs.add(type);
+ }
+
+ public void setTypedefs(final Set<TypeDefinition<?>> typedefs) {
+ this.typedefs = typedefs;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public void setPath(SchemaPath schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public void setStatus(final Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public Set<UsesNodeBuilder> getUses() {
+ return addedUsesNodes;
+ }
+
+ @Override
+ public void addUsesNode(final UsesNodeBuilder usesBuilder) {
+ addedUsesNodes.add(usesBuilder);
+ }
+
+ public void setUsesnodes(final Set<UsesNode> usesNodes) {
+ this.usesNodes = usesNodes;
+ }
+
+ @Override
+ public String toString() {
+ return "grouping " + qname.getLocalName();
+ }
+
+ private final class GroupingDefinitionImpl implements GroupingDefinition {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status;
+ private boolean addedByUses;
+ private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
+ private Set<GroupingDefinition> groupings = Collections.emptySet();
+ private Set<TypeDefinition<?>> typeDefinitions = Collections.emptySet();
+ private Set<UsesNode> uses = Collections.emptySet();
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private GroupingDefinitionImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ private void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ final Set<DataSchemaNode> result = new TreeSet<DataSchemaNode>(Comparators.SCHEMA_NODE_COMP);
+ result.addAll(childNodes.values());
+ return result;
+ }
+
+ private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
+ this.childNodes = childNodes;
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return groupings;
+ }
+
+ private void setGroupings(Set<GroupingDefinition> groupings) {
+ this.groupings = groupings;
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return uses;
+ }
+
+ private void setUses(Set<UsesNode> uses) {
+ this.uses = uses;
+ }
+
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return typeDefinitions;
+ }
+
+ private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
+ this.typeDefinitions = typeDefinitions;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(QName name) {
+ return childNodes.get(name);
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(String name) {
+ DataSchemaNode result = null;
+ for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
+ if (entry.getKey().getLocalName().equals(name)) {
+ result = entry.getValue();
+ break;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final GroupingDefinitionImpl other = (GroupingDefinitionImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(GroupingDefinitionImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("qname=" + qname);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+
+public final class IdentitySchemaNodeBuilder extends AbstractSchemaNodeBuilder {
+ private boolean isBuilt;
+ private final IdentitySchemaNodeImpl instance;
+ private IdentitySchemaNodeBuilder baseIdentityBuilder;
+ private IdentitySchemaNode baseIdentity;
+ private String baseIdentityName;
+
+ IdentitySchemaNodeBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ instance = new IdentitySchemaNodeImpl(qname);
+ }
+
+ @Override
+ public IdentitySchemaNode build() {
+ if (!isBuilt) {
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+
+ if (baseIdentity == null) {
+ if (baseIdentityBuilder != null) {
+ instance.setBaseIdentity(baseIdentityBuilder.build());
+ }
+ } else {
+ instance.setBaseIdentity(baseIdentity);
+ }
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+
+ return instance;
+ }
+
+ public String getBaseIdentityName() {
+ return baseIdentityName;
+ }
+
+ public void setBaseIdentityName(final String baseIdentityName) {
+ this.baseIdentityName = baseIdentityName;
+ }
+
+ public void setBaseIdentity(final IdentitySchemaNodeBuilder baseType) {
+ this.baseIdentityBuilder = baseType;
+ }
+
+ public void setBaseIdentity(final IdentitySchemaNode baseType) {
+ this.baseIdentity = baseType;
+ }
+
+ @Override
+ public String toString() {
+ return "identity " + qname.getLocalName();
+ }
+
+ private final class IdentitySchemaNodeImpl implements IdentitySchemaNode {
+ private final QName qname;
+ private IdentitySchemaNode baseIdentity;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private SchemaPath path;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private IdentitySchemaNodeImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public IdentitySchemaNode getBaseIdentity() {
+ return baseIdentity;
+ }
+
+ private void setBaseIdentity(final IdentitySchemaNode baseIdentity) {
+ this.baseIdentity = baseIdentity;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(final Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(final SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
+ if (unknownSchemaNodes != null) {
+ this.unknownNodes = unknownSchemaNodes;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ IdentitySchemaNodeImpl other = (IdentitySchemaNodeImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(IdentitySchemaNodeImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("base=" + baseIdentity);
+ sb.append(", qname=" + qname);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
+import org.opendaylight.controller.yang.model.util.IdentityrefType;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractTypeAwareBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+/**
+ * Builder for YANG union type. User can add type to this union as
+ * TypeDefinition object (resolved type) or in form of TypeDefinitionBuilder.
+ * When build is called, types in builder form will be built and add to resolved
+ * types.
+ */
+public final class IdentityrefTypeBuilder extends AbstractTypeAwareBuilder implements TypeDefinitionBuilder {
+ private static final String NAME = "identityref";
+
+ private final String baseString;
+ private final SchemaPath schemaPath;
+ private QName baseQName;
+
+ IdentityrefTypeBuilder(final String moduleName, final int line, final String baseString, final SchemaPath schemaPath) {
+ super(moduleName, line, null);
+ this.baseString = baseString;
+ this.schemaPath = schemaPath;
+ }
+
+ @Override
+ public IdentityrefType build() {
+ return new IdentityrefType(baseQName, schemaPath);
+ }
+
+ public String getBaseString() {
+ return baseString;
+ }
+
+ public void setBaseQName(QName baseQName) {
+ this.baseQName = baseQName;
+ }
+
+ @Override
+ public TypeDefinition<?> getType() {
+ return null;
+ }
+
+ @Override
+ public TypeDefinitionBuilder getTypedef() {
+ return null;
+ }
+
+ @Override
+ public void setType(final TypeDefinition<?> type) {
+ throw new YangParseException(moduleName, line, "Can not set type to " + NAME);
+ }
+
+ @Override
+ public void setTypedef(final TypeDefinitionBuilder tdb) {
+ throw new YangParseException(moduleName, line, "Can not set type to " + NAME);
+ }
+
+ @Override
+ public void setPath(final SchemaPath schemaPath) {
+ throw new YangParseException(moduleName, line, "Can not set path to " + NAME);
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ throw new YangParseException(moduleName, line, "Can not set description to " + NAME);
+ }
+
+ @Override
+ public void setReference(final String reference) {
+ throw new YangParseException(moduleName, line, "Can not set reference to " + NAME);
+ }
+
+ @Override
+ public void setStatus(final Status status) {
+ throw new YangParseException(moduleName, line, "Can not set status to " + NAME);
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return false;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ throw new YangParseException(moduleName, line, "Identityref type can not be added by uses.");
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownNodes() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void addUnknownNodeBuilder(final UnknownSchemaNodeBuilder unknownNode) {
+ throw new YangParseException(moduleName, line, "Can not add unknown node to " + NAME);
+ }
+
+ @Override
+ public QName getQName() {
+ return null;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return null;
+ }
+
+ @Override
+ public String getDescription() {
+ return null;
+ }
+
+ @Override
+ public String getReference() {
+ return null;
+ }
+
+ @Override
+ public Status getStatus() {
+ return null;
+ }
+
+ @Override
+ public List<RangeConstraint> getRanges() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void setRanges(List<RangeConstraint> ranges) {
+ throw new YangParseException(moduleName, line, "Can not set ranges to " + NAME);
+ }
+
+ @Override
+ public List<LengthConstraint> getLengths() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void setLengths(List<LengthConstraint> lengths) {
+ throw new YangParseException(moduleName, line, "Can not set lengths to " + NAME);
+ }
+
+ @Override
+ public List<PatternConstraint> getPatterns() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void setPatterns(List<PatternConstraint> patterns) {
+ throw new YangParseException(moduleName, line, "Can not set patterns to " + NAME);
+ }
+
+ @Override
+ public Integer getFractionDigits() {
+ return null;
+ }
+
+ @Override
+ public void setFractionDigits(Integer fractionDigits) {
+ throw new YangParseException(moduleName, line, "Can not set fraction digits to " + NAME);
+ }
+
+ @Override
+ public List<UnknownSchemaNodeBuilder> getUnknownNodeBuilders() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Object getDefaultValue() {
+ return null;
+ }
+
+ @Override
+ public void setDefaultValue(Object defaultValue) {
+ throw new YangParseException(moduleName, line, "Can not set default value to " + NAME);
+ }
+
+ @Override
+ public String getUnits() {
+ return null;
+ }
+
+ @Override
+ public void setUnits(String units) {
+ throw new YangParseException(moduleName, line, "Can not set units to " + NAME);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder result = new StringBuilder(IdentityrefTypeBuilder.class.getSimpleName() + "[");
+ result.append(", base=" + baseQName);
+ result.append("]");
+ return result.toString();
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractTypeAwareBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+
+public final class LeafListSchemaNodeBuilder extends AbstractTypeAwareBuilder implements DataSchemaNodeBuilder,
+ GroupingMember {
+ private boolean isBuilt;
+ private final LeafListSchemaNodeImpl instance;
+ // SchemaNode args
+ private SchemaPath schemaPath;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ // DataSchemaNode args
+ private boolean augmenting;
+ private boolean addedByUses;
+ private Boolean configuration;
+ private final ConstraintsBuilder constraints;
+ // LeafListSchemaNode args
+ private boolean userOrdered;
+
+ public LeafListSchemaNodeBuilder(final String moduleName, final int line, final QName qname,
+ final SchemaPath schemaPath) {
+ super(moduleName, line, qname);
+ this.schemaPath = schemaPath;
+ instance = new LeafListSchemaNodeImpl(qname);
+ constraints = new ConstraintsBuilder(moduleName, line);
+ }
+
+ public LeafListSchemaNodeBuilder(final LeafListSchemaNodeBuilder b) {
+ super(b.getModuleName(), b.getLine(), b.getQName());
+ instance = new LeafListSchemaNodeImpl(qname);
+
+ type = b.getType();
+ typedef = b.getTypedef();
+
+ constraints = b.getConstraints();
+ schemaPath = b.getPath();
+ description = b.getDescription();
+ reference = b.getReference();
+ status = b.getStatus();
+ augmenting = b.isAugmenting();
+ addedByUses = b.isAddedByUses();
+ configuration = b.isConfiguration();
+ userOrdered = b.isUserOrdered();
+ unknownNodes = b.unknownNodes;
+ addedUnknownNodes.addAll(b.getUnknownNodeBuilders());
+ }
+
+ @Override
+ public LeafListSchemaNode build() {
+ if (!isBuilt) {
+ instance.setConstraints(constraints.build());
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setAugmenting(augmenting);
+ instance.setAddedByUses(addedByUses);
+ instance.setConfiguration(configuration);
+ instance.setUserOrdered(userOrdered);
+
+ if (type == null) {
+ instance.setType(typedef.build());
+ } else {
+ instance.setType(type);
+ }
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+ return instance;
+ }
+
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public void setPath(final SchemaPath schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ @Override
+ public void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ public Boolean isConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ public void setConfiguration(Boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintsBuilder getConstraints() {
+ return constraints;
+ }
+
+ public boolean isUserOrdered() {
+ return userOrdered;
+ }
+
+ public void setUserOrdered(final boolean userOrdered) {
+ this.userOrdered = userOrdered;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LeafListSchemaNodeBuilder other = (LeafListSchemaNodeBuilder) obj;
+ if (schemaPath == null) {
+ if (other.schemaPath != null) {
+ return false;
+ }
+ } else if (!schemaPath.equals(other.schemaPath)) {
+ return false;
+ }
+ if (parent == null) {
+ if (other.parent != null) {
+ return false;
+ }
+ } else if (!parent.equals(other.parent)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "leaf-list " + qname.getLocalName();
+ }
+
+ private final class LeafListSchemaNodeImpl implements LeafListSchemaNode {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private boolean augmenting;
+ private boolean addedByUses;
+ private boolean configuration;
+ private ConstraintDefinition constraintsDef;
+ private TypeDefinition<?> type;
+ private boolean userOrdered;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private LeafListSchemaNodeImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(final SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ private void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ private void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public boolean isConfiguration() {
+ return configuration;
+ }
+
+ private void setConfiguration(boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintDefinition getConstraints() {
+ return constraintsDef;
+ }
+
+ private void setConstraints(ConstraintDefinition constraintsDef) {
+ this.constraintsDef = constraintsDef;
+ }
+
+ @Override
+ public TypeDefinition<?> getType() {
+ return type;
+ }
+
+ public void setType(TypeDefinition<? extends TypeDefinition<?>> type) {
+ this.type = type;
+ }
+
+ @Override
+ public boolean isUserOrdered() {
+ return userOrdered;
+ }
+
+ private void setUserOrdered(boolean userOrdered) {
+ this.userOrdered = userOrdered;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LeafListSchemaNodeImpl other = (LeafListSchemaNodeImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(LeafListSchemaNodeImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append(qname);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractTypeAwareBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+
+public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder implements DataSchemaNodeBuilder,
+ GroupingMember {
+ private boolean isBuilt;
+ private final LeafSchemaNodeImpl instance;
+ // SchemaNode args
+ private SchemaPath schemaPath;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ // DataSchemaNode args
+ private boolean augmenting;
+ private boolean addedByUses;
+ private Boolean configuration;
+ private final ConstraintsBuilder constraints;
+ // leaf args
+ private String defaultStr;
+ private String unitsStr;
+
+ public LeafSchemaNodeBuilder(final String moduleName, final int line, final QName qname, final SchemaPath schemaPath) {
+ super(moduleName, line, qname);
+ this.schemaPath = schemaPath;
+ instance = new LeafSchemaNodeImpl(qname);
+ constraints = new ConstraintsBuilder(moduleName, line);
+ }
+
+ public LeafSchemaNodeBuilder(final LeafSchemaNodeBuilder b) {
+ super(b.getModuleName(), b.getLine(), b.getQName());
+ instance = new LeafSchemaNodeImpl(qname);
+ constraints = b.getConstraints();
+ schemaPath = b.getPath();
+
+ type = b.getType();
+ typedef = b.getTypedef();
+
+ description = b.getDescription();
+ reference = b.getReference();
+ status = b.getStatus();
+ augmenting = b.isAugmenting();
+ addedByUses = b.isAddedByUses();
+ configuration = b.isConfiguration();
+ unknownNodes = b.unknownNodes;
+ addedUnknownNodes.addAll(b.getUnknownNodeBuilders());
+
+ defaultStr = b.getDefaultStr();
+ unitsStr = b.getUnits();
+ }
+
+ @Override
+ public LeafSchemaNode build() {
+ if (!isBuilt) {
+ instance.setPath(schemaPath);
+ instance.setConstraints(constraints.build());
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setAugmenting(augmenting);
+ instance.setAddedByUses(addedByUses);
+ instance.setConfiguration(configuration);
+ instance.setDefault(defaultStr);
+ instance.setUnits(unitsStr);
+
+ // TYPE
+ if (type == null) {
+ instance.setType(typedef.build());
+ } else {
+ instance.setType(type);
+ }
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+ return instance;
+ }
+
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public void setPath(final SchemaPath path) {
+ this.schemaPath = path;
+ }
+
+ @Override
+ public ConstraintsBuilder getConstraints() {
+ return constraints;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public void setStatus(final Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ @Override
+ public void setAugmenting(final boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ public Boolean isConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ public void setConfiguration(final Boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ public String getDefaultStr() {
+ return defaultStr;
+ }
+
+ public void setDefaultStr(String defaultStr) {
+ this.defaultStr = defaultStr;
+ }
+
+ public String getUnits() {
+ return unitsStr;
+ }
+
+ public void setUnits(String unitsStr) {
+ this.unitsStr = unitsStr;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LeafSchemaNodeBuilder other = (LeafSchemaNodeBuilder) obj;
+ if (schemaPath == null) {
+ if (other.schemaPath != null) {
+ return false;
+ }
+ } else if (!schemaPath.equals(other.schemaPath)) {
+ return false;
+ }
+ if (parent == null) {
+ if (other.parent != null) {
+ return false;
+ }
+ } else if (!parent.equals(other.parent)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "leaf " + qname.getLocalName();
+ }
+
+ private final class LeafSchemaNodeImpl implements LeafSchemaNode {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private boolean augmenting;
+ private boolean addedByUses;
+ private boolean configuration;
+ private ConstraintDefinition constraintsDef;
+ private TypeDefinition<?> type;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+ private String defaultStr;
+ private String unitsStr;
+
+ private LeafSchemaNodeImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(final SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ private void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ private void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public boolean isConfiguration() {
+ return configuration;
+ }
+
+ private void setConfiguration(boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintDefinition getConstraints() {
+ return constraintsDef;
+ }
+
+ private void setConstraints(ConstraintDefinition constraintsDef) {
+ this.constraintsDef = constraintsDef;
+ }
+
+ @Override
+ public TypeDefinition<?> getType() {
+ return type;
+ }
+
+ private void setType(TypeDefinition<? extends TypeDefinition<?>> type) {
+ this.type = type;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public String getDefault() {
+ return defaultStr;
+ }
+
+ private void setDefault(String defaultStr) {
+ this.defaultStr = defaultStr;
+ }
+
+ @Override
+ public String getUnits() {
+ return unitsStr;
+ }
+
+ public void setUnits(String unitsStr) {
+ this.unitsStr = unitsStr;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LeafSchemaNodeImpl other = (LeafSchemaNodeImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(LeafSchemaNodeImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("qname=" + qname);
+ sb.append(", path=" + path);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+public final class ListSchemaNodeBuilder extends AbstractDataNodeContainerBuilder implements DataSchemaNodeBuilder,
+ AugmentationTargetBuilder, GroupingMember {
+ private boolean isBuilt;
+ private final ListSchemaNodeImpl instance;
+ // SchemaNode args
+ private SchemaPath schemaPath;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ // DataSchemaNode args
+ private boolean augmenting;
+ private boolean addedByUses;
+ private Boolean configuration;
+ private final ConstraintsBuilder constraints;
+ // DataNodeContainer args
+ private Set<TypeDefinition<?>> typedefs;
+ private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
+ private Set<UsesNode> usesNodes;
+ private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
+ // AugmentationTarget args
+ private Set<AugmentationSchema> augmentations;
+ private final Set<AugmentationSchemaBuilder> addedAugmentations = new HashSet<AugmentationSchemaBuilder>();
+ // ListSchemaNode args
+ private List<QName> keyDefinition = Collections.emptyList();
+ private boolean userOrdered;
+
+ public ListSchemaNodeBuilder(final String moduleName, final int line, final QName qname, final SchemaPath schemaPath) {
+ super(moduleName, line, qname);
+ this.schemaPath = schemaPath;
+ instance = new ListSchemaNodeImpl(qname);
+ constraints = new ConstraintsBuilder(moduleName, line);
+ }
+
+ public ListSchemaNodeBuilder(final ListSchemaNodeBuilder b) {
+ super(b.getModuleName(), b.getLine(), b.getQName());
+ instance = new ListSchemaNodeImpl(b.getQName());
+ constraints = b.getConstraints();
+ schemaPath = b.getPath();
+ description = b.getDescription();
+ reference = b.getReference();
+ status = b.getStatus();
+ augmenting = b.isAugmenting();
+ addedByUses = b.isAddedByUses();
+ configuration = b.isConfiguration();
+ keyDefinition = b.getKeyDefinition();
+ userOrdered = b.isUserOrdered();
+ childNodes = b.getChildNodes();
+ addedChildNodes.addAll(b.getChildNodeBuilders());
+ groupings = b.getGroupings();
+ addedGroupings.addAll(b.getGroupingBuilders());
+ typedefs = b.typedefs;
+ addedTypedefs.addAll(b.getTypeDefinitionBuilders());
+ usesNodes = b.usesNodes;
+ addedUsesNodes.addAll(b.getUsesNodes());
+ augmentations = b.augmentations;
+ addedAugmentations.addAll(b.getAugmentations());
+ unknownNodes = b.unknownNodes;
+ addedUnknownNodes.addAll(b.getUnknownNodeBuilders());
+ }
+
+ @Override
+ public ListSchemaNode build() {
+ if (!isBuilt) {
+ instance.setKeyDefinition(keyDefinition);
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setAugmenting(augmenting);
+ instance.setAddedByUses(addedByUses);
+ instance.setConfiguration(configuration);
+ instance.setUserOrdered(userOrdered);
+
+ // CHILD NODES
+ final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
+ if (childNodes == null || childNodes.isEmpty()) {
+ for (DataSchemaNodeBuilder node : addedChildNodes) {
+ childs.put(node.getQName(), node.build());
+ }
+ } else {
+ for (DataSchemaNode node : childNodes) {
+ childs.put(node.getQName(), node);
+ }
+ }
+ instance.setChildNodes(childs);
+
+ // TYPEDEFS
+ if (typedefs == null) {
+ typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
+ for (TypeDefinitionBuilder entry : addedTypedefs) {
+ typedefs.add(entry.build());
+ }
+ }
+ instance.setTypeDefinitions(typedefs);
+
+ // USES
+ if (usesNodes == null) {
+ usesNodes = new HashSet<UsesNode>();
+ for (UsesNodeBuilder builder : addedUsesNodes) {
+ usesNodes.add(builder.build());
+ }
+ }
+ instance.setUses(usesNodes);
+
+ // GROUPINGS
+ if (groupings == null) {
+ groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
+ for (GroupingBuilder builder : addedGroupings) {
+ groupings.add(builder.build());
+ }
+ }
+ instance.setGroupings(groupings);
+
+ // AUGMENTATIONS
+ if (augmentations == null) {
+ augmentations = new HashSet<AugmentationSchema>();
+ for (AugmentationSchemaBuilder builder : addedAugmentations) {
+ augmentations.add(builder.build());
+ }
+ }
+ instance.setAvailableAugmentations(augmentations);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ instance.setConstraints(constraints.build());
+ instance.setAvailableAugmentations(augmentations);
+
+ isBuilt = true;
+ }
+ return instance;
+ }
+
+ @Override
+ public void rebuild() {
+ isBuilt = false;
+ build();
+ }
+
+ @Override
+ public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
+ return addedTypedefs;
+ }
+
+ @Override
+ public void addTypedef(final TypeDefinitionBuilder type) {
+ String typeName = type.getQName().getLocalName();
+ for (TypeDefinitionBuilder addedTypedef : addedTypedefs) {
+ throw new YangParseException(moduleName, type.getLine(), "Can not add typedef '" + typeName
+ + "': typedef with same name already declared at line " + addedTypedef.getLine());
+ }
+ addedTypedefs.add(type);
+ }
+
+ public void setTypedefs(final Set<TypeDefinition<?>> typedefs) {
+ this.typedefs = typedefs;
+ }
+
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public void setPath(final SchemaPath schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ public Set<UsesNodeBuilder> getUsesNodes() {
+ return addedUsesNodes;
+ }
+
+ @Override
+ public void addUsesNode(final UsesNodeBuilder usesBuilder) {
+ addedUsesNodes.add(usesBuilder);
+ }
+
+ public void setUsesnodes(final Set<UsesNode> usesNodes) {
+ this.usesNodes = usesNodes;
+ }
+
+ public Set<AugmentationSchemaBuilder> getAugmentations() {
+ return addedAugmentations;
+ }
+
+ @Override
+ public void addAugmentation(AugmentationSchemaBuilder augment) {
+ addedAugmentations.add(augment);
+ }
+
+ public void setAugmentations(final Set<AugmentationSchema> augmentations) {
+ this.augmentations = augmentations;
+ }
+
+ public List<QName> getKeyDefinition() {
+ return keyDefinition;
+ }
+
+ public void setKeyDefinition(final List<QName> keyDefinition) {
+ if (keyDefinition != null) {
+ this.keyDefinition = keyDefinition;
+ }
+ }
+
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ @Override
+ public void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ public Boolean isConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ public void setConfiguration(Boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintsBuilder getConstraints() {
+ return constraints;
+ }
+
+ public boolean isUserOrdered() {
+ return userOrdered;
+ }
+
+ public void setUserOrdered(final boolean userOrdered) {
+ this.userOrdered = userOrdered;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ListSchemaNodeBuilder other = (ListSchemaNodeBuilder) obj;
+ if (schemaPath == null) {
+ if (other.schemaPath != null) {
+ return false;
+ }
+ } else if (!schemaPath.equals(other.schemaPath)) {
+ return false;
+ }
+ if (parent == null) {
+ if (other.parent != null) {
+ return false;
+ }
+ } else if (!parent.equals(other.parent)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "list " + qname.getLocalName();
+ }
+
+ public final class ListSchemaNodeImpl implements ListSchemaNode {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private List<QName> keyDefinition = Collections.emptyList();
+ private boolean augmenting;
+ private boolean addedByUses;
+ private boolean configuration;
+ private ConstraintDefinition constraints;
+ private Set<AugmentationSchema> augmentations = Collections.emptySet();
+ private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
+ private Set<TypeDefinition<?>> typeDefinitions = Collections.emptySet();
+ private Set<GroupingDefinition> groupings = Collections.emptySet();
+ private Set<UsesNode> uses = Collections.emptySet();
+ private boolean userOrdered;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private ListSchemaNodeImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(final SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public List<QName> getKeyDefinition() {
+ return keyDefinition;
+ }
+
+ private void setKeyDefinition(List<QName> keyDefinition) {
+ if (keyDefinition != null) {
+ this.keyDefinition = keyDefinition;
+ }
+ }
+
+ @Override
+ public boolean isAugmenting() {
+ return augmenting;
+ }
+
+ private void setAugmenting(boolean augmenting) {
+ this.augmenting = augmenting;
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ private void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public boolean isConfiguration() {
+ return configuration;
+ }
+
+ private void setConfiguration(boolean configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public ConstraintDefinition getConstraints() {
+ return constraints;
+ }
+
+ private void setConstraints(ConstraintDefinition constraints) {
+ this.constraints = constraints;
+ }
+
+ @Override
+ public Set<AugmentationSchema> getAvailableAugmentations() {
+ return augmentations;
+ }
+
+ private void setAvailableAugmentations(Set<AugmentationSchema> augmentations) {
+ if (augmentations != null) {
+ this.augmentations = augmentations;
+ }
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ return new HashSet<DataSchemaNode>(childNodes.values());
+ }
+
+ private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
+ if (childNodes != null) {
+ this.childNodes = childNodes;
+ }
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return groupings;
+ }
+
+ private void setGroupings(Set<GroupingDefinition> groupings) {
+ if (groupings != null) {
+ this.groupings = groupings;
+ }
+ }
+
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return typeDefinitions;
+ }
+
+ private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
+ if (typeDefinitions != null) {
+ this.typeDefinitions = typeDefinitions;
+ }
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return uses;
+ }
+
+ private void setUses(Set<UsesNode> uses) {
+ if (uses != null) {
+ this.uses = uses;
+ }
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(QName name) {
+ return childNodes.get(name);
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(String name) {
+ DataSchemaNode result = null;
+ for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
+ if (entry.getKey().getLocalName().equals(name)) {
+ result = entry.getValue();
+ break;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isUserOrdered() {
+ return userOrdered;
+ }
+
+ private void setUserOrdered(boolean userOrdered) {
+ this.userOrdered = userOrdered;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ public ListSchemaNodeBuilder toBuilder() {
+ return ListSchemaNodeBuilder.this;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final ListSchemaNodeImpl other = (ListSchemaNodeImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(ListSchemaNodeImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("qname=" + qname);
+ sb.append(", path=" + path);
+ sb.append(", keyDefinition=" + keyDefinition);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.Deviation;
+import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
+import org.opendaylight.controller.yang.model.api.FeatureDefinition;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.ModuleImport;
+import org.opendaylight.controller.yang.model.api.NotificationDefinition;
+import org.opendaylight.controller.yang.model.api.RpcDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.Builder;
+import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+import org.opendaylight.controller.yang.parser.util.RefineHolder;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+/**
+ * Builder of Module object. If this module is dependent on external
+ * module/modules, these dependencies must be resolved before module is built,
+ * otherwise result may not be valid.
+ */
+public class ModuleBuilder extends AbstractDataNodeContainerBuilder {
+ private final ModuleImpl instance;
+ private final String name;
+ private URI namespace;
+ private String prefix;
+ private Date revision;
+
+ private int augmentsResolved;
+
+ private final LinkedList<Builder> actualPath = new LinkedList<Builder>();
+ private final Set<TypeAwareBuilder> dirtyNodes = new HashSet<TypeAwareBuilder>();
+
+ private final Set<ModuleImport> imports = new HashSet<ModuleImport>();
+ private final List<AugmentationSchemaBuilder> addedAugments = new ArrayList<AugmentationSchemaBuilder>();
+ private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<AugmentationSchemaBuilder>();
+ private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
+ private final List<UsesNodeBuilder> allUsesNodes = new ArrayList<UsesNodeBuilder>();
+ private final Set<RpcDefinitionBuilder> addedRpcs = new HashSet<RpcDefinitionBuilder>();
+ private final Set<NotificationBuilder> addedNotifications = new HashSet<NotificationBuilder>();
+ private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<IdentitySchemaNodeBuilder>();
+ private final Set<FeatureBuilder> addedFeatures = new HashSet<FeatureBuilder>();
+ private final Set<DeviationBuilder> addedDeviations = new HashSet<DeviationBuilder>();
+ private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
+ private final List<ExtensionBuilder> addedExtensions = new ArrayList<ExtensionBuilder>();
+ private final List<UnknownSchemaNodeBuilder> allUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
+
+ public ModuleBuilder(final String name) {
+ super(name, 0, null);
+ this.name = name;
+ instance = new ModuleImpl(name);
+ actualPath.push(this);
+ }
+
+ /**
+ * Build new Module object based on this builder.
+ */
+ @Override
+ public Module build() {
+ instance.setPrefix(prefix);
+ instance.setRevision(revision);
+ instance.setImports(imports);
+ instance.setNamespace(namespace);
+
+ // TYPEDEFS
+ final Set<TypeDefinition<?>> typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
+ for (TypeDefinitionBuilder tdb : addedTypedefs) {
+ typedefs.add(tdb.build());
+ }
+ instance.setTypeDefinitions(typedefs);
+
+ // CHILD NODES
+ final Map<QName, DataSchemaNode> children = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
+ for (DataSchemaNodeBuilder child : addedChildNodes) {
+ children.put(child.getQName(), child.build());
+ }
+ instance.setChildNodes(children);
+
+ // GROUPINGS
+ final Set<GroupingDefinition> groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
+ for (GroupingBuilder gb : addedGroupings) {
+ groupings.add(gb.build());
+ }
+ instance.setGroupings(groupings);
+
+ // USES
+ final Set<UsesNode> usesDefinitions = new HashSet<UsesNode>();
+ for (UsesNodeBuilder unb : addedUsesNodes) {
+ usesDefinitions.add(unb.build());
+ }
+ instance.setUses(usesDefinitions);
+
+ // FEATURES
+ final Set<FeatureDefinition> features = new TreeSet<FeatureDefinition>(Comparators.SCHEMA_NODE_COMP);
+ for (FeatureBuilder fb : addedFeatures) {
+ features.add(fb.build());
+ }
+ instance.setFeatures(features);
+
+ // NOTIFICATIONS
+ final Set<NotificationDefinition> notifications = new TreeSet<NotificationDefinition>(
+ Comparators.SCHEMA_NODE_COMP);
+ for (NotificationBuilder entry : addedNotifications) {
+ notifications.add(entry.build());
+ }
+ instance.setNotifications(notifications);
+
+ // AUGMENTATIONS
+ final Set<AugmentationSchema> augmentations = new HashSet<AugmentationSchema>();
+ for (AugmentationSchemaBuilder builder : addedAugments) {
+ augmentations.add(builder.build());
+ }
+ instance.setAugmentations(augmentations);
+
+ // RPCs
+ final Set<RpcDefinition> rpcs = new TreeSet<RpcDefinition>(Comparators.SCHEMA_NODE_COMP);
+ for (RpcDefinitionBuilder rpc : addedRpcs) {
+ rpcs.add(rpc.build());
+ }
+ instance.setRpcs(rpcs);
+
+ // DEVIATIONS
+ final Set<Deviation> deviations = new HashSet<Deviation>();
+ for (DeviationBuilder entry : addedDeviations) {
+ deviations.add(entry.build());
+ }
+ instance.setDeviations(deviations);
+
+ // EXTENSIONS
+ final List<ExtensionDefinition> extensions = new ArrayList<ExtensionDefinition>();
+ for (ExtensionBuilder eb : addedExtensions) {
+ extensions.add(eb.build());
+ }
+ Collections.sort(extensions, Comparators.SCHEMA_NODE_COMP);
+ instance.setExtensionSchemaNodes(extensions);
+
+ // IDENTITIES
+ final Set<IdentitySchemaNode> identities = new TreeSet<IdentitySchemaNode>(Comparators.SCHEMA_NODE_COMP);
+ for (IdentitySchemaNodeBuilder id : addedIdentities) {
+ identities.add(id.build());
+ }
+ instance.setIdentities(identities);
+
+ // UNKNOWN NODES
+ final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder unb : addedUnknownNodes) {
+ unknownNodes.add(unb.build());
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ return instance;
+ }
+
+ @Override
+ public void setParent(Builder parent) {
+ throw new YangParseException(name, 0, "Can not set parent to module");
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return null;
+ }
+
+ @Override
+ public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
+ return addedTypedefs;
+ }
+
+ public void enterNode(final Builder node) {
+ actualPath.push(node);
+ }
+
+ public void exitNode() {
+ actualPath.pop();
+ }
+
+ public Builder getActualNode() {
+ if (actualPath.isEmpty()) {
+ return null;
+ } else {
+ return actualPath.get(0);
+ }
+ }
+
+ public Builder getActualParent() {
+ if (actualPath.size() < 2) {
+ return null;
+ } else {
+ return actualPath.get(1);
+ }
+ }
+
+ public Set<TypeAwareBuilder> getDirtyNodes() {
+ return dirtyNodes;
+ }
+
+ public List<AugmentationSchemaBuilder> getAllAugments() {
+ return allAugments;
+ }
+
+ public Set<IdentitySchemaNodeBuilder> getIdentities() {
+ return addedIdentities;
+ }
+
+ public List<UsesNodeBuilder> getAllUsesNodes() {
+ return allUsesNodes;
+ }
+
+ public Set<DeviationBuilder> getDeviations() {
+ return addedDeviations;
+ }
+
+ public List<UnknownSchemaNodeBuilder> getAllUnknownNodes() {
+ return allUnknownNodes;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public URI getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(final URI namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public Date getRevision() {
+ return revision;
+ }
+
+ public int getAugmentsResolved() {
+ return augmentsResolved;
+ }
+
+ public void augmentResolved() {
+ augmentsResolved++;
+ }
+
+ public void markActualNodeDirty() {
+ final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) getActualNode();
+ dirtyNodes.add(nodeBuilder);
+ }
+
+ public void setRevision(final Date revision) {
+ this.revision = revision;
+ }
+
+ public void setPrefix(final String prefix) {
+ this.prefix = prefix;
+ }
+
+ public void setYangVersion(final String yangVersion) {
+ instance.setYangVersion(yangVersion);
+ }
+
+ public void setDescription(final String description) {
+ instance.setDescription(description);
+ }
+
+ public void setReference(final String reference) {
+ instance.setReference(reference);
+ }
+
+ public void setOrganization(final String organization) {
+ instance.setOrganization(organization);
+ }
+
+ public void setContact(final String contact) {
+ instance.setContact(contact);
+ }
+
+ public boolean addModuleImport(final String moduleName, final Date revision, final String prefix) {
+ final ModuleImport moduleImport = createModuleImport(moduleName, revision, prefix);
+ return imports.add(moduleImport);
+ }
+
+ public Set<ModuleImport> getModuleImports() {
+ return imports;
+ }
+
+ public ExtensionBuilder addExtension(final QName qname, final int line) {
+ final String extName = qname.getLocalName();
+ for (ExtensionBuilder addedExtension : addedExtensions) {
+ if (addedExtension.getQName().getLocalName().equals(extName)) {
+ throw new YangParseException(moduleName, line, "Can not add extension '" + extName
+ + "': extension with same name already declared at line " + addedExtension.getLine());
+ }
+ }
+ final ExtensionBuilder builder = new ExtensionBuilder(name, line, qname);
+ addedExtensions.add(builder);
+ return builder;
+ }
+
+ public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName qname, final SchemaPath schemaPath) {
+ final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
+
+ Builder parent = getActualNode();
+ builder.setParent(parent);
+ addChildToParent(parent, builder, qname.getLocalName());
+
+ return builder;
+ }
+
+ public ListSchemaNodeBuilder addListNode(final int line, final QName qname, final SchemaPath schemaPath) {
+ final ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(name, line, qname, schemaPath);
+
+ Builder parent = getActualNode();
+ builder.setParent(parent);
+ addChildToParent(parent, builder, qname.getLocalName());
+
+ return builder;
+ }
+
+ public LeafSchemaNodeBuilder addLeafNode(final int line, final QName qname, final SchemaPath schemaPath) {
+ final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(name, line, qname, schemaPath);
+
+ Builder parent = getActualNode();
+ builder.setParent(parent);
+ addChildToParent(parent, builder, qname.getLocalName());
+
+ return builder;
+ }
+
+ public LeafListSchemaNodeBuilder addLeafListNode(final int line, final QName qname, final SchemaPath schemaPath) {
+ final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(name, line, qname, schemaPath);
+
+ Builder parent = getActualNode();
+ builder.setParent(parent);
+ addChildToParent(parent, builder, qname.getLocalName());
+
+ return builder;
+ }
+
+ public GroupingBuilder addGrouping(final int line, final QName qname) {
+ final GroupingBuilder builder = new GroupingBuilderImpl(name, line, qname);
+
+ Builder parent = getActualNode();
+ builder.setParent(parent);
+
+ String groupingName = qname.getLocalName();
+ if (parent.equals(this)) {
+ for (GroupingBuilder addedGrouping : addedGroupings) {
+ if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
+ throw new YangParseException(name, line, "grouping with same name '" + groupingName
+ + "' already declared at line " + addedGrouping.getLine());
+ }
+ }
+ addedGroupings.add(builder);
+ } else {
+ if (parent instanceof DataNodeContainerBuilder) {
+ DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
+ for (GroupingBuilder addedGrouping : parentNode.getGroupingBuilders()) {
+ if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
+ throw new YangParseException(name, line, "grouping with same name '" + groupingName
+ + "' already declared at line " + addedGrouping.getLine());
+ }
+ }
+ parentNode.addGrouping(builder);
+ } else if (parent instanceof RpcDefinitionBuilder) {
+ RpcDefinitionBuilder parentNode = (RpcDefinitionBuilder) parent;
+ for (GroupingBuilder child : parentNode.getGroupings()) {
+ if (child.getQName().getLocalName().equals(groupingName)) {
+ throw new YangParseException(name, line, "grouping with same name '" + groupingName
+ + "' already declared at line " + child.getLine());
+ }
+ }
+ parentNode.addGrouping(builder);
+ } else {
+ throw new YangParseException(name, line, "Unresolved parent of grouping " + groupingName);
+ }
+ }
+
+ return builder;
+ }
+
+ public AugmentationSchemaBuilder addAugment(final int line, final String augmentTargetStr) {
+ final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name, line, augmentTargetStr);
+
+ Builder parent = getActualNode();
+ builder.setParent(parent);
+
+ if (parent.equals(this)) {
+ // augment can be declared only under 'module' ...
+ addedAugments.add(builder);
+ } else {
+ // ... or 'uses' statement
+ if (parent instanceof UsesNodeBuilder) {
+ ((UsesNodeBuilder) parent).addAugment(builder);
+ } else {
+ throw new YangParseException(name, line, "Augment can be declared only under module or uses statement.");
+ }
+ }
+ allAugments.add(builder);
+
+ return builder;
+ }
+
+ @Override
+ public void addUsesNode(UsesNodeBuilder usesBuilder) {
+ addedUsesNodes.add(usesBuilder);
+ allUsesNodes.add(usesBuilder);
+ }
+
+ public UsesNodeBuilder addUsesNode(final int line, final String groupingPathStr) {
+ final UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(name, line, groupingPathStr);
+
+ Builder parent = getActualNode();
+ usesBuilder.setParent(parent);
+
+ if (parent.equals(this)) {
+ addedUsesNodes.add(usesBuilder);
+ } else {
+ if (!(parent instanceof DataNodeContainerBuilder)) {
+ throw new YangParseException(name, line, "Unresolved parent of uses '" + groupingPathStr + "'.");
+ }
+ if (parent instanceof AugmentationSchemaBuilder) {
+ usesBuilder.setAugmenting(true);
+ }
+ ((DataNodeContainerBuilder) parent).addUsesNode(usesBuilder);
+ }
+ allUsesNodes.add(usesBuilder);
+ return usesBuilder;
+ }
+
+ public void addRefine(final RefineHolder refine) {
+ final Builder parent = getActualNode();
+ if (!(parent instanceof UsesNodeBuilder)) {
+ throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
+ }
+ ((UsesNodeBuilder) parent).addRefine(refine);
+ refine.setParent(parent);
+ }
+
+ public RpcDefinitionBuilder addRpc(final int line, final QName qname) {
+ Builder parent = getActualNode();
+ if (!(parent.equals(this))) {
+ throw new YangParseException(name, line, "rpc can be defined only in module or submodule");
+ }
+
+ final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(name, line, qname);
+
+ String rpcName = qname.getLocalName();
+ for (RpcDefinitionBuilder rpc : addedRpcs) {
+ if (rpc.getQName().getLocalName().equals(rpcName)) {
+ throw new YangParseException(name, line, "rpc with same name '" + rpcName
+ + "' already declared at line " + rpc.getLine());
+ }
+ }
+ for (DataSchemaNodeBuilder addedChild : addedChildNodes) {
+ if (addedChild.getQName().getLocalName().equals(rpcName)) {
+ throw new YangParseException(name, line, "Can not add rpc: node with same name '" + rpcName
+ + "' already declared at line " + addedChild.getLine());
+ }
+ }
+ for (NotificationBuilder addedNotification : addedNotifications) {
+ if (addedNotification.getQName().getLocalName().equals(rpcName)) {
+ throw new YangParseException(name, line, "Can not add rpc: notification with same name '" + rpcName
+ + "' already declared at line " + addedNotification.getLine());
+ }
+ }
+ addedRpcs.add(rpcBuilder);
+ return rpcBuilder;
+ }
+
+ public ContainerSchemaNodeBuilder addRpcInput(final int line, final QName qname, final SchemaPath schemaPath) {
+ final Builder parent = getActualNode();
+ if (!(parent instanceof RpcDefinitionBuilder)) {
+ throw new YangParseException(name, line, "input can be defined only in rpc statement");
+ }
+ final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
+
+ final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
+ inputBuilder.setParent(rpc);
+
+ rpc.setInput(inputBuilder);
+ return inputBuilder;
+ }
+
+ public ContainerSchemaNodeBuilder addRpcOutput(final SchemaPath schemaPath, final QName qname, final int line) {
+ final Builder parent = getActualNode();
+ if (!(parent instanceof RpcDefinitionBuilder)) {
+ throw new YangParseException(name, line, "output can be defined only in rpc statement");
+ }
+ final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
+
+ final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
+ outputBuilder.setParent(rpc);
+
+ rpc.setOutput(outputBuilder);
+ return outputBuilder;
+ }
+
+ public NotificationBuilder addNotification(final int line, final QName qname) {
+ final Builder parent = getActualNode();
+ if (!(parent.equals(this))) {
+ throw new YangParseException(name, line, "notification can be defined only in module or submodule");
+ }
+
+ String notificationName = qname.getLocalName();
+ for (NotificationBuilder nb : addedNotifications) {
+ if (nb.getQName().equals(qname)) {
+ throw new YangParseException(name, line, "notification with same name '" + notificationName
+ + "' already declared at line " + nb.getLine());
+ }
+ }
+ for (RpcDefinitionBuilder rpc : addedRpcs) {
+ if (rpc.getQName().getLocalName().equals(notificationName)) {
+ throw new YangParseException(name, line, "Can not add notification: rpc with same name '"
+ + notificationName + "' already declared at line " + rpc.getLine());
+ }
+ }
+ for (DataSchemaNodeBuilder addedChild : addedChildNodes) {
+ if (addedChild.getQName().getLocalName().equals(notificationName)) {
+ throw new YangParseException(name, line, "Can not add notification: node with same name '"
+ + notificationName + "' already declared at line " + addedChild.getLine());
+ }
+ }
+
+ final NotificationBuilder builder = new NotificationBuilder(name, line, qname);
+ addedNotifications.add(builder);
+
+ return builder;
+ }
+
+ public FeatureBuilder addFeature(final int line, final QName qname) {
+ Builder parent = getActualNode();
+ if (!(parent.equals(this))) {
+ throw new YangParseException(name, line, "feature can be defined only in module or submodule");
+ }
+
+ final FeatureBuilder builder = new FeatureBuilder(name, line, qname);
+
+ String featureName = qname.getLocalName();
+ for (FeatureBuilder addedFeature : addedFeatures) {
+ if (addedFeature.getQName().getLocalName().equals(featureName)) {
+ throw new YangParseException(name, line, "feature with same name '" + featureName
+ + "' already declared at line " + addedFeature.getLine());
+ }
+ }
+ addedFeatures.add(builder);
+ return builder;
+ }
+
+ public ChoiceBuilder addChoice(final int line, final QName qname) {
+ final ChoiceBuilder builder = new ChoiceBuilder(name, line, qname);
+
+ Builder parent = getActualNode();
+ builder.setParent(parent);
+ addChildToParent(parent, builder, qname.getLocalName());
+
+ return builder;
+ }
+
+ public ChoiceCaseBuilder addCase(final int line, final QName qname) {
+ Builder parent = getActualNode();
+ if (parent == null || parent.equals(this)) {
+ throw new YangParseException(name, line, "'case' parent not found");
+ }
+
+ final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(name, line, qname);
+ builder.setParent(parent);
+
+ if (parent instanceof ChoiceBuilder) {
+ ((ChoiceBuilder) parent).addCase(builder);
+ } else if (parent instanceof AugmentationSchemaBuilder) {
+ ((AugmentationSchemaBuilder) parent).addChildNode(builder);
+ } else {
+ throw new YangParseException(name, line, "Unresolved parent of 'case' " + qname.getLocalName());
+ }
+
+ return builder;
+ }
+
+ public AnyXmlBuilder addAnyXml(final int line, final QName qname, final SchemaPath schemaPath) {
+ final AnyXmlBuilder builder = new AnyXmlBuilder(name, line, qname, schemaPath);
+
+ Builder parent = getActualNode();
+ builder.setParent(parent);
+ addChildToParent(parent, builder, qname.getLocalName());
+
+ return builder;
+ }
+
+ @Override
+ public void addTypedef(TypeDefinitionBuilder typedefBuilder) {
+ String nodeName = typedefBuilder.getQName().getLocalName();
+ for (TypeDefinitionBuilder tdb : addedTypedefs) {
+ if (tdb.getQName().getLocalName().equals(nodeName)) {
+ throw new YangParseException(name, typedefBuilder.getLine(), "typedef with same name '" + nodeName
+ + "' already declared at line " + tdb.getLine());
+ }
+ }
+ addedTypedefs.add(typedefBuilder);
+ }
+
+ public TypeDefinitionBuilderImpl addTypedef(final int line, final QName qname) {
+ final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(name, line, qname);
+
+ Builder parent = getActualNode();
+ builder.setParent(parent);
+
+ String typedefName = qname.getLocalName();
+ if (parent.equals(this)) {
+ for (TypeDefinitionBuilder tdb : addedTypedefs) {
+ if (tdb.getQName().getLocalName().equals(typedefName)) {
+ throw new YangParseException(name, line, "typedef with same name '" + typedefName
+ + "' already declared at line " + tdb.getLine());
+ }
+ }
+ addedTypedefs.add(builder);
+ } else {
+ if (parent instanceof DataNodeContainerBuilder) {
+ DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
+ for (TypeDefinitionBuilder child : parentNode.getTypeDefinitionBuilders()) {
+ if (child.getQName().getLocalName().equals(typedefName)) {
+ throw new YangParseException(name, line, "typedef with same name '" + typedefName
+ + "' already declared at line " + child.getLine());
+ }
+ }
+ parentNode.addTypedef(builder);
+ } else if (parent instanceof RpcDefinitionBuilder) {
+ RpcDefinitionBuilder rpcParent = (RpcDefinitionBuilder) parent;
+ for (TypeDefinitionBuilder tdb : rpcParent.getTypeDefinitions()) {
+ if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
+ throw new YangParseException(name, line, "typedef with same name '" + typedefName
+ + "' already declared at line " + tdb.getLine());
+ }
+ }
+ rpcParent.addTypedef(builder);
+ } else {
+ throw new YangParseException(name, line, "Unresolved parent of typedef " + typedefName);
+ }
+ }
+
+ return builder;
+ }
+
+ public void setType(final TypeDefinition<?> type) {
+ Builder parent = getActualNode();
+ if (parent == null || !(parent instanceof TypeAwareBuilder)) {
+ throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
+ + "'. Invalid parent node: " + parent);
+ }
+ ((TypeAwareBuilder) parent).setType(type);
+ }
+
+ public UnionTypeBuilder addUnionType(final int line, final URI namespace, final Date revision) {
+ final Builder parent = getActualNode();
+ if (parent == null) {
+ throw new YangParseException(name, line, "Unresolved parent of union type");
+ } else {
+ final UnionTypeBuilder union = new UnionTypeBuilder(name, line);
+ if (parent instanceof TypeAwareBuilder) {
+ ((TypeAwareBuilder) parent).setTypedef(union);
+ return union;
+ } else {
+ throw new YangParseException(name, line, "Invalid parent of union type.");
+ }
+ }
+ }
+
+ public void addIdentityrefType(final int line, final SchemaPath schemaPath, final String baseString) {
+ final IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(name, line, baseString, schemaPath);
+
+ final Builder parent = getActualNode();
+ if (parent == null) {
+ throw new YangParseException(name, line, "Unresolved parent of identityref type.");
+ } else {
+ if (parent instanceof TypeAwareBuilder) {
+ final TypeAwareBuilder typeParent = (TypeAwareBuilder) parent;
+ typeParent.setTypedef(identityref);
+ dirtyNodes.add(typeParent);
+ } else {
+ throw new YangParseException(name, line, "Invalid parent of identityref type.");
+ }
+ }
+ }
+
+ public DeviationBuilder addDeviation(final int line, final String targetPath) {
+ Builder parent = getActualNode();
+ if (!(parent.equals(this))) {
+ throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
+ }
+
+ final DeviationBuilder builder = new DeviationBuilder(name, line, targetPath);
+ addedDeviations.add(builder);
+ return builder;
+ }
+
+ public IdentitySchemaNodeBuilder addIdentity(final QName qname, final List<String> parentPath, final int line) {
+ Builder parent = getActualNode();
+ if (!(parent.equals(this))) {
+ throw new YangParseException(name, line, "identity can be defined only in module or submodule");
+ }
+ String identityName = qname.getLocalName();
+ for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
+ if (idBuilder.getQName().equals(qname)) {
+ throw new YangParseException(name, line, "identity with same name '" + identityName
+ + "' already declared at line " + idBuilder.getLine());
+ }
+ }
+
+ final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(name, line, qname);
+ addedIdentities.add(builder);
+ return builder;
+ }
+
+ @Override
+ public void addUnknownNodeBuilder(final UnknownSchemaNodeBuilder builder) {
+ addedUnknownNodes.add(builder);
+ allUnknownNodes.add(builder);
+ }
+
+ public UnknownSchemaNodeBuilder addUnknownSchemaNode(final int line, final QName qname) {
+ final Builder parent = getActualNode();
+ final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(name, line, qname);
+ builder.setParent(parent);
+ allUnknownNodes.add(builder);
+
+ if (parent.equals(this)) {
+ addedUnknownNodes.add(builder);
+ } else {
+ if (parent instanceof SchemaNodeBuilder) {
+ ((SchemaNodeBuilder) parent).addUnknownNodeBuilder(builder);
+ } else if (parent instanceof DataNodeContainerBuilder) {
+ ((DataNodeContainerBuilder) parent).addUnknownNodeBuilder(builder);
+ } else if (parent instanceof RefineHolder) {
+ ((RefineHolder) parent).addUnknownNodeBuilder(builder);
+ } else {
+ throw new YangParseException(name, line, "Unresolved parent of unknown node '" + qname.getLocalName()
+ + "'");
+ }
+ }
+
+ return builder;
+ }
+
+ @Override
+ public String toString() {
+ return "module " + name;
+ }
+
+ private final class ModuleImpl implements Module {
+ private URI namespace;
+ private final String name;
+ private Date revision;
+ private String prefix;
+ private String yangVersion;
+ private String description;
+ private String reference;
+ private String organization;
+ private String contact;
+ private Set<ModuleImport> imports = Collections.emptySet();
+ private Set<FeatureDefinition> features = Collections.emptySet();
+ private Set<TypeDefinition<?>> typeDefinitions = Collections.emptySet();
+ private Set<NotificationDefinition> notifications = Collections.emptySet();
+ private Set<AugmentationSchema> augmentations = Collections.emptySet();
+ private Set<RpcDefinition> rpcs = Collections.emptySet();
+ private Set<Deviation> deviations = Collections.emptySet();
+ private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
+ private Set<GroupingDefinition> groupings = Collections.emptySet();
+ private Set<UsesNode> uses = Collections.emptySet();
+ private List<ExtensionDefinition> extensionNodes = Collections.emptyList();
+ private Set<IdentitySchemaNode> identities = Collections.emptySet();
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private ModuleImpl(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public URI getNamespace() {
+ return namespace;
+ }
+
+ private void setNamespace(URI namespace) {
+ this.namespace = namespace;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Date getRevision() {
+ return revision;
+ }
+
+ private void setRevision(Date revision) {
+ this.revision = revision;
+ }
+
+ @Override
+ public String getPrefix() {
+ return prefix;
+ }
+
+ private void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ @Override
+ public String getYangVersion() {
+ return yangVersion;
+ }
+
+ private void setYangVersion(String yangVersion) {
+ this.yangVersion = yangVersion;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public String getOrganization() {
+ return organization;
+ }
+
+ private void setOrganization(String organization) {
+ this.organization = organization;
+ }
+
+ @Override
+ public String getContact() {
+ return contact;
+ }
+
+ private void setContact(String contact) {
+ this.contact = contact;
+ }
+
+ @Override
+ public Set<ModuleImport> getImports() {
+ return imports;
+ }
+
+ private void setImports(Set<ModuleImport> imports) {
+ if (imports != null) {
+ this.imports = imports;
+ }
+ }
+
+ @Override
+ public Set<FeatureDefinition> getFeatures() {
+ return features;
+ }
+
+ private void setFeatures(Set<FeatureDefinition> features) {
+ if (features != null) {
+ this.features = features;
+ }
+ }
+
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return typeDefinitions;
+ }
+
+ private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
+ if (typeDefinitions != null) {
+ this.typeDefinitions = typeDefinitions;
+ }
+ }
+
+ @Override
+ public Set<NotificationDefinition> getNotifications() {
+ return notifications;
+ }
+
+ private void setNotifications(Set<NotificationDefinition> notifications) {
+ if (notifications != null) {
+ this.notifications = notifications;
+ }
+ }
+
+ @Override
+ public Set<AugmentationSchema> getAugmentations() {
+ return augmentations;
+ }
+
+ private void setAugmentations(Set<AugmentationSchema> augmentations) {
+ if (augmentations != null) {
+ this.augmentations = augmentations;
+ }
+ }
+
+ @Override
+ public Set<RpcDefinition> getRpcs() {
+ return rpcs;
+ }
+
+ private void setRpcs(Set<RpcDefinition> rpcs) {
+ if (rpcs != null) {
+ this.rpcs = rpcs;
+ }
+ }
+
+ @Override
+ public Set<Deviation> getDeviations() {
+ return deviations;
+ }
+
+ private void setDeviations(Set<Deviation> deviations) {
+ if (deviations != null) {
+ this.deviations = deviations;
+ }
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ return new LinkedHashSet<DataSchemaNode>(childNodes.values());
+ }
+
+ private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
+ if (childNodes != null) {
+ this.childNodes = childNodes;
+ }
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return groupings;
+ }
+
+ private void setGroupings(Set<GroupingDefinition> groupings) {
+ if (groupings != null) {
+ this.groupings = groupings;
+ }
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return uses;
+ }
+
+ private void setUses(Set<UsesNode> uses) {
+ if (uses != null) {
+ this.uses = uses;
+ }
+ }
+
+ @Override
+ public List<ExtensionDefinition> getExtensionSchemaNodes() {
+ return extensionNodes;
+ }
+
+ private void setExtensionSchemaNodes(final List<ExtensionDefinition> extensionNodes) {
+ if (extensionNodes != null) {
+ this.extensionNodes = extensionNodes;
+ }
+ }
+
+ @Override
+ public Set<IdentitySchemaNode> getIdentities() {
+ return identities;
+ }
+
+ private void setIdentities(final Set<IdentitySchemaNode> identities) {
+ if (identities != null) {
+ this.identities = identities;
+ }
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(final List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(QName name) {
+ return childNodes.get(name);
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(String name) {
+ DataSchemaNode result = null;
+ for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
+ if (entry.getKey().getLocalName().equals(name)) {
+ result = entry.getValue();
+ break;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((revision == null) ? 0 : revision.hashCode());
+ result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
+ result = prime * result + ((yangVersion == null) ? 0 : yangVersion.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ModuleImpl other = (ModuleImpl) obj;
+ if (namespace == null) {
+ if (other.namespace != null) {
+ return false;
+ }
+ } else if (!namespace.equals(other.namespace)) {
+ return false;
+ }
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ if (revision == null) {
+ if (other.revision != null) {
+ return false;
+ }
+ } else if (!revision.equals(other.revision)) {
+ return false;
+ }
+ if (prefix == null) {
+ if (other.prefix != null) {
+ return false;
+ }
+ } else if (!prefix.equals(other.prefix)) {
+ return false;
+ }
+ if (yangVersion == null) {
+ if (other.yangVersion != null) {
+ return false;
+ }
+ } else if (!yangVersion.equals(other.yangVersion)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(ModuleImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append("name=" + name);
+ sb.append(", namespace=" + namespace);
+ sb.append(", revision=" + revision);
+ sb.append(", prefix=" + prefix);
+ sb.append(", yangVersion=" + yangVersion);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Add child to parent. Method checks for duplicates and add given child
+ * node to parent. If node with same name is found, throws exception. If
+ * parent is null, child node will be added directly to module.
+ *
+ * @param parent
+ * @param child
+ * @param childName
+ */
+ private void addChildToParent(final Builder parent, final DataSchemaNodeBuilder child, final String childName) {
+ final int line = child.getLine();
+ if (parent.equals(this)) {
+ // if parent == null => node is defined under module
+ // All leafs, leaf-lists, lists, containers, choices, rpcs,
+ // notifications, and anyxmls defined within a parent node or at the
+ // top level of the module or its submodules share the same
+ // identifier namespace.
+ for (DataSchemaNodeBuilder childNode : addedChildNodes) {
+ if (childNode.getQName().getLocalName().equals(childName)) {
+ throw new YangParseException(name, line, "Can not add '" + child
+ + "': node with same name already declared at line " + childNode.getLine());
+ }
+ }
+ for (RpcDefinitionBuilder rpc : addedRpcs) {
+ if (rpc.getQName().getLocalName().equals(childName)) {
+ throw new YangParseException(name, line, "Can not add '" + child
+ + "': rpc with same name already declared at line " + rpc.getLine());
+ }
+ }
+ for (NotificationBuilder notification : addedNotifications) {
+ if (notification.getQName().getLocalName().equals(childName)) {
+ throw new YangParseException(name, line, "Can not add '" + child
+ + "': notification with same name already declared at line " + notification.getLine());
+ }
+ }
+ addedChildNodes.add(child);
+ } else {
+ // no need for checking rpc and notification because they can be
+ // defined only under module or submodule
+ if (parent instanceof DataNodeContainerBuilder) {
+ DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
+ for (DataSchemaNodeBuilder childNode : parentNode.getChildNodeBuilders()) {
+ if (childNode.getQName().getLocalName().equals(childName)) {
+ throw new YangParseException(name, line, "Can not add '" + child + "': node with same name '"
+ + childName + "' already declared at line " + childNode.getLine());
+ }
+ }
+ parentNode.addChildNode(child);
+ } else if (parent instanceof ChoiceBuilder) {
+ ChoiceBuilder parentNode = (ChoiceBuilder) parent;
+ for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) {
+ if (caseBuilder.getQName().getLocalName().equals(childName)) {
+ throw new YangParseException(name, line, "Can not add '" + child + "': case with same name '"
+ + childName + "' already declared at line " + caseBuilder.getLine());
+ }
+ }
+ parentNode.addCase(child);
+ } else {
+ throw new YangParseException(name, line, "Unresolved parent of node '" + childName + "'.");
+ }
+ }
+ }
+
+ private ModuleImport createModuleImport(final String moduleName, final Date revision, final String prefix) {
+ final ModuleImport moduleImport = new ModuleImport() {
+ @Override
+ public String getModuleName() {
+ return moduleName;
+ }
+
+ @Override
+ public Date getRevision() {
+ return revision;
+ }
+
+ @Override
+ public String getPrefix() {
+ return prefix;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((moduleName == null) ? 0 : moduleName.hashCode());
+ result = prime * result + ((revision == null) ? 0 : revision.hashCode());
+ result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ModuleImport other = (ModuleImport) obj;
+ if (getModuleName() == null) {
+ if (other.getModuleName() != null) {
+ return false;
+ }
+ } else if (!getModuleName().equals(other.getModuleName())) {
+ return false;
+ }
+ if (getRevision() == null) {
+ if (other.getRevision() != null) {
+ return false;
+ }
+ } else if (!getRevision().equals(other.getRevision())) {
+ return false;
+ }
+ if (getPrefix() == null) {
+ if (other.getPrefix() != null) {
+ return false;
+ }
+ } else if (!getPrefix().equals(other.getPrefix())) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "ModuleImport[moduleName=" + moduleName + ", revision=" + revision + ", prefix=" + prefix + "]";
+ }
+ };
+ return moduleImport;
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.NotificationDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+
+public final class NotificationBuilder extends AbstractDataNodeContainerBuilder implements SchemaNodeBuilder,
+ AugmentationTargetBuilder {
+ private boolean isBuilt;
+ private final NotificationDefinitionImpl instance;
+ private SchemaPath schemaPath;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
+ private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
+ private Set<AugmentationSchema> augmentations;
+ private final Set<AugmentationSchemaBuilder> addedAugmentations = new HashSet<AugmentationSchemaBuilder>();
+
+ NotificationBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ instance = new NotificationDefinitionImpl(qname);
+ }
+
+ @Override
+ public NotificationDefinition build() {
+ if (!isBuilt) {
+ instance.setPath(schemaPath);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+
+ // CHILD NODES
+ final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
+ for (DataSchemaNodeBuilder node : addedChildNodes) {
+ childs.put(node.getQName(), node.build());
+ }
+ instance.setChildNodes(childs);
+
+ // GROUPINGS
+ final Set<GroupingDefinition> groupingDefs = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
+ for (GroupingBuilder builder : addedGroupings) {
+ groupingDefs.add(builder.build());
+ }
+ instance.setGroupings(groupingDefs);
+
+ // TYPEDEFS
+ final Set<TypeDefinition<?>> typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
+ for (TypeDefinitionBuilder entry : addedTypedefs) {
+ typedefs.add(entry.build());
+ }
+ instance.setTypeDefinitions(typedefs);
+
+ // USES
+ final Set<UsesNode> uses = new HashSet<UsesNode>();
+ for (UsesNodeBuilder builder : addedUsesNodes) {
+ uses.add(builder.build());
+ }
+ instance.setUses(uses);
+
+ // AUGMENTATIONS
+ if (augmentations == null) {
+ augmentations = new HashSet<AugmentationSchema>();
+ for (AugmentationSchemaBuilder builder : addedAugmentations) {
+ augmentations.add(builder.build());
+ }
+ }
+ instance.setAvailableAugmentations(augmentations);
+
+ // UNKNOWN NODES
+ final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+
+ return instance;
+ }
+
+ @Override
+ public void rebuild() {
+ isBuilt = false;
+ build();
+ }
+
+ @Override
+ public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
+ return addedTypedefs;
+ }
+
+ @Override
+ public void addTypedef(final TypeDefinitionBuilder type) {
+ addedTypedefs.add(type);
+ }
+
+ @Override
+ public void addUsesNode(final UsesNodeBuilder usesNodeBuilder) {
+ addedUsesNodes.add(usesNodeBuilder);
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public void setPath(SchemaPath schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public void setStatus(final Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ public Set<AugmentationSchemaBuilder> getAugmentations() {
+ return addedAugmentations;
+ }
+
+ @Override
+ public void addAugmentation(AugmentationSchemaBuilder augment) {
+ addedAugmentations.add(augment);
+ }
+
+ public void setAugmentations(final Set<AugmentationSchema> augmentations) {
+ this.augmentations = augmentations;
+ }
+
+ @Override
+ public String toString() {
+ return "notification " + getQName().getLocalName();
+ }
+
+ public final class NotificationDefinitionImpl implements NotificationDefinition {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
+ private Set<GroupingDefinition> groupings = Collections.emptySet();
+ private Set<TypeDefinition<?>> typeDefinitions = Collections.emptySet();
+ private Set<UsesNode> uses = Collections.emptySet();
+ private Set<AugmentationSchema> augmentations = Collections.emptySet();
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private NotificationDefinitionImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(final SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ return new HashSet<DataSchemaNode>(childNodes.values());
+ }
+
+ private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
+ if (childNodes != null) {
+ this.childNodes = childNodes;
+ }
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return groupings;
+ }
+
+ private void setGroupings(Set<GroupingDefinition> groupings) {
+ if (groupings != null) {
+ this.groupings = groupings;
+ }
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return uses;
+ }
+
+ private void setUses(Set<UsesNode> uses) {
+ if (uses != null) {
+ this.uses = uses;
+ }
+ }
+
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return typeDefinitions;
+ }
+
+ private void setTypeDefinitions(final Set<TypeDefinition<?>> typeDefinitions) {
+ if (typeDefinitions != null) {
+ this.typeDefinitions = typeDefinitions;
+ }
+ }
+
+ @Override
+ public Set<AugmentationSchema> getAvailableAugmentations() {
+ return augmentations;
+ }
+
+ private void setAvailableAugmentations(Set<AugmentationSchema> augmentations) {
+ if (augmentations != null) {
+ this.augmentations = augmentations;
+ }
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(final List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(QName name) {
+ return childNodes.get(name);
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(String name) {
+ DataSchemaNode result = null;
+ for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
+ if (entry.getKey().getLocalName().equals(name)) {
+ result = entry.getValue();
+ break;
+ }
+ }
+ return result;
+ }
+
+ public NotificationBuilder toBuilder() {
+ return NotificationBuilder.this;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final NotificationDefinitionImpl other = (NotificationDefinitionImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(NotificationDefinitionImpl.class.getSimpleName());
+ sb.append("[qname=" + qname + ", path=" + path + "]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.RpcDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+
+public final class RpcDefinitionBuilder extends AbstractSchemaNodeBuilder {
+ private boolean isBuilt;
+ private final RpcDefinitionImpl instance;
+ private ContainerSchemaNodeBuilder inputBuilder;
+ private ContainerSchemaNodeBuilder outputBuilder;
+ private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
+ private final Set<GroupingBuilder> addedGroupings = new HashSet<GroupingBuilder>();
+
+ RpcDefinitionBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ this.instance = new RpcDefinitionImpl(qname);
+ }
+
+ @Override
+ public RpcDefinition build() {
+ if (!isBuilt) {
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+
+ final ContainerSchemaNode input = inputBuilder == null ? null : inputBuilder.build();
+ final ContainerSchemaNode output = outputBuilder == null ? null : outputBuilder.build();
+ instance.setInput(input);
+ instance.setOutput(output);
+
+ instance.setPath(schemaPath);
+
+ // TYPEDEFS
+ final Set<TypeDefinition<?>> typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
+ for (TypeDefinitionBuilder entry : addedTypedefs) {
+ typedefs.add(entry.build());
+ }
+ instance.setTypeDefinitions(typedefs);
+
+ // GROUPINGS
+ final Set<GroupingDefinition> groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
+ for (GroupingBuilder entry : addedGroupings) {
+ groupings.add(entry.build());
+ }
+ instance.setGroupings(groupings);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+ return instance;
+ }
+
+ void setInput(final ContainerSchemaNodeBuilder inputBuilder) {
+ this.inputBuilder = inputBuilder;
+ }
+
+ void setOutput(final ContainerSchemaNodeBuilder outputBuilder) {
+ this.outputBuilder = outputBuilder;
+ }
+
+ public Set<TypeDefinitionBuilder> getTypeDefinitions() {
+ return addedTypedefs;
+ }
+
+ public void addTypedef(final TypeDefinitionBuilder type) {
+ addedTypedefs.add(type);
+ }
+
+ public Set<GroupingBuilder> getGroupings() {
+ return addedGroupings;
+ }
+
+ public void addGrouping(GroupingBuilder grouping) {
+ addedGroupings.add(grouping);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof RpcDefinitionBuilder)) {
+ return false;
+ }
+ final RpcDefinitionBuilder other = (RpcDefinitionBuilder) obj;
+ if (other.qname == null) {
+ if (this.qname != null) {
+ return false;
+ }
+ } else if (!other.qname.equals(this.qname)) {
+ return false;
+ }
+ if (other.schemaPath == null) {
+ if (this.schemaPath != null) {
+ return false;
+ }
+ } else if (!other.schemaPath.equals(this.schemaPath)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "rpc " + qname.getLocalName();
+ }
+
+ private final class RpcDefinitionImpl implements RpcDefinition {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status;
+ private ContainerSchemaNode input;
+ private ContainerSchemaNode output;
+ private Set<TypeDefinition<?>> typeDefinitions;
+ private Set<GroupingDefinition> groupings;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ private RpcDefinitionImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public ContainerSchemaNode getInput() {
+ return input;
+ }
+
+ private void setInput(ContainerSchemaNode input) {
+ this.input = input;
+ }
+
+ @Override
+ public ContainerSchemaNode getOutput() {
+ return output;
+ }
+
+ private void setOutput(ContainerSchemaNode output) {
+ this.output = output;
+ }
+
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return typeDefinitions;
+ }
+
+ private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
+ this.typeDefinitions = typeDefinitions;
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return groupings;
+ }
+
+ private void setGroupings(Set<GroupingDefinition> groupings) {
+ this.groupings = groupings;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final RpcDefinitionImpl other = (RpcDefinitionImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(RpcDefinitionImpl.class.getSimpleName() + "[");
+ sb.append("qname=" + qname);
+ sb.append(", path=" + path);
+ sb.append(", input=" + input);
+ sb.append(", output=" + output + "]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.model.util.UnknownType;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractTypeAwareBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+public final class TypeDefinitionBuilderImpl extends AbstractTypeAwareBuilder implements TypeDefinitionBuilder {
+ private SchemaPath schemaPath;
+ private List<RangeConstraint> ranges = Collections.emptyList();
+ private List<LengthConstraint> lengths = Collections.emptyList();
+ private List<PatternConstraint> patterns = Collections.emptyList();
+ private Integer fractionDigits = null;
+
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private String units;
+ private Object defaultValue;
+ private boolean addedByUses;
+
+ public TypeDefinitionBuilderImpl(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ }
+
+ public TypeDefinitionBuilderImpl(TypeDefinitionBuilder tdb) {
+ super(tdb.getModuleName(), tdb.getLine(), tdb.getQName());
+ schemaPath = tdb.getPath();
+
+ type = tdb.getType();
+ typedef = tdb.getTypedef();
+
+ unknownNodes = tdb.getUnknownNodes();
+ for (UnknownSchemaNodeBuilder usnb : tdb.getUnknownNodeBuilders()) {
+ addedUnknownNodes.add(usnb);
+ }
+ ranges = tdb.getRanges();
+ lengths = tdb.getLengths();
+ patterns = tdb.getPatterns();
+ fractionDigits = tdb.getFractionDigits();
+
+ description = tdb.getDescription();
+ reference = tdb.getReference();
+ status = tdb.getStatus();
+ units = tdb.getUnits();
+ defaultValue = tdb.getDefaultValue();
+ addedByUses = tdb.isAddedByUses();
+ }
+
+ @Override
+ public TypeDefinition<? extends TypeDefinition<?>> build() {
+ TypeDefinition<?> result = null;
+ ExtendedType.Builder typeBuilder = null;
+ if ((type == null || type instanceof UnknownType) && typedef == null) {
+ throw new YangParseException("Unresolved type: '" + qname.getLocalName() + "'.");
+ }
+ if (type == null || type instanceof UnknownType) {
+ type = typedef.build();
+ }
+
+ typeBuilder = new ExtendedType.Builder(qname, type, description, reference, schemaPath);
+
+ typeBuilder.status(status);
+ typeBuilder.units(units);
+ typeBuilder.defaultValue(defaultValue);
+ typeBuilder.addedByUses(addedByUses);
+
+ typeBuilder.ranges(ranges);
+ typeBuilder.lengths(lengths);
+ typeBuilder.patterns(patterns);
+ typeBuilder.fractionDigits(fractionDigits);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ typeBuilder.unknownSchemaNodes(unknownNodes);
+ result = typeBuilder.build();
+ return result;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public void setPath(final SchemaPath schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public void setStatus(final Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public String getUnits() {
+ return units;
+ }
+
+ @Override
+ public void setUnits(final String units) {
+ this.units = units;
+ }
+
+ @Override
+ public Object getDefaultValue() {
+ return defaultValue;
+ }
+
+ @Override
+ public void setDefaultValue(final Object defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownNodes() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<RangeConstraint> getRanges() {
+ return ranges;
+ }
+
+ @Override
+ public void setRanges(final List<RangeConstraint> ranges) {
+ if (ranges != null) {
+ this.ranges = ranges;
+ }
+ }
+
+ @Override
+ public List<LengthConstraint> getLengths() {
+ return lengths;
+ }
+
+ @Override
+ public void setLengths(final List<LengthConstraint> lengths) {
+ if (lengths != null) {
+ this.lengths = lengths;
+ }
+ }
+
+ @Override
+ public List<PatternConstraint> getPatterns() {
+ return patterns;
+ }
+
+ @Override
+ public void setPatterns(final List<PatternConstraint> patterns) {
+ if (patterns != null) {
+ this.patterns = patterns;
+ }
+ }
+
+ @Override
+ public Integer getFractionDigits() {
+ return fractionDigits;
+ }
+
+ @Override
+ public void setFractionDigits(final Integer fractionDigits) {
+ this.fractionDigits = fractionDigits;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder result = new StringBuilder("TypedefBuilder[" + qname.getLocalName());
+ result.append(", type=");
+ if (type == null) {
+ result.append(typedef);
+ } else {
+ result.append(type);
+ }
+ result.append("]");
+ return result.toString();
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
+import org.opendaylight.controller.yang.model.util.UnionType;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractTypeAwareBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+
+/**
+ * Builder for YANG union type. User can add type to this union as
+ * TypeDefinition object (resolved type) or in form of TypeDefinitionBuilder.
+ * When build is called, types in builder form will be built and add to resolved
+ * types.
+ */
+public final class UnionTypeBuilder extends AbstractTypeAwareBuilder implements TypeDefinitionBuilder {
+ private final static String NAME = "union";
+
+ private final List<TypeDefinition<?>> types;
+ private final List<TypeDefinitionBuilder> typedefs;
+ private UnionType instance;
+ private boolean isBuilt;
+
+ private SchemaPath path;
+
+ public UnionTypeBuilder(final String moduleName, final int line) {
+ super(moduleName, line, null);
+ types = new ArrayList<TypeDefinition<?>>();
+ typedefs = new ArrayList<TypeDefinitionBuilder>();
+ }
+
+ public List<TypeDefinition<?>> getTypes() {
+ return types;
+ }
+
+ @Override
+ public TypeDefinition<?> getType() {
+ return null;
+ }
+
+ public List<TypeDefinitionBuilder> getTypedefs() {
+ return Collections.unmodifiableList(typedefs);
+ }
+
+ @Override
+ public TypeDefinitionBuilder getTypedef() {
+ return null;
+ }
+
+ @Override
+ public void setType(final TypeDefinition<?> type) {
+ types.add(type);
+ }
+
+ @Override
+ public void setTypedef(final TypeDefinitionBuilder tdb) {
+ typedefs.add(tdb);
+ }
+
+ @Override
+ public UnionType build() {
+ if (!isBuilt) {
+ instance = new UnionType(path, types);
+ for (TypeDefinitionBuilder tdb : typedefs) {
+ types.add(tdb.build());
+ }
+ isBuilt = true;
+ }
+ return instance;
+ }
+
+ @Override
+ public void setPath(final SchemaPath schemaPath) {
+ this.path = schemaPath;
+ }
+
+ @Override
+ public void setDescription(final String description) {
+ throw new YangParseException(moduleName, line, "Can not set description to " + NAME);
+ }
+
+ @Override
+ public void setReference(final String reference) {
+ throw new YangParseException(moduleName, line, "Can not set reference to " + NAME);
+ }
+
+ @Override
+ public void setStatus(final Status status) {
+ throw new YangParseException(moduleName, line, "Can not set status to " + NAME);
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return false;
+ }
+
+ @Override
+ public void setAddedByUses(final boolean addedByUses) {
+ throw new YangParseException(moduleName, line, "Union type can not be added by uses.");
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownNodes() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void addUnknownNodeBuilder(final UnknownSchemaNodeBuilder unknownNode) {
+ // not yet supported
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ @Override
+ public String getDescription() {
+ return null;
+ }
+
+ @Override
+ public String getReference() {
+ return null;
+ }
+
+ @Override
+ public Status getStatus() {
+ return null;
+ }
+
+ @Override
+ public List<RangeConstraint> getRanges() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void setRanges(List<RangeConstraint> ranges) {
+ throw new YangParseException(moduleName, line, "Can not set ranges to " + NAME);
+ }
+
+ @Override
+ public List<LengthConstraint> getLengths() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void setLengths(List<LengthConstraint> lengths) {
+ throw new YangParseException(moduleName, line, "Can not set lengths to " + NAME);
+ }
+
+ @Override
+ public List<PatternConstraint> getPatterns() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void setPatterns(List<PatternConstraint> patterns) {
+ throw new YangParseException(moduleName, line, "Can not set patterns to " + NAME);
+ }
+
+ @Override
+ public Integer getFractionDigits() {
+ return null;
+ }
+
+ @Override
+ public void setFractionDigits(Integer fractionDigits) {
+ throw new YangParseException(moduleName, line, "Can not set fraction digits to " + NAME);
+ }
+
+ @Override
+ public List<UnknownSchemaNodeBuilder> getUnknownNodeBuilders() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Object getDefaultValue() {
+ return null;
+ }
+
+ @Override
+ public void setDefaultValue(Object defaultValue) {
+ throw new YangParseException(moduleName, line, "Can not set default value to " + NAME);
+ }
+
+ @Override
+ public String getUnits() {
+ return null;
+ }
+
+ @Override
+ public void setUnits(String units) {
+ throw new YangParseException(moduleName, line, "Can not set units to " + NAME);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder result = new StringBuilder(UnionTypeBuilder.class.getSimpleName() + "[");
+ result.append(", types=" + types);
+ result.append(", typedefs=" + typedefs);
+ result.append("]");
+ return result.toString();
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.builder.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.Comparators;
+
+public final class UnknownSchemaNodeBuilder extends AbstractSchemaNodeBuilder {
+ private boolean isBuilt;
+ private final UnknownSchemaNodeImpl instance;
+ private boolean addedByUses;
+ private QName nodeType;
+ private String nodeParameter;
+
+ public UnknownSchemaNodeBuilder(final String moduleName, final int line, final QName qname) {
+ super(moduleName, line, qname);
+ instance = new UnknownSchemaNodeImpl(qname);
+ }
+
+ public UnknownSchemaNodeBuilder(UnknownSchemaNodeBuilder b) {
+ super(b.getModuleName(), b.getLine(), b.getQName());
+ instance = new UnknownSchemaNodeImpl(qname);
+ schemaPath = b.getPath();
+ description = b.getDescription();
+ reference = b.getReference();
+ status = b.getStatus();
+ addedByUses = b.isAddedByUses();
+ unknownNodes = b.unknownNodes;
+ addedUnknownNodes.addAll(b.addedUnknownNodes);
+ nodeType = b.getNodeType();
+ nodeParameter = b.getNodeParameter();
+ }
+
+ @Override
+ public UnknownSchemaNode build() {
+ if (!isBuilt) {
+ instance.setPath(schemaPath);
+ instance.setNodeType(nodeType);
+ instance.setNodeParameter(nodeParameter);
+ instance.setDescription(description);
+ instance.setReference(reference);
+ instance.setStatus(status);
+ instance.setAddedByUses(addedByUses);
+
+ // UNKNOWN NODES
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
+ }
+
+ return instance;
+ }
+
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ public void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ public QName getNodeType() {
+ return nodeType;
+ }
+
+ public void setNodeType(final QName nodeType) {
+ this.nodeType = nodeType;
+ }
+
+ public String getNodeParameter() {
+ return nodeParameter;
+ }
+
+ public void setNodeParameter(final String nodeParameter) {
+ this.nodeParameter = nodeParameter;
+ }
+
+ private final class UnknownSchemaNodeImpl implements UnknownSchemaNode {
+ private final QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status = Status.CURRENT;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+ private QName nodeType;
+ private String nodeParameter;
+ private boolean addedByUses;
+
+ private UnknownSchemaNodeImpl(final QName qname) {
+ this.qname = qname;
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ private void setPath(final SchemaPath path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ private void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ private void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ private void setStatus(final Status status) {
+ if (status != null) {
+ this.status = status;
+ }
+ }
+
+ @Override
+ public boolean isAddedByUses() {
+ return addedByUses;
+ }
+
+ private void setAddedByUses(final boolean addedByUses) {
+ this.addedByUses = addedByUses;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(final List<UnknownSchemaNode> unknownNodes) {
+ if (unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public QName getNodeType() {
+ return nodeType;
+ }
+
+ private void setNodeType(final QName nodeType) {
+ this.nodeType = nodeType;
+ }
+
+ @Override
+ public String getNodeParameter() {
+ return nodeParameter;
+ }
+
+ private void setNodeParameter(final String nodeParameter) {
+ this.nodeParameter = nodeParameter;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(UnknownSchemaNodeImpl.class.getSimpleName());
+ sb.append("[");
+ sb.append(qname);
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.parser.builder.impl;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;\r
+import org.opendaylight.controller.yang.model.api.SchemaNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaPath;\r
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.UsesNode;\r
+import org.opendaylight.controller.yang.parser.builder.api.AbstractBuilder;\r
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;\r
+import org.opendaylight.controller.yang.parser.builder.api.Builder;\r
+import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;\r
+import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;\r
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;\r
+import org.opendaylight.controller.yang.parser.util.RefineHolder;\r
+import org.opendaylight.controller.yang.parser.util.YangParseException;\r
+\r
+public final class UsesNodeBuilderImpl extends AbstractBuilder implements UsesNodeBuilder {\r
+ private boolean isBuilt;\r
+ private UsesNodeImpl instance;\r
+ private DataNodeContainerBuilder parent;\r
+ private final String groupingName;\r
+ private SchemaPath groupingPath;\r
+ private boolean augmenting;\r
+ private boolean addedByUses;\r
+ private final Set<AugmentationSchemaBuilder> addedAugments = new HashSet<AugmentationSchemaBuilder>();\r
+ private final List<SchemaNodeBuilder> refineBuilders = new ArrayList<SchemaNodeBuilder>();\r
+ private final List<RefineHolder> refines = new ArrayList<RefineHolder>();\r
+\r
+ public UsesNodeBuilderImpl(final String moduleName, final int line, final String groupingName) {\r
+ super(moduleName, line);\r
+ this.groupingName = groupingName;\r
+ }\r
+\r
+ public UsesNodeBuilderImpl(UsesNodeBuilder b) {\r
+ super(b.getModuleName(), b.getLine());\r
+ groupingName = b.getGroupingName();\r
+ parent = b.getParent();\r
+ groupingPath = b.getGroupingPath();\r
+ augmenting = b.isAugmenting();\r
+ addedByUses = b.isAddedByUses();\r
+ addedAugments.addAll(b.getAugmentations());\r
+ refineBuilders.addAll(b.getRefineNodes());\r
+ refines.addAll(b.getRefines());\r
+ }\r
+\r
+ @Override\r
+ public UsesNode build() {\r
+ if (!isBuilt) {\r
+ instance = new UsesNodeImpl(groupingPath);\r
+ instance.setAugmenting(augmenting);\r
+ instance.setAddedByUses(addedByUses);\r
+\r
+ // AUGMENTATIONS\r
+ final Set<AugmentationSchema> augments = new HashSet<AugmentationSchema>();\r
+ for (AugmentationSchemaBuilder builder : addedAugments) {\r
+ augments.add(builder.build());\r
+ }\r
+ instance.setAugmentations(augments);\r
+\r
+ // REFINES\r
+ final Map<SchemaPath, SchemaNode> refineNodes = new HashMap<SchemaPath, SchemaNode>();\r
+ for (SchemaNodeBuilder refineBuilder : refineBuilders) {\r
+ SchemaNode refineNode = refineBuilder.build();\r
+ refineNodes.put(refineNode.getPath(), refineNode);\r
+ }\r
+ instance.setRefines(refineNodes);\r
+\r
+ // UNKNOWN NODES\r
+ List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();\r
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {\r
+ unknownNodes.add(b.build());\r
+ }\r
+ instance.setUnknownSchemaNodes(unknownNodes);\r
+\r
+ isBuilt = true;\r
+ }\r
+ return instance;\r
+ }\r
+\r
+ @Override\r
+ public DataNodeContainerBuilder getParent() {\r
+ return parent;\r
+ }\r
+\r
+ @Override\r
+ public void setParent(Builder parent) {\r
+ if (!(parent instanceof DataNodeContainerBuilder)) {\r
+ throw new YangParseException(moduleName, line, "Unresolved parent of uses '" + groupingName + "'.");\r
+ }\r
+ this.parent = (DataNodeContainerBuilder) parent;\r
+ }\r
+\r
+ @Override\r
+ public SchemaPath getGroupingPath() {\r
+ return groupingPath;\r
+ }\r
+\r
+ @Override\r
+ public void setGroupingPath(SchemaPath groupingPath) {\r
+ this.groupingPath = groupingPath;\r
+ }\r
+\r
+ @Override\r
+ public String getGroupingName() {\r
+ return groupingName;\r
+ }\r
+\r
+ @Override\r
+ public Set<AugmentationSchemaBuilder> getAugmentations() {\r
+ return addedAugments;\r
+ }\r
+\r
+ @Override\r
+ public void addAugment(final AugmentationSchemaBuilder augmentBuilder) {\r
+ addedAugments.add(augmentBuilder);\r
+ }\r
+\r
+ @Override\r
+ public boolean isAugmenting() {\r
+ return augmenting;\r
+ }\r
+\r
+ @Override\r
+ public void setAugmenting(final boolean augmenting) {\r
+ this.augmenting = augmenting;\r
+ }\r
+\r
+ @Override\r
+ public boolean isAddedByUses() {\r
+ return addedByUses;\r
+ }\r
+\r
+ @Override\r
+ public void setAddedByUses(final boolean addedByUses) {\r
+ this.addedByUses = addedByUses;\r
+ }\r
+\r
+ @Override\r
+ public List<SchemaNodeBuilder> getRefineNodes() {\r
+ return refineBuilders;\r
+ }\r
+\r
+ @Override\r
+ public void addRefineNode(SchemaNodeBuilder refineNode) {\r
+ refineBuilders.add(refineNode);\r
+ }\r
+\r
+ @Override\r
+ public List<RefineHolder> getRefines() {\r
+ return refines;\r
+ }\r
+\r
+ @Override\r
+ public void addRefine(RefineHolder refine) {\r
+ refines.add(refine);\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + ((groupingName == null) ? 0 : groupingName.hashCode());\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (getClass() != obj.getClass())\r
+ return false;\r
+ UsesNodeBuilderImpl other = (UsesNodeBuilderImpl) obj;\r
+ if (groupingName == null) {\r
+ if (other.groupingName != null)\r
+ return false;\r
+ } else if (!groupingName.equals(other.groupingName))\r
+ return false;\r
+\r
+ if (parent == null) {\r
+ if (other.parent != null)\r
+ return false;\r
+ } else if (!parent.equals(other.parent))\r
+ return false;\r
+ if (refines == null) {\r
+ if (other.refines != null)\r
+ return false;\r
+ } else if (!refines.equals(other.refines))\r
+ return false;\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "uses '" + groupingName + "'";\r
+ }\r
+\r
+ public final class UsesNodeImpl implements UsesNode {\r
+ private final SchemaPath groupingPath;\r
+ private Set<AugmentationSchema> augmentations = Collections.emptySet();\r
+ private boolean augmenting;\r
+ private boolean addedByUses;\r
+ private Map<SchemaPath, SchemaNode> refines = Collections.emptyMap();\r
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();\r
+\r
+ private UsesNodeImpl(final SchemaPath groupingPath) {\r
+ this.groupingPath = groupingPath;\r
+ }\r
+\r
+ @Override\r
+ public SchemaPath getGroupingPath() {\r
+ return groupingPath;\r
+ }\r
+\r
+ @Override\r
+ public Set<AugmentationSchema> getAugmentations() {\r
+ return augmentations;\r
+ }\r
+\r
+ private void setAugmentations(final Set<AugmentationSchema> augmentations) {\r
+ if (augmentations != null) {\r
+ this.augmentations = augmentations;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public boolean isAugmenting() {\r
+ return augmenting;\r
+ }\r
+\r
+ private void setAugmenting(final boolean augmenting) {\r
+ this.augmenting = augmenting;\r
+ }\r
+\r
+ @Override\r
+ public boolean isAddedByUses() {\r
+ return addedByUses;\r
+ }\r
+\r
+ private void setAddedByUses(final boolean addedByUses) {\r
+ this.addedByUses = addedByUses;\r
+ }\r
+\r
+ @Override\r
+ public Map<SchemaPath, SchemaNode> getRefines() {\r
+ return refines;\r
+ }\r
+\r
+ private void setRefines(Map<SchemaPath, SchemaNode> refines) {\r
+ if (refines != null) {\r
+ this.refines = refines;\r
+ }\r
+ }\r
+\r
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {\r
+ return unknownNodes;\r
+ }\r
+\r
+ private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {\r
+ if (unknownSchemaNodes != null) {\r
+ this.unknownNodes = unknownSchemaNodes;\r
+ }\r
+ }\r
+\r
+ public UsesNodeBuilder toBuilder() {\r
+ return UsesNodeBuilderImpl.this;\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + ((groupingPath == null) ? 0 : groupingPath.hashCode());\r
+ result = prime * result + ((augmentations == null) ? 0 : augmentations.hashCode());\r
+ result = prime * result + (augmenting ? 1231 : 1237);\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj) {\r
+ return true;\r
+ }\r
+ if (obj == null) {\r
+ return false;\r
+ }\r
+ if (getClass() != obj.getClass()) {\r
+ return false;\r
+ }\r
+ final UsesNodeImpl other = (UsesNodeImpl) obj;\r
+ if (groupingPath == null) {\r
+ if (other.groupingPath != null) {\r
+ return false;\r
+ }\r
+ } else if (!groupingPath.equals(other.groupingPath)) {\r
+ return false;\r
+ }\r
+ if (augmentations == null) {\r
+ if (other.augmentations != null) {\r
+ return false;\r
+ }\r
+ } else if (!augmentations.equals(other.augmentations)) {\r
+ return false;\r
+ }\r
+ if (augmenting != other.augmenting) {\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ StringBuilder sb = new StringBuilder(UsesNodeImpl.class.getSimpleName());\r
+ sb.append("[groupingPath=" + groupingPath + "]");\r
+ return sb.toString();\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.NotificationDefinition;
+import org.opendaylight.controller.yang.model.api.RpcDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+
+final class SchemaContextImpl implements SchemaContext {
+ private final Set<Module> modules;
+
+ SchemaContextImpl(final Set<Module> modules) {
+ this.modules = modules;
+ }
+
+ @Override
+ public Set<DataSchemaNode> getDataDefinitions() {
+ final Set<DataSchemaNode> dataDefs = new HashSet<DataSchemaNode>();
+ for (Module m : modules) {
+ dataDefs.addAll(m.getChildNodes());
+ }
+ return dataDefs;
+ }
+
+ @Override
+ public Set<Module> getModules() {
+ return modules;
+ }
+
+ @Override
+ public Set<NotificationDefinition> getNotifications() {
+ final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
+ for (Module m : modules) {
+ notifications.addAll(m.getNotifications());
+ }
+ return notifications;
+ }
+
+ @Override
+ public Set<RpcDefinition> getOperations() {
+ final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
+ for (Module m : modules) {
+ rpcs.addAll(m.getRpcs());
+ }
+ return rpcs;
+ }
+
+ @Override
+ public Set<ExtensionDefinition> getExtensions() {
+ final Set<ExtensionDefinition> extensions = new HashSet<ExtensionDefinition>();
+ for (Module m : modules) {
+ extensions.addAll(m.getExtensionSchemaNodes());
+ }
+ return extensions;
+ }
+
+ @Override
+ public Module findModuleByName(final String name, final Date revision) {
+ if (name != null) {
+ for (final Module module : modules) {
+ if (revision == null) {
+ if (module.getName().equals(name)) {
+ return module;
+ }
+ } else if (module.getName().equals(name) && module.getRevision().equals(revision)) {
+ return module;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Module findModuleByNamespace(final URI namespace) {
+ if (namespace != null) {
+ for (final Module module : modules) {
+ if (module.getNamespace().equals(namespace)) {
+ return module;
+ }
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class YangErrorListener extends BaseErrorListener {
+ private final static Logger logger = LoggerFactory.getLogger(YangErrorListener.class);
+
+ @Override
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
+ String msg, RecognitionException e) {
+ logger.warn("line " + line + ":" + charPositionInLine + " " + msg);
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import static org.opendaylight.controller.yang.parser.util.ParserUtils.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+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;
+
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.opendaylight.controller.antlrv4.code.gen.YangLexer;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataNodeContainer;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.model.util.IdentityrefType;
+import org.opendaylight.controller.yang.model.util.UnknownType;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.Builder;
+import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.DeviationBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.GroupingBuilderImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.IdentityrefTypeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.RpcDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.UsesNodeBuilderImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.UsesNodeBuilderImpl.UsesNodeImpl;
+import org.opendaylight.controller.yang.parser.util.ModuleDependencySort;
+import org.opendaylight.controller.yang.parser.util.RefineHolder;
+import org.opendaylight.controller.yang.parser.util.RefineUtils;
+import org.opendaylight.controller.yang.parser.util.TypeConstraints;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+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 LOG = LoggerFactory.getLogger(YangParserImpl.class);
+
+ @Override
+ public Set<Module> parseYangModels(final List<File> yangFiles) {
+ return Sets.newLinkedHashSet(parseYangModelsMapped(yangFiles).values());
+ }
+
+ @Override
+ public Set<Module> parseYangModels(final List<File> yangFiles, final SchemaContext context) {
+ if (yangFiles != null) {
+ final Map<InputStream, File> inputStreams = Maps.newHashMap();
+
+ for (final File yangFile : yangFiles) {
+ try {
+ inputStreams.put(new FileInputStream(yangFile), yangFile);
+ } catch (FileNotFoundException e) {
+ LOG.warn("Exception while reading yang file: " + yangFile.getName(), e);
+ }
+ }
+
+ Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
+
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
+ Lists.newArrayList(inputStreams.keySet()), builderToStreamMap);
+
+ for (InputStream is : inputStreams.keySet()) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ LOG.debug("Failed to close stream.");
+ }
+ }
+
+ return new LinkedHashSet<Module>(buildWithContext(modules, context).values());
+ }
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams) {
+ return Sets.newHashSet(parseYangModelsFromStreamsMapped(yangModelStreams).values());
+ }
+
+ @Override
+ public Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams, SchemaContext context) {
+ if (yangModelStreams != null) {
+ Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersWithContext(
+ yangModelStreams, builderToStreamMap, context);
+ return new LinkedHashSet<Module>(buildWithContext(modules, context).values());
+ }
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Map<File, Module> parseYangModelsMapped(List<File> yangFiles) {
+ if (yangFiles != null) {
+ final Map<InputStream, File> inputStreams = Maps.newHashMap();
+
+ for (final File yangFile : yangFiles) {
+ try {
+ inputStreams.put(new FileInputStream(yangFile), yangFile);
+ } catch (FileNotFoundException e) {
+ LOG.warn("Exception while reading yang file: " + yangFile.getName(), e);
+ }
+ }
+
+ Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
+ Lists.newArrayList(inputStreams.keySet()), builderToStreamMap);
+
+ for (InputStream is : inputStreams.keySet()) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ LOG.debug("Failed to close stream.");
+ }
+ }
+
+ Map<File, Module> retVal = Maps.newLinkedHashMap();
+ Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
+
+ for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap.entrySet()) {
+ retVal.put(inputStreams.get(builderToStreamMap.get(builderToModule.getKey())),
+ builderToModule.getValue());
+ }
+
+ return retVal;
+ }
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<InputStream, Module> parseYangModelsFromStreamsMapped(final List<InputStream> yangModelStreams) {
+ Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
+
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(yangModelStreams,
+ builderToStreamMap);
+ Map<InputStream, Module> retVal = Maps.newLinkedHashMap();
+ Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
+
+ for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap.entrySet()) {
+ retVal.put(builderToStreamMap.get(builderToModule.getKey()), builderToModule.getValue());
+ }
+ return retVal;
+ }
+
+ @Override
+ public SchemaContext resolveSchemaContext(final Set<Module> modules) {
+ return new SchemaContextImpl(modules);
+ }
+
+ private ModuleBuilder[] parseModuleBuilders(List<InputStream> inputStreams,
+ Map<ModuleBuilder, InputStream> streamToBuilderMap) {
+
+ final ParseTreeWalker walker = new ParseTreeWalker();
+ final List<ParseTree> trees = parseStreams(inputStreams);
+ final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
+
+ // validate yang
+ new YangModelBasicValidator(walker).validate(trees);
+
+ YangParserListenerImpl yangModelParser = null;
+ for (int i = 0; i < trees.size(); i++) {
+ yangModelParser = new YangParserListenerImpl();
+ walker.walk(yangModelParser, trees.get(i));
+ ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
+
+ // We expect the order of trees and streams has to be the same
+ streamToBuilderMap.put(moduleBuilder, inputStreams.get(i));
+ builders[i] = moduleBuilder;
+ }
+ return builders;
+ }
+
+ private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(final List<InputStream> yangFileStreams,
+ Map<ModuleBuilder, InputStream> streamToBuilderMap) {
+ return resolveModuleBuildersWithContext(yangFileStreams, streamToBuilderMap, null);
+ }
+
+ private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersWithContext(
+ final List<InputStream> yangFileStreams, final Map<ModuleBuilder, InputStream> streamToBuilderMap,
+ final SchemaContext context) {
+ final ModuleBuilder[] builders = parseModuleBuilders(yangFileStreams, streamToBuilderMap);
+
+ // Linked Hash Map MUST be used because Linked Hash Map preserves ORDER
+ // of items stored in map.
+ final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> modules = new LinkedHashMap<String, TreeMap<Date, ModuleBuilder>>();
+
+ // module dependency graph sorted
+ List<ModuleBuilder> sorted = null;
+ if (context == null) {
+ sorted = ModuleDependencySort.sort(builders);
+ } else {
+ sorted = ModuleDependencySort.sortWithContext(context, builders);
+ }
+
+ for (final ModuleBuilder builder : sorted) {
+ if (builder == null) {
+ continue;
+ }
+ final String builderName = builder.getName();
+ Date builderRevision = builder.getRevision();
+ if (builderRevision == null) {
+ builderRevision = new Date(0L);
+ }
+ TreeMap<Date, ModuleBuilder> builderByRevision = modules.get(builderName);
+ if (builderByRevision == null) {
+ builderByRevision = new TreeMap<Date, ModuleBuilder>();
+ }
+ builderByRevision.put(builderRevision, builder);
+ modules.put(builderName, builderByRevision);
+ }
+ return modules;
+ }
+
+ private List<ParseTree> parseStreams(final List<InputStream> yangStreams) {
+ final List<ParseTree> trees = new ArrayList<ParseTree>();
+ for (InputStream yangStream : yangStreams) {
+ trees.add(parseStream(yangStream));
+ }
+ return trees;
+ }
+
+ private ParseTree parseStream(final InputStream yangStream) {
+ ParseTree result = null;
+ try {
+ final ANTLRInputStream input = new ANTLRInputStream(yangStream);
+ final YangLexer lexer = new YangLexer(input);
+ final CommonTokenStream tokens = new CommonTokenStream(lexer);
+ final YangParser parser = new YangParser(tokens);
+ parser.removeErrorListeners();
+ parser.addErrorListener(new YangErrorListener());
+
+ result = parser.yang();
+ } catch (IOException e) {
+ LOG.warn("Exception while reading yang file: " + yangStream, e);
+ }
+ return result;
+ }
+
+ private Map<ModuleBuilder, Module> build(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
+ // fix unresolved nodes
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
+ final ModuleBuilder moduleBuilder = childEntry.getValue();
+ fixUnresolvedNodes(modules, moduleBuilder);
+ }
+ }
+ resolveAugments(modules);
+ resolveDeviations(modules);
+
+ // build
+ // LinkedHashMap MUST be used otherwise the values will not maintain
+ // order!
+ // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html
+ final Map<ModuleBuilder, Module> result = new LinkedHashMap<ModuleBuilder, Module>();
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
+ for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
+ final ModuleBuilder moduleBuilder = childEntry.getValue();
+ final Module module = moduleBuilder.build();
+ modulesByRevision.put(childEntry.getKey(), module);
+ result.put(moduleBuilder, module);
+ }
+ }
+ return result;
+ }
+
+ private Map<ModuleBuilder, Module> buildWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ SchemaContext context) {
+ // fix unresolved nodes
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
+ final ModuleBuilder moduleBuilder = childEntry.getValue();
+ fixUnresolvedNodesWithContext(modules, moduleBuilder, context);
+ }
+ }
+ resolveAugmentsWithContext(modules, context);
+ resolveDeviationsWithContext(modules, context);
+
+ // build
+ // LinkedHashMap MUST be used otherwise the values will not maintain
+ // order!
+ // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html
+ final Map<ModuleBuilder, Module> result = new LinkedHashMap<ModuleBuilder, Module>();
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
+ for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
+ final ModuleBuilder moduleBuilder = childEntry.getValue();
+ final Module module = moduleBuilder.build();
+ modulesByRevision.put(childEntry.getKey(), module);
+ result.put(moduleBuilder, module);
+ }
+ }
+ return result;
+ }
+
+ private void fixUnresolvedNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder) {
+ resolveDirtyNodes(modules, builder);
+ resolveIdentities(modules, builder);
+ resolveUsesRefine(modules, builder);
+ resolveUnknownNodes(modules, builder);
+ }
+
+ private void fixUnresolvedNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder builder, final SchemaContext context) {
+ resolveDirtyNodesWithContext(modules, builder, context);
+ resolveIdentitiesWithContext(modules, builder, context);
+ resolveUsesRefineWithContext(modules, builder, context);
+ resolveUnknownNodesWithContext(modules, builder, context);
+ }
+
+ /**
+ * Search for dirty nodes (node which contains UnknownType) and resolve
+ * unknown types.
+ *
+ * @param modules
+ * all available modules
+ * @param module
+ * current module
+ */
+ private void resolveDirtyNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+ final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
+ if (!dirtyNodes.isEmpty()) {
+ for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
+ if (nodeToResolve instanceof UnionTypeBuilder) {
+ // special handling for union types
+ resolveTypeUnion((UnionTypeBuilder) nodeToResolve, modules, module);
+ } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) {
+ // special handling for identityref types
+ IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef();
+ nodeToResolve.setType(new IdentityrefType(findFullQName(modules, module, idref), idref.getPath()));
+ } else {
+ resolveType(nodeToResolve, modules, module);
+ }
+ }
+ }
+ }
+
+ private void resolveDirtyNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder module, SchemaContext context) {
+ final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
+ if (!dirtyNodes.isEmpty()) {
+ for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
+ if (nodeToResolve instanceof UnionTypeBuilder) {
+ // special handling for union types
+ resolveTypeUnionWithContext((UnionTypeBuilder) nodeToResolve, modules, module, context);
+ } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) {
+ // special handling for identityref types
+ IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef();
+ nodeToResolve.setType(new IdentityrefType(findFullQName(modules, module, idref), idref.getPath()));
+ } else {
+ resolveTypeWithContext(nodeToResolve, modules, module, context);
+ }
+ }
+ }
+ }
+
+ /**
+ * Resolve unknown type of node. It is assumed that type of node is either
+ * UnknownType or ExtendedType with UnknownType as base type.
+ *
+ * @param nodeToResolve
+ * node with type to resolve
+ * @param modules
+ * all loaded modules
+ * @param module
+ * current module
+ */
+ private void resolveType(final TypeAwareBuilder nodeToResolve,
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+ TypeDefinitionBuilder resolvedType = null;
+ final int line = nodeToResolve.getLine();
+ final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
+ final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
+ final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, unknownTypeQName.getPrefix(),
+ line);
+
+ final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve, dependentModule,
+ unknownTypeQName.getLocalName(), module.getName(), line);
+
+ if (nodeToResolveType instanceof ExtendedType) {
+ final ExtendedType extType = (ExtendedType) nodeToResolveType;
+ final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
+ modules, module, nodeToResolve.getLine());
+ resolvedType = newType;
+ } else {
+ resolvedType = targetTypeBuilder;
+ }
+
+ // validate constraints
+ final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve,
+ new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, null);
+ constraints.validateConstraints();
+
+ nodeToResolve.setTypedef(resolvedType);
+ }
+
+ /**
+ * Resolve unknown type of node. It is assumed that type of node is either
+ * UnknownType or ExtendedType with UnknownType as base type.
+ *
+ * @param nodeToResolve
+ * node with type to resolve
+ * @param modules
+ * all loaded modules
+ * @param module
+ * current module
+ * @param context
+ * SchemaContext containing already resolved modules
+ */
+ private void resolveTypeWithContext(final TypeAwareBuilder nodeToResolve,
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
+ final SchemaContext context) {
+ TypeDefinitionBuilder resolvedType = null;
+ final int line = nodeToResolve.getLine();
+ final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
+ final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
+ final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
+ unknownTypeQName.getPrefix(), line);
+
+ if (dependentModuleBuilder == null) {
+ final Module dependentModule = findModuleFromContext(context, module, unknownTypeQName.getPrefix(), line);
+ final Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
+ final TypeDefinition<?> type = findTypeByName(types, unknownTypeQName.getLocalName());
+
+ if (nodeToResolveType instanceof ExtendedType) {
+ final ExtendedType extType = (ExtendedType) nodeToResolveType;
+ final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, module,
+ nodeToResolve.getLine());
+
+ nodeToResolve.setTypedef(newType);
+ } else {
+ if (nodeToResolve instanceof TypeDefinitionBuilder) {
+ TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) nodeToResolve;
+ TypeConstraints tc = findConstraintsFromTypeBuilder(nodeToResolve,
+ new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, context);
+ tdb.setLengths(tc.getLength());
+ tdb.setPatterns(tc.getPatterns());
+ tdb.setRanges(tc.getRange());
+ tdb.setFractionDigits(tc.getFractionDigits());
+ }
+ nodeToResolve.setType(type);
+ }
+
+ } else {
+ final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
+ dependentModuleBuilder, unknownTypeQName.getLocalName(), module.getName(), line);
+
+ if (nodeToResolveType instanceof ExtendedType) {
+ final ExtendedType extType = (ExtendedType) nodeToResolveType;
+ final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
+ modules, module, nodeToResolve.getLine());
+ resolvedType = newType;
+ } else {
+ resolvedType = targetTypeBuilder;
+ }
+
+ // validate constraints
+ final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve, new TypeConstraints(
+ module.getName(), nodeToResolve.getLine()), modules, module, context);
+ constraints.validateConstraints();
+
+ nodeToResolve.setTypedef(resolvedType);
+ }
+ }
+
+ private void resolveTypeUnion(final UnionTypeBuilder union,
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder) {
+
+ final List<TypeDefinition<?>> unionTypes = union.getTypes();
+ final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
+ for (TypeDefinition<?> unionType : unionTypes) {
+ if (unionType instanceof UnknownType) {
+ final UnknownType ut = (UnknownType) unionType;
+ final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
+ .getPrefix(), union.getLine());
+ final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModule, ut
+ .getQName().getLocalName(), builder.getName(), union.getLine());
+ union.setTypedef(resolvedType);
+ toRemove.add(ut);
+ } else if (unionType instanceof ExtendedType) {
+ final ExtendedType extType = (ExtendedType) unionType;
+ final TypeDefinition<?> extTypeBase = extType.getBaseType();
+ if (extTypeBase instanceof UnknownType) {
+ final UnknownType ut = (UnknownType) extTypeBase;
+ final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
+ .getPrefix(), union.getLine());
+ final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union, dependentModule,
+ ut.getQName().getLocalName(), builder.getName(), union.getLine());
+
+ final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
+ extType, modules, builder, union.getLine());
+
+ union.setTypedef(newType);
+ toRemove.add(extType);
+ }
+ }
+ }
+ unionTypes.removeAll(toRemove);
+ }
+
+ private void resolveTypeUnionWithContext(final UnionTypeBuilder union,
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder,
+ final SchemaContext context) {
+
+ final List<TypeDefinition<?>> unionTypes = union.getTypes();
+ final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
+ for (TypeDefinition<?> unionType : unionTypes) {
+ if (unionType instanceof UnknownType) {
+ final UnknownType ut = (UnknownType) unionType;
+ final QName utQName = ut.getQName();
+ final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
+ utQName.getPrefix(), union.getLine());
+
+ if (dependentModuleBuilder == null) {
+ Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
+ union.getLine());
+ Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
+ TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
+ union.setType(type);
+ toRemove.add(ut);
+ } else {
+ final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModuleBuilder,
+ utQName.getLocalName(), builder.getName(), union.getLine());
+ union.setTypedef(resolvedType);
+ toRemove.add(ut);
+ }
+
+ } else if (unionType instanceof ExtendedType) {
+ final ExtendedType extType = (ExtendedType) unionType;
+ TypeDefinition<?> extTypeBase = extType.getBaseType();
+ if (extTypeBase instanceof UnknownType) {
+ final UnknownType ut = (UnknownType) extTypeBase;
+ final QName utQName = ut.getQName();
+ final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
+ utQName.getPrefix(), union.getLine());
+
+ if (dependentModuleBuilder == null) {
+ final Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
+ union.getLine());
+ Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
+ TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
+ final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, builder, 0);
+
+ union.setTypedef(newType);
+ toRemove.add(extType);
+ } else {
+ final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union,
+ dependentModuleBuilder, utQName.getLocalName(), builder.getName(), union.getLine());
+
+ final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
+ extType, modules, builder, union.getLine());
+
+ union.setTypedef(newType);
+ toRemove.add(extType);
+ }
+ }
+ }
+ }
+ unionTypes.removeAll(toRemove);
+ }
+
+ /**
+ * Go through all augment definitions and resolve them. It is expected that
+ * modules are already sorted by their dependencies. This method also finds
+ * augment target node and add child nodes to it.
+ *
+ * @param modules
+ * all available modules
+ */
+ private void resolveAugments(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
+ final List<ModuleBuilder> allModulesList = new ArrayList<ModuleBuilder>();
+ final Set<ModuleBuilder> allModulesSet = new HashSet<ModuleBuilder>();
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
+ allModulesList.add(inner.getValue());
+ allModulesSet.add(inner.getValue());
+ }
+ }
+
+ for (int i = 0; i < allModulesList.size(); i++) {
+ final ModuleBuilder module = allModulesList.get(i);
+ // try to resolve augments in module
+ resolveAugment(modules, module);
+ // while all augments are not resolved
+ final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
+ while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
+ ModuleBuilder nextModule = null;
+ // try resolve other module augments
+ try {
+ nextModule = allModulesIterator.next();
+ resolveAugment(modules, nextModule);
+ } catch (NoSuchElementException e) {
+ throw new YangParseException("Failed to resolve augments in module '" + module.getName() + "'.", e);
+ }
+ // then try to resolve first module again
+ resolveAugment(modules, module);
+ }
+ }
+ }
+
+ /**
+ * Tries to resolve augments in given module. If augment target node is not
+ * found, do nothing.
+ *
+ * @param modules
+ * all available modules
+ * @param module
+ * current module
+ */
+ private void resolveAugment(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+ if (module.getAugmentsResolved() < module.getAllAugments().size()) {
+ for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
+
+ if (!augmentBuilder.isResolved()) {
+ final SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
+ final List<QName> path = augmentTargetSchemaPath.getPath();
+
+ final QName qname = path.get(0);
+ String prefix = qname.getPrefix();
+ if (prefix == null) {
+ prefix = module.getPrefix();
+ }
+
+ final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, prefix,
+ augmentBuilder.getLine());
+ processAugmentation(augmentBuilder, path, module, dependentModule);
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Go through all augment definitions and resolve them. This method works in
+ * same way as {@link #resolveAugments(Map)} except that if target node is
+ * not found in loaded modules, it search for target node in given context.
+ *
+ * @param modules
+ * all loaded modules
+ * @param context
+ * SchemaContext containing already resolved modules
+ */
+ private void resolveAugmentsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final SchemaContext context) {
+ final List<ModuleBuilder> allModulesList = new ArrayList<ModuleBuilder>();
+ final Set<ModuleBuilder> allModulesSet = new HashSet<ModuleBuilder>();
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
+ allModulesList.add(inner.getValue());
+ allModulesSet.add(inner.getValue());
+ }
+ }
+
+ for (int i = 0; i < allModulesList.size(); i++) {
+ final ModuleBuilder module = allModulesList.get(i);
+ // try to resolve augments in module
+ resolveAugmentWithContext(modules, module, context);
+ // while all augments are not resolved
+ final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
+ while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
+ ModuleBuilder nextModule = null;
+ // try resolve other module augments
+ try {
+ nextModule = allModulesIterator.next();
+ resolveAugmentWithContext(modules, nextModule, context);
+ } catch (NoSuchElementException e) {
+ throw new YangParseException("Failed to resolve augments in module '" + module.getName() + "'.", e);
+ }
+ // then try to resolve first module again
+ resolveAugmentWithContext(modules, module, context);
+ }
+ }
+ }
+
+ /**
+ * Tries to resolve augments in given module. If augment target node is not
+ * found, do nothing.
+ *
+ * @param modules
+ * all available modules
+ * @param module
+ * current module
+ */
+ private void resolveAugmentWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder module, final SchemaContext context) {
+ if (module.getAugmentsResolved() < module.getAllAugments().size()) {
+
+ for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
+ final int line = augmentBuilder.getLine();
+
+ if (!augmentBuilder.isResolved()) {
+ final List<QName> path = augmentBuilder.getTargetPath().getPath();
+ final QName qname = path.get(0);
+ String prefix = qname.getPrefix();
+ if (prefix == null) {
+ prefix = module.getPrefix();
+ }
+
+ // try to find augment target module in loaded modules...
+ final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix,
+ line);
+ if (dependentModuleBuilder == null) {
+ // perform augmentation on module from context and
+ // continue to next augment
+ processAugmentationOnContext(augmentBuilder, path, module, prefix, line, context);
+ continue;
+ } else {
+ processAugmentation(augmentBuilder, path, module, dependentModuleBuilder);
+ }
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Go through identity statements defined in current module and resolve
+ * their 'base' statement if present.
+ *
+ * @param modules
+ * all modules
+ * @param module
+ * module being resolved
+ */
+ private void resolveIdentities(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+ final Set<IdentitySchemaNodeBuilder> identities = module.getIdentities();
+ for (IdentitySchemaNodeBuilder identity : identities) {
+ final String baseIdentityName = identity.getBaseIdentityName();
+ if (baseIdentityName != null) {
+ String baseIdentityPrefix = null;
+ String baseIdentityLocalName = null;
+ if (baseIdentityName.contains(":")) {
+ final String[] splitted = baseIdentityName.split(":");
+ baseIdentityPrefix = splitted[0];
+ baseIdentityLocalName = splitted[1];
+ } else {
+ baseIdentityPrefix = module.getPrefix();
+ baseIdentityLocalName = baseIdentityName;
+ }
+ final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, baseIdentityPrefix,
+ identity.getLine());
+
+ final Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModule.getIdentities();
+ for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
+ if (idBuilder.getQName().getLocalName().equals(baseIdentityLocalName)) {
+ identity.setBaseIdentity(idBuilder);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Go through identity statements defined in current module and resolve
+ * their 'base' statement. Method tries to find base identity in given
+ * modules. If base identity is not found, method will search it in context.
+ *
+ * @param modules
+ * all loaded modules
+ * @param module
+ * current module
+ * @param context
+ * SchemaContext containing already resolved modules
+ */
+ private void resolveIdentitiesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder module, final SchemaContext context) {
+ final Set<IdentitySchemaNodeBuilder> identities = module.getIdentities();
+ for (IdentitySchemaNodeBuilder identity : identities) {
+ final String baseIdentityName = identity.getBaseIdentityName();
+ if (baseIdentityName != null) {
+ String baseIdentityPrefix = null;
+ String baseIdentityLocalName = null;
+ if (baseIdentityName.contains(":")) {
+ final String[] splitted = baseIdentityName.split(":");
+ baseIdentityPrefix = splitted[0];
+ baseIdentityLocalName = splitted[1];
+ } else {
+ baseIdentityPrefix = module.getPrefix();
+ baseIdentityLocalName = baseIdentityName;
+ }
+ final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
+ baseIdentityPrefix, identity.getLine());
+
+ if (dependentModuleBuilder == null) {
+ final Module dependentModule = findModuleFromContext(context, module, baseIdentityPrefix,
+ identity.getLine());
+ final Set<IdentitySchemaNode> dependentModuleIdentities = dependentModule.getIdentities();
+ for (IdentitySchemaNode idNode : dependentModuleIdentities) {
+ if (idNode.getQName().getLocalName().equals(baseIdentityLocalName)) {
+ identity.setBaseIdentity(idNode);
+ }
+ }
+ } else {
+ final Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModuleBuilder
+ .getIdentities();
+ for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
+ if (idBuilder.getQName().getLocalName().equals(baseIdentityLocalName)) {
+ identity.setBaseIdentity(idBuilder);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Go through uses statements defined in current module and resolve their
+ * refine statements.
+ *
+ * @param modules
+ * all modules
+ * @param module
+ * module being resolved
+ */
+ private void resolveUsesRefine(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+ final List<UsesNodeBuilder> allModuleUses = module.getAllUsesNodes();
+ for (UsesNodeBuilder usesNode : allModuleUses) {
+ // refine
+ final int line = usesNode.getLine();
+ final GroupingBuilder targetGrouping = getTargetGroupingFromModules(usesNode, modules, module);
+ usesNode.setGroupingPath(targetGrouping.getPath());
+ for (RefineHolder refine : usesNode.getRefines()) {
+ final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(targetGrouping,
+ refine, module.getName());
+ if (nodeToRefine instanceof GroupingMember) {
+ ((GroupingMember) nodeToRefine).setAddedByUses(true);
+ }
+ RefineUtils.performRefine(nodeToRefine, refine, line);
+ usesNode.addRefineNode(nodeToRefine);
+ }
+
+ // child nodes
+ processUsesNode(module, usesNode, targetGrouping);
+ }
+ }
+
+ /**
+ * Tries to search target grouping in given modules and resolve refine
+ * nodes. If grouping is not found in modules, method tries to find it in
+ * modules from context.
+ *
+ * @param modules
+ * all loaded modules
+ * @param module
+ * current module
+ * @param context
+ * SchemaContext containing already resolved modules
+ */
+ private void resolveUsesRefineWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder module, final SchemaContext context) {
+ final List<UsesNodeBuilder> moduleUses = module.getAllUsesNodes();
+ for (UsesNodeBuilder usesNode : moduleUses) {
+ final int line = usesNode.getLine();
+
+ final GroupingBuilder targetGroupingBuilder = getTargetGroupingFromModules(usesNode, modules, module);
+ if (targetGroupingBuilder == null) {
+ final GroupingDefinition targetGrouping = getTargetGroupingFromContext(usesNode, module, context);
+ usesNode.setGroupingPath(targetGrouping.getPath());
+ for (RefineHolder refine : usesNode.getRefines()) {
+ final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingDefinition(
+ targetGrouping, refine);
+ if (nodeToRefine instanceof GroupingMember) {
+ ((GroupingMember) nodeToRefine).setAddedByUses(true);
+ }
+ RefineUtils.performRefine(nodeToRefine, refine, line);
+ usesNode.addRefineNode(nodeToRefine);
+ }
+
+ processUsesNode(usesNode, targetGrouping);
+ } else {
+ usesNode.setGroupingPath(targetGroupingBuilder.getPath());
+ for (RefineHolder refine : usesNode.getRefines()) {
+ final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(
+ targetGroupingBuilder, refine, module.getName());
+ if (nodeToRefine instanceof GroupingMember) {
+ ((GroupingMember) nodeToRefine).setAddedByUses(true);
+ }
+ RefineUtils.performRefine(nodeToRefine, refine, line);
+ usesNode.addRefineNode(nodeToRefine);
+ }
+
+ processUsesNode(module, usesNode, targetGroupingBuilder);
+ }
+ }
+ }
+
+ /**
+ * Search given modules for grouping by name defined in uses node.
+ *
+ * @param usesBuilder
+ * builder of uses statement
+ * @param modules
+ * all loaded modules
+ * @param module
+ * current module
+ * @return grouping with given name if found, null otherwise
+ */
+ private GroupingBuilder getTargetGroupingFromModules(final UsesNodeBuilder usesBuilder,
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+ final int line = usesBuilder.getLine();
+ final String groupingString = usesBuilder.getGroupingName();
+ String groupingPrefix;
+ String groupingName;
+
+ if (groupingString.contains(":")) {
+ String[] splitted = groupingString.split(":");
+ if (splitted.length != 2 || groupingString.contains("/")) {
+ throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
+ }
+ groupingPrefix = splitted[0];
+ groupingName = splitted[1];
+ } else {
+ groupingPrefix = module.getPrefix();
+ groupingName = groupingString;
+ }
+
+ ModuleBuilder dependentModule = null;
+ if (groupingPrefix.equals(module.getPrefix())) {
+ dependentModule = module;
+ } else {
+ dependentModule = findDependentModuleBuilder(modules, module, groupingPrefix, line);
+ }
+
+ if (dependentModule == null) {
+ return null;
+ }
+
+ GroupingBuilder result = null;
+ Set<GroupingBuilder> groupings = dependentModule.getGroupingBuilders();
+ result = findGroupingBuilder(groupings, groupingName);
+ if (result != null) {
+ return result;
+ }
+
+ Builder parent = usesBuilder.getParent();
+
+ while (parent != null) {
+ if (parent instanceof DataNodeContainerBuilder) {
+ groupings = ((DataNodeContainerBuilder) parent).getGroupingBuilders();
+ } else if (parent instanceof RpcDefinitionBuilder) {
+ groupings = ((RpcDefinitionBuilder) parent).getGroupings();
+ }
+ result = findGroupingBuilder(groupings, groupingName);
+ if (result == null) {
+ parent = parent.getParent();
+ } else {
+ break;
+ }
+ }
+
+ if (result == null) {
+ throw new YangParseException(module.getName(), line, "Referenced grouping '" + groupingName
+ + "' not found.");
+ }
+ return result;
+ }
+
+ /**
+ * Search context for grouping by name defined in uses node.
+ *
+ * @param usesBuilder
+ * builder of uses statement
+ * @param module
+ * current module
+ * @param context
+ * SchemaContext containing already resolved modules
+ * @return grouping with given name if found, null otherwise
+ */
+ private GroupingDefinition getTargetGroupingFromContext(final UsesNodeBuilder usesBuilder,
+ final ModuleBuilder module, final SchemaContext context) {
+ final int line = usesBuilder.getLine();
+ String groupingString = usesBuilder.getGroupingName();
+ String groupingPrefix;
+ String groupingName;
+
+ if (groupingString.contains(":")) {
+ String[] splitted = groupingString.split(":");
+ if (splitted.length != 2 || groupingString.contains("/")) {
+ throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
+ }
+ groupingPrefix = splitted[0];
+ groupingName = splitted[1];
+ } else {
+ groupingPrefix = module.getPrefix();
+ groupingName = groupingString;
+ }
+
+ Module dependentModule = findModuleFromContext(context, module, groupingPrefix, line);
+ return findGroupingDefinition(dependentModule.getGroupings(), groupingName);
+ }
+
+ /**
+ * Add nodes defined in target grouping to current context. Refinement has
+ * to be already performed.
+ *
+ * @param module current module
+ * @param usesNode
+ * @param targetGrouping
+ */
+ private void processUsesNode(final ModuleBuilder module, final UsesNodeBuilder usesNode, final GroupingBuilder targetGrouping) {
+ List<SchemaNodeBuilder> refineNodes = usesNode.getRefineNodes();
+ DataNodeContainerBuilder parent = usesNode.getParent();
+ URI namespace = null;
+ Date revision = null;
+ String prefix = null;
+ if (parent instanceof ModuleBuilder || parent instanceof AugmentationSchemaBuilder) {
+ namespace = module.getNamespace();
+ revision = module.getRevision();
+ prefix = module.getPrefix();
+ } else {
+ QName parentQName = parent.getQName();
+ namespace = parentQName.getNamespace();
+ revision = parentQName.getRevision();
+ prefix = parentQName.getPrefix();
+ }
+ SchemaPath parentPath = parent.getPath();
+ for (DataSchemaNodeBuilder child : targetGrouping.getChildNodeBuilders()) {
+ if (child != null) {
+ // if node is refined, take it from refined nodes and continue
+ SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
+ if (refined != null) {
+ refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName(), namespace,
+ revision, prefix));
+ parent.addChildNode((DataSchemaNodeBuilder) refined);
+ continue;
+ }
+
+ DataSchemaNodeBuilder newChild = null;
+ if (child instanceof AnyXmlBuilder) {
+ newChild = new AnyXmlBuilder((AnyXmlBuilder) child);
+ } else if (child instanceof ChoiceBuilder) {
+ newChild = new ChoiceBuilder((ChoiceBuilder) child);
+ } else if (child instanceof ContainerSchemaNodeBuilder) {
+ newChild = new ContainerSchemaNodeBuilder((ContainerSchemaNodeBuilder) child);
+ } else if (child instanceof LeafListSchemaNodeBuilder) {
+ newChild = new LeafListSchemaNodeBuilder((LeafListSchemaNodeBuilder) child);
+ } else if (child instanceof LeafSchemaNodeBuilder) {
+ newChild = new LeafSchemaNodeBuilder((LeafSchemaNodeBuilder) child);
+ } else if (child instanceof ListSchemaNodeBuilder) {
+ newChild = new ListSchemaNodeBuilder((ListSchemaNodeBuilder) child);
+ }
+
+ if (newChild == null) {
+ throw new YangParseException(usesNode.getModuleName(), usesNode.getLine(),
+ "Unknown member of target grouping while resolving uses node.");
+ }
+
+ if (newChild instanceof GroupingMember) {
+ ((GroupingMember) newChild).setAddedByUses(true);
+ }
+
+ newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName(), namespace, revision,
+ prefix));
+ parent.addChildNode(newChild);
+ }
+ }
+ for (GroupingBuilder g : targetGrouping.getGroupingBuilders()) {
+ GroupingBuilder newGrouping = new GroupingBuilderImpl(g);
+ newGrouping.setAddedByUses(true);
+ newGrouping.setPath(createSchemaPath(parentPath, newGrouping.getQName().getLocalName(), namespace,
+ revision, prefix));
+ parent.addGrouping(newGrouping);
+ }
+ for (TypeDefinitionBuilder td : targetGrouping.getTypeDefinitionBuilders()) {
+ TypeDefinitionBuilder newType = new TypeDefinitionBuilderImpl(td);
+ newType.setAddedByUses(true);
+ newType.setPath(createSchemaPath(parentPath, newType.getQName().getLocalName(), namespace, revision, prefix));
+ parent.addTypedef(newType);
+ }
+ for (UsesNodeBuilder un : targetGrouping.getUses()) {
+ UsesNodeBuilder newUses = new UsesNodeBuilderImpl(un);
+ newUses.setAddedByUses(true);
+ // uses has not path
+ parent.addUsesNode(newUses);
+ }
+ for (UnknownSchemaNodeBuilder un : targetGrouping.getUnknownNodeBuilders()) {
+ UnknownSchemaNodeBuilder newUn = new UnknownSchemaNodeBuilder(un);
+ newUn.setAddedByUses(true);
+ newUn.setPath(createSchemaPath(parentPath, un.getQName().getLocalName(), namespace, revision, prefix));
+ parent.addUnknownNodeBuilder(newUn);
+ }
+ }
+
+ private void processUsesNode(final UsesNodeBuilder usesNode, final GroupingDefinition targetGrouping) {
+ final String moduleName = usesNode.getModuleName();
+ final int line = usesNode.getLine();
+ List<SchemaNodeBuilder> refineNodes = usesNode.getRefineNodes();
+ DataNodeContainerBuilder parent = usesNode.getParent();
+ URI namespace = null;
+ Date revision = null;
+ String prefix = null;
+ if (parent instanceof ModuleBuilder) {
+ ModuleBuilder module = (ModuleBuilder) parent;
+ namespace = module.getNamespace();
+ revision = module.getRevision();
+ prefix = module.getPrefix();
+ } else {
+ QName parentQName = parent.getQName();
+ namespace = parentQName.getNamespace();
+ revision = parentQName.getRevision();
+ prefix = parentQName.getPrefix();
+ }
+ SchemaPath parentPath = parent.getPath();
+ for (DataSchemaNode child : targetGrouping.getChildNodes()) {
+ if (child != null) {
+ // if node is refined, take it from refined nodes and continue
+ SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
+ if (refined != null) {
+ refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName(), namespace,
+ revision, prefix));
+ parent.addChildNode((DataSchemaNodeBuilder) refined);
+ continue;
+ }
+
+ DataSchemaNodeBuilder newChild = null;
+ if (child instanceof AnyXmlSchemaNode) {
+ newChild = createAnyXml((AnyXmlSchemaNode) child, moduleName, line);
+ } else if (child instanceof ChoiceNode) {
+ newChild = createChoice((ChoiceNode) child, moduleName, line);
+ } else if (child instanceof ContainerSchemaNode) {
+ newChild = createContainer((ContainerSchemaNode) child, moduleName, line);
+ } else if (child instanceof LeafListSchemaNode) {
+ newChild = createLeafList((LeafListSchemaNode) child, moduleName, line);
+ } else if (child instanceof LeafSchemaNode) {
+ newChild = createLeafBuilder((LeafSchemaNode) child, moduleName, line);
+ } else if (child instanceof ListSchemaNode) {
+ newChild = createList((ListSchemaNode) child, moduleName, line);
+ }
+
+ if (newChild == null) {
+ throw new YangParseException(moduleName, line,
+ "Unknown member of target grouping while resolving uses node.");
+ }
+
+ if (newChild instanceof GroupingMember) {
+ ((GroupingMember) newChild).setAddedByUses(true);
+ }
+ newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName(), namespace, revision,
+ prefix));
+ parent.addChildNode(newChild);
+ }
+ }
+ for (GroupingDefinition g : targetGrouping.getGroupings()) {
+ GroupingBuilder newGrouping = createGrouping(g, moduleName, line);
+ newGrouping.setAddedByUses(true);
+ newGrouping.setPath(createSchemaPath(parentPath, newGrouping.getQName().getLocalName(), namespace,
+ revision, prefix));
+ parent.addGrouping(newGrouping);
+ }
+ for (TypeDefinition<?> td : targetGrouping.getTypeDefinitions()) {
+ TypeDefinitionBuilder newType = createTypedef((ExtendedType) td, moduleName, line);
+ newType.setAddedByUses(true);
+ newType.setPath(createSchemaPath(parentPath, newType.getQName().getLocalName(), namespace, revision, prefix));
+ parent.addTypedef(newType);
+ }
+ for (UsesNode un : targetGrouping.getUses()) {
+ if (un instanceof UsesNodeImpl) {
+ UsesNodeBuilder newUses = new UsesNodeBuilderImpl(((UsesNodeImpl) un).toBuilder());
+ newUses.setAddedByUses(true);
+ // uses has not path
+ parent.addUsesNode(newUses);
+ }
+ }
+ for (UnknownSchemaNode un : targetGrouping.getUnknownSchemaNodes()) {
+ UnknownSchemaNodeBuilder newNode = createUnknownSchemaNode(un, moduleName, line);
+ newNode.setAddedByUses(true);
+ newNode.setPath(createSchemaPath(parentPath, un.getQName().getLocalName(), namespace, revision, prefix));
+ parent.addUnknownNodeBuilder(newNode);
+ }
+ }
+
+ private QName findFullQName(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
+ final IdentityrefTypeBuilder idref) {
+ QName result = null;
+ String baseString = idref.getBaseString();
+ if (baseString.contains(":")) {
+ String[] splittedBase = baseString.split(":");
+ if (splittedBase.length > 2) {
+ throw new YangParseException(module.getName(), idref.getLine(), "Failed to parse identityref base: "
+ + baseString);
+ }
+ String prefix = splittedBase[0];
+ String name = splittedBase[1];
+ ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, prefix, idref.getLine());
+ result = new QName(dependentModule.getNamespace(), dependentModule.getRevision(), prefix, name);
+ } else {
+ result = new QName(module.getNamespace(), module.getRevision(), module.getPrefix(), baseString);
+ }
+ return result;
+ }
+
+ private void resolveUnknownNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+ for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) {
+ QName nodeType = usnb.getNodeType();
+ if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
+ try {
+ ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, nodeType.getPrefix(),
+ usnb.getLine());
+ QName newNodeType = new QName(dependentModule.getNamespace(), dependentModule.getRevision(),
+ nodeType.getPrefix(), nodeType.getLocalName());
+ usnb.setNodeType(newNodeType);
+ } catch (YangParseException e) {
+ LOG.debug(module.getName(), usnb.getLine(), "Failed to find unknown node type: " + nodeType);
+ }
+ }
+ }
+ }
+
+ private void resolveUnknownNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder module, final SchemaContext context) {
+ for (UnknownSchemaNodeBuilder unknownNodeBuilder : module.getAllUnknownNodes()) {
+ QName nodeType = unknownNodeBuilder.getNodeType();
+ if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
+ try {
+ ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
+ nodeType.getPrefix(), unknownNodeBuilder.getLine());
+
+ QName newNodeType = null;
+ if (dependentModuleBuilder == null) {
+ Module dependentModule = findModuleFromContext(context, module, nodeType.getPrefix(),
+ unknownNodeBuilder.getLine());
+ newNodeType = new QName(dependentModule.getNamespace(), dependentModule.getRevision(),
+ nodeType.getPrefix(), nodeType.getLocalName());
+ } else {
+ newNodeType = new QName(dependentModuleBuilder.getNamespace(),
+ dependentModuleBuilder.getRevision(), nodeType.getPrefix(), nodeType.getLocalName());
+ }
+
+ unknownNodeBuilder.setNodeType(newNodeType);
+ } catch (YangParseException e) {
+ LOG.debug(module.getName(), unknownNodeBuilder.getLine(), "Failed to find unknown node type: "
+ + nodeType);
+ }
+ }
+ }
+ }
+
+ private void resolveDeviations(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
+ ModuleBuilder b = inner.getValue();
+ resolveDeviation(modules, b);
+ }
+ }
+ }
+
+ private void resolveDeviation(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+ for (DeviationBuilder dev : module.getDeviations()) {
+ int line = dev.getLine();
+ SchemaPath targetPath = dev.getTargetPath();
+ List<QName> path = targetPath.getPath();
+ QName q0 = path.get(0);
+ String prefix = q0.getPrefix();
+ if (prefix == null) {
+ prefix = module.getPrefix();
+ }
+
+ ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
+ processDeviation(dev, dependentModuleBuilder, path, module);
+ }
+ }
+
+ private void resolveDeviationsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final SchemaContext context) {
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
+ ModuleBuilder b = inner.getValue();
+ resolveDeviationWithContext(modules, b, context);
+ }
+ }
+ }
+
+ private void resolveDeviationWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder module, final SchemaContext context) {
+ for (DeviationBuilder dev : module.getDeviations()) {
+ int line = dev.getLine();
+ SchemaPath targetPath = dev.getTargetPath();
+ List<QName> path = targetPath.getPath();
+ QName q0 = path.get(0);
+ String prefix = q0.getPrefix();
+ if (prefix == null) {
+ prefix = module.getPrefix();
+ }
+ String name = null;
+
+ ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
+ if (dependentModuleBuilder == null) {
+ Module dependentModule = findModuleFromContext(context, module, prefix, line);
+ Object currentParent = dependentModule;
+
+ for (int i = 0; i < path.size(); i++) {
+ if (currentParent == null) {
+ throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+ }
+ QName q = path.get(i);
+ name = q.getLocalName();
+ if (currentParent instanceof DataNodeContainer) {
+ currentParent = ((DataNodeContainer) currentParent).getDataChildByName(name);
+ }
+ }
+
+ if (currentParent == null) {
+ throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+ }
+ if (currentParent instanceof SchemaNode) {
+ dev.setTargetPath(((SchemaNode) currentParent).getPath());
+ }
+
+ } else {
+ processDeviation(dev, dependentModuleBuilder, path, module);
+ }
+ }
+ }
+
+ /**
+ * Correct deviation target path in deviation builder.
+ *
+ * @param dev
+ * deviation
+ * @param dependentModuleBuilder
+ * module containing deviation target
+ * @param path
+ * current deviation target path
+ * @param module
+ * current module
+ */
+ private void processDeviation(final DeviationBuilder dev, final ModuleBuilder dependentModuleBuilder,
+ final List<QName> path, final ModuleBuilder module) {
+ final int line = dev.getLine();
+ Builder currentParent = dependentModuleBuilder;
+
+ for (int i = 0; i < path.size(); i++) {
+ if (currentParent == null) {
+ throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+ }
+ QName q = path.get(i);
+ String name = q.getLocalName();
+ if (currentParent instanceof DataNodeContainerBuilder) {
+ currentParent = ((DataNodeContainerBuilder) currentParent).getDataChildByName(name);
+ }
+ }
+
+ if (currentParent == null || !(currentParent instanceof SchemaNodeBuilder)) {
+ throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+ }
+ dev.setTargetPath(((SchemaNodeBuilder) currentParent).getPath());
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import static org.opendaylight.controller.yang.parser.util.ParserListenerUtils.*;
+
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Stack;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.opendaylight.controller.antlrv4.code.gen.*;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Contact_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Container_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_delete_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_not_supported_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_replace_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_list_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Organization_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Presence_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.util.YangTypesConverter;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceCaseBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.DeviationBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ExtensionBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.FeatureBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.NotificationBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.RpcDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.util.RefineHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class YangParserListenerImpl extends YangParserBaseListener {
+ private static final Logger logger = LoggerFactory.getLogger(YangParserListenerImpl.class);
+
+ private ModuleBuilder moduleBuilder;
+ private String moduleName;
+ private URI namespace;
+ private String yangModelPrefix;
+ private Date revision = new Date(0L);
+
+ public final static DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ private final Stack<String> actualPath = new Stack<String>();
+
+ @Override
+ public void enterModule_stmt(YangParser.Module_stmtContext ctx) {
+ moduleName = stringFromNode(ctx);
+ logger.debug("enter module " + moduleName);
+ actualPath.push(moduleName);
+ moduleBuilder = new ModuleBuilder(moduleName);
+
+ String description = null;
+ String reference = null;
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ } else {
+ if (description != null && reference != null) {
+ break;
+ }
+ }
+ }
+ moduleBuilder.setDescription(description);
+ moduleBuilder.setReference(reference);
+ }
+
+ @Override
+ public void exitModule_stmt(YangParser.Module_stmtContext ctx) {
+ exitLog("module", actualPath.pop());
+ }
+
+ @Override
+ public void enterModule_header_stmts(Module_header_stmtsContext ctx) {
+ enterLog("module_header", "", ctx.getStart().getLine());
+ String yangVersion = null;
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ final ParseTree treeNode = ctx.getChild(i);
+ if (treeNode instanceof Namespace_stmtContext) {
+ final String namespaceStr = stringFromNode(treeNode);
+ namespace = URI.create(namespaceStr);
+ moduleBuilder.setNamespace(namespace);
+ setLog("namespace", namespaceStr);
+ } else if (treeNode instanceof Prefix_stmtContext) {
+ yangModelPrefix = stringFromNode(treeNode);
+ moduleBuilder.setPrefix(yangModelPrefix);
+ setLog("prefix", yangModelPrefix);
+ } else if (treeNode instanceof Yang_version_stmtContext) {
+ yangVersion = stringFromNode(treeNode);
+ setLog("yang-version", yangVersion);
+ }
+ }
+
+ if (yangVersion == null) {
+ yangVersion = "1";
+ }
+ moduleBuilder.setYangVersion(yangVersion);
+ }
+
+ @Override
+ public void exitModule_header_stmts(Module_header_stmtsContext ctx) {
+ exitLog("module_header", "");
+ }
+
+ @Override
+ public void enterMeta_stmts(YangParser.Meta_stmtsContext ctx) {
+ enterLog("meta_stmt", "", ctx.getStart().getLine());
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Organization_stmtContext) {
+ final String organization = stringFromNode(child);
+ moduleBuilder.setOrganization(organization);
+ setLog("organization", organization);
+ } else if (child instanceof Contact_stmtContext) {
+ final String contact = stringFromNode(child);
+ moduleBuilder.setContact(contact);
+ setLog("contact", contact);
+ } else if (child instanceof Description_stmtContext) {
+ final String description = stringFromNode(child);
+ moduleBuilder.setDescription(description);
+ setLog("description", description);
+ } else if (child instanceof Reference_stmtContext) {
+ final String reference = stringFromNode(child);
+ moduleBuilder.setReference(reference);
+ setLog("reference", reference);
+ }
+ }
+ }
+
+ @Override
+ public void exitMeta_stmts(YangParser.Meta_stmtsContext ctx) {
+ exitLog("meta_stmt", "");
+ }
+
+ @Override
+ public void enterRevision_stmts(Revision_stmtsContext ctx) {
+ enterLog("revisions", "", ctx.getStart().getLine());
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ final ParseTree treeNode = ctx.getChild(i);
+ if (treeNode instanceof Revision_stmtContext) {
+ updateRevisionForRevisionStatement(treeNode);
+ }
+ }
+ }
+
+ @Override
+ public void exitRevision_stmts(Revision_stmtsContext ctx) {
+ exitLog("revisions", "");
+ }
+
+ private void updateRevisionForRevisionStatement(final ParseTree treeNode) {
+ final String revisionDateStr = stringFromNode(treeNode);
+ try {
+ final Date revision = simpleDateFormat.parse(revisionDateStr);
+ if ((revision != null) && (this.revision.compareTo(revision) < 0)) {
+ this.revision = revision;
+ moduleBuilder.setRevision(this.revision);
+ setLog("revision", this.revision.toString());
+ for (int i = 0; i < treeNode.getChildCount(); ++i) {
+ ParseTree child = treeNode.getChild(i);
+ if (child instanceof Reference_stmtContext) {
+ moduleBuilder.setReference(stringFromNode(child));
+ }
+ }
+ }
+ } catch (ParseException e) {
+ final String message = "Failed to parse revision string: " + revisionDateStr;
+ logger.warn(message);
+ }
+ }
+
+ @Override
+ public void enterImport_stmt(Import_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String importName = stringFromNode(ctx);
+ enterLog("import", importName, line);
+
+ String importPrefix = null;
+ Date importRevision = null;
+
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ final ParseTree treeNode = ctx.getChild(i);
+ if (treeNode instanceof Prefix_stmtContext) {
+ importPrefix = stringFromNode(treeNode);
+ }
+ if (treeNode instanceof Revision_date_stmtContext) {
+ String importRevisionStr = stringFromNode(treeNode);
+ try {
+ importRevision = simpleDateFormat.parse(importRevisionStr);
+ } catch (ParseException e) {
+ logger.warn("Failed to parse import revision-date at line " + line + ": " + importRevisionStr);
+ }
+ }
+ }
+ moduleBuilder.addModuleImport(importName, importRevision, importPrefix);
+ setLog("import", "(" + importName + "; " + importRevision + "; " + importPrefix + ")");
+ }
+
+ @Override
+ public void exitImport_stmt(Import_stmtContext ctx) {
+ exitLog("import", "");
+ }
+
+ @Override
+ public void enterAugment_stmt(YangParser.Augment_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String augmentPath = stringFromNode(ctx);
+ enterLog("augment", augmentPath, line);
+
+ AugmentationSchemaBuilder builder = moduleBuilder.addAugment(line, augmentPath);
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ builder.setDescription(stringFromNode(child));
+ } else if (child instanceof Reference_stmtContext) {
+ builder.setReference(stringFromNode(child));
+ } else if (child instanceof Status_stmtContext) {
+ builder.setStatus(parseStatus((Status_stmtContext) child));
+ } else if (child instanceof When_stmtContext) {
+ builder.addWhenCondition(stringFromNode(child));
+ }
+ }
+
+ moduleBuilder.enterNode(builder);
+ actualPath.push(augmentPath);
+ }
+
+ @Override
+ public void exitAugment_stmt(YangParser.Augment_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("augment", actualPath.pop());
+ }
+
+ @Override
+ public void enterExtension_stmt(YangParser.Extension_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String extName = stringFromNode(ctx);
+ enterLog("extension", extName, line);
+
+ QName qname = new QName(namespace, revision, yangModelPrefix, extName);
+ ExtensionBuilder builder = moduleBuilder.addExtension(qname, line);
+ parseSchemaNodeArgs(ctx, builder);
+
+ String argument = null;
+ boolean yin = false;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Argument_stmtContext) {
+ argument = stringFromNode(child);
+ yin = parseYinValue((Argument_stmtContext) child);
+ break;
+ }
+ }
+ builder.setArgument(argument);
+ builder.setYinElement(yin);
+
+ moduleBuilder.enterNode(builder);
+ actualPath.push(extName);
+ }
+
+ @Override
+ public void exitExtension_stmt(YangParser.Extension_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("extension", actualPath.pop());
+ }
+
+ @Override
+ public void enterTypedef_stmt(YangParser.Typedef_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String typedefName = stringFromNode(ctx);
+ enterLog("typedef", typedefName, line);
+
+ QName typedefQName = new QName(namespace, revision, yangModelPrefix, typedefName);
+ TypeDefinitionBuilder builder = moduleBuilder.addTypedef(line, typedefQName);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(typedefName);
+
+ builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+ parseSchemaNodeArgs(ctx, builder);
+ builder.setUnits(parseUnits(ctx));
+ builder.setDefaultValue(parseDefault(ctx));
+ }
+
+ @Override
+ public void exitTypedef_stmt(YangParser.Typedef_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("typedef", actualPath.pop());
+ }
+
+ @Override
+ public void enterType_stmt(YangParser.Type_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String typeName = stringFromNode(ctx);
+ enterLog("type", typeName, line);
+
+ final QName typeQName = parseQName(typeName);
+
+ TypeDefinition<?> type = null;
+ Type_body_stmtsContext typeBody = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ if (ctx.getChild(i) instanceof Type_body_stmtsContext) {
+ typeBody = (Type_body_stmtsContext) ctx.getChild(i);
+ break;
+ }
+ }
+
+ // if this is base yang type...
+ if (YangTypesConverter.isBaseYangType(typeName)) {
+ if (typeBody == null) {
+ // check for types which must have body
+ checkMissingBody(typeName, moduleName, line);
+ // if there are no constraints, just grab default base yang type
+ type = YangTypesConverter.javaTypeForBaseYangType(actualPath, namespace, revision, typeName);
+ moduleBuilder.setType(type);
+ } else {
+ if ("union".equals(typeName)) {
+ SchemaPath p = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
+ UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(line, namespace, revision);
+ moduleBuilder.enterNode(unionBuilder);
+ unionBuilder.setPath(p);
+ } else if ("identityref".equals(typeName)) {
+ SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
+ moduleBuilder.addIdentityrefType(line, path, getIdentityrefBase(typeBody));
+ } else {
+ type = parseTypeWithBody(typeName, typeBody, actualPath, namespace, revision, yangModelPrefix,
+ moduleBuilder.getActualNode());
+ moduleBuilder.setType(type);
+ }
+ }
+ } else {
+ type = parseUnknownTypeWithBody(typeQName, typeBody, actualPath, namespace, revision, yangModelPrefix,
+ moduleBuilder.getActualNode());
+ // add parent node of this type statement to dirty nodes
+ moduleBuilder.markActualNodeDirty();
+ moduleBuilder.setType(type);
+ }
+
+ actualPath.push(typeName);
+ }
+
+ private QName parseQName(String typeName) {
+ QName typeQName;
+ if (typeName.contains(":")) {
+ String[] splittedName = typeName.split(":");
+ String prefix = splittedName[0];
+ String name = splittedName[1];
+ if (prefix.equals(yangModelPrefix)) {
+ typeQName = new QName(namespace, revision, prefix, name);
+ } else {
+ typeQName = new QName(null, null, prefix, name);
+ }
+ } else {
+ typeQName = new QName(namespace, revision, yangModelPrefix, typeName);
+ }
+ return typeQName;
+ }
+
+ @Override
+ public void exitType_stmt(YangParser.Type_stmtContext ctx) {
+ final String typeName = stringFromNode(ctx);
+ if ("union".equals(typeName)) {
+ moduleBuilder.exitNode();
+ }
+ exitLog("type", actualPath.pop());
+ }
+
+ @Override
+ public void enterGrouping_stmt(YangParser.Grouping_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String groupName = stringFromNode(ctx);
+ enterLog("grouping", groupName, line);
+
+ QName groupQName = new QName(namespace, revision, yangModelPrefix, groupName);
+ GroupingBuilder builder = moduleBuilder.addGrouping(ctx.getStart().getLine(), groupQName);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(groupName);
+
+ builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+ parseSchemaNodeArgs(ctx, builder);
+ }
+
+ @Override
+ public void exitGrouping_stmt(YangParser.Grouping_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("grouping", actualPath.pop());
+ }
+
+ @Override
+ public void enterContainer_stmt(Container_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String containerName = stringFromNode(ctx);
+ enterLog("container", containerName, line);
+
+ QName containerQName = new QName(namespace, revision, yangModelPrefix, containerName);
+ SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, containerName);
+
+ ContainerSchemaNodeBuilder builder = moduleBuilder.addContainerNode(line, containerQName, path);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(containerName);
+
+ parseSchemaNodeArgs(ctx, builder);
+ parseConstraints(ctx, builder.getConstraints());
+ builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
+
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ final ParseTree childNode = ctx.getChild(i);
+ if (childNode instanceof Presence_stmtContext) {
+ builder.setPresence(true);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void exitContainer_stmt(Container_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("container", actualPath.pop());
+ }
+
+ @Override
+ public void enterLeaf_stmt(Leaf_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String leafName = stringFromNode(ctx);
+ enterLog("leaf", leafName, line);
+
+ QName leafQName = new QName(namespace, revision, yangModelPrefix, leafName);
+ SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, leafName);
+
+ LeafSchemaNodeBuilder builder = moduleBuilder.addLeafNode(line, leafQName, schemaPath);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(leafName);
+
+ parseSchemaNodeArgs(ctx, builder);
+ parseConstraints(ctx, builder.getConstraints());
+ builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
+
+ String defaultStr = null;
+ String unitsStr = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Default_stmtContext) {
+ defaultStr = stringFromNode(child);
+ } else if (child instanceof Units_stmtContext) {
+ unitsStr = stringFromNode(child);
+ }
+ }
+ builder.setDefaultStr(defaultStr);
+ builder.setUnits(unitsStr);
+ }
+
+ @Override
+ public void exitLeaf_stmt(YangParser.Leaf_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("leaf", actualPath.pop());
+ }
+
+ @Override
+ public void enterUses_stmt(YangParser.Uses_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String groupingPathStr = stringFromNode(ctx);
+ enterLog("uses", groupingPathStr, line);
+
+ UsesNodeBuilder builder = moduleBuilder.addUsesNode(line, groupingPathStr);
+
+ moduleBuilder.enterNode(builder);
+ actualPath.push(groupingPathStr);
+ }
+
+ @Override
+ public void exitUses_stmt(YangParser.Uses_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("uses", actualPath.pop());
+ }
+
+ @Override public void enterUses_augment_stmt(YangParser.Uses_augment_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String augmentPath = stringFromNode(ctx);
+ enterLog("augment", augmentPath, line);
+
+ AugmentationSchemaBuilder builder = moduleBuilder.addAugment(line, augmentPath);
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ builder.setDescription(stringFromNode(child));
+ } else if (child instanceof Reference_stmtContext) {
+ builder.setReference(stringFromNode(child));
+ } else if (child instanceof Status_stmtContext) {
+ builder.setStatus(parseStatus((Status_stmtContext) child));
+ } else if (child instanceof When_stmtContext) {
+ builder.addWhenCondition(stringFromNode(child));
+ }
+ }
+
+ moduleBuilder.enterNode(builder);
+ actualPath.push(augmentPath);
+ }
+
+ @Override public void exitUses_augment_stmt(YangParser.Uses_augment_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("augment", actualPath.pop());
+ }
+
+ @Override
+ public void enterRefine_stmt(YangParser.Refine_stmtContext ctx) {
+ final String refineString = stringFromNode(ctx);
+ enterLog("refine", refineString, ctx.getStart().getLine());
+
+ RefineHolder refine = parseRefine(ctx, moduleName);
+ moduleBuilder.addRefine(refine);
+ moduleBuilder.enterNode(refine);
+ actualPath.push(refineString);
+ }
+
+ @Override
+ public void exitRefine_stmt(YangParser.Refine_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("refine", actualPath.pop());
+ }
+
+ @Override
+ public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String leafListName = stringFromNode(ctx);
+ enterLog("leaf-list", leafListName, line);
+
+ QName leafListQName = new QName(namespace, revision, yangModelPrefix, leafListName);
+ SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, leafListName);
+
+ LeafListSchemaNodeBuilder builder = moduleBuilder.addLeafListNode(line, leafListQName, schemaPath);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(leafListName);
+
+ parseSchemaNodeArgs(ctx, builder);
+ parseConstraints(ctx, builder.getConstraints());
+ builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, ctx.getStart().getLine()));
+
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ final ParseTree childNode = ctx.getChild(i);
+ if (childNode instanceof Ordered_by_stmtContext) {
+ final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode;
+ final boolean userOrdered = parseUserOrdered(orderedBy);
+ builder.setUserOrdered(userOrdered);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void exitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("leaf-list", actualPath.pop());
+ }
+
+ @Override
+ public void enterList_stmt(List_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String listName = stringFromNode(ctx);
+ enterLog("list", listName, line);
+
+ QName listQName = new QName(namespace, revision, yangModelPrefix, listName);
+ SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, listName);
+
+ ListSchemaNodeBuilder builder = moduleBuilder.addListNode(line, listQName, schemaPath);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(listName);
+
+ parseSchemaNodeArgs(ctx, builder);
+ parseConstraints(ctx, builder.getConstraints());
+ builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
+
+ String keyDefinition = "";
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ ParseTree childNode = ctx.getChild(i);
+ if (childNode instanceof Ordered_by_stmtContext) {
+ final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode;
+ final boolean userOrdered = parseUserOrdered(orderedBy);
+ builder.setUserOrdered(userOrdered);
+ } else if (childNode instanceof Key_stmtContext) {
+ keyDefinition = stringFromNode(childNode);
+ List<QName> key = createListKey(keyDefinition, namespace, revision, yangModelPrefix);
+ builder.setKeyDefinition(key);
+ }
+ }
+ }
+
+ @Override
+ public void exitList_stmt(List_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("list", actualPath.pop());
+ }
+
+ @Override
+ public void enterAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String anyXmlName = stringFromNode(ctx);
+ enterLog("anyxml", anyXmlName, line);
+
+ QName anyXmlQName = new QName(namespace, revision, yangModelPrefix, anyXmlName);
+ SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, anyXmlName);
+
+ AnyXmlBuilder builder = moduleBuilder.addAnyXml(line, anyXmlQName, schemaPath);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(anyXmlName);
+
+ parseSchemaNodeArgs(ctx, builder);
+ parseConstraints(ctx, builder.getConstraints());
+ builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
+ }
+
+ @Override
+ public void exitAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("anyxml", actualPath.pop());
+ }
+
+ @Override
+ public void enterChoice_stmt(YangParser.Choice_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String choiceName = stringFromNode(ctx);
+ enterLog("choice", choiceName, line);
+
+ QName choiceQName = new QName(namespace, revision, yangModelPrefix, choiceName);
+
+ ChoiceBuilder builder = moduleBuilder.addChoice(line, choiceQName);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(choiceName);
+
+ builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+ parseSchemaNodeArgs(ctx, builder);
+ parseConstraints(ctx, builder.getConstraints());
+ builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
+
+ // set 'default' case
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Default_stmtContext) {
+ String defaultCase = stringFromNode(child);
+ builder.setDefaultCase(defaultCase);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void exitChoice_stmt(YangParser.Choice_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("choice", actualPath.pop());
+ }
+
+ @Override
+ public void enterCase_stmt(YangParser.Case_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String caseName = stringFromNode(ctx);
+ enterLog("case", caseName, line);
+
+ QName caseQName = new QName(namespace, revision, yangModelPrefix, caseName);
+ ChoiceCaseBuilder builder = moduleBuilder.addCase(line, caseQName);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(caseName);
+
+ builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+ parseSchemaNodeArgs(ctx, builder);
+ parseConstraints(ctx, builder.getConstraints());
+ }
+
+ @Override
+ public void exitCase_stmt(YangParser.Case_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("case", actualPath.pop());
+ }
+
+ @Override
+ public void enterNotification_stmt(YangParser.Notification_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String notificationName = stringFromNode(ctx);
+ enterLog("notification", notificationName, line);
+
+ QName notificationQName = new QName(namespace, revision, yangModelPrefix, notificationName);
+ NotificationBuilder builder = moduleBuilder.addNotification(line, notificationQName);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(notificationName);
+
+ builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+ parseSchemaNodeArgs(ctx, builder);
+ }
+
+ @Override
+ public void exitNotification_stmt(YangParser.Notification_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("notification", actualPath.pop());
+ }
+
+ // Unknown nodes
+ @Override
+ public void enterIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String nodeParameter = stringFromNode(ctx);
+ enterLog("unknown-node", nodeParameter, line);
+
+ QName nodeType = null;
+
+ final String nodeTypeStr = ctx.getChild(0).getText();
+ final String[] splittedElement = nodeTypeStr.split(":");
+ if (splittedElement.length == 1) {
+ nodeType = new QName(null, null, yangModelPrefix, splittedElement[0]);
+ } else {
+ nodeType = new QName(null, null, splittedElement[0], splittedElement[1]);
+ }
+
+ QName qname;
+ if (nodeParameter != null) {
+ String[] splittedName = nodeParameter.split(":");
+ if (splittedName.length == 2) {
+ qname = new QName(null, null, splittedName[0], splittedName[1]);
+ } else {
+ qname = new QName(namespace, revision, yangModelPrefix, splittedName[0]);
+ }
+ } else {
+ qname = new QName(namespace, revision, yangModelPrefix, nodeParameter);
+ }
+
+ UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(line, qname);
+ builder.setNodeType(nodeType);
+ builder.setNodeParameter(nodeParameter);
+ actualPath.push(nodeParameter);
+ builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+ parseSchemaNodeArgs(ctx, builder);
+ moduleBuilder.enterNode(builder);
+ }
+
+ @Override
+ public void exitIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("unknown-node", actualPath.pop());
+ }
+
+ @Override
+ public void enterRpc_stmt(YangParser.Rpc_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String rpcName = stringFromNode(ctx);
+ enterLog("rpc", rpcName, line);
+
+ QName rpcQName = new QName(namespace, revision, yangModelPrefix, rpcName);
+ RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(line, rpcQName);
+ moduleBuilder.enterNode(rpcBuilder);
+ actualPath.push(rpcName);
+
+ rpcBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+ parseSchemaNodeArgs(ctx, rpcBuilder);
+ }
+
+ @Override
+ public void exitRpc_stmt(YangParser.Rpc_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("rpc", actualPath.pop());
+ }
+
+ @Override
+ public void enterInput_stmt(YangParser.Input_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String input = "input";
+ enterLog(input, input, line);
+
+ QName rpcQName = new QName(namespace, revision, yangModelPrefix, input);
+ SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, input);
+
+ ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcInput(line, rpcQName, path);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(input);
+
+ parseSchemaNodeArgs(ctx, builder);
+ parseConstraints(ctx, builder.getConstraints());
+ }
+
+ @Override
+ public void exitInput_stmt(YangParser.Input_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("input", actualPath.pop());
+ }
+
+ @Override
+ public void enterOutput_stmt(YangParser.Output_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String output = "output";
+ enterLog(output, output, line);
+
+ QName rpcQName = new QName(namespace, revision, yangModelPrefix, output);
+ SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, output);
+
+ ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcOutput(path, rpcQName, line);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(output);
+
+ parseSchemaNodeArgs(ctx, builder);
+ parseConstraints(ctx, builder.getConstraints());
+ }
+
+ @Override
+ public void exitOutput_stmt(YangParser.Output_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("output", actualPath.pop());
+ }
+
+ @Override
+ public void enterFeature_stmt(YangParser.Feature_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String featureName = stringFromNode(ctx);
+ enterLog("feature", featureName, line);
+
+ QName featureQName = new QName(namespace, revision, yangModelPrefix, featureName);
+ FeatureBuilder featureBuilder = moduleBuilder.addFeature(line, featureQName);
+ moduleBuilder.enterNode(featureBuilder);
+ actualPath.push(featureName);
+
+ featureBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+ parseSchemaNodeArgs(ctx, featureBuilder);
+ }
+
+ @Override
+ public void exitFeature_stmt(YangParser.Feature_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("feature", actualPath.pop());
+ }
+
+ @Override
+ public void enterDeviation_stmt(YangParser.Deviation_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String targetPath = stringFromNode(ctx);
+ enterLog("deviation", targetPath, line);
+
+ String reference = null;
+ String deviate = null;
+ DeviationBuilder builder = moduleBuilder.addDeviation(line, targetPath);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(targetPath);
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ } else if (child instanceof Deviate_not_supported_stmtContext) {
+ deviate = stringFromNode(child);
+ } else if (child instanceof Deviate_add_stmtContext) {
+ deviate = stringFromNode(child);
+ } else if (child instanceof Deviate_replace_stmtContext) {
+ deviate = stringFromNode(child);
+ } else if (child instanceof Deviate_delete_stmtContext) {
+ deviate = stringFromNode(child);
+ }
+ }
+ builder.setReference(reference);
+ builder.setDeviate(deviate);
+ }
+
+ @Override
+ public void exitDeviation_stmt(YangParser.Deviation_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("deviation", actualPath.pop());
+ }
+
+ @Override
+ public void enterIdentity_stmt(YangParser.Identity_stmtContext ctx) {
+ final int line = ctx.getStart().getLine();
+ final String identityName = stringFromNode(ctx);
+ enterLog("identity", identityName, line);
+
+ final QName identityQName = new QName(namespace, revision, yangModelPrefix, identityName);
+ IdentitySchemaNodeBuilder builder = moduleBuilder.addIdentity(identityQName, actualPath, line);
+ moduleBuilder.enterNode(builder);
+ actualPath.push(identityName);
+
+ builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+ parseSchemaNodeArgs(ctx, builder);
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Base_stmtContext) {
+ String baseIdentityName = stringFromNode(child);
+ builder.setBaseIdentityName(baseIdentityName);
+ }
+ }
+ }
+
+ @Override
+ public void exitIdentity_stmt(YangParser.Identity_stmtContext ctx) {
+ moduleBuilder.exitNode();
+ exitLog("identity", actualPath.pop());
+ }
+
+ public ModuleBuilder getModuleBuilder() {
+ return moduleBuilder;
+ }
+
+ private void enterLog(String p1, String p2, int line) {
+ logger.debug("entering " + p1 + " " + p2 + " (" + line + ")");
+ }
+
+ private void exitLog(String p1, String p2) {
+ logger.debug("exiting " + p1 + " " + p2);
+ }
+
+ private void setLog(String p1, String p2) {
+ logger.debug("setting " + p1 + " " + p2);
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;
+
+final class BitImpl implements BitsTypeDefinition.Bit {
+ private final Long position;
+ private final QName qname;
+ private final SchemaPath schemaPath;
+ private final String description;
+ private final String reference;
+ private final Status status;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+
+ BitImpl(final Long position, final QName qname,
+ final SchemaPath schemaPath, final String description,
+ final String reference, final Status status,
+ final List<UnknownSchemaNode> unknownNodes) {
+ this.position = position;
+ this.qname = qname;
+ this.schemaPath = schemaPath;
+ this.description = description;
+ this.reference = reference;
+ this.status = status;
+ if(unknownNodes != null) {
+ this.unknownNodes = unknownNodes;
+ }
+ }
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ @Override
+ public Long getPosition() {
+ return position;
+ }
+
+ @Override
+ public String getName() {
+ return qname.getLocalName();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result
+ + ((schemaPath == null) ? 0 : schemaPath.hashCode());
+ result = prime * result
+ + ((position == null) ? 0 : position.hashCode());
+ result = prime
+ * result
+ + ((unknownNodes == null) ? 0 : unknownNodes.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Bit other = (Bit) obj;
+ if (qname == null) {
+ if (other.getQName() != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.getQName())) {
+ return false;
+ }
+ if (schemaPath == null) {
+ if (other.getPath() != null) {
+ return false;
+ }
+ } else if (!schemaPath.equals(other.getPath())) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return Bit.class.getSimpleName() + "[name="
+ + qname.getLocalName() + ", position=" + position + "]";
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import java.util.Comparator;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
+
+public class Comparators {
+
+ public static final QNameComparator QNAME_COMP = new QNameComparator();
+ public static final SchemaNodeComparator SCHEMA_NODE_COMP = new SchemaNodeComparator();
+
+ private Comparators() {
+ }
+
+ private static final class QNameComparator implements Comparator<QName> {
+ @Override
+ public int compare(QName o1, QName o2) {
+ return o1.getLocalName().compareTo(o2.getLocalName());
+ }
+ }
+
+ private static final class SchemaNodeComparator implements Comparator<SchemaNode> {
+ @Override
+ public int compare(SchemaNode o1, SchemaNode o2) {
+ return o1.getQName().getLocalName().compareTo(o2.getQName().getLocalName());
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.ModuleImport;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.controller.yang.parser.impl.YangParserListenerImpl;
+import org.opendaylight.controller.yang.parser.util.TopologicalSort.Node;
+import org.opendaylight.controller.yang.parser.util.TopologicalSort.NodeImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ * Creates a module dependency graph from provided {@link ModuleBuilder}s and
+ * provides a {@link #sort()} method. It is topological sort and returns modules
+ * in order in which they should be processed (e.g. if A imports B, sort returns
+ * {B, A}).
+ */
+public final class ModuleDependencySort {
+
+ private static final Date DEFAULT_REVISION = new Date(0);
+ private static final Logger logger = LoggerFactory.getLogger(ModuleDependencySort.class);
+
+ /**
+ * Topological sort of module builder dependency graph.
+ *
+ * @return Sorted list of Module builders. Modules can be further processed
+ * in returned order.
+ */
+ public static List<ModuleBuilder> sort(ModuleBuilder... builders) {
+ List<Node> sorted = sortInternal(Arrays.asList(builders));
+ // Cast to ModuleBuilder from Node and return
+ return Lists.transform(sorted, new Function<Node, ModuleBuilder>() {
+
+ @Override
+ public ModuleBuilder apply(Node input) {
+ return (ModuleBuilder) ((ModuleNodeImpl) input).getReference();
+ }
+ });
+ }
+
+ public static List<ModuleBuilder> sortWithContext(SchemaContext context, ModuleBuilder... builders) {
+ List<Object> modules = new ArrayList<Object>();
+ Collections.addAll(modules, builders);
+ modules.addAll(context.getModules());
+
+ List<Node> sorted = sortInternal(modules);
+ // Cast to ModuleBuilder from Node if possible and return
+ return Lists.transform(sorted, new Function<Node, ModuleBuilder>() {
+
+ @Override
+ public ModuleBuilder apply(Node input) {
+ if (((ModuleNodeImpl) input).getReference() instanceof ModuleBuilder) {
+ return (ModuleBuilder) ((ModuleNodeImpl) input).getReference();
+ } else {
+ return null;
+ }
+ }
+ });
+ }
+
+ /**
+ * Topological sort of module dependency graph.
+ *
+ * @return Sorted list of Modules. Modules can be further processed in
+ * returned order.
+ */
+ public static List<Module> sort(Module... modules) {
+ List<Node> sorted = sortInternal(Arrays.asList(modules));
+ // Cast to Module from Node and return
+ return Lists.transform(sorted, new Function<Node, Module>() {
+
+ @Override
+ public Module apply(Node input) {
+ return (Module) ((ModuleNodeImpl) input).getReference();
+ }
+ });
+ }
+
+ private static List<Node> sortInternal(List<?> modules) {
+ Map<String, Map<Date, ModuleNodeImpl>> moduleGraph = createModuleGraph(modules);
+
+ Set<Node> nodes = Sets.newHashSet();
+ for (Map<Date, ModuleNodeImpl> map : moduleGraph.values()) {
+ for (ModuleNodeImpl node : map.values()) {
+ nodes.add(node);
+ }
+ }
+
+ return TopologicalSort.sort(nodes);
+ }
+
+ @VisibleForTesting
+ static Map<String, Map<Date, ModuleNodeImpl>> createModuleGraph(List<?> builders) {
+ Map<String, Map<Date, ModuleNodeImpl>> moduleGraph = Maps.newHashMap();
+
+ processModules(moduleGraph, builders);
+ processDependencies(moduleGraph, builders);
+
+ return moduleGraph;
+ }
+
+ /**
+ * Extract module:revision from module builders
+ */
+ private static void processDependencies(Map<String, Map<Date, ModuleNodeImpl>> moduleGraph, List<?> builders) {
+ Map<String, Date> imported = Maps.newHashMap();
+
+ // Create edges in graph
+ for (Object mb : builders) {
+
+ String fromName = null;
+ Date fromRevision = null;
+ Set<ModuleImport> imports = null;
+
+ if (mb instanceof Module) {
+ fromName = ((Module) mb).getName();
+ fromRevision = ((Module) mb).getRevision();
+ imports = ((Module) mb).getImports();
+ } else if (mb instanceof ModuleBuilder) {
+ fromName = ((ModuleBuilder) mb).getName();
+ fromRevision = ((ModuleBuilder) mb).getRevision();
+ imports = ((ModuleBuilder) mb).getModuleImports();
+ }
+ // no need to check if other Type of object, check is performed in
+ // process modules
+
+ if (fromRevision == null)
+ fromRevision = DEFAULT_REVISION;
+
+ for (ModuleImport imprt : imports) {
+ String toName = imprt.getModuleName();
+ Date toRevision = imprt.getRevision() == null ? DEFAULT_REVISION : imprt.getRevision();
+
+ ModuleNodeImpl from = moduleGraph.get(fromName).get(fromRevision);
+
+ ModuleNodeImpl to = getModuleByNameAndRevision(moduleGraph, fromName, fromRevision, toName, toRevision);
+
+ /*
+ * Check imports: If module is imported twice with different
+ * revisions then throw exception
+ */
+ if (imported.get(toName) != null && !imported.get(toName).equals(toRevision)) {
+ if (!imported.get(toName).equals(DEFAULT_REVISION) && !toRevision.equals(DEFAULT_REVISION)) {
+ ex(String.format("Module:%s imported twice with different revisions:%s, %s", toName,
+ formatRevDate(imported.get(toName)), formatRevDate(toRevision)));
+ }
+
+ }
+
+ imported.put(toName, toRevision);
+
+ from.addEdge(to);
+ }
+ }
+ }
+
+ /**
+ * Get imported module by its name and revision from moduleGraph
+ */
+ private static ModuleNodeImpl getModuleByNameAndRevision(Map<String, Map<Date, ModuleNodeImpl>> moduleGraph,
+ String fromName, Date fromRevision, String toName, Date toRevision) {
+ ModuleNodeImpl to = null;
+
+ if (moduleGraph.get(toName) == null || !moduleGraph.get(toName).containsKey(toRevision)) {
+ // If revision is not specified in import, but module exists
+ // with different revisions, take first
+ if (moduleGraph.get(toName) != null && !moduleGraph.get(toName).isEmpty()
+ && toRevision.equals(DEFAULT_REVISION)) {
+ to = moduleGraph.get(toName).values().iterator().next();
+ logger.warn(String
+ .format("Import:%s:%s by module:%s:%s does not specify revision, using:%s:%s for module dependency sort",
+ toName, formatRevDate(toRevision), fromName, formatRevDate(fromRevision), to.getName(),
+ formatRevDate(to.getRevision())));
+ } else
+ ex(String.format("Not existing module imported:%s:%s by:%s:%s", toName, formatRevDate(toRevision),
+ fromName, formatRevDate(fromRevision)));
+ } else {
+ to = moduleGraph.get(toName).get(toRevision);
+ }
+ return to;
+ }
+
+ private static void ex(String message) {
+ throw new YangValidationException(message);
+ }
+
+ /**
+ * Extract dependencies from module builders or modules to fill dependency
+ * graph
+ */
+ private static void processModules(Map<String, Map<Date, ModuleNodeImpl>> moduleGraph, List<?> builders) {
+
+ // Process nodes
+ for (Object mb : builders) {
+
+ String name = null;
+ Date rev = null;
+
+ if (mb instanceof Module) {
+ name = ((Module) mb).getName();
+ rev = ((Module) mb).getRevision();
+ } else if (mb instanceof ModuleBuilder) {
+ name = ((ModuleBuilder) mb).getName();
+ rev = ((ModuleBuilder) mb).getRevision();
+ } else {
+ throw new IllegalStateException(String.format(
+ "Unexpected type of node for sort, expected only:%s, %s, got:%s", Module.class,
+ ModuleBuilder.class, mb.getClass()));
+ }
+
+ if (rev == null)
+ rev = DEFAULT_REVISION;
+
+ if (moduleGraph.get(name) == null)
+ moduleGraph.put(name, Maps.<Date, ModuleNodeImpl> newHashMap());
+
+ if (moduleGraph.get(name).get(rev) != null)
+ ex(String.format("Module:%s with revision:%s declared twice", name, formatRevDate(rev)));
+
+ moduleGraph.get(name).put(rev, new ModuleNodeImpl(name, rev, mb));
+ }
+ }
+
+ private static String formatRevDate(Date rev) {
+ return rev == DEFAULT_REVISION ? "default" : YangParserListenerImpl.simpleDateFormat.format(rev);
+ }
+
+ @VisibleForTesting
+ static class ModuleNodeImpl extends NodeImpl {
+ private final String name;
+ private final Date revision;
+ private final Object originalObject;
+
+ public ModuleNodeImpl(String name, Date revision, Object builder) {
+ this.name = name;
+ this.revision = revision;
+ this.originalObject = builder;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Date getRevision() {
+ return revision;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((revision == null) ? 0 : revision.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ModuleNodeImpl other = (ModuleNodeImpl) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (revision == null) {
+ if (other.revision != null)
+ return false;
+ } else if (!revision.equals(other.revision))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Module [name=" + name + ", revision=" + formatRevDate(revision) + "]";
+ }
+
+ public Object getReference() {
+ return originalObject;
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import org.opendaylight.controller.yang.model.api.MustDefinition;
+import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
+
+final class MustDefinitionImpl implements MustDefinition {
+ private final String mustStr;
+ private final String description;
+ private final String reference;
+ private final String errorAppTag;
+ private final String errorMessage;
+
+ MustDefinitionImpl(String mustStr, String description, String reference,
+ String errorAppTag, String errorMessage) {
+ this.mustStr = mustStr;
+ this.description = description;
+ this.reference = reference;
+ this.errorAppTag = errorAppTag;
+ this.errorMessage = errorMessage;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getErrorAppTag() {
+ return errorAppTag;
+ }
+
+ @Override
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public RevisionAwareXPath getXpath() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((mustStr == null) ? 0 : mustStr.hashCode());
+ result = prime * result
+ + ((description == null) ? 0 : description.hashCode());
+ result = prime * result
+ + ((reference == null) ? 0 : reference.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final MustDefinitionImpl other = (MustDefinitionImpl) obj;
+ if (mustStr == null) {
+ if (other.mustStr != null) {
+ return false;
+ }
+ } else if (!mustStr.equals(other.mustStr)) {
+ return false;
+ }
+ if (description == null) {
+ if (other.description != null) {
+ return false;
+ }
+ } else if (!description.equals(other.description)) {
+ return false;
+ }
+ if (reference == null) {
+ if (other.reference != null) {
+ return false;
+ }
+ } else if (!reference.equals(other.reference)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return mustStr;
+ }
+
+}
--- /dev/null
+/*
+ * 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/eplv10.html
+ */
+package org.opendaylight.controller.yang.parser.util;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Stack;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.opendaylight.controller.antlrv4.code.gen.*;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bit_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bits_specificationContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Decimal64_specificationContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_specificationContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Error_app_tag_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Error_message_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Fraction_digits_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Identityref_specificationContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Instance_identifier_specificationContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leafref_specificationContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Length_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Max_elements_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Max_value_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Min_elements_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Min_value_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Must_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Numerical_restrictionsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Path_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Pattern_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Position_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Presence_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Range_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_anyxml_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_choice_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_container_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_leaf_list_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_leaf_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_list_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_pomContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.String_restrictionsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Value_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_stmtContext;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.MustDefinition;
+import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;
+import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
+import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
+import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefinition;
+import org.opendaylight.controller.yang.model.util.BaseConstraints;
+import org.opendaylight.controller.yang.model.util.BaseTypes;
+import org.opendaylight.controller.yang.model.util.BinaryType;
+import org.opendaylight.controller.yang.model.util.BitsType;
+import org.opendaylight.controller.yang.model.util.Decimal64;
+import org.opendaylight.controller.yang.model.util.EnumerationType;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.model.util.InstanceIdentifier;
+import org.opendaylight.controller.yang.model.util.Int16;
+import org.opendaylight.controller.yang.model.util.Int32;
+import org.opendaylight.controller.yang.model.util.Int64;
+import org.opendaylight.controller.yang.model.util.Int8;
+import org.opendaylight.controller.yang.model.util.Leafref;
+import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl;
+import org.opendaylight.controller.yang.model.util.StringType;
+import org.opendaylight.controller.yang.model.util.Uint16;
+import org.opendaylight.controller.yang.model.util.Uint32;
+import org.opendaylight.controller.yang.model.util.Uint64;
+import org.opendaylight.controller.yang.model.util.Uint8;
+import org.opendaylight.controller.yang.model.util.UnknownType;
+import org.opendaylight.controller.yang.parser.builder.api.Builder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceCaseBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ConstraintsBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ParserListenerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(ParserListenerUtils.class);
+
+ private ParserListenerUtils() {
+ }
+
+ /**
+ * Parse given tree and get first string value.
+ *
+ * @param treeNode
+ * tree to parse
+ * @return first string value from given tree
+ */
+ public static String stringFromNode(final ParseTree treeNode) {
+ final String result = "";
+ for (int i = 0; i < treeNode.getChildCount(); ++i) {
+ if (treeNode.getChild(i) instanceof StringContext) {
+ final StringContext context = (StringContext) treeNode.getChild(i);
+ if (context != null) {
+ return context.getChild(0).getText().replace("\"", "");
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse 'description', 'reference' and 'status' statements and fill in
+ * given builder.
+ *
+ * @param ctx
+ * context to parse
+ * @param builder
+ * builder to fill in with parsed statements
+ */
+ public static void parseSchemaNodeArgs(final ParseTree ctx, final SchemaNodeBuilder builder) {
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ final ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ final String desc = stringFromNode(child);
+ builder.setDescription(desc);
+ } else if (child instanceof Reference_stmtContext) {
+ final String ref = stringFromNode(child);
+ builder.setReference(ref);
+ } else if (child instanceof Status_stmtContext) {
+ final Status status = parseStatus((Status_stmtContext) child);
+ builder.setStatus(status);
+ }
+ }
+ }
+
+ /**
+ * Parse given context and return its value;
+ *
+ * @param ctx
+ * status context
+ * @return value parsed from context
+ */
+ public static Status parseStatus(final Status_stmtContext ctx) {
+ Status result = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree statusArg = ctx.getChild(i);
+ if (statusArg instanceof Status_argContext) {
+ String statusArgStr = stringFromNode(statusArg);
+ if ("current".equals(statusArgStr)) {
+ result = Status.CURRENT;
+ } else if ("deprecated".equals(statusArgStr)) {
+ result = Status.DEPRECATED;
+ } else if ("obsolete".equals(statusArgStr)) {
+ result = Status.OBSOLETE;
+ } else {
+ LOG.warn("Invalid 'status' statement: " + statusArgStr);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse given tree and returns units statement as string.
+ *
+ * @param ctx
+ * context to parse
+ * @return value of units statement as string or null if there is no units
+ * statement
+ */
+ public static String parseUnits(final ParseTree ctx) {
+ String units = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Units_stmtContext) {
+ units = stringFromNode(child);
+ break;
+ }
+ }
+ return units;
+ }
+
+ /**
+ * Parse given tree and returns default statement as string.
+ *
+ * @param ctx
+ * context to parse
+ * @return value of default statement as string or null if there is no
+ * default statement
+ */
+ public static String parseDefault(final ParseTree ctx) {
+ String defaultValue = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Default_stmtContext) {
+ defaultValue = stringFromNode(child);
+ break;
+ }
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Create SchemaPath from actualPath and names.
+ *
+ * @param actualPath
+ * current position in model
+ * @param namespace
+ * @param revision
+ * @param prefix
+ * @param names
+ * @return SchemaPath object.
+ */
+ public static SchemaPath createActualSchemaPath(final List<String> actualPath, final URI namespace,
+ final Date revision, final String prefix, final String... names) {
+ final List<QName> path = new ArrayList<QName>();
+ QName qname;
+ // start from index 1 - module name omited
+ for (int i = 1; i < actualPath.size(); i++) {
+ qname = new QName(namespace, revision, prefix, actualPath.get(i));
+ path.add(qname);
+ }
+ for (String name : names) {
+ qname = new QName(namespace, revision, prefix, name);
+ path.add(qname);
+ }
+ return new SchemaPath(path, true);
+ }
+
+ /**
+ * Create SchemaPath from given string.
+ *
+ * @param augmentPath
+ * string representation of path
+ * @return SchemaPath object
+ */
+ public static SchemaPath parseAugmentPath(final String augmentPath) {
+ final boolean absolute = augmentPath.startsWith("/");
+ final String[] splittedPath = augmentPath.split("/");
+ List<QName> path = new ArrayList<QName>();
+ QName name;
+ for (String pathElement : splittedPath) {
+ if (pathElement.length() > 0) {
+ String[] splittedElement = pathElement.split(":");
+ if (splittedElement.length == 1) {
+ name = new QName(null, null, null, splittedElement[0]);
+ } else {
+ name = new QName(null, null, splittedElement[0], splittedElement[1]);
+ }
+ path.add(name);
+ }
+ }
+ return new SchemaPath(path, absolute);
+ }
+
+ /**
+ * Create java.util.List of QName objects from given key definition as
+ * string.
+ *
+ * @param keyDefinition
+ * key definition as string
+ * @param namespace
+ * current namespace
+ * @param revision
+ * current revision
+ * @param prefix
+ * current prefix
+ * @return YANG list key as java.util.List of QName objects
+ */
+ public static List<QName> createListKey(final String keyDefinition, final URI namespace, final Date revision,
+ final String prefix) {
+ List<QName> key = new ArrayList<QName>();
+ String[] splittedKey = keyDefinition.split(" ");
+
+ QName qname = null;
+ for (String keyElement : splittedKey) {
+ if (keyElement.length() != 0) {
+ qname = new QName(namespace, revision, prefix, keyElement);
+ key.add(qname);
+ }
+ }
+ return key;
+ }
+
+ /**
+ * Parse given type body of enumeration statement.
+ *
+ * @param ctx
+ * type body context to parse
+ * @param path
+ * actual position in YANG model
+ * @param moduleName current module name
+ * @param namespace
+ * @param revision
+ * @param prefix
+ * @return List of EnumPair object parsed from given context
+ */
+ private static List<EnumTypeDefinition.EnumPair> getEnumConstants(final Type_body_stmtsContext ctx,
+ final List<String> path, final String moduleName, final URI namespace, final Date revision, final String prefix) {
+ List<EnumTypeDefinition.EnumPair> enumConstants = new ArrayList<EnumTypeDefinition.EnumPair>();
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree enumSpecChild = ctx.getChild(i);
+ if (enumSpecChild instanceof Enum_specificationContext) {
+ int highestValue = -1;
+ for (int j = 0; j < enumSpecChild.getChildCount(); j++) {
+ ParseTree enumChild = enumSpecChild.getChild(j);
+ if (enumChild instanceof Enum_stmtContext) {
+ EnumPair enumPair = createEnumPair((Enum_stmtContext) enumChild, highestValue, path, moduleName, namespace,
+ revision, prefix);
+ if (enumPair.getValue() > highestValue) {
+ highestValue = enumPair.getValue();
+ }
+ enumConstants.add(enumPair);
+ }
+ }
+ }
+ }
+ return enumConstants;
+ }
+
+ /**
+ * Parse enum statement context
+ *
+ * @param ctx
+ * enum statement context
+ * @param highestValue
+ * current highest value in enumeration
+ * @param path
+ * actual position in YANG model
+ * @param moduleName
+ * current module name
+ * @param namespace
+ * @param revision
+ * @param prefix
+ * @return EnumPair object parsed from given context
+ */
+ private static EnumTypeDefinition.EnumPair createEnumPair(final Enum_stmtContext ctx, final int highestValue,
+ final List<String> path, final String moduleName, final URI namespace, final Date revision,
+ final String prefix) {
+ final String name = stringFromNode(ctx);
+ final QName qname = new QName(namespace, revision, prefix, name);
+ Integer value = null;
+
+ String description = null;
+ String reference = null;
+ Status status = null;
+
+ List<String> enumPairPath = new ArrayList<String>(path);
+ enumPairPath.add(name);
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Value_stmtContext) {
+ String valueStr = stringFromNode(child);
+ value = Integer.valueOf(valueStr);
+ } else if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ } else if (child instanceof Status_stmtContext) {
+ status = parseStatus((Status_stmtContext) child);
+ }
+ }
+
+ if (value == null) {
+ value = highestValue + 1;
+ }
+ if (value < -2147483648 || value > 2147483647) {
+ throw new YangParseException(moduleName, ctx.getStart().getLine(), "Error on enum '" + name
+ + "': the enum value MUST be in the range from -2147483648 to 2147483647, but was: " + value);
+ }
+
+ EnumPairImpl result = new EnumPairImpl();
+ result.qname = qname;
+ result.path = createActualSchemaPath(enumPairPath, namespace, revision, prefix);
+ result.description = description;
+ result.reference = reference;
+ result.status = status;
+ result.name = name;
+ result.value = value;
+ return result;
+ }
+
+ /**
+ * Internal implementation of EnumPair.
+ */
+ private static class EnumPairImpl implements EnumTypeDefinition.EnumPair {
+ private QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+ private String name;
+ private Integer value;
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return unknownNodes;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Integer getValue() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ result = prime * result + ((unknownNodes == null) ? 0 : unknownNodes.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ EnumPairImpl other = (EnumPairImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ if (unknownNodes == null) {
+ if (other.unknownNodes != null) {
+ return false;
+ }
+ } else if (!unknownNodes.equals(other.unknownNodes)) {
+ return false;
+ }
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ if (value == null) {
+ if (other.value != null) {
+ return false;
+ }
+ } else if (!value.equals(other.value)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return EnumTypeDefinition.EnumPair.class.getSimpleName() + "[name=" + name + ", value=" + value + "]";
+ }
+ }
+
+ /**
+ * Get and parse range from given type body context.
+ *
+ * @param ctx
+ * type body context to parse
+ * @return List of RangeConstraint created from this context
+ */
+ private static List<RangeConstraint> getRangeConstraints(final Type_body_stmtsContext ctx, final String moduleName) {
+ List<RangeConstraint> rangeConstraints = Collections.emptyList();
+ outer: for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree numRestrChild = ctx.getChild(i);
+ if (numRestrChild instanceof Numerical_restrictionsContext) {
+ for (int j = 0; j < numRestrChild.getChildCount(); j++) {
+ ParseTree rangeChild = numRestrChild.getChild(j);
+ if (rangeChild instanceof Range_stmtContext) {
+ rangeConstraints = parseRangeConstraints((Range_stmtContext) rangeChild, moduleName);
+ break outer;
+ }
+ }
+ }
+ }
+ return rangeConstraints;
+ }
+
+ /**
+ * Parse given range context.
+ *
+ * @param ctx
+ * range context to parse
+ * @return List of RangeConstraints parsed from this context
+ */
+ private static List<RangeConstraint> parseRangeConstraints(final Range_stmtContext ctx, final String moduleName) {
+ final int line = ctx.getStart().getLine();
+ List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
+ String description = null;
+ String reference = null;
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ }
+ }
+
+ String rangeStr = stringFromNode(ctx);
+ String trimmed = rangeStr.replace(" ", "");
+ String[] splittedRange = trimmed.split("\\|");
+ for (String rangeDef : splittedRange) {
+ String[] splittedRangeDef = rangeDef.split("\\.\\.");
+ Number min;
+ Number max;
+ if (splittedRangeDef.length == 1) {
+ min = max = parseNumberConstraintValue(splittedRangeDef[0], moduleName, line);
+ } else {
+ min = parseNumberConstraintValue(splittedRangeDef[0], moduleName, line);
+ max = parseNumberConstraintValue(splittedRangeDef[1], moduleName, line);
+ }
+ RangeConstraint range = BaseConstraints.rangeConstraint(min, max, description, reference);
+ rangeConstraints.add(range);
+ }
+
+ return rangeConstraints;
+ }
+
+ /**
+ * Get and parse length from given type body context.
+ *
+ * @param ctx
+ * type body context to parse
+ * @return List of LengthConstraint created from this context
+ */
+ private static List<LengthConstraint> getLengthConstraints(final Type_body_stmtsContext ctx, final String moduleName) {
+ List<LengthConstraint> lengthConstraints = Collections.emptyList();
+ outer: for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree stringRestrChild = ctx.getChild(i);
+ if (stringRestrChild instanceof String_restrictionsContext) {
+ for (int j = 0; j < stringRestrChild.getChildCount(); j++) {
+ ParseTree lengthChild = stringRestrChild.getChild(j);
+ if (lengthChild instanceof Length_stmtContext) {
+ lengthConstraints = parseLengthConstraints((Length_stmtContext) lengthChild, moduleName);
+ break outer;
+ }
+ }
+ }
+ }
+ return lengthConstraints;
+ }
+
+ /**
+ * Parse given length context.
+ *
+ * @param ctx
+ * length context to parse
+ * @return List of LengthConstraints parsed from this context
+ */
+ private static List<LengthConstraint> parseLengthConstraints(final Length_stmtContext ctx, final String moduleName) {
+ final int line = ctx.getStart().getLine();
+ List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
+ String description = null;
+ String reference = null;
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ }
+ }
+
+ String lengthStr = stringFromNode(ctx);
+ String trimmed = lengthStr.replace(" ", "");
+ String[] splittedRange = trimmed.split("\\|");
+ for (String rangeDef : splittedRange) {
+ String[] splittedRangeDef = rangeDef.split("\\.\\.");
+ Number min;
+ Number max;
+ if (splittedRangeDef.length == 1) {
+ min = max = parseNumberConstraintValue(splittedRangeDef[0], moduleName, line);
+ } else {
+ min = parseNumberConstraintValue(splittedRangeDef[0], moduleName, line);
+ max = parseNumberConstraintValue(splittedRangeDef[1], moduleName, line);
+ }
+ LengthConstraint range = BaseConstraints.lengthConstraint(min, max, description, reference);
+ lengthConstraints.add(range);
+ }
+
+ return lengthConstraints;
+ }
+
+ /**
+ * @param value
+ * value to parse
+ * @return wrapper object of primitive java type or UnknownBoundaryNumber if
+ * type is one of special YANG values 'min' or 'max'
+ */
+ private static Number parseNumberConstraintValue(final String value, final String moduleName, final int line) {
+ Number result = null;
+ if ("min".equals(value) || "max".equals(value)) {
+ result = new UnknownBoundaryNumber(value);
+ } else {
+ try {
+ result = Long.valueOf(value);
+ } catch (NumberFormatException e) {
+ throw new YangParseException(moduleName, line, "Unable to parse range value '" + value + "'.", e);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse type body and return pattern constraints.
+ *
+ * @param ctx
+ * type body
+ * @return list of pattern constraints
+ */
+ private static List<PatternConstraint> getPatternConstraint(final Type_body_stmtsContext ctx) {
+ List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree stringRestrChild = ctx.getChild(i);
+ if (stringRestrChild instanceof String_restrictionsContext) {
+ for (int j = 0; j < stringRestrChild.getChildCount(); j++) {
+ ParseTree lengthChild = stringRestrChild.getChild(j);
+ if (lengthChild instanceof Pattern_stmtContext) {
+ patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild));
+ }
+ }
+ }
+ }
+ return patterns;
+ }
+
+ /**
+ * Internal helper method.
+ *
+ * @param ctx
+ * pattern context
+ * @return PatternConstraint object
+ */
+ private static PatternConstraint parsePatternConstraint(final Pattern_stmtContext ctx) {
+ String description = null;
+ String reference = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ }
+ }
+ String pattern = patternStringFromNode(ctx);
+ return BaseConstraints.patternConstraint(pattern, description, reference);
+ }
+
+ /**
+ * Parse given context and return pattern value.
+ *
+ * @param ctx
+ * context to parse
+ * @return pattern value as String
+ */
+ public static String patternStringFromNode(final Pattern_stmtContext ctx) {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof StringContext) {
+ for (int j = 0; j < child.getChildCount(); j++) {
+ if (j % 2 == 0) {
+ String patternToken = child.getChild(j).getText();
+ result.append(patternToken.substring(1, patternToken.length() - 1));
+ }
+ }
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Get fraction digits value from type body.
+ *
+ * @param ctx
+ * type body context to parse
+ * @param moduleName
+ * name of current module
+ * @return 'fraction-digits' value if present in given context, null
+ * otherwise
+ */
+ private static Integer getFractionDigits(Type_body_stmtsContext ctx, String moduleName) {
+ Integer result = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree dec64specChild = ctx.getChild(i);
+ if (dec64specChild instanceof Decimal64_specificationContext) {
+ result = parseFractionDigits((Decimal64_specificationContext) dec64specChild, moduleName);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse decimal64 fraction-digits value.
+ *
+ * @param ctx
+ * decimal64 context
+ * @param moduleName
+ * name of current module
+ * @return fraction-digits value as Integer
+ */
+ private static Integer parseFractionDigits(Decimal64_specificationContext ctx, String moduleName) {
+ Integer result = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree fdChild = ctx.getChild(i);
+ if (fdChild instanceof Fraction_digits_stmtContext) {
+ String value = stringFromNode(fdChild);
+ try {
+ result = Integer.valueOf(value);
+ } catch (NumberFormatException e) {
+ throw new YangParseException(moduleName, ctx.getStart().getLine(),
+ "Unable to parse fraction digits value '" + value + "'.", e);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Internal helper method for parsing bit statements from given type body
+ * context.
+ *
+ * @param ctx
+ * type body context to parse
+ * @param actualPath
+ * current position in YANG model
+ * @param moduleName current module name
+ * @param namespace
+ * @param revision
+ * @param prefix
+ * @return List of Bit objects created from this context
+ */
+ private static List<BitsTypeDefinition.Bit> getBits(Type_body_stmtsContext ctx, List<String> actualPath,
+ String moduleName, URI namespace, Date revision, String prefix) {
+ final List<BitsTypeDefinition.Bit> bits = new ArrayList<BitsTypeDefinition.Bit>();
+ for (int j = 0; j < ctx.getChildCount(); j++) {
+ ParseTree bitsSpecChild = ctx.getChild(j);
+ if (bitsSpecChild instanceof Bits_specificationContext) {
+ long highestPosition = -1;
+ for (int k = 0; k < bitsSpecChild.getChildCount(); k++) {
+ ParseTree bitChild = bitsSpecChild.getChild(k);
+ if (bitChild instanceof Bit_stmtContext) {
+ Bit bit = parseBit((Bit_stmtContext) bitChild, highestPosition, actualPath, moduleName, namespace,
+ revision, prefix);
+ if (bit.getPosition() > highestPosition) {
+ highestPosition = bit.getPosition();
+ }
+ bits.add(bit);
+ }
+ }
+ }
+ }
+ return bits;
+ }
+
+ /**
+ * Internal helper method for parsing bit context.
+ *
+ * @param ctx
+ * bit statement context to parse
+ * @param highestPosition
+ * current highest position in bits type
+ * @param actualPath
+ * current position in YANG model
+ * @param moduleName current module name
+ * @param namespace
+ * @param revision
+ * @param prefix
+ * @return Bit object parsed from this context
+ */
+ private static BitsTypeDefinition.Bit parseBit(final Bit_stmtContext ctx, long highestPosition,
+ List<String> actualPath, final String moduleName, final URI namespace, final Date revision, final String prefix) {
+ String name = stringFromNode(ctx);
+ final QName qname = new QName(namespace, revision, prefix, name);
+ Long position = null;
+
+ String description = null;
+ String reference = null;
+ Status status = Status.CURRENT;
+
+ Stack<String> bitPath = new Stack<String>();
+ bitPath.addAll(actualPath);
+ bitPath.add(name);
+
+ SchemaPath schemaPath = createActualSchemaPath(bitPath, namespace, revision, prefix);
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Position_stmtContext) {
+ String positionStr = stringFromNode(child);
+ position = Long.valueOf(positionStr);
+ } else if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ } else if (child instanceof Status_stmtContext) {
+ status = parseStatus((Status_stmtContext) child);
+ }
+ }
+
+ if (position == null) {
+ position = highestPosition + 1;
+ }
+ if (position < 0 || position > 4294967295L) {
+ throw new YangParseException(moduleName, ctx.getStart().getLine(), "Error on bit '" + name
+ + "': the position value MUST be in the range 0 to 4294967295");
+ }
+
+ final List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+ return new BitImpl(position, qname, schemaPath, description, reference, status, unknownNodes);
+ }
+
+ /**
+ * Parse 'ordered-by' statement.
+ *
+ * The 'ordered-by' statement defines whether the order of entries within a
+ * list are determined by the user or the system. The argument is one of the
+ * strings "system" or "user". If not present, order defaults to "system".
+ *
+ * @param ctx
+ * Ordered_by_stmtContext
+ * @return true, if ordered-by contains value 'user', false otherwise
+ */
+ public static boolean parseUserOrdered(Ordered_by_stmtContext ctx) {
+ boolean result = false;
+ for (int j = 0; j < ctx.getChildCount(); j++) {
+ ParseTree orderArg = ctx.getChild(j);
+ if (orderArg instanceof Ordered_by_argContext) {
+ String orderStr = stringFromNode(orderArg);
+ if ("system".equals(orderStr)) {
+ result = false;
+ } else if ("user".equals(orderStr)) {
+ result = true;
+ } else {
+ LOG.warn("Invalid 'ordered-by' statement.");
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Get config statement from given context. If there is no config statement,
+ * return config value of parent
+ *
+ * @param ctx
+ * context to parse
+ * @param parent
+ * parent node
+ * @param moduleName
+ * name of current module
+ * @param line
+ * line in current module
+ * @return config statement parsed from given context
+ */
+ public static Boolean getConfig(final ParseTree ctx, final Builder parent, final String moduleName, final int line) {
+ Boolean result = null;
+ // parse configuration statement
+ Boolean config = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Config_stmtContext) {
+ config = parseConfig((Config_stmtContext) child, moduleName);
+ break;
+ }
+ }
+
+ // If 'config' is not specified, the default is the same as the parent
+ // schema node's 'config' value
+ if (config == null) {
+ if (parent instanceof DataSchemaNodeBuilder) {
+ Boolean parentConfig = ((DataSchemaNodeBuilder) parent).isConfiguration();
+ // If the parent node is a rpc input or output, it can has
+ // config set to null
+ result = parentConfig == null ? true : parentConfig;
+ } else if (parent instanceof ChoiceCaseBuilder) {
+ // If the parent node is a 'case' node, the value is the same as
+ // the 'case' node's parent 'choice' node
+ ChoiceCaseBuilder choiceCase = (ChoiceCaseBuilder) parent;
+ Builder choice = choiceCase.getParent();
+ Boolean parentConfig = null;
+ if (choice instanceof ChoiceBuilder) {
+ parentConfig = ((ChoiceBuilder) choice).isConfiguration();
+ } else {
+ parentConfig = true;
+ }
+ result = parentConfig;
+ } else {
+ result = true;
+ }
+ } else {
+ // Check first: if a node has 'config' set to 'false', no node
+ // underneath it can have 'config' set to 'true'
+ if (parent instanceof DataSchemaNodeBuilder && !(parent instanceof ChoiceCaseBuilder)) {
+ Boolean parentConfig = ((DataSchemaNodeBuilder) parent).isConfiguration();
+ if (!parentConfig && config) {
+ throw new YangParseException(moduleName, line,
+ "Can not set 'config' to 'true' if parent node has 'config' set to 'false'");
+ }
+ }
+ result = config;
+ }
+
+ return result;
+ }
+
+ /**
+ * Parse config statement.
+ *
+ * @param ctx
+ * config context to parse
+ * @param moduleName current module name
+ * @return true if given context contains string 'true', false otherwise
+ */
+ private static Boolean parseConfig(final Config_stmtContext ctx, final String moduleName) {
+ Boolean result = null;
+ if (ctx != null) {
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ final ParseTree configContext = ctx.getChild(i);
+ if (configContext instanceof Config_argContext) {
+ final String value = stringFromNode(configContext);
+ if ("true".equals(value)) {
+ result = true;
+ break;
+ } else if ("false".equals(value)) {
+ result = false;
+ break;
+ } else {
+ throw new YangParseException(moduleName, ctx.getStart().getLine(),
+ "Failed to parse 'config' statement value: '" + value + "'.");
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse type body and create UnknownType definition.
+ *
+ * @param typedefQName
+ * qname of current type
+ * @param ctx
+ * type body
+ * @param actualPath
+ * @param namespace
+ * @param revision
+ * @param prefix
+ * @param parent
+ * @return UnknownType object with constraints from parsed type body
+ */
+ public static TypeDefinition<?> parseUnknownTypeWithBody(final QName typedefQName,
+ final Type_body_stmtsContext ctx, final List<String> actualPath, final URI namespace, final Date revision,
+ final String prefix, final Builder parent) {
+ String moduleName = parent.getModuleName();
+ String typeName = typedefQName.getLocalName();
+
+ UnknownType.Builder unknownType = new UnknownType.Builder(typedefQName);
+
+ if (ctx != null) {
+ List<RangeConstraint> rangeStatements = getRangeConstraints(ctx, moduleName);
+ List<LengthConstraint> lengthStatements = getLengthConstraints(ctx, moduleName);
+ List<PatternConstraint> patternStatements = getPatternConstraint(ctx);
+ Integer fractionDigits = getFractionDigits(ctx, moduleName);
+
+ if (parent instanceof TypeDefinitionBuilder) {
+ TypeDefinitionBuilder typedef = (TypeDefinitionBuilder) parent;
+ typedef.setRanges(rangeStatements);
+ typedef.setLengths(lengthStatements);
+ typedef.setPatterns(patternStatements);
+ typedef.setFractionDigits(fractionDigits);
+ return unknownType.build();
+ } else {
+ TypeDefinition<?> baseType = unknownType.build();
+ TypeDefinition<?> result = null;
+ QName qname = new QName(namespace, revision, prefix, typeName);
+ SchemaPath schemaPath = createTypeSchemaPath(actualPath, namespace, revision, prefix, typeName, false,
+ false);
+
+ ExtendedType.Builder typeBuilder = new ExtendedType.Builder(qname, baseType, null, null, schemaPath);
+ typeBuilder.ranges(rangeStatements);
+ typeBuilder.lengths(lengthStatements);
+ typeBuilder.patterns(patternStatements);
+ typeBuilder.fractionDigits(fractionDigits);
+ result = typeBuilder.build();
+
+ return result;
+ }
+ }
+
+ return unknownType.build();
+ }
+
+ /**
+ * Create TypeDefinition object based on given type name and type body.
+ *
+ * @param typeName
+ * name of type
+ * @param typeBody
+ * type body context
+ * @param actualPath
+ * current path in schema
+ * @param namespace
+ * current namespace
+ * @param revision
+ * current revision
+ * @param prefix
+ * current prefix
+ * @param parent
+ * parent builder
+ * @return TypeDefinition object based on parsed values.
+ */
+ public static TypeDefinition<?> parseTypeWithBody(final String typeName,
+ final Type_body_stmtsContext typeBody, final List<String> actualPath, final URI namespace,
+ final Date revision, final String prefix, final Builder parent) {
+ final String moduleName = parent.getModuleName();
+ final int line = typeBody.getStart().getLine();
+ TypeDefinition<?> baseType = null;
+
+ Integer fractionDigits = getFractionDigits(typeBody, moduleName);
+ List<LengthConstraint> lengthStatements = getLengthConstraints(typeBody, moduleName);
+ List<PatternConstraint> patternStatements = getPatternConstraint(typeBody);
+ List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody, moduleName);
+
+ TypeConstraints constraints = new TypeConstraints(moduleName, line);
+ constraints.addFractionDigits(fractionDigits);
+ constraints.addLengths(lengthStatements);
+ constraints.addPatterns(patternStatements);
+ constraints.addRanges(rangeStatements);
+
+ SchemaPath baseTypePathFinal = createTypeSchemaPath(actualPath, namespace, revision, prefix, typeName, true,
+ true);
+ SchemaPath baseTypePath = createTypeSchemaPath(actualPath, namespace, revision, prefix, typeName, true, false);
+
+ if ("decimal64".equals(typeName)) {
+ if (rangeStatements.isEmpty()) {
+ return new Decimal64(baseTypePathFinal, fractionDigits);
+ }
+ Decimal64 decimalType = new Decimal64(baseTypePath, fractionDigits);
+ constraints.addRanges(decimalType.getRangeStatements());
+ baseType = decimalType;
+ } else if (typeName.startsWith("int")) {
+ IntegerTypeDefinition intType = null;
+ if ("int8".equals(typeName)) {
+ intType = new Int8(baseTypePath);
+ } else if ("int16".equals(typeName)) {
+ intType = new Int16(baseTypePath);
+ } else if ("int32".equals(typeName)) {
+ intType = new Int32(baseTypePath);
+ } else if ("int64".equals(typeName)) {
+ intType = new Int64(baseTypePath);
+ }
+ if (intType == null) {
+ throw new YangParseException(moduleName, line, "Unknown yang type " + typeName);
+ }
+ constraints.addRanges(intType.getRangeStatements());
+ baseType = intType;
+ } else if (typeName.startsWith("uint")) {
+ UnsignedIntegerTypeDefinition uintType = null;
+ if ("uint8".equals(typeName)) {
+ uintType = new Uint8(baseTypePath);
+ } else if ("uint16".equals(typeName)) {
+ uintType = new Uint16(baseTypePath);
+ } else if ("uint32".equals(typeName)) {
+ uintType = new Uint32(baseTypePath);
+ } else if ("uint64".equals(typeName)) {
+ uintType = new Uint64(baseTypePath);
+ }
+ if (uintType == null) {
+ throw new YangParseException(moduleName, line, "Unknown yang type " + typeName);
+ }
+ constraints.addRanges(uintType.getRangeStatements());
+ baseType = uintType;
+ } else if ("enumeration".equals(typeName)) {
+ List<EnumTypeDefinition.EnumPair> enumConstants = getEnumConstants(typeBody, actualPath, moduleName, namespace,
+ revision, prefix);
+ return new EnumerationType(baseTypePathFinal, enumConstants);
+ } else if ("string".equals(typeName)) {
+ StringTypeDefinition stringType = new StringType(baseTypePath);
+ constraints.addLengths(stringType.getLengthStatements());
+ baseType = stringType;
+ } else if ("bits".equals(typeName)) {
+ return new BitsType(baseTypePathFinal, getBits(typeBody, actualPath, moduleName, namespace, revision, prefix));
+ } else if ("leafref".equals(typeName)) {
+ final String path = parseLeafrefPath(typeBody);
+ final boolean absolute = path.startsWith("/");
+ RevisionAwareXPath xpath = new RevisionAwareXPathImpl(path, absolute);
+ return new Leafref(baseTypePathFinal, xpath);
+ } else if ("binary".equals(typeName)) {
+ BinaryTypeDefinition binaryType = new BinaryType(baseTypePath);
+ constraints.addLengths(binaryType.getLengthConstraints());
+ baseType = binaryType;
+ } else if ("instance-identifier".equals(typeName)) {
+ boolean requireInstance = isRequireInstance(typeBody);
+ return new InstanceIdentifier(baseTypePath, null, requireInstance);
+ }
+
+ if (parent instanceof TypeDefinitionBuilder && !(parent instanceof UnionTypeBuilder)) {
+ TypeDefinitionBuilder typedef = (TypeDefinitionBuilder) parent;
+ typedef.setRanges(constraints.getRange());
+ typedef.setLengths(constraints.getLength());
+ typedef.setPatterns(constraints.getPatterns());
+ typedef.setFractionDigits(constraints.getFractionDigits());
+ return baseType;
+ }
+
+ TypeDefinition<?> result = null;
+ QName qname = new QName(namespace, revision, prefix, typeName);
+ ExtendedType.Builder typeBuilder = null;
+
+ SchemaPath schemaPath = createTypeSchemaPath(actualPath, namespace, revision, prefix, typeName, false, false);
+ typeBuilder = new ExtendedType.Builder(qname, baseType, "", "", schemaPath);
+
+ typeBuilder.ranges(constraints.getRange());
+ typeBuilder.lengths(constraints.getLength());
+ typeBuilder.patterns(constraints.getPatterns());
+ typeBuilder.fractionDigits(constraints.getFractionDigits());
+
+ result = typeBuilder.build();
+ return result;
+ }
+
+ /**
+ * Create SchemaPath object from given path list with namespace, revision
+ * and prefix based on given values.
+ *
+ * @param actualPath
+ * current position in model
+ * @param namespace
+ * @param revision
+ * @param prefix
+ * @param typeName
+ * @param isBaseYangType
+ * if this is base yang type
+ * @param isBaseYangTypeFinal
+ * if this is base yang type without restrictions
+ * @return SchemaPath object.
+ */
+ private static SchemaPath createTypeSchemaPath(final List<String> actualPath, final URI namespace,
+ final Date revision, final String prefix, final String typeName, final boolean isBaseYangType,
+ final boolean isBaseYangTypeFinal) {
+ List<String> typePath = new ArrayList<String>(actualPath);
+ if (isBaseYangType && !isBaseYangTypeFinal) {
+ typePath.add(typeName);
+ }
+
+ final List<QName> path = new ArrayList<QName>();
+ QName qname;
+ // start from index 1 -> module name omited
+ for (int i = 1; i < typePath.size(); i++) {
+ qname = new QName(namespace, revision, prefix, typePath.get(i));
+ path.add(qname);
+ }
+ QName typeQName;
+ if (isBaseYangType) {
+ typeQName = new QName(BaseTypes.BaseTypesNamespace, typeName);
+ } else {
+ typeQName = new QName(namespace, revision, prefix, typeName);
+ }
+ path.add(typeQName);
+ return new SchemaPath(path, true);
+ }
+
+ /**
+ * Parse given context and find identityref base value.
+ *
+ * @param ctx
+ * type body
+ * @return identityref base value as String
+ */
+ public static String getIdentityrefBase(Type_body_stmtsContext ctx) {
+ String result = null;
+ outer: for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Identityref_specificationContext) {
+ for (int j = 0; j < child.getChildCount(); j++) {
+ ParseTree baseArg = child.getChild(j);
+ if (baseArg instanceof Base_stmtContext) {
+ result = stringFromNode(baseArg);
+ break outer;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse type body statement and find require-instance value.
+ *
+ * @param ctx
+ * type body context
+ * @return require-instance value
+ */
+ private static boolean isRequireInstance(Type_body_stmtsContext ctx) {
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Instance_identifier_specificationContext) {
+ for (int j = 0; j < child.getChildCount(); j++) {
+ ParseTree reqStmt = child.getChild(j);
+ if (reqStmt instanceof Require_instance_stmtContext) {
+ for (int k = 0; k < reqStmt.getChildCount(); k++) {
+ ParseTree reqArg = reqStmt.getChild(k);
+ if (reqArg instanceof Require_instance_argContext) {
+ return Boolean.valueOf(stringFromNode(reqArg));
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Parse type body statement and find leafref path.
+ *
+ * @param ctx
+ * type body context
+ * @return leafref path as String
+ */
+ private static String parseLeafrefPath(Type_body_stmtsContext ctx) {
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Leafref_specificationContext) {
+ for (int j = 0; j < child.getChildCount(); j++) {
+ ParseTree leafRefSpec = child.getChild(j);
+ if (leafRefSpec instanceof Path_stmtContext) {
+ return stringFromNode(leafRefSpec);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Internal helper method for parsing must statement.
+ *
+ * @param ctx
+ * Must_stmtContext
+ * @return MustDefinition object based on parsed context
+ */
+ public static MustDefinition parseMust(final YangParser.Must_stmtContext ctx) {
+ StringBuilder mustText = new StringBuilder();
+ String description = null;
+ String reference = null;
+ String errorAppTag = null;
+ String errorMessage = null;
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof StringContext) {
+ final StringContext context = (StringContext) child;
+ if (context.getChildCount() == 1) {
+ String mustPart = context.getChild(0).getText();
+ // trim start and end quotation
+ mustText.append(mustPart.substring(1, mustPart.length() - 1));
+ } else {
+ for (int j = 0; j < context.getChildCount(); j++) {
+ String mustPart = context.getChild(j).getText();
+ if (j == 0) {
+ mustText.append(mustPart.substring(0, mustPart.length() - 1));
+ continue;
+ }
+ if (j % 2 == 0) {
+ mustText.append(mustPart.substring(1));
+ }
+ }
+ }
+ } else if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ } else if (child instanceof Error_app_tag_stmtContext) {
+ errorAppTag = stringFromNode(child);
+ } else if (child instanceof Error_message_stmtContext) {
+ errorMessage = stringFromNode(child);
+ }
+ }
+
+ MustDefinition must = new MustDefinitionImpl(mustText.toString(), description, reference, errorAppTag,
+ errorMessage);
+ return must;
+ }
+
+ /**
+ * Parse given context and set constraints to constraints builder.
+ *
+ * @param ctx
+ * context to parse
+ * @param constraints
+ * ConstraintsBuilder to fill
+ */
+ public static void parseConstraints(final ParseTree ctx, final ConstraintsBuilder constraints) {
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ final ParseTree childNode = ctx.getChild(i);
+ if (childNode instanceof Max_elements_stmtContext) {
+ Integer max = parseMaxElements((Max_elements_stmtContext) childNode, constraints.getModuleName());
+ constraints.setMaxElements(max);
+ } else if (childNode instanceof Min_elements_stmtContext) {
+ Integer min = parseMinElements((Min_elements_stmtContext) childNode, constraints.getModuleName());
+ constraints.setMinElements(min);
+ } else if (childNode instanceof Must_stmtContext) {
+ MustDefinition must = parseMust((Must_stmtContext) childNode);
+ constraints.addMustDefinition(must);
+ } else if (childNode instanceof Mandatory_stmtContext) {
+ for (int j = 0; j < childNode.getChildCount(); j++) {
+ ParseTree mandatoryTree = ctx.getChild(j);
+ if (mandatoryTree instanceof Mandatory_argContext) {
+ Boolean mandatory = Boolean.valueOf(stringFromNode(mandatoryTree));
+ constraints.setMandatory(mandatory);
+ }
+ }
+ } else if (childNode instanceof When_stmtContext) {
+ constraints.addWhenCondition(stringFromNode(childNode));
+ }
+ }
+ }
+
+ private static Integer parseMinElements(Min_elements_stmtContext ctx, String moduleName) {
+ Integer result = null;
+ try {
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree minArg = ctx.getChild(i);
+ if (minArg instanceof Min_value_argContext) {
+ result = Integer.valueOf(stringFromNode(minArg));
+ }
+ }
+ if (result == null) {
+ throw new IllegalArgumentException();
+ }
+ return result;
+ } catch (Exception e) {
+ throw new YangParseException(moduleName, ctx.getStart().getLine(), "Failed to parse min-elements.", e);
+ }
+ }
+
+ private static Integer parseMaxElements(Max_elements_stmtContext ctx, String moduleName) {
+ Integer result = null;
+ try {
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree maxArg = ctx.getChild(i);
+ if (maxArg instanceof Max_value_argContext) {
+ result = Integer.valueOf(stringFromNode(maxArg));
+ }
+ }
+ if (result == null) {
+ throw new IllegalArgumentException();
+ }
+ return result;
+ } catch (Exception e) {
+ throw new YangParseException(moduleName, ctx.getStart().getLine(), "Failed to parse max-elements.", e);
+ }
+ }
+
+ /**
+ * Parse given context and return yin value.
+ *
+ * @param ctx
+ * context to parse
+ * @return true if value is 'true', false otherwise
+ */
+ public static boolean parseYinValue(Argument_stmtContext ctx) {
+ boolean yinValue = false;
+ outer: for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree yin = ctx.getChild(i);
+ if (yin instanceof Yin_element_stmtContext) {
+ for (int j = 0; j < yin.getChildCount(); j++) {
+ ParseTree yinArg = yin.getChild(j);
+ if (yinArg instanceof Yin_element_argContext) {
+ String yinString = stringFromNode(yinArg);
+ if ("true".equals(yinString)) {
+ yinValue = true;
+ break outer;
+ }
+ }
+ }
+ }
+ }
+ return yinValue;
+ }
+
+ /**
+ * Check this base type.
+ *
+ * @param typeName
+ * base YANG type name
+ * @param moduleName
+ * name of current module
+ * @param line
+ * line in module
+ * @throws YangParseException
+ * if this is one of YANG type which MUST contain additional
+ * informations in its body
+ */
+ public static void checkMissingBody(final String typeName, final String moduleName, final int line)
+ throws YangParseException {
+ if ("decimal64".equals(typeName)) {
+ throw new YangParseException(moduleName, line,
+ "The 'fraction-digits' statement MUST be present if the type is 'decimal64'.");
+ } else if ("identityref".equals(typeName)) {
+ throw new YangParseException(moduleName, line,
+ "The 'base' statement MUST be present if the type is 'identityref'.");
+ } else if ("leafref".equals(typeName)) {
+ throw new YangParseException(moduleName, line,
+ "The 'path' statement MUST be present if the type is 'leafref'.");
+ } else if ("bits".equals(typeName)) {
+ throw new YangParseException(moduleName, line, "The 'bit' statement MUST be present if the type is 'bits'.");
+ } else if ("enumeration".equals(typeName)) {
+ throw new YangParseException(moduleName, line,
+ "The 'enum' statement MUST be present if the type is 'enumeration'.");
+ }
+ }
+
+ /**
+ * Parse refine statement.
+ *
+ * @param refineCtx
+ * refine statement
+ * @return RefineHolder object representing this refine statement
+ */
+ public static RefineHolder parseRefine(Refine_stmtContext refineCtx, String moduleName) {
+ final String refineTarget = stringFromNode(refineCtx);
+ final RefineHolder refine = new RefineHolder(moduleName, refineCtx.getStart().getLine(), refineTarget);
+ for (int i = 0; i < refineCtx.getChildCount(); i++) {
+ ParseTree refinePom = refineCtx.getChild(i);
+ if (refinePom instanceof Refine_pomContext) {
+ for (int j = 0; j < refinePom.getChildCount(); j++) {
+ ParseTree refineStmt = refinePom.getChild(j);
+ parseRefineDefault(refine, refineStmt);
+
+ if (refineStmt instanceof Refine_leaf_stmtsContext) {
+ parseRefine(refine, (Refine_leaf_stmtsContext) refineStmt);
+ } else if (refineStmt instanceof Refine_container_stmtsContext) {
+ parseRefine(refine, (Refine_container_stmtsContext) refineStmt);
+ } else if (refineStmt instanceof Refine_list_stmtsContext) {
+ parseRefine(refine, (Refine_list_stmtsContext) refineStmt);
+ } else if (refineStmt instanceof Refine_leaf_list_stmtsContext) {
+ parseRefine(refine, (Refine_leaf_list_stmtsContext) refineStmt);
+ } else if (refineStmt instanceof Refine_choice_stmtsContext) {
+ parseRefine(refine, (Refine_choice_stmtsContext) refineStmt);
+ } else if (refineStmt instanceof Refine_anyxml_stmtsContext) {
+ parseRefine(refine, (Refine_anyxml_stmtsContext) refineStmt);
+ }
+ }
+ }
+ }
+ return refine;
+ }
+
+ private static void parseRefineDefault(RefineHolder refine, ParseTree refineStmt) {
+ for (int i = 0; i < refineStmt.getChildCount(); i++) {
+ ParseTree refineArg = refineStmt.getChild(i);
+ if (refineArg instanceof Description_stmtContext) {
+ String description = stringFromNode(refineArg);
+ refine.setDescription(description);
+ } else if (refineArg instanceof Reference_stmtContext) {
+ String reference = stringFromNode(refineArg);
+ refine.setReference(reference);
+ } else if (refineArg instanceof Config_stmtContext) {
+ Boolean config = parseConfig((Config_stmtContext) refineArg, refine.getModuleName());
+ refine.setConfiguration(config);
+ }
+ }
+ }
+
+ private static RefineHolder parseRefine(RefineHolder refine, Refine_leaf_stmtsContext refineStmt) {
+ for (int i = 0; i < refineStmt.getChildCount(); i++) {
+ ParseTree refineArg = refineStmt.getChild(i);
+ if (refineArg instanceof Default_stmtContext) {
+ String defaultStr = stringFromNode(refineArg);
+ refine.setDefaultStr(defaultStr);
+ } else if (refineArg instanceof Mandatory_stmtContext) {
+ for (int j = 0; j < refineArg.getChildCount(); j++) {
+ ParseTree mandatoryTree = refineArg.getChild(j);
+ if (mandatoryTree instanceof Mandatory_argContext) {
+ Boolean mandatory = Boolean.valueOf(stringFromNode(mandatoryTree));
+ refine.setMandatory(mandatory);
+ }
+ }
+ } else if (refineArg instanceof Must_stmtContext) {
+ MustDefinition must = parseMust((Must_stmtContext) refineArg);
+ refine.setMust(must);
+
+ }
+ }
+ return refine;
+ }
+
+ private static RefineHolder parseRefine(RefineHolder refine, Refine_container_stmtsContext refineStmt) {
+ for (int i = 0; i < refineStmt.getChildCount(); i++) {
+ ParseTree refineArg = refineStmt.getChild(i);
+ if (refineArg instanceof Must_stmtContext) {
+ MustDefinition must = parseMust((Must_stmtContext) refineArg);
+ refine.setMust(must);
+ } else if (refineArg instanceof Presence_stmtContext) {
+ refine.setPresence(true);
+ }
+ }
+ return refine;
+ }
+
+ private static RefineHolder parseRefine(RefineHolder refine, Refine_list_stmtsContext refineStmt) {
+ for (int i = 0; i < refineStmt.getChildCount(); i++) {
+ ParseTree refineArg = refineStmt.getChild(i);
+ if (refineArg instanceof Must_stmtContext) {
+ MustDefinition must = parseMust((Must_stmtContext) refineArg);
+ refine.setMust(must);
+ } else if (refineArg instanceof Max_elements_stmtContext) {
+ Integer max = parseMaxElements((Max_elements_stmtContext) refineArg, refine.getModuleName());
+ refine.setMaxElements(max);
+ } else if (refineArg instanceof Min_elements_stmtContext) {
+ Integer min = parseMinElements((Min_elements_stmtContext) refineArg, refine.getModuleName());
+ refine.setMinElements(min);
+ }
+ }
+ return refine;
+ }
+
+ private static RefineHolder parseRefine(RefineHolder refine, Refine_leaf_list_stmtsContext refineStmt) {
+ for (int i = 0; i < refineStmt.getChildCount(); i++) {
+ ParseTree refineArg = refineStmt.getChild(i);
+ if (refineArg instanceof Must_stmtContext) {
+ MustDefinition must = parseMust((Must_stmtContext) refineArg);
+ refine.setMust(must);
+ } else if (refineArg instanceof Max_elements_stmtContext) {
+ Integer max = parseMaxElements((Max_elements_stmtContext) refineArg, refine.getModuleName());
+ refine.setMaxElements(max);
+ } else if (refineArg instanceof Min_elements_stmtContext) {
+ Integer min = parseMinElements((Min_elements_stmtContext) refineArg, refine.getModuleName());
+ refine.setMinElements(min);
+ }
+ }
+ return refine;
+ }
+
+ private static RefineHolder parseRefine(RefineHolder refine, Refine_choice_stmtsContext refineStmt) {
+ for (int i = 0; i < refineStmt.getChildCount(); i++) {
+ ParseTree refineArg = refineStmt.getChild(i);
+ if (refineArg instanceof Default_stmtContext) {
+ String defaultStr = stringFromNode(refineArg);
+ refine.setDefaultStr(defaultStr);
+ } else if (refineArg instanceof Mandatory_stmtContext) {
+ for (int j = 0; j < refineArg.getChildCount(); j++) {
+ ParseTree mandatoryTree = refineArg.getChild(j);
+ if (mandatoryTree instanceof Mandatory_argContext) {
+ Boolean mandatory = Boolean.valueOf(stringFromNode(mandatoryTree));
+ refine.setMandatory(mandatory);
+ }
+ }
+ }
+ }
+ return refine;
+ }
+
+ private static RefineHolder parseRefine(RefineHolder refine, Refine_anyxml_stmtsContext refineStmt) {
+ for (int i = 0; i < refineStmt.getChildCount(); i++) {
+ ParseTree refineArg = refineStmt.getChild(i);
+ if (refineArg instanceof Must_stmtContext) {
+ MustDefinition must = parseMust((Must_stmtContext) refineArg);
+ refine.setMust(must);
+ } else if (refineArg instanceof Mandatory_stmtContext) {
+ for (int j = 0; j < refineArg.getChildCount(); j++) {
+ ParseTree mandatoryTree = refineArg.getChild(j);
+ if (mandatoryTree instanceof Mandatory_argContext) {
+ Boolean mandatory = Boolean.valueOf(stringFromNode(mandatoryTree));
+ refine.setMandatory(mandatory);
+ }
+ }
+ }
+ }
+ return refine;
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataNodeContainer;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.ModuleImport;
+import org.opendaylight.controller.yang.model.api.MustDefinition;
+import org.opendaylight.controller.yang.model.api.NotificationDefinition;
+import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.EmptyTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
+import org.opendaylight.controller.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.InstanceIdentifierTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
+import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefinition;
+import org.opendaylight.controller.yang.model.util.BinaryType;
+import org.opendaylight.controller.yang.model.util.BitsType;
+import org.opendaylight.controller.yang.model.util.BooleanType;
+import org.opendaylight.controller.yang.model.util.Decimal64;
+import org.opendaylight.controller.yang.model.util.EmptyType;
+import org.opendaylight.controller.yang.model.util.EnumerationType;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.model.util.IdentityrefType;
+import org.opendaylight.controller.yang.model.util.InstanceIdentifier;
+import org.opendaylight.controller.yang.model.util.Int16;
+import org.opendaylight.controller.yang.model.util.Int32;
+import org.opendaylight.controller.yang.model.util.Int64;
+import org.opendaylight.controller.yang.model.util.Int8;
+import org.opendaylight.controller.yang.model.util.Leafref;
+import org.opendaylight.controller.yang.model.util.StringType;
+import org.opendaylight.controller.yang.model.util.Uint16;
+import org.opendaylight.controller.yang.model.util.Uint32;
+import org.opendaylight.controller.yang.model.util.Uint64;
+import org.opendaylight.controller.yang.model.util.Uint8;
+import org.opendaylight.controller.yang.model.util.UnionType;
+import org.opendaylight.controller.yang.model.util.UnknownType;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.Builder;
+import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder.ChoiceNodeImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceCaseBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceCaseBuilder.ChoiceCaseNodeImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.ConstraintsBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder.ContainerSchemaNodeImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.GroupingBuilderImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.IdentityrefTypeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder.ListSchemaNodeImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.NotificationBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.NotificationBuilder.NotificationDefinitionImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.RpcDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
+
+public final class ParserUtils {
+
+ private ParserUtils() {
+ }
+
+ /**
+ * Create new SchemaPath from given path and name.
+ *
+ * Append new qname to schema path created from name argument. New QName
+ * gets namespace, revision and prefix same as last qname in current schema
+ * path.
+ *
+ * @param schemaPath
+ * @param name
+ * @return
+ */
+ public static SchemaPath createSchemaPath(SchemaPath schemaPath, String name, URI namespace, Date revision, String prefix) {
+ List<QName> path = new ArrayList<QName>();
+ if(schemaPath != null) {
+ path.addAll(schemaPath.getPath());
+ }
+ QName newQName = new QName(namespace, revision, prefix, name);
+ path.add(newQName);
+ boolean abs = schemaPath == null ? true : schemaPath.isAbsolute();
+ return new SchemaPath(path, abs);
+ }
+
+ /**
+ * Get module import referenced by given prefix.
+ *
+ * @param builder
+ * module to search
+ * @param prefix
+ * prefix associated with import
+ * @return ModuleImport based on given prefix
+ */
+ public static ModuleImport getModuleImport(final ModuleBuilder builder, final String prefix) {
+ ModuleImport moduleImport = null;
+ for (ModuleImport mi : builder.getModuleImports()) {
+ if (mi.getPrefix().equals(prefix)) {
+ moduleImport = mi;
+ break;
+ }
+ }
+ return moduleImport;
+ }
+
+ /**
+ * Find dependent module based on given prefix
+ *
+ * @param modules
+ * all available modules
+ * @param module
+ * current module
+ * @param prefix
+ * target module prefix
+ * @param line
+ * current line in yang model
+ * @return
+ */
+ public static ModuleBuilder findDependentModuleBuilder(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder module, final String prefix, final int line) {
+ ModuleBuilder dependentModule = null;
+ Date dependentModuleRevision = null;
+
+ if (prefix.equals(module.getPrefix())) {
+ dependentModule = module;
+ } else {
+ final ModuleImport dependentModuleImport = getModuleImport(module, prefix);
+ if (dependentModuleImport == null) {
+ throw new YangParseException(module.getName(), line, "No import found with prefix '" + prefix + "'.");
+ }
+ final String dependentModuleName = dependentModuleImport.getModuleName();
+ dependentModuleRevision = dependentModuleImport.getRevision();
+
+ final TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
+ if (moduleBuildersByRevision == null) {
+ return null;
+ }
+ if (dependentModuleRevision == null) {
+ dependentModule = moduleBuildersByRevision.lastEntry().getValue();
+ } else {
+ dependentModule = moduleBuildersByRevision.get(dependentModuleRevision);
+ }
+ }
+ return dependentModule;
+ }
+
+ /**
+ * Find module from context based on prefix.
+ *
+ * @param context
+ * schema context
+ * @param currentModule
+ * current module
+ * @param prefix
+ * current prefix used to reference dependent module
+ * @param line
+ * current line in yang model
+ * @return module based on given prefix if found in context, null otherwise
+ */
+ public static Module findModuleFromContext(final SchemaContext context, final ModuleBuilder currentModule,
+ final String prefix, final int line) {
+ TreeMap<Date, Module> modulesByRevision = new TreeMap<Date, Module>();
+
+ Date dependentModuleRevision = null;
+
+ final ModuleImport dependentModuleImport = ParserUtils.getModuleImport(currentModule, prefix);
+ if (dependentModuleImport == null) {
+ throw new YangParseException(currentModule.getName(), line, "No import found with prefix '" + prefix + "'.");
+ }
+ final String dependentModuleName = dependentModuleImport.getModuleName();
+ dependentModuleRevision = dependentModuleImport.getRevision();
+
+ for (Module contextModule : context.getModules()) {
+ if (contextModule.getName().equals(dependentModuleName)) {
+ Date revision = contextModule.getRevision();
+ if (revision == null) {
+ revision = new Date(0L);
+ }
+ modulesByRevision.put(revision, contextModule);
+ break;
+ }
+ }
+
+ Module result = null;
+ if (dependentModuleRevision == null) {
+ result = modulesByRevision.get(modulesByRevision.firstKey());
+ } else {
+ result = modulesByRevision.get(dependentModuleRevision);
+ }
+
+ return result;
+ }
+
+ /**
+ * Find grouping by name.
+ *
+ * @param groupings
+ * collection of grouping builders to search
+ * @param name
+ * name of grouping
+ * @return grouping with given name if present in collection, null otherwise
+ */
+ public static GroupingBuilder findGroupingBuilder(Set<GroupingBuilder> groupings, String name) {
+ for (GroupingBuilder grouping : groupings) {
+ if (grouping.getQName().getLocalName().equals(name)) {
+ return grouping;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find grouping by name.
+ *
+ * @param groupings
+ * collection of grouping definitions to search
+ * @param name
+ * name of grouping
+ * @return grouping with given name if present in collection, null otherwise
+ */
+ public static GroupingDefinition findGroupingDefinition(Set<GroupingDefinition> groupings, String name) {
+ for (GroupingDefinition grouping : groupings) {
+ if (grouping.getQName().getLocalName().equals(name)) {
+ return grouping;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Search types for type with given name.
+ *
+ * @param types
+ * types to search
+ * @param name
+ * name of type
+ * @return type with given name if present in collection, null otherwise
+ */
+ public static TypeDefinitionBuilder findTypedefBuilderByName(Set<TypeDefinitionBuilder> types, String name) {
+ for (TypeDefinitionBuilder td : types) {
+ if (td.getQName().getLocalName().equals(name)) {
+ return td;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find type by name.
+ *
+ * @param types
+ * collection of types
+ * @param typeName
+ * type name
+ * @return type with given name if it is present in collection, null
+ * otherwise
+ */
+ public static TypeDefinition<?> findTypeByName(Set<TypeDefinition<?>> types, String typeName) {
+ for (TypeDefinition<?> type : types) {
+ if (type.getQName().getLocalName().equals(typeName)) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Parse uses path.
+ *
+ * @param usesPath
+ * as String
+ * @return SchemaPath from given String
+ */
+ public static SchemaPath parseUsesPath(final String usesPath) {
+ final boolean absolute = usesPath.startsWith("/");
+ final String[] splittedPath = usesPath.split("/");
+ final List<QName> path = new ArrayList<QName>();
+ QName name;
+ for (String pathElement : splittedPath) {
+ if (pathElement.length() > 0) {
+ final String[] splittedElement = pathElement.split(":");
+ if (splittedElement.length == 1) {
+ name = new QName(null, null, null, splittedElement[0]);
+ } else {
+ name = new QName(null, null, splittedElement[0], splittedElement[1]);
+ }
+ path.add(name);
+ }
+ }
+ return new SchemaPath(path, absolute);
+ }
+
+ /**
+ * Check if node is present in refine nodes.
+ *
+ * @param nodeQName
+ * qname of node
+ * @param refineNodes
+ * collections of refined nodes
+ * @return true, if node with given qname was found, false otherwise
+ */
+ public static SchemaNodeBuilder getRefined(QName nodeQName, List<SchemaNodeBuilder> refineNodes) {
+ for (SchemaNodeBuilder rn : refineNodes) {
+ if (rn.getQName().equals(nodeQName)) {
+ return rn;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Pull restriction from type and add them to constraints.
+ *
+ * @param type
+ * @param constraints
+ */
+ public static void mergeConstraints(final TypeDefinition<?> type, final TypeConstraints constraints) {
+ if (type instanceof DecimalTypeDefinition) {
+ constraints.addRanges(((DecimalTypeDefinition) type).getRangeStatements());
+ constraints.addFractionDigits(((DecimalTypeDefinition) type).getFractionDigits());
+ } else if (type instanceof IntegerTypeDefinition) {
+ constraints.addRanges(((IntegerTypeDefinition) type).getRangeStatements());
+ } else if (type instanceof StringTypeDefinition) {
+ constraints.addPatterns(((StringTypeDefinition) type).getPatterns());
+ constraints.addLengths(((StringTypeDefinition) type).getLengthStatements());
+ } else if (type instanceof BinaryTypeDefinition) {
+ constraints.addLengths(((BinaryTypeDefinition) type).getLengthConstraints());
+ }
+ }
+
+ /**
+ * Find node in grouping by name.
+ *
+ * @param grouping
+ * grouping to search
+ * @param refineNodeName
+ * name of node
+ * @return builder of node with given name if present in grouping, null
+ * otherwise
+ */
+ public static Builder findRefineTargetBuilder(final GroupingBuilder grouping, final String refineNodeName) {
+ // search child nodes
+ Builder result = grouping.getDataChildByName(refineNodeName);
+ // search groupings
+ if (result == null) {
+ Set<GroupingBuilder> grps = grouping.getGroupingBuilders();
+ for (GroupingBuilder gr : grps) {
+ if (gr.getQName().getLocalName().equals(refineNodeName)) {
+ result = gr;
+ break;
+ }
+ }
+ }
+ // search typedefs
+ if (result == null) {
+ Set<TypeDefinitionBuilder> typedefs = grouping.getTypeDefinitionBuilders();
+ for (TypeDefinitionBuilder typedef : typedefs) {
+ if (typedef.getQName().getLocalName().equals(refineNodeName)) {
+ result = typedef;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Find node in grouping by name.
+ *
+ * @param builder
+ * grouping to search
+ * @param refineNodeName
+ * name of node
+ * @return node with given name if present in grouping, null otherwise
+ */
+ public static Object findRefineTargetNode(final GroupingDefinition builder, final String refineNodeName) {
+ Object result = builder.getDataChildByName(refineNodeName);
+ if (result == null) {
+ Set<GroupingDefinition> grps = builder.getGroupings();
+ for (GroupingDefinition gr : grps) {
+ if (gr.getQName().getLocalName().equals(refineNodeName)) {
+ result = gr;
+ break;
+ }
+ }
+ }
+ if (result == null) {
+ Set<TypeDefinition<?>> typedefs = builder.getTypeDefinitions();
+ for (TypeDefinition<?> typedef : typedefs) {
+ if (typedef.getQName().getLocalName().equals(refineNodeName)) {
+ result = typedef;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Add all augment's child nodes to given target.
+ *
+ * @param augment
+ * builder of augment statement
+ * @param target
+ * augmentation target node
+ */
+ public static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final DataNodeContainerBuilder target) {
+ boolean usesAugment = augment.getParent() instanceof UsesNodeBuilder;
+ for (DataSchemaNodeBuilder builder : augment.getChildNodeBuilders()) {
+ builder.setAugmenting(true);
+ if (usesAugment) {
+ if (builder instanceof GroupingMember) {
+ ((GroupingMember) builder).setAddedByUses(true);
+ }
+ }
+ correctAugmentChildPath(builder, target.getPath());
+ target.addChildNode(builder);
+ }
+ }
+
+ /**
+ * Add all augment's child nodes to given target.
+ *
+ * @param augment
+ * builder of augment statement
+ * @param target
+ * augmentation target choice node
+ */
+ public static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final ChoiceBuilder target) {
+ boolean usesAugment = augment.getParent() instanceof UsesNodeBuilder;
+ for (DataSchemaNodeBuilder builder : augment.getChildNodeBuilders()) {
+ builder.setAugmenting(true);
+ if (usesAugment) {
+ if (builder instanceof GroupingMember) {
+ ((GroupingMember) builder).setAddedByUses(true);
+ }
+ }
+ correctAugmentChildPath(builder, target.getPath());
+ target.addCase(builder);
+ }
+ }
+
+ private static void correctAugmentChildPath(final DataSchemaNodeBuilder childNode, final SchemaPath parentSchemaPath) {
+ // set correct path
+ List<QName> targetNodePath = new ArrayList<QName>(parentSchemaPath.getPath());
+ targetNodePath.add(childNode.getQName());
+ childNode.setPath(new SchemaPath(targetNodePath, true));
+
+ // set correct path for all child nodes
+ if (childNode instanceof DataNodeContainerBuilder) {
+ DataNodeContainerBuilder dataNodeContainer = (DataNodeContainerBuilder) childNode;
+ for (DataSchemaNodeBuilder child : dataNodeContainer.getChildNodeBuilders()) {
+ correctAugmentChildPath(child, childNode.getPath());
+ }
+ }
+
+ // set correct path for all cases
+ if (childNode instanceof ChoiceBuilder) {
+ ChoiceBuilder choiceBuilder = (ChoiceBuilder) childNode;
+ for (ChoiceCaseBuilder choiceCaseBuilder : choiceBuilder.getCases()) {
+ correctAugmentChildPath(choiceCaseBuilder, childNode.getPath());
+ }
+ }
+
+ // if node can contains type, correct path for this type too
+ if (childNode instanceof TypeAwareBuilder) {
+ TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) childNode;
+ correctTypeAwareNodePath(nodeBuilder, parentSchemaPath);
+ }
+ }
+
+ /**
+ * Repair schema path of node type.
+ *
+ * @param node
+ * node which contains type statement
+ * @param parentSchemaPath
+ * schema path of parent node
+ */
+ private static void correctTypeAwareNodePath(final TypeAwareBuilder node, final SchemaPath parentSchemaPath) {
+ final QName nodeBuilderQName = node.getQName();
+ final TypeDefinition<?> nodeType = node.getType();
+
+ Integer fd = null;
+ List<LengthConstraint> lengths = null;
+ List<PatternConstraint> patterns = null;
+ List<RangeConstraint> ranges = null;
+
+ if (nodeType != null) {
+ if (nodeType instanceof ExtendedType) {
+ ExtendedType et = (ExtendedType) nodeType;
+ if (nodeType.getQName().getLocalName().equals(nodeType.getBaseType().getQName().getLocalName())) {
+ fd = et.getFractionDigits();
+ lengths = et.getLengths();
+ patterns = et.getPatterns();
+ ranges = et.getRanges();
+ if (!hasConstraints(fd, lengths, patterns, ranges)) {
+ return;
+ }
+ }
+ }
+ TypeDefinition<?> newType = createCorrectTypeDefinition(parentSchemaPath, nodeBuilderQName, nodeType);
+ node.setType(newType);
+ } else {
+ TypeDefinitionBuilder nodeBuilderTypedef = node.getTypedef();
+
+ fd = nodeBuilderTypedef.getFractionDigits();
+ lengths = nodeBuilderTypedef.getLengths();
+ patterns = nodeBuilderTypedef.getPatterns();
+ ranges = nodeBuilderTypedef.getRanges();
+
+ String tdbTypeName = nodeBuilderTypedef.getQName().getLocalName();
+ String baseTypeName = null;
+ if (nodeBuilderTypedef.getType() == null) {
+ baseTypeName = nodeBuilderTypedef.getTypedef().getQName().getLocalName();
+ } else {
+ baseTypeName = nodeBuilderTypedef.getType().getQName().getLocalName();
+ }
+ if (!(tdbTypeName.equals(baseTypeName))) {
+ return;
+ }
+
+ if (!hasConstraints(fd, lengths, patterns, ranges)) {
+ return;
+ }
+
+ SchemaPath newSchemaPath = createNewSchemaPath(nodeBuilderTypedef.getPath(), nodeBuilderQName,
+ nodeBuilderTypedef.getQName());
+ nodeBuilderTypedef.setPath(newSchemaPath);
+ }
+ }
+
+ /**
+ * Check if there are some constraints.
+ *
+ * @param fd
+ * fraction digits
+ * @param lengths
+ * length constraints
+ * @param patterns
+ * pattern constraints
+ * @param ranges
+ * range constraints
+ * @return true, if any of constraints are present, false otherwise
+ */
+ private static boolean hasConstraints(final Integer fd, final List<LengthConstraint> lengths,
+ final List<PatternConstraint> patterns, final List<RangeConstraint> ranges) {
+ if (fd == null && (lengths == null || lengths.isEmpty()) && (patterns == null || patterns.isEmpty())
+ && (ranges == null || ranges.isEmpty())) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private static TypeDefinition<?> createCorrectTypeDefinition(SchemaPath parentSchemaPath, QName nodeQName,
+ TypeDefinition<?> nodeType) {
+ TypeDefinition<?> result = null;
+
+ if (nodeType != null) {
+ QName nodeTypeQName = nodeType.getQName();
+ SchemaPath newSchemaPath = createNewSchemaPath(parentSchemaPath, nodeQName, nodeTypeQName);
+
+ if (nodeType instanceof BinaryTypeDefinition) {
+ BinaryTypeDefinition binType = (BinaryTypeDefinition) nodeType;
+
+ // List<Byte> bytes = (List<Byte>) binType.getDefaultValue();
+ // workaround to get rid of 'Unchecked cast' warning
+ List<Byte> bytes = new ArrayList<Byte>();
+ Object defaultValue = binType.getDefaultValue();
+ if (defaultValue instanceof List) {
+ for (Object o : List.class.cast(defaultValue)) {
+ if (o instanceof Byte) {
+ bytes.add((Byte) o);
+ }
+ }
+ }
+ result = new BinaryType(newSchemaPath, bytes);
+ } else if (nodeType instanceof BitsTypeDefinition) {
+ BitsTypeDefinition bitsType = (BitsTypeDefinition) nodeType;
+ result = new BitsType(newSchemaPath, bitsType.getBits());
+ } else if (nodeType instanceof BooleanTypeDefinition) {
+ result = new BooleanType(newSchemaPath);
+ } else if (nodeType instanceof DecimalTypeDefinition) {
+ DecimalTypeDefinition decimalType = (DecimalTypeDefinition) nodeType;
+ result = new Decimal64(newSchemaPath, decimalType.getFractionDigits());
+ } else if (nodeType instanceof EmptyTypeDefinition) {
+ result = new EmptyType(newSchemaPath);
+ } else if (nodeType instanceof EnumTypeDefinition) {
+ EnumTypeDefinition enumType = (EnumTypeDefinition) nodeType;
+ result = new EnumerationType(newSchemaPath, (EnumPair) enumType.getDefaultValue(), enumType.getValues());
+ } else if (nodeType instanceof IdentityrefTypeDefinition) {
+ IdentityrefTypeDefinition idrefType = (IdentityrefTypeDefinition) nodeType;
+ result = new IdentityrefType(idrefType.getIdentity(), newSchemaPath);
+ } else if (nodeType instanceof InstanceIdentifierTypeDefinition) {
+ InstanceIdentifierTypeDefinition instIdType = (InstanceIdentifierTypeDefinition) nodeType;
+ return new InstanceIdentifier(newSchemaPath, instIdType.getPathStatement(),
+ instIdType.requireInstance());
+ } else if (nodeType instanceof StringTypeDefinition) {
+ result = createNewStringType(parentSchemaPath, nodeQName, (StringTypeDefinition) nodeType);
+ } else if (nodeType instanceof IntegerTypeDefinition) {
+ result = createNewIntType(parentSchemaPath, nodeQName, (IntegerTypeDefinition) nodeType);
+ } else if (nodeType instanceof UnsignedIntegerTypeDefinition) {
+ result = createNewUintType(parentSchemaPath, nodeQName, (UnsignedIntegerTypeDefinition) nodeType);
+ } else if (nodeType instanceof LeafrefTypeDefinition) {
+ result = new Leafref(newSchemaPath, ((LeafrefTypeDefinition) nodeType).getPathStatement());
+ } else if (nodeType instanceof UnionTypeDefinition) {
+ UnionTypeDefinition unionType = (UnionTypeDefinition) nodeType;
+ return new UnionType(newSchemaPath, unionType.getTypes());
+ } else if (nodeType instanceof ExtendedType) {
+ ExtendedType extType = (ExtendedType) nodeType;
+ result = createNewExtendedType(extType, newSchemaPath);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Create new ExtendedType based on given type and with schema path.
+ *
+ * @param newPath
+ * schema path for new type
+ * @param oldType
+ * type based
+ * @return
+ */
+ private static ExtendedType createNewExtendedType(final ExtendedType oldType, final SchemaPath newPath) {
+ QName qname = oldType.getQName();
+ TypeDefinition<?> baseType = oldType.getBaseType();
+ String desc = oldType.getDescription();
+ String ref = oldType.getReference();
+ ExtendedType.Builder builder = new ExtendedType.Builder(qname, baseType, desc, ref, newPath);
+ builder.status(oldType.getStatus());
+ builder.lengths(oldType.getLengths());
+ builder.patterns(oldType.getPatterns());
+ builder.ranges(oldType.getRanges());
+ builder.fractionDigits(oldType.getFractionDigits());
+ builder.unknownSchemaNodes(oldType.getUnknownSchemaNodes());
+ return builder.build();
+ }
+
+ private static StringTypeDefinition createNewStringType(final SchemaPath schemaPath, final QName nodeQName,
+ final StringTypeDefinition nodeType) {
+ final List<QName> path = schemaPath.getPath();
+ final List<QName> newPath = new ArrayList<QName>(path);
+ newPath.add(nodeQName);
+ newPath.add(nodeType.getQName());
+ final SchemaPath newSchemaPath = new SchemaPath(newPath, schemaPath.isAbsolute());
+ return new StringType(newSchemaPath);
+ }
+
+ private static IntegerTypeDefinition createNewIntType(final SchemaPath schemaPath, final QName nodeQName,
+ final IntegerTypeDefinition type) {
+ final QName typeQName = type.getQName();
+ final SchemaPath newSchemaPath = createNewSchemaPath(schemaPath, nodeQName, typeQName);
+ final String localName = typeQName.getLocalName();
+
+ if ("int8".equals(localName)) {
+ return new Int8(newSchemaPath);
+ } else if ("int16".equals(localName)) {
+ return new Int16(newSchemaPath);
+ } else if ("int32".equals(localName)) {
+ return new Int32(newSchemaPath);
+ } else if ("int64".equals(localName)) {
+ return new Int64(newSchemaPath);
+ } else {
+ return null;
+ }
+ }
+
+ private static UnsignedIntegerTypeDefinition createNewUintType(final SchemaPath schemaPath, final QName nodeQName,
+ final UnsignedIntegerTypeDefinition type) {
+ final QName typeQName = type.getQName();
+ final SchemaPath newSchemaPath = createNewSchemaPath(schemaPath, nodeQName, typeQName);
+ final String localName = typeQName.getLocalName();
+
+ if ("uint8".equals(localName)) {
+ return new Uint8(newSchemaPath);
+ } else if ("uint16".equals(localName)) {
+ return new Uint16(newSchemaPath);
+ } else if ("uint32".equals(localName)) {
+ return new Uint32(newSchemaPath);
+ } else if ("uint64".equals(localName)) {
+ return new Uint64(newSchemaPath);
+ } else {
+ return null;
+ }
+ }
+
+ private static SchemaPath createNewSchemaPath(final SchemaPath schemaPath, final QName currentQName,
+ final QName qname) {
+ List<QName> newPath = new ArrayList<QName>(schemaPath.getPath());
+ newPath.add(currentQName);
+ newPath.add(qname);
+ return new SchemaPath(newPath, schemaPath.isAbsolute());
+ }
+
+ /**
+ * Create LeafSchemaNodeBuilder from given LeafSchemaNode.
+ *
+ * @param leaf
+ * leaf from which to create builder
+ * @param line
+ * line in module
+ * @return builder object from leaf
+ */
+ public static LeafSchemaNodeBuilder createLeafBuilder(LeafSchemaNode leaf, String moduleName, int line) {
+ final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(moduleName, line, leaf.getQName(),
+ leaf.getPath());
+ convertDataSchemaNode(leaf, builder);
+ builder.setConfiguration(leaf.isConfiguration());
+ final TypeDefinition<?> type = leaf.getType();
+ builder.setType(type);
+ builder.setPath(leaf.getPath());
+ builder.setUnknownNodes(leaf.getUnknownSchemaNodes());
+ builder.setDefaultStr(leaf.getDefault());
+ builder.setUnits(leaf.getUnits());
+ return builder;
+ }
+
+ public static ContainerSchemaNodeBuilder createContainer(ContainerSchemaNode container, String moduleName, int line) {
+ final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(moduleName, line,
+ container.getQName(), container.getPath());
+ convertDataSchemaNode(container, builder);
+ builder.setConfiguration(container.isConfiguration());
+ builder.setUnknownNodes(container.getUnknownSchemaNodes());
+ builder.setChildNodes(container.getChildNodes());
+ builder.setGroupings(container.getGroupings());
+ builder.setTypedefs(container.getTypeDefinitions());
+ builder.setAugmentations(container.getAvailableAugmentations());
+ builder.setUsesnodes(container.getUses());
+ builder.setPresence(container.isPresenceContainer());
+ return builder;
+ }
+
+ public static ListSchemaNodeBuilder createList(ListSchemaNode list, String moduleName, int line) {
+ ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(moduleName, line, list.getQName(), list.getPath());
+ convertDataSchemaNode(list, builder);
+ builder.setConfiguration(list.isConfiguration());
+ builder.setUnknownNodes(list.getUnknownSchemaNodes());
+ builder.setTypedefs(list.getTypeDefinitions());
+ builder.setChildNodes(list.getChildNodes());
+ builder.setGroupings(list.getGroupings());
+ builder.setAugmentations(list.getAvailableAugmentations());
+ builder.setUsesnodes(list.getUses());
+ builder.setUserOrdered(builder.isUserOrdered());
+ return builder;
+ }
+
+ public static LeafListSchemaNodeBuilder createLeafList(LeafListSchemaNode leafList, String moduleName, int line) {
+ final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(moduleName, line, leafList.getQName(),
+ leafList.getPath());
+ convertDataSchemaNode(leafList, builder);
+ builder.setConfiguration(leafList.isConfiguration());
+ builder.setType(leafList.getType());
+ builder.setUnknownNodes(leafList.getUnknownSchemaNodes());
+ builder.setUserOrdered(leafList.isUserOrdered());
+ return builder;
+ }
+
+ public static ChoiceBuilder createChoice(ChoiceNode choice, String moduleName, int line) {
+ final ChoiceBuilder builder = new ChoiceBuilder(moduleName, line, choice.getQName());
+ convertDataSchemaNode(choice, builder);
+ builder.setConfiguration(choice.isConfiguration());
+ builder.setCases(choice.getCases());
+ builder.setUnknownNodes(choice.getUnknownSchemaNodes());
+ builder.setDefaultCase(choice.getDefaultCase());
+ return builder;
+ }
+
+ public static AnyXmlBuilder createAnyXml(AnyXmlSchemaNode anyxml, String moduleName, int line) {
+ final AnyXmlBuilder builder = new AnyXmlBuilder(moduleName, line, anyxml.getQName(), anyxml.getPath());
+ convertDataSchemaNode(anyxml, builder);
+ builder.setConfiguration(anyxml.isConfiguration());
+ builder.setUnknownNodes(anyxml.getUnknownSchemaNodes());
+ return builder;
+ }
+
+ public static GroupingBuilder createGrouping(GroupingDefinition grouping, String moduleName, int line) {
+ final GroupingBuilderImpl builder = new GroupingBuilderImpl(moduleName, line, grouping.getQName());
+ builder.setPath(grouping.getPath());
+ builder.setChildNodes(grouping.getChildNodes());
+ builder.setGroupings(grouping.getGroupings());
+ builder.setTypedefs(grouping.getTypeDefinitions());
+ builder.setUsesnodes(grouping.getUses());
+ builder.setUnknownNodes(grouping.getUnknownSchemaNodes());
+ builder.setDescription(grouping.getDescription());
+ builder.setReference(grouping.getReference());
+ builder.setStatus(grouping.getStatus());
+ return builder;
+ }
+
+ public static TypeDefinitionBuilder createTypedef(ExtendedType typedef, String moduleName, int line) {
+ final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(moduleName, line, typedef.getQName());
+ builder.setPath(typedef.getPath());
+ builder.setDefaultValue(typedef.getDefaultValue());
+ builder.setUnits(typedef.getUnits());
+ builder.setDescription(typedef.getDescription());
+ builder.setReference(typedef.getReference());
+ builder.setStatus(typedef.getStatus());
+ builder.setRanges(typedef.getRanges());
+ builder.setLengths(typedef.getLengths());
+ builder.setPatterns(typedef.getPatterns());
+ builder.setFractionDigits(typedef.getFractionDigits());
+ final TypeDefinition<?> type = typedef.getBaseType();
+ builder.setType(type);
+ builder.setUnits(typedef.getUnits());
+ builder.setUnknownNodes(typedef.getUnknownSchemaNodes());
+ return builder;
+ }
+
+ public static UnknownSchemaNodeBuilder createUnknownSchemaNode(UnknownSchemaNode unknownNode, String moduleName,
+ int line) {
+ final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(moduleName, line, unknownNode.getQName());
+ builder.setPath(unknownNode.getPath());
+ builder.setUnknownNodes(unknownNode.getUnknownSchemaNodes());
+ builder.setDescription(unknownNode.getDescription());
+ builder.setReference(unknownNode.getReference());
+ builder.setStatus(unknownNode.getStatus());
+ builder.setAddedByUses(unknownNode.isAddedByUses());
+ builder.setNodeType(unknownNode.getNodeType());
+ builder.setNodeParameter(unknownNode.getNodeParameter());
+ return builder;
+ }
+
+ /**
+ * Set DataSchemaNode arguments to builder object
+ *
+ * @param node
+ * node from which arguments should be read
+ * @param builder
+ * builder to which arguments should be set
+ */
+ private static void convertDataSchemaNode(DataSchemaNode node, DataSchemaNodeBuilder builder) {
+ builder.setPath(node.getPath());
+ builder.setDescription(node.getDescription());
+ builder.setReference(node.getReference());
+ builder.setStatus(node.getStatus());
+ builder.setAugmenting(node.isAugmenting());
+ copyConstraintsFromDefinition(node.getConstraints(), builder.getConstraints());
+ }
+
+ /**
+ * Copy constraints from constraints definition to constraints builder.
+ *
+ * @param nodeConstraints
+ * definition from which constraints will be copied
+ * @param constraints
+ * builder to which constraints will be added
+ */
+ private static void copyConstraintsFromDefinition(final ConstraintDefinition nodeConstraints,
+ final ConstraintsBuilder constraints) {
+ final RevisionAwareXPath when = nodeConstraints.getWhenCondition();
+ final Set<MustDefinition> must = nodeConstraints.getMustConstraints();
+
+ if (when != null) {
+ constraints.addWhenCondition(when.toString());
+ }
+ if (must != null) {
+ for (MustDefinition md : must) {
+ constraints.addMustDefinition(md);
+ }
+ }
+ constraints.setMandatory(nodeConstraints.isMandatory());
+ constraints.setMinElements(nodeConstraints.getMinElements());
+ constraints.setMaxElements(nodeConstraints.getMaxElements());
+ }
+
+ public static void processAugmentationOnContext(final AugmentationSchemaBuilder augmentBuilder,
+ final List<QName> path, final ModuleBuilder module, final String prefix, final int line,
+ final SchemaContext context) {
+ final Module dependentModule = findModuleFromContext(context, module, prefix, line);
+ if (dependentModule == null) {
+ throw new YangParseException(module.getName(), line, "Failed to find referenced module with prefix "
+ + prefix + ".");
+ }
+ SchemaNode node = dependentModule.getDataChildByName(path.get(0).getLocalName());
+ if (node == null) {
+ Set<NotificationDefinition> notifications = dependentModule.getNotifications();
+ for (NotificationDefinition ntf : notifications) {
+ if (ntf.getQName().getLocalName().equals(path.get(0).getLocalName())) {
+ node = ntf;
+ break;
+ }
+ }
+ }
+ if (node == null) {
+ return;
+ }
+
+ for (int i = 1; i < path.size(); i++) {
+ if (node instanceof DataNodeContainer) {
+ DataNodeContainer ref = (DataNodeContainer) node;
+ node = ref.getDataChildByName(path.get(i).getLocalName());
+ }
+ }
+ if (node == null) {
+ return;
+ }
+
+ if (node instanceof ContainerSchemaNodeImpl) {
+ // includes container, input and output statement
+ ContainerSchemaNodeImpl c = (ContainerSchemaNodeImpl) node;
+ ContainerSchemaNodeBuilder cb = c.toBuilder();
+ fillAugmentTarget(augmentBuilder, cb);
+ ((AugmentationTargetBuilder) cb).addAugmentation(augmentBuilder);
+ SchemaPath oldPath = cb.getPath();
+ cb.rebuild();
+ augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+ augmentBuilder.setResolved(true);
+ module.augmentResolved();
+ } else if (node instanceof ListSchemaNodeImpl) {
+ ListSchemaNodeImpl l = (ListSchemaNodeImpl) node;
+ ListSchemaNodeBuilder lb = l.toBuilder();
+ fillAugmentTarget(augmentBuilder, lb);
+ ((AugmentationTargetBuilder) lb).addAugmentation(augmentBuilder);
+ SchemaPath oldPath = lb.getPath();
+ lb.rebuild();
+ augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+ augmentBuilder.setResolved(true);
+ module.augmentResolved();
+ } else if (node instanceof ChoiceNodeImpl) {
+ ChoiceNodeImpl ch = (ChoiceNodeImpl) node;
+ ChoiceBuilder chb = ch.toBuilder();
+ fillAugmentTarget(augmentBuilder, chb);
+ ((AugmentationTargetBuilder) chb).addAugmentation(augmentBuilder);
+ SchemaPath oldPath = chb.getPath();
+ chb.rebuild();
+ augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+ augmentBuilder.setResolved(true);
+ module.augmentResolved();
+ } else if (node instanceof ChoiceCaseNodeImpl) {
+ ChoiceCaseNodeImpl chc = (ChoiceCaseNodeImpl) node;
+ ChoiceCaseBuilder chcb = chc.toBuilder();
+ fillAugmentTarget(augmentBuilder, chcb);
+ ((AugmentationTargetBuilder) chcb).addAugmentation(augmentBuilder);
+ SchemaPath oldPath = chcb.getPath();
+ chcb.rebuild();
+ augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+ augmentBuilder.setResolved(true);
+ module.augmentResolved();
+ } else if (node instanceof NotificationDefinitionImpl) {
+ NotificationDefinitionImpl nd = (NotificationDefinitionImpl) node;
+ NotificationBuilder nb = nd.toBuilder();
+ fillAugmentTarget(augmentBuilder, nb);
+ ((AugmentationTargetBuilder) nb).addAugmentation(augmentBuilder);
+ SchemaPath oldPath = nb.getPath();
+ nb.rebuild();
+ augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+ augmentBuilder.setResolved(true);
+ module.augmentResolved();
+ } else {
+ throw new YangParseException(module.getName(), line, "Target of type " + node.getClass()
+ + " cannot be augmented.");
+ }
+ }
+
+ public static void processAugmentation(final AugmentationSchemaBuilder augmentBuilder, final List<QName> path,
+ final ModuleBuilder module, final ModuleBuilder dependentModuleBuilder) {
+ DataSchemaNodeBuilder currentParent = null;
+ for (DataSchemaNodeBuilder child : dependentModuleBuilder.getChildNodeBuilders()) {
+ final QName childQName = child.getQName();
+ if (childQName.getLocalName().equals(path.get(0).getLocalName())) {
+ currentParent = child;
+ break;
+ }
+ }
+
+ if (currentParent == null) {
+ return;
+ }
+
+ for (int i = 1; i < path.size(); i++) {
+ final QName currentQName = path.get(i);
+ DataSchemaNodeBuilder newParent = null;
+ if (currentParent instanceof DataNodeContainerBuilder) {
+ for (DataSchemaNodeBuilder child : ((DataNodeContainerBuilder) currentParent).getChildNodeBuilders()) {
+ final QName childQName = child.getQName();
+ if (childQName.getLocalName().equals(currentQName.getLocalName())) {
+ newParent = child;
+ break;
+ }
+ }
+ } else if (currentParent instanceof ChoiceBuilder) {
+ for (ChoiceCaseBuilder caseBuilder : ((ChoiceBuilder) currentParent).getCases()) {
+ final QName caseQName = caseBuilder.getQName();
+ if (caseQName.getLocalName().equals(currentQName.getLocalName())) {
+ newParent = caseBuilder;
+ break;
+ }
+ }
+ }
+
+ if (newParent == null) {
+ break; // node not found, quit search
+ } else {
+ currentParent = newParent;
+ }
+ }
+
+ final String currentName = currentParent.getQName().getLocalName();
+ final String lastAugmentPathElementName = path.get(path.size() - 1).getLocalName();
+ if (currentName.equals(lastAugmentPathElementName)) {
+
+ if (currentParent instanceof ChoiceBuilder) {
+ fillAugmentTarget(augmentBuilder, (ChoiceBuilder) currentParent);
+ } else {
+ fillAugmentTarget(augmentBuilder, (DataNodeContainerBuilder) currentParent);
+ }
+ ((AugmentationTargetBuilder) currentParent).addAugmentation(augmentBuilder);
+ SchemaPath oldPath = currentParent.getPath();
+ augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+ augmentBuilder.setResolved(true);
+ module.augmentResolved();
+ }
+ }
+
+ /**
+ * Create new type builder based on old type with new base type.
+ *
+ * @param newBaseType
+ * new base type builder
+ * @param oldExtendedType
+ * old type
+ * @param modules
+ * all loaded modules
+ * @param module
+ * current module
+ * @param line
+ * current line in module
+ * @return new type builder based on old type with new base type
+ */
+ public static TypeDefinitionBuilder extendedTypeWithNewBaseTypeBuilder(final TypeDefinitionBuilder newBaseType,
+ final ExtendedType oldExtendedType, final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder module, final int line) {
+ final TypeConstraints tc = new TypeConstraints(module.getName(), line);
+ tc.addFractionDigits(oldExtendedType.getFractionDigits());
+ tc.addLengths(oldExtendedType.getLengths());
+ tc.addPatterns(oldExtendedType.getPatterns());
+ tc.addRanges(oldExtendedType.getRanges());
+
+ final TypeConstraints constraints = findConstraintsFromTypeBuilder(newBaseType, tc, modules, module, null);
+ final TypeDefinitionBuilderImpl newType = new TypeDefinitionBuilderImpl(module.getModuleName(), line,
+ oldExtendedType.getQName());
+ newType.setTypedef(newBaseType);
+ newType.setPath(oldExtendedType.getPath());
+ newType.setDescription(oldExtendedType.getDescription());
+ newType.setReference(oldExtendedType.getReference());
+ newType.setStatus(oldExtendedType.getStatus());
+ newType.setLengths(constraints.getLength());
+ newType.setPatterns(constraints.getPatterns());
+ newType.setRanges(constraints.getRange());
+ newType.setFractionDigits(constraints.getFractionDigits());
+ newType.setUnits(oldExtendedType.getUnits());
+ newType.setDefaultValue(oldExtendedType.getDefaultValue());
+ newType.setUnknownNodes(oldExtendedType.getUnknownSchemaNodes());
+ return newType;
+ }
+
+ /**
+ * Create new type builder based on old type with new base type.
+ *
+ * @param newBaseType
+ * new base type
+ * @param oldExtendedType
+ * old type
+ * @param modules
+ * all loaded modules
+ * @param module
+ * current module
+ * @param line
+ * current line in module
+ * @return new type builder based on old type with new base type
+ */
+ public static TypeDefinitionBuilder extendedTypeWithNewBaseType(final TypeDefinition<?> newBaseType,
+ final ExtendedType oldExtendedType, final ModuleBuilder module, final int line) {
+ final TypeConstraints tc = new TypeConstraints(module.getName(), line);
+
+ final TypeConstraints constraints = findConstraintsFromTypeDefinition(newBaseType, tc);
+ final TypeDefinitionBuilderImpl newType = new TypeDefinitionBuilderImpl(module.getModuleName(), line,
+ oldExtendedType.getQName());
+ newType.setType(newBaseType);
+ newType.setPath(oldExtendedType.getPath());
+ newType.setDescription(oldExtendedType.getDescription());
+ newType.setReference(oldExtendedType.getReference());
+ newType.setStatus(oldExtendedType.getStatus());
+ newType.setLengths(constraints.getLength());
+ newType.setPatterns(constraints.getPatterns());
+ newType.setRanges(constraints.getRange());
+ newType.setFractionDigits(constraints.getFractionDigits());
+ newType.setUnits(oldExtendedType.getUnits());
+ newType.setDefaultValue(oldExtendedType.getDefaultValue());
+ newType.setUnknownNodes(oldExtendedType.getUnknownSchemaNodes());
+ return newType;
+ }
+
+ /**
+ * Pull restrictions from type and add them to constraints.
+ *
+ * @param typeToResolve
+ * type from which constraints will be read
+ * @param constraints
+ * constraints object to which constraints will be added
+ * @return constraints contstraints object containing constraints from given
+ * type
+ */
+ private static TypeConstraints findConstraintsFromTypeDefinition(final TypeDefinition<?> typeToResolve,
+ final TypeConstraints constraints) {
+ // union type cannot be restricted
+ if (typeToResolve instanceof UnionTypeDefinition) {
+ return constraints;
+ }
+ if (typeToResolve instanceof ExtendedType) {
+ ExtendedType extType = (ExtendedType) typeToResolve;
+ constraints.addFractionDigits(extType.getFractionDigits());
+ constraints.addLengths(extType.getLengths());
+ constraints.addPatterns(extType.getPatterns());
+ constraints.addRanges(extType.getRanges());
+ return findConstraintsFromTypeDefinition(extType.getBaseType(), constraints);
+ } else {
+ mergeConstraints(typeToResolve, constraints);
+ return constraints;
+ }
+ }
+
+ public static TypeConstraints findConstraintsFromTypeBuilder(final TypeAwareBuilder nodeToResolve,
+ final TypeConstraints constraints, final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder builder, final SchemaContext context) {
+
+ // union and identityref types cannot be restricted
+ if (nodeToResolve instanceof UnionTypeBuilder || nodeToResolve instanceof IdentityrefTypeBuilder) {
+ return constraints;
+ }
+
+ if (nodeToResolve instanceof TypeDefinitionBuilder) {
+ TypeDefinitionBuilder typedefToResolve = (TypeDefinitionBuilder) nodeToResolve;
+ constraints.addFractionDigits(typedefToResolve.getFractionDigits());
+ constraints.addLengths(typedefToResolve.getLengths());
+ constraints.addPatterns(typedefToResolve.getPatterns());
+ constraints.addRanges(typedefToResolve.getRanges());
+ }
+
+ TypeDefinition<?> type = nodeToResolve.getType();
+ if (type == null) {
+ return findConstraintsFromTypeBuilder(nodeToResolve.getTypedef(), constraints, modules, builder, context);
+ } else {
+ QName qname = type.getQName();
+ if (type instanceof UnknownType) {
+ ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder, qname.getPrefix(),
+ nodeToResolve.getLine());
+ if (dependentModuleBuilder == null) {
+ if (context == null) {
+ throw new YangParseException(builder.getName(), nodeToResolve.getLine(),
+ "Failed to resolved type constraints.");
+ }
+ Module dm = findModuleFromContext(context, builder, qname.getPrefix(), nodeToResolve.getLine());
+ TypeDefinition<?> t = findTypeByName(dm.getTypeDefinitions(), qname.getLocalName());
+ if (t instanceof ExtendedType) {
+ ExtendedType extType = (ExtendedType) t;
+ constraints.addFractionDigits(extType.getFractionDigits());
+ constraints.addLengths(extType.getLengths());
+ constraints.addPatterns(extType.getPatterns());
+ constraints.addRanges(extType.getRanges());
+ return constraints;
+ } else {
+ mergeConstraints(t, constraints);
+ return constraints;
+ }
+ } else {
+ TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve, dependentModuleBuilder,
+ qname.getLocalName(), builder.getName(), nodeToResolve.getLine());
+ return findConstraintsFromTypeBuilder(tdb, constraints, modules, dependentModuleBuilder, context);
+ }
+ } else if (type instanceof ExtendedType) {
+ ExtendedType extType = (ExtendedType) type;
+ constraints.addFractionDigits(extType.getFractionDigits());
+ constraints.addLengths(extType.getLengths());
+ constraints.addPatterns(extType.getPatterns());
+ constraints.addRanges(extType.getRanges());
+
+ TypeDefinition<?> base = extType.getBaseType();
+ if (base instanceof UnknownType) {
+ ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, base.getQName()
+ .getPrefix(), nodeToResolve.getLine());
+ TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve, dependentModule, base
+ .getQName().getLocalName(), builder.getName(), nodeToResolve.getLine());
+ return findConstraintsFromTypeBuilder(tdb, constraints, modules, dependentModule, context);
+ } else {
+ // it has to be base yang type
+ mergeConstraints(type, constraints);
+ return constraints;
+ }
+ } else {
+ // it is base yang type
+ mergeConstraints(type, constraints);
+ return constraints;
+ }
+ }
+ }
+
+ /**
+ * Search for type definition builder by name.
+ *
+ * @param dirtyNodeSchemaPath
+ * schema path of node which contains unresolved type
+ * @param dependentModule
+ * module which should contains referenced type
+ * @param typeName
+ * name of type definition
+ * @param currentModuleName
+ * name of current module
+ * @param line
+ * current line in yang model
+ * @return
+ */
+ public static TypeDefinitionBuilder findTypeDefinitionBuilder(final TypeAwareBuilder nodeToResolve,
+ final ModuleBuilder dependentModule, final String typeName, final String currentModuleName, final int line) {
+
+ TypeDefinitionBuilder result = null;
+
+ Set<TypeDefinitionBuilder> typedefs = dependentModule.getTypeDefinitionBuilders();
+ result = findTypedefBuilderByName(typedefs, typeName);
+ if (result != null) {
+ return result;
+ }
+
+ Builder parent = nodeToResolve.getParent();
+ while (parent != null) {
+ if (parent instanceof DataNodeContainerBuilder) {
+ typedefs = ((DataNodeContainerBuilder) parent).getTypeDefinitionBuilders();
+ } else if (parent instanceof RpcDefinitionBuilder) {
+ typedefs = ((RpcDefinitionBuilder) parent).getTypeDefinitions();
+ }
+ result = findTypedefBuilderByName(typedefs, typeName);
+ if (result == null) {
+ parent = parent.getParent();
+ } else {
+ break;
+ }
+ }
+
+ if (result == null) {
+ throw new YangParseException(currentModuleName, line, "Referenced type '" + typeName + "' not found.");
+ }
+ return result;
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import org.opendaylight.controller.yang.model.api.MustDefinition;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractBuilder;
+
+public final class RefineHolder extends AbstractBuilder {
+ private final String name;
+ private String defaultStr;
+ private String description;
+ private String reference;
+ private Boolean config;
+ private Boolean mandatory;
+ private Boolean presence;
+ private MustDefinition must;
+ private Integer minElements;
+ private Integer maxElements;
+
+ public RefineHolder(final String moduleName, final int line, final String name) {
+ super(moduleName, line);
+ this.name = name;
+ }
+
+ public String getDefaultStr() {
+ return defaultStr;
+ }
+
+ public void setDefaultStr(final String defaultStr) {
+ this.defaultStr = defaultStr;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public String getReference() {
+ return reference;
+ }
+
+ public void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ public Boolean isConfiguration() {
+ return config;
+ }
+
+ public void setConfiguration(final Boolean config) {
+ this.config = config;
+ }
+
+ public Boolean isMandatory() {
+ return mandatory;
+ }
+
+ public void setMandatory(Boolean mandatory) {
+ this.mandatory = mandatory;
+ }
+
+ public Boolean isPresence() {
+ return presence;
+ }
+
+ public void setPresence(Boolean presence) {
+ this.presence = presence;
+ }
+
+ public MustDefinition getMust() {
+ return must;
+ }
+
+ public void setMust(MustDefinition must) {
+ this.must = must;
+ }
+
+ public Integer getMinElements() {
+ return minElements;
+ }
+
+ public void setMinElements(Integer minElements) {
+ this.minElements = minElements;
+ }
+
+ public Integer getMaxElements() {
+ return maxElements;
+ }
+
+ public void setMaxElements(Integer maxElements) {
+ this.maxElements = maxElements;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Object build() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((addedUnknownNodes == null) ? 0 : addedUnknownNodes.hashCode());
+ result = prime * result + ((config == null) ? 0 : config.hashCode());
+ result = prime * result + ((defaultStr == null) ? 0 : defaultStr.hashCode());
+ result = prime * result + ((description == null) ? 0 : description.hashCode());
+ result = prime * result + ((mandatory == null) ? 0 : mandatory.hashCode());
+ result = prime * result + ((maxElements == null) ? 0 : maxElements.hashCode());
+ result = prime * result + ((minElements == null) ? 0 : minElements.hashCode());
+ result = prime * result + ((must == null) ? 0 : must.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((parent == null) ? 0 : parent.hashCode());
+ result = prime * result + ((presence == null) ? 0 : presence.hashCode());
+ result = prime * result + ((reference == null) ? 0 : reference.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ RefineHolder other = (RefineHolder) obj;
+ if (addedUnknownNodes == null) {
+ if (other.addedUnknownNodes != null)
+ return false;
+ } else if (!addedUnknownNodes.equals(other.addedUnknownNodes))
+ return false;
+ if (config == null) {
+ if (other.config != null)
+ return false;
+ } else if (!config.equals(other.config))
+ return false;
+ if (defaultStr == null) {
+ if (other.defaultStr != null)
+ return false;
+ } else if (!defaultStr.equals(other.defaultStr))
+ return false;
+ if (description == null) {
+ if (other.description != null)
+ return false;
+ } else if (!description.equals(other.description))
+ return false;
+ if (mandatory == null) {
+ if (other.mandatory != null)
+ return false;
+ } else if (!mandatory.equals(other.mandatory))
+ return false;
+ if (maxElements == null) {
+ if (other.maxElements != null)
+ return false;
+ } else if (!maxElements.equals(other.maxElements))
+ return false;
+ if (minElements == null) {
+ if (other.minElements != null)
+ return false;
+ } else if (!minElements.equals(other.minElements))
+ return false;
+ if (must == null) {
+ if (other.must != null)
+ return false;
+ } else if (!must.equals(other.must))
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (parent == null) {
+ if (other.parent != null)
+ return false;
+ } else if (!parent.equals(other.parent))
+ return false;
+ if (presence == null) {
+ if (other.presence != null)
+ return false;
+ } else if (!presence.equals(other.presence))
+ return false;
+ if (reference == null) {
+ if (other.reference != null)
+ return false;
+ } else if (!reference.equals(other.reference))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "refine " + name;
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import static org.opendaylight.controller.yang.parser.util.ParserUtils.*;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.MustDefinition;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.parser.builder.api.Builder;
+import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.GroupingBuilderImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
+
+/**
+ * Utility class with helper methods to perform operations tied to refine
+ * process.
+ */
+public class RefineUtils {
+
+ private RefineUtils() {
+ }
+
+ /**
+ * Find original builder of node to refine and return copy of this builder.
+ * <p>
+ * We must create and use a copy of builder to preserve original builder
+ * state, because this object will be refined (modified) and later added to
+ * {@link UsesNodeBuilder}.
+ * </p>
+ *
+ * @param targetGrouping
+ * builder of grouping which should contains node to refine
+ * @param refine
+ * refine object containing informations about refine
+ * @param moduleName
+ * current module name
+ * @return
+ */
+ public static SchemaNodeBuilder getRefineNodeFromGroupingBuilder(final GroupingBuilder targetGrouping,
+ final RefineHolder refine, final String moduleName) {
+ Builder result = null;
+ final Builder lookedUpBuilder = findRefineTargetBuilder(targetGrouping, refine.getName());
+ if (lookedUpBuilder instanceof LeafSchemaNodeBuilder) {
+ result = new LeafSchemaNodeBuilder((LeafSchemaNodeBuilder) lookedUpBuilder);
+ } else if (lookedUpBuilder instanceof ContainerSchemaNodeBuilder) {
+ result = new ContainerSchemaNodeBuilder((ContainerSchemaNodeBuilder) lookedUpBuilder);
+ } else if (lookedUpBuilder instanceof ListSchemaNodeBuilder) {
+ result = new ListSchemaNodeBuilder((ListSchemaNodeBuilder) lookedUpBuilder);
+ } else if (lookedUpBuilder instanceof LeafListSchemaNodeBuilder) {
+ result = new LeafListSchemaNodeBuilder((LeafListSchemaNodeBuilder) lookedUpBuilder);
+ } else if (lookedUpBuilder instanceof ChoiceBuilder) {
+ result = new ChoiceBuilder((ChoiceBuilder) lookedUpBuilder);
+ } else if (lookedUpBuilder instanceof AnyXmlBuilder) {
+ result = new AnyXmlBuilder((AnyXmlBuilder) lookedUpBuilder);
+ } else if (lookedUpBuilder instanceof GroupingBuilder) {
+ result = new GroupingBuilderImpl((GroupingBuilder) lookedUpBuilder);
+ } else if (lookedUpBuilder instanceof TypeDefinitionBuilder) {
+ result = new TypeDefinitionBuilderImpl((TypeDefinitionBuilder) lookedUpBuilder);
+ } else {
+ throw new YangParseException(moduleName, refine.getLine(), "Target '" + refine.getName()
+ + "' can not be refined");
+ }
+ return (SchemaNodeBuilder) result;
+ }
+
+ /**
+ * Create builder object from refine target node.
+ *
+ * @param grouping
+ * grouping which should contains node to refine
+ * @param refine
+ * refine object containing informations about refine
+ * @return
+ */
+ public static SchemaNodeBuilder getRefineNodeFromGroupingDefinition(final GroupingDefinition grouping,
+ final RefineHolder refine) {
+ final String moduleName = refine.getModuleName();
+ final int line = refine.getLine();
+ SchemaNodeBuilder result = null;
+ final Object lookedUpNode = findRefineTargetNode(grouping, refine.getName());
+ if (lookedUpNode instanceof LeafSchemaNode) {
+ result = createLeafBuilder((LeafSchemaNode) lookedUpNode, moduleName, line);
+ } else if (lookedUpNode instanceof ContainerSchemaNode) {
+ result = createContainer((ContainerSchemaNode) lookedUpNode, moduleName, line);
+ } else if (lookedUpNode instanceof ListSchemaNode) {
+ result = createList((ListSchemaNode) lookedUpNode, moduleName, line);
+ } else if (lookedUpNode instanceof LeafListSchemaNode) {
+ result = createLeafList((LeafListSchemaNode) lookedUpNode, moduleName, line);
+ } else if (lookedUpNode instanceof ChoiceNode) {
+ result = createChoice((ChoiceNode) lookedUpNode, moduleName, line);
+ } else if (lookedUpNode instanceof AnyXmlSchemaNode) {
+ result = createAnyXml((AnyXmlSchemaNode) lookedUpNode, moduleName, line);
+ } else if (lookedUpNode instanceof GroupingDefinition) {
+ result = createGrouping((GroupingDefinition) lookedUpNode, moduleName, line);
+ } else if (lookedUpNode instanceof TypeDefinition) {
+ result = createTypedef((ExtendedType) lookedUpNode, moduleName, line);
+ } else {
+ throw new YangParseException(moduleName, line, "Target '" + refine.getName() + "' can not be refined");
+ }
+ return result;
+ }
+
+ public static void refineLeaf(LeafSchemaNodeBuilder leaf, RefineHolder refine) {
+ String defaultStr = refine.getDefaultStr();
+ Boolean mandatory = refine.isMandatory();
+ MustDefinition must = refine.getMust();
+ List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodeBuilders();
+
+ if (defaultStr != null && !("".equals(defaultStr))) {
+ leaf.setDefaultStr(defaultStr);
+ }
+ if (mandatory != null) {
+ leaf.getConstraints().setMandatory(mandatory);
+ }
+ if (must != null) {
+ leaf.getConstraints().addMustDefinition(must);
+ }
+ if (unknownNodes != null) {
+ for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
+ leaf.addUnknownNodeBuilder(unknown);
+ }
+ }
+ }
+
+ public static void refineContainer(ContainerSchemaNodeBuilder container, RefineHolder refine, int line) {
+ Boolean presence = refine.isPresence();
+ MustDefinition must = refine.getMust();
+ List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodeBuilders();
+
+ if (presence != null) {
+ container.setPresence(presence);
+ }
+ if (must != null) {
+ container.getConstraints().addMustDefinition(must);
+ }
+ if (unknownNodes != null) {
+ for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
+ container.addUnknownNodeBuilder(unknown);
+ }
+ }
+ }
+
+ public static void refineList(ListSchemaNodeBuilder list, RefineHolder refine, int line) {
+ MustDefinition must = refine.getMust();
+ Integer min = refine.getMinElements();
+ Integer max = refine.getMaxElements();
+ List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodeBuilders();
+
+ if (must != null) {
+ list.getConstraints().addMustDefinition(must);
+ }
+ if (min != null) {
+ list.getConstraints().setMinElements(min);
+ }
+ if (max != null) {
+ list.getConstraints().setMaxElements(max);
+ }
+ if (unknownNodes != null) {
+ for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
+ list.addUnknownNodeBuilder(unknown);
+ }
+ }
+ }
+
+ public static void refineLeafList(LeafListSchemaNodeBuilder leafList, RefineHolder refine, int line) {
+ MustDefinition must = refine.getMust();
+ Integer min = refine.getMinElements();
+ Integer max = refine.getMaxElements();
+ List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodeBuilders();
+
+ if (must != null) {
+ leafList.getConstraints().addMustDefinition(must);
+ }
+ if (min != null) {
+ leafList.getConstraints().setMinElements(min);
+ }
+ if (max != null) {
+ leafList.getConstraints().setMaxElements(max);
+ }
+ if (unknownNodes != null) {
+ for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
+ leafList.addUnknownNodeBuilder(unknown);
+ }
+ }
+ }
+
+ public static void refineChoice(ChoiceBuilder choice, RefineHolder refine, int line) {
+ String defaultStr = refine.getDefaultStr();
+ Boolean mandatory = refine.isMandatory();
+ List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodeBuilders();
+
+ if (defaultStr != null) {
+ choice.setDefaultCase(defaultStr);
+ }
+ if (mandatory != null) {
+ choice.getConstraints().setMandatory(mandatory);
+ }
+ if (unknownNodes != null) {
+ for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
+ choice.addUnknownNodeBuilder(unknown);
+ }
+ }
+ }
+
+ public static void refineAnyxml(AnyXmlBuilder anyXml, RefineHolder refine, int line) {
+ Boolean mandatory = refine.isMandatory();
+ MustDefinition must = refine.getMust();
+ List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodeBuilders();
+
+ if (mandatory != null) {
+ anyXml.getConstraints().setMandatory(mandatory);
+ }
+ if (must != null) {
+ anyXml.getConstraints().addMustDefinition(must);
+ }
+ if (unknownNodes != null) {
+ for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
+ anyXml.addUnknownNodeBuilder(unknown);
+ }
+ }
+ }
+
+ /**
+ * Check if refine can be performed on given node.
+ *
+ * @param node
+ * node to refine
+ * @param refine
+ * refine object containing information about refine process
+ */
+ public static void checkRefine(SchemaNodeBuilder node, RefineHolder refine) {
+ String moduleName = refine.getModuleName();
+ int line = refine.getLine();
+ String name = node.getQName().getLocalName();
+
+ String defaultStr = refine.getDefaultStr();
+ Boolean mandatory = refine.isMandatory();
+ Boolean presence = refine.isPresence();
+ MustDefinition must = refine.getMust();
+ Integer min = refine.getMinElements();
+ Integer max = refine.getMaxElements();
+
+ if (node instanceof AnyXmlBuilder) {
+ checkRefineDefault(node, defaultStr, moduleName, line);
+ checkRefinePresence(node, presence, moduleName, line);
+ checkRefineMinMax(name, min, max, moduleName, line);
+ } else if (node instanceof ChoiceBuilder) {
+ checkRefinePresence(node, presence, moduleName, line);
+ checkRefineMust(node, must, moduleName, line);
+ checkRefineMinMax(name, min, max, moduleName, line);
+ } else if (node instanceof ContainerSchemaNodeBuilder) {
+ checkRefineDefault(node, defaultStr, moduleName, line);
+ checkRefineMandatory(node, mandatory, moduleName, line);
+ checkRefineMust(node, must, moduleName, line);
+ checkRefineMinMax(name, min, max, moduleName, line);
+ } else if (node instanceof LeafSchemaNodeBuilder) {
+ checkRefinePresence(node, presence, moduleName, line);
+ checkRefineMinMax(name, min, max, moduleName, line);
+ } else if (node instanceof LeafListSchemaNodeBuilder || node instanceof ListSchemaNodeBuilder) {
+ checkRefineDefault(node, defaultStr, moduleName, line);
+ checkRefinePresence(node, presence, moduleName, line);
+ checkRefineMandatory(node, mandatory, moduleName, line);
+ } else if (node instanceof GroupingBuilder || node instanceof TypeDefinitionBuilder
+ || node instanceof UsesNodeBuilder) {
+ checkRefineDefault(node, defaultStr, moduleName, line);
+ checkRefinePresence(node, presence, moduleName, line);
+ checkRefineMandatory(node, mandatory, moduleName, line);
+ checkRefineMust(node, must, moduleName, line);
+ checkRefineMinMax(name, min, max, moduleName, line);
+ }
+ }
+
+ private static void checkRefineDefault(SchemaNodeBuilder node, String defaultStr, String moduleName, int line) {
+ if (defaultStr != null) {
+ throw new YangParseException(moduleName, line, "Can not refine 'default' for '"
+ + node.getQName().getLocalName() + "'.");
+ }
+ }
+
+ private static void checkRefineMandatory(SchemaNodeBuilder node, Boolean mandatory, String moduleName, int line) {
+ if (mandatory != null) {
+ throw new YangParseException(moduleName, line, "Can not refine 'mandatory' for '"
+ + node.getQName().getLocalName() + "'.");
+ }
+ }
+
+ private static void checkRefinePresence(SchemaNodeBuilder node, Boolean presence, String moduleName, int line) {
+ if (presence != null) {
+ throw new YangParseException(moduleName, line, "Can not refine 'presence' for '"
+ + node.getQName().getLocalName() + "'.");
+ }
+ }
+
+ private static void checkRefineMust(SchemaNodeBuilder node, MustDefinition must, String moduleName, int line) {
+ if (must != null) {
+ throw new YangParseException(moduleName, line, "Can not refine 'must' for '"
+ + node.getQName().getLocalName() + "'.");
+ }
+ }
+
+ private static void checkRefineMinMax(String refineTargetName, Integer min, Integer max, String moduleName, int line) {
+ if (min != null || max != null) {
+ throw new YangParseException(moduleName, line, "Can not refine 'min-elements' or 'max-elements' for '"
+ + refineTargetName + "'.");
+ }
+ }
+
+ /**
+ * Perform refine operation of following parameters:
+ * <ul>
+ * <li>description</li>
+ * <li>reference</li>
+ * <li>config</li>
+ * </ul>
+ *
+ * These parameters may be refined for any node.
+ *
+ * @param node
+ * node to refine
+ * @param refine
+ * refine object containing information about refine process
+ */
+ public static void refineDefault(final Builder node, final RefineHolder refine) {
+ final String moduleName = refine.getModuleName();
+ final int line = refine.getLine();
+ Class<? extends Builder> cls = node.getClass();
+
+ String description = refine.getDescription();
+ if (description != null) {
+ try {
+ Method method = cls.getDeclaredMethod("setDescription", String.class);
+ method.invoke(node, description);
+ } catch (Exception e) {
+ throw new YangParseException(moduleName, line, "Cannot refine description in " + cls.getName(), e);
+ }
+ }
+
+ String reference = refine.getReference();
+ if (reference != null) {
+ try {
+ Method method = cls.getDeclaredMethod("setReference", String.class);
+ method.invoke(node, reference);
+ } catch (Exception e) {
+ throw new YangParseException(moduleName, line, "Cannot refine reference in " + cls.getName(), e);
+ }
+ }
+
+ Boolean config = refine.isConfiguration();
+ if (config != null) {
+ try {
+ Method method = cls.getDeclaredMethod("setConfiguration", Boolean.class);
+ method.invoke(node, config);
+ } catch (Exception e) {
+ throw new YangParseException(moduleName, line, "Cannot refine config in " + cls.getName(), e);
+ }
+ }
+ }
+
+ /**
+ * Perform refine operation on given node.
+ *
+ * @param nodeToRefine
+ * builder of node to refine
+ * @param refine
+ * refine object containing information about refine process
+ * @param line
+ * current line in yang model
+ */
+ public static void performRefine(SchemaNodeBuilder nodeToRefine, RefineHolder refine, int line) {
+ checkRefine(nodeToRefine, refine);
+ refineDefault(nodeToRefine, refine);
+ if (nodeToRefine instanceof LeafSchemaNodeBuilder) {
+ refineLeaf((LeafSchemaNodeBuilder) nodeToRefine, refine);
+ } else if (nodeToRefine instanceof ContainerSchemaNodeBuilder) {
+ refineContainer((ContainerSchemaNodeBuilder) nodeToRefine, refine, line);
+ } else if (nodeToRefine instanceof ListSchemaNodeBuilder) {
+ refineList((ListSchemaNodeBuilder) nodeToRefine, refine, line);
+ } else if (nodeToRefine instanceof LeafListSchemaNodeBuilder) {
+ refineLeafList((LeafListSchemaNodeBuilder) nodeToRefine, refine, line);
+ } else if (nodeToRefine instanceof ChoiceBuilder) {
+ refineChoice((ChoiceBuilder) nodeToRefine, refine, line);
+ } else if (nodeToRefine instanceof AnyXmlBuilder) {
+ refineAnyxml((AnyXmlBuilder) nodeToRefine, refine, line);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Utility class that provides topological sort
+ */
+public final class TopologicalSort {
+
+ /**
+ * Topological sort of dependent nodes in acyclic graphs.
+ *
+ * @return Sorted {@link List} of {@link Node}s. Order: Nodes with no
+ * dependencies starting.
+ * @throws IllegalStateException
+ * when cycle is present in the graph
+ */
+ public static List<Node> sort(Set<Node> nodes) {
+ List<Node> sortedNodes = Lists.newArrayList();
+
+ Set<Node> dependentNodes = getDependentNodes(nodes);
+
+ while (!dependentNodes.isEmpty()) {
+ Node n = dependentNodes.iterator().next();
+ dependentNodes.remove(n);
+
+ sortedNodes.add(n);
+
+ for (Edge e : n.getInEdges()) {
+ Node m = e.getFrom();
+ m.getOutEdges().remove(e);
+
+ if (m.getOutEdges().isEmpty()) {
+ dependentNodes.add(m);
+ }
+ }
+ }
+
+ detectCycles(nodes);
+
+ return sortedNodes;
+ }
+
+ private static Set<Node> getDependentNodes(Set<Node> nodes) {
+ Set<Node> S = Sets.newHashSet();
+ for (Node n : nodes) {
+ if (n.getOutEdges().size() == 0) {
+ S.add(n);
+ }
+ }
+ return S;
+ }
+
+ private static void detectCycles(Set<Node> nodes) {
+ // Detect cycles
+ boolean cycle = false;
+ Node cycledNode = null;
+
+ for (Node n : nodes) {
+ if (!n.getOutEdges().isEmpty()) {
+ cycle = true;
+ cycledNode = n;
+ break;
+ }
+ }
+ Preconditions.checkState(cycle == false,
+ "Cycle detected in graph around node: " + cycledNode);
+ }
+
+ /**
+ * Interface for nodes in graph that can be sorted topologically
+ */
+ public static interface Node {
+ Set<Edge> getInEdges();
+
+ Set<Edge> getOutEdges();
+ }
+
+ /**
+ * Interface for edges in graph that can be sorted topologically
+ */
+ public static interface Edge {
+ Node getFrom();
+
+ Node getTo();
+ }
+
+ /**
+ * Basic Node implementation.
+ */
+ public static class NodeImpl implements Node {
+ private final Set<Edge> inEdges;
+ private final Set<Edge> outEdges;
+
+ @Override
+ public Set<Edge> getInEdges() {
+ return inEdges;
+ }
+
+ @Override
+ public Set<Edge> getOutEdges() {
+ return outEdges;
+ }
+
+ public void addEdge(Node to) {
+ Edge e = new EdgeImpl(this, to);
+ outEdges.add(e);
+ to.getInEdges().add(e);
+ }
+
+ public NodeImpl() {
+ inEdges = Sets.newHashSet();
+ outEdges = Sets.newHashSet();
+ }
+ }
+
+ /**
+ * Basic Edge implementation
+ */
+ public static class EdgeImpl implements Edge {
+ private final Node from;
+ private final Node to;
+
+ @Override
+ public Node getFrom() {
+ return from;
+ }
+
+ @Override
+ public Node getTo() {
+ return to;
+ }
+
+ public EdgeImpl(Node from, Node to) {
+ this.from = from;
+ this.to = to;
+
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((from == null) ? 0 : from.hashCode());
+ result = prime * result + ((to == null) ? 0 : to.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ EdgeImpl other = (EdgeImpl) obj;
+ if (from == null) {
+ if (other.from != null)
+ return false;
+ } else if (!from.equals(other.from))
+ return false;
+ if (to == null) {
+ if (other.to != null)
+ return false;
+ } else if (!to.equals(other.to))
+ return false;
+ return true;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
+import org.opendaylight.controller.yang.model.util.BaseConstraints;
+
+/**
+ * Holder object for holding YANG type constraints.
+ */
+public final class TypeConstraints {
+ private final String moduleName;
+ private final int line;
+ private final List<List<RangeConstraint>> ranges = new ArrayList<List<RangeConstraint>>();
+ private final List<List<LengthConstraint>> lengths = new ArrayList<List<LengthConstraint>>();
+ private final List<List<PatternConstraint>> patterns = new ArrayList<List<PatternConstraint>>();
+ private final List<Integer> fractionDigits = new ArrayList<Integer>();
+
+ public TypeConstraints(final String moduleName, final int line) {
+ this.moduleName = moduleName;
+ this.line = line;
+ }
+
+ List<List<RangeConstraint>> getAllRanges() {
+ return ranges;
+ }
+
+ public List<RangeConstraint> getRange() {
+ if (ranges.size() < 2) {
+ return Collections.emptyList();
+ }
+
+ final List<RangeConstraint> resolved = ranges.get(0);
+ RangeConstraint firstRange = resolved.get(0);
+ RangeConstraint lastRange = resolved.get(resolved.size() - 1);
+ Number min = firstRange.getMin();
+ Number max = lastRange.getMax();
+
+ if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
+ if (ranges.size() > 1) {
+ validateRange(resolved);
+ }
+ return resolved;
+ }
+
+ if (firstRange.equals(lastRange)) {
+ if (min instanceof UnknownBoundaryNumber) {
+ min = resolveMinRange(min);
+ }
+ if (max instanceof UnknownBoundaryNumber) {
+ max = resolveMaxRange(max);
+ }
+ firstRange = BaseConstraints.rangeConstraint(min, max, firstRange.getDescription(),
+ firstRange.getReference());
+ resolved.set(0, firstRange);
+ lastRange = BaseConstraints.rangeConstraint(min, max, lastRange.getDescription(), lastRange.getReference());
+ resolved.set(resolved.size() - 1, lastRange);
+ } else {
+ if (min instanceof UnknownBoundaryNumber) {
+ min = resolveMinRange(min);
+ firstRange = BaseConstraints.rangeConstraint(min, firstRange.getMax(), firstRange.getDescription(),
+ firstRange.getReference());
+ resolved.set(0, firstRange);
+ }
+ if (max instanceof UnknownBoundaryNumber) {
+ max = resolveMaxRange(max);
+ lastRange = BaseConstraints.rangeConstraint(lastRange.getMin(), max, lastRange.getDescription(),
+ lastRange.getReference());
+ resolved.set(resolved.size() - 1, lastRange);
+ }
+ }
+ if (this.ranges.size() > 1) {
+ validateRange(resolved);
+ }
+ return resolved;
+ }
+
+ private Number resolveMinRange(Number min) {
+ int i = 1;
+ while (min instanceof UnknownBoundaryNumber) {
+ final List<RangeConstraint> act = ranges.get(i);
+ min = act.get(0).getMin();
+ i++;
+ }
+ return min;
+ }
+
+ private Number resolveMaxRange(Number max) {
+ int i = 1;
+ while (max instanceof UnknownBoundaryNumber) {
+ final List<RangeConstraint> act = ranges.get(i);
+ max = act.get(act.size() - 1).getMax();
+ i++;
+ }
+ return max;
+ }
+
+ public void addRanges(final List<RangeConstraint> ranges) {
+ if (ranges != null && !(ranges.isEmpty())) {
+ this.ranges.add(ranges);
+ }
+ }
+
+ public List<List<LengthConstraint>> getAllLengths() {
+ return lengths;
+ }
+
+ public List<LengthConstraint> getLength() {
+ if (lengths.size() < 2) {
+ return Collections.emptyList();
+ }
+
+ final List<LengthConstraint> resolved = lengths.get(0);
+ LengthConstraint firstLength = resolved.get(0);
+ LengthConstraint lastLength = resolved.get(resolved.size() - 1);
+ Number min = firstLength.getMin();
+ Number max = lastLength.getMax();
+
+ if (!(min instanceof UnknownBoundaryNumber) && !(max instanceof UnknownBoundaryNumber)) {
+ if (lengths.size() > 1) {
+ validateLength(resolved);
+ }
+ return resolved;
+ }
+
+ if (firstLength.equals(lastLength)) {
+ if (min instanceof UnknownBoundaryNumber) {
+ min = resolveMinLength(min);
+ }
+ if (max instanceof UnknownBoundaryNumber) {
+ max = resolveMaxLength(max);
+ }
+ firstLength = BaseConstraints.lengthConstraint(min, max, firstLength.getDescription(),
+ firstLength.getReference());
+ resolved.set(0, firstLength);
+ lastLength = BaseConstraints.lengthConstraint(min, max, lastLength.getDescription(),
+ lastLength.getReference());
+ resolved.set(resolved.size() - 1, lastLength);
+ } else {
+ if (min instanceof UnknownBoundaryNumber) {
+ min = resolveMinLength(min);
+ firstLength = BaseConstraints.lengthConstraint(min, firstLength.getMax(), firstLength.getDescription(),
+ firstLength.getReference());
+ resolved.set(0, firstLength);
+ }
+ if (max instanceof UnknownBoundaryNumber) {
+ max = resolveMaxLength(max);
+ lastLength = BaseConstraints.lengthConstraint(lastLength.getMin(), max, lastLength.getDescription(),
+ lastLength.getReference());
+ resolved.set(resolved.size() - 1, lastLength);
+ }
+ }
+
+ if (lengths.size() > 1) {
+ validateLength(resolved);
+ }
+ return resolved;
+ }
+
+ private Number resolveMinLength(Number min) {
+ int i = 1;
+ while (min instanceof UnknownBoundaryNumber) {
+ final List<LengthConstraint> act = lengths.get(i);
+ min = act.get(0).getMin();
+ i++;
+ }
+ return min;
+ }
+
+ private Number resolveMaxLength(Number max) {
+ int i = 1;
+ while (max instanceof UnknownBoundaryNumber) {
+ final List<LengthConstraint> act = lengths.get(i);
+ max = act.get(act.size() - 1).getMax();
+ i++;
+ }
+ return max;
+ }
+
+ public void addLengths(final List<LengthConstraint> lengths) {
+ if (lengths != null && !(lengths.isEmpty())) {
+ this.lengths.add(lengths);
+ }
+ }
+
+ public List<PatternConstraint> getPatterns() {
+ if(patterns.isEmpty()) {
+ return Collections.emptyList();
+ }
+ return patterns.get(0);
+ }
+
+ public void addPatterns(final List<PatternConstraint> patterns) {
+ this.patterns.add(patterns);
+ }
+
+ public Integer getFractionDigits() {
+ if (fractionDigits.isEmpty()) {
+ return null;
+ }
+ return fractionDigits.get(0);
+ }
+
+ public void addFractionDigits(final Integer fractionDigits) {
+ this.fractionDigits.add(fractionDigits);
+ }
+
+ public void validateConstraints() {
+ validateLength();
+ validateRange();
+ }
+
+ private void validateRange() {
+ if (ranges.size() < 2) {
+ return;
+ }
+ List<RangeConstraint> typeRange = getRange();
+
+ for (RangeConstraint range : typeRange) {
+ if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
+ throw new YangParseException(moduleName, line, "Unresolved range constraints");
+ }
+ final long min = range.getMin().longValue();
+ final long max = range.getMax().longValue();
+
+ List<RangeConstraint> parentRanges = ranges.get(1);
+ boolean check = false;
+ for (RangeConstraint r : parentRanges) {
+ Number parentMinNumber = r.getMin();
+ if (parentMinNumber instanceof UnknownBoundaryNumber) {
+ parentMinNumber = resolveMinRange(parentMinNumber);
+ }
+ long parentMin = parentMinNumber.longValue();
+
+ Number parentMaxNumber = r.getMax();
+ if (parentMaxNumber instanceof UnknownBoundaryNumber) {
+ parentMaxNumber = resolveMaxRange(parentMaxNumber);
+ }
+ long parentMax = parentMaxNumber.longValue();
+
+ if (parentMin <= min && parentMax >= max) {
+ check = true;
+ break;
+ }
+ }
+ if (!check) {
+ throw new YangParseException(moduleName, line, "Invalid range constraint: <" + min + ", " + max
+ + "> (parent: " + parentRanges + ").");
+ }
+ }
+ }
+
+ private void validateRange(List<RangeConstraint> typeRange) {
+ if (ranges.size() < 2) {
+ return;
+ }
+
+ for (RangeConstraint range : typeRange) {
+ if (range.getMin() instanceof UnknownBoundaryNumber || range.getMax() instanceof UnknownBoundaryNumber) {
+ throw new YangParseException(moduleName, line, "Unresolved range constraints");
+ }
+ final long min = range.getMin().longValue();
+ final long max = range.getMax().longValue();
+
+ List<RangeConstraint> parentRanges = ranges.get(1);
+ boolean check = false;
+ for (RangeConstraint r : parentRanges) {
+ Number parentMinNumber = r.getMin();
+ if (parentMinNumber instanceof UnknownBoundaryNumber) {
+ parentMinNumber = resolveMinRange(parentMinNumber);
+ }
+ long parentMin = parentMinNumber.longValue();
+
+ Number parentMaxNumber = r.getMax();
+ if (parentMaxNumber instanceof UnknownBoundaryNumber) {
+ parentMaxNumber = resolveMaxRange(parentMaxNumber);
+ }
+ long parentMax = parentMaxNumber.longValue();
+
+ if (parentMin <= min && parentMax >= max) {
+ check = true;
+ break;
+ }
+ }
+ if (!check) {
+ throw new YangParseException(moduleName, line, "Invalid range constraint: <" + min + ", " + max
+ + "> (parent: " + parentRanges + ").");
+ }
+ }
+ }
+
+ private void validateLength() {
+ if (lengths.size() < 2) {
+ return;
+ }
+ List<LengthConstraint> typeLength = getLength();
+
+ for (LengthConstraint length : typeLength) {
+ if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
+ throw new YangParseException(moduleName, line, "Unresolved length constraints");
+ }
+ final long min = length.getMin().longValue();
+ final long max = length.getMax().longValue();
+
+ List<LengthConstraint> parentLengths = lengths.get(1);
+ boolean check = false;
+ for (LengthConstraint lc : parentLengths) {
+ Number parentMinNumber = lc.getMin();
+ if (parentMinNumber instanceof UnknownBoundaryNumber) {
+ parentMinNumber = resolveMinLength(parentMinNumber);
+ }
+ long parentMin = parentMinNumber.longValue();
+
+ Number parentMaxNumber = lc.getMax();
+ if (parentMaxNumber instanceof UnknownBoundaryNumber) {
+ parentMaxNumber = resolveMaxLength(parentMaxNumber);
+ }
+ long parentMax = parentMaxNumber.longValue();
+
+ if (parentMin <= min && parentMax >= max) {
+ check = true;
+ break;
+ }
+ }
+ if (!check) {
+ throw new YangParseException(moduleName, line, "Invalid length constraint: <" + min + ", " + max
+ + "> (parent: " + parentLengths + ").");
+ }
+ }
+ }
+
+ private void validateLength(List<LengthConstraint> typeLength) {
+ if (lengths.size() < 2) {
+ return;
+ }
+
+ for (LengthConstraint length : typeLength) {
+ if (length.getMin() instanceof UnknownBoundaryNumber || length.getMax() instanceof UnknownBoundaryNumber) {
+ throw new YangParseException(moduleName, line, "Unresolved length constraints");
+ }
+ final long min = length.getMin().longValue();
+ final long max = length.getMax().longValue();
+
+ List<LengthConstraint> parentLengths = lengths.get(1);
+ boolean check = false;
+ for (LengthConstraint lc : parentLengths) {
+ Number parentMinNumber = lc.getMin();
+ if (parentMinNumber instanceof UnknownBoundaryNumber) {
+ parentMinNumber = resolveMinLength(parentMinNumber);
+ }
+ long parentMin = parentMinNumber.longValue();
+
+ Number parentMaxNumber = lc.getMax();
+ if (parentMaxNumber instanceof UnknownBoundaryNumber) {
+ parentMaxNumber = resolveMaxLength(parentMaxNumber);
+ }
+ long parentMax = parentMaxNumber.longValue();
+
+ if (parentMin <= min && parentMax >= max) {
+ check = true;
+ break;
+ }
+ }
+ if (!check) {
+ throw new YangParseException(moduleName, line, "Invalid length constraint: <" + min + ", " + max
+ + "> (parent: " + parentLengths + ").");
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+/**
+ * Marker object representing special 'min' or 'max' values in YANG.
+ */
+final class UnknownBoundaryNumber extends Number {
+ private static final long serialVersionUID = 1464861684686434869L;
+
+ private final String value;
+
+ UnknownBoundaryNumber(final String value) {
+ this.value = value;
+ }
+
+ @Override
+ public int intValue() {
+ return 0;
+ }
+
+ @Override
+ public long longValue() {
+ return 0;
+ }
+
+ @Override
+ public float floatValue() {
+ return 0;
+ }
+
+ @Override
+ public double doubleValue() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+}
--- /dev/null
+/*
+ * 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/eplv10.html
+ */
+package org.opendaylight.controller.yang.parser.util;
+
+public class YangParseException extends RuntimeException {
+ private static final long serialVersionUID = 1239548963471793178L;
+
+ public YangParseException(final String errorMsg) {
+ super(errorMsg);
+ }
+
+ public YangParseException(final String errorMsg, final Exception exception) {
+ super(errorMsg, exception);
+ }
+
+ public YangParseException(final String moduleName, final int line,
+ final String errorMsg) {
+ super("Error in module '" + moduleName + "' at line " + line + ": "
+ + errorMsg);
+ }
+
+ public YangParseException(final String moduleName, final int line,
+ final String errorMsg, final Exception exception) {
+ super("Error in module '" + moduleName + "' at line " + line + ": "
+ + errorMsg, exception);
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+/**
+ * Unchecked exception thrown if yang definition is not valid according to
+ * {@link YangModelBasicValidationListener}
+ */
+public final class YangValidationException extends RuntimeException {
+
+ private static final long serialVersionUID = 7414330400390825381L;
+
+ public YangValidationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public YangValidationException(String message) {
+ super(message);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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/eplv10.html
+ */
+package org.opendaylight.controller.yang.validator;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
+import org.opendaylight.controller.yang.parser.impl.YangParserListenerImpl;
+import org.opendaylight.controller.yang.parser.util.YangValidationException;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Reusable checks of basic constraints on yang statements
+ */
+final class BasicValidations {
+
+ static final String SUPPORTED_YANG_VERSION = "1";
+
+ static void checkNotPresentBoth(ParseTree parent,
+ Class<? extends ParseTree> childType1,
+ Class<? extends ParseTree> childType2) {
+ if (BasicValidations.checkPresentChildOfTypeSafe(parent, childType1,
+ true)
+ && BasicValidations.checkPresentChildOfTypeSafe(parent,
+ childType2, false))
+ ValidationUtil
+ .ex(ValidationUtil
+ .f("(In (sub)module:%s) Both %s and %s statement present in %s:%s",
+ ValidationUtil.getRootParentName(parent),
+ ValidationUtil
+ .getSimpleStatementName(childType1),
+ ValidationUtil
+ .getSimpleStatementName(childType2),
+ ValidationUtil
+ .getSimpleStatementName(parent
+ .getClass()),
+ ValidationUtil.getName(parent)));
+ }
+
+ static void checkOnlyPermittedValues(ParseTree ctx,
+ Set<String> permittedValues) {
+ String mandatory = ValidationUtil.getName(ctx);
+ String rootParentName = ValidationUtil.getRootParentName(ctx);
+
+ if (!permittedValues.contains(mandatory))
+ ValidationUtil
+ .ex(ValidationUtil
+ .f("(In (sub)module:%s) %s:%s, illegal value for %s statement, only permitted:%s",
+ rootParentName, ValidationUtil
+ .getSimpleStatementName(ctx
+ .getClass()), mandatory,
+ ValidationUtil.getSimpleStatementName(ctx
+ .getClass()), permittedValues));
+ }
+
+ static void checkUniquenessInNamespace(ParseTree stmt, Set<String> uniques) {
+ String name = ValidationUtil.getName(stmt);
+ String rootParentName = ValidationUtil.getRootParentName(stmt);
+
+ if (uniques.contains(name))
+ ValidationUtil.ex(ValidationUtil.f(
+ "(In (sub)module:%s) %s:%s not unique in (sub)module",
+ rootParentName,
+ ValidationUtil.getSimpleStatementName(stmt.getClass()),
+ name));
+ uniques.add(name);
+ }
+
+ /**
+ * Check if only one module or submodule is present in session(one yang
+ * file)
+ */
+ static void checkOnlyOneModulePresent(String moduleName, String globalId) {
+ if (globalId != null)
+ ValidationUtil.ex(ValidationUtil
+ .f("Multiple (sub)modules per file"));
+ }
+
+ static void checkPresentYangVersion(ParseTree ctx, String moduleName) {
+ if (!checkPresentChildOfTypeSafe(ctx, Yang_version_stmtContext.class,
+ true))
+ ValidationUtil
+ .ex(ValidationUtil
+ .f("Yang version statement not present in module:%s, Validating as yang version:%s",
+ moduleName, SUPPORTED_YANG_VERSION));
+ }
+
+ static void checkDateFormat(ParseTree stmt, DateFormat format) {
+ try {
+ format.parse(ValidationUtil.getName(stmt));
+ } catch (ParseException e) {
+ String exceptionMessage = ValidationUtil
+ .f("(In (sub)module:%s) %s:%s, invalid date format expected date format is:%s",
+ ValidationUtil.getRootParentName(stmt),
+ ValidationUtil.getSimpleStatementName(stmt
+ .getClass()), ValidationUtil.getName(stmt),
+ YangParserListenerImpl.simpleDateFormat
+ .format(new Date()));
+ ValidationUtil.ex(exceptionMessage);
+ }
+ }
+
+ static Pattern identifierPattern = Pattern
+ .compile("[a-zA-Z_][a-zA-Z0-9_.-]*");
+
+ static void checkIdentifier(ParseTree statement) {
+ checkIdentifierInternal(statement, ValidationUtil.getName(statement));
+ }
+
+ static void checkIdentifierInternal(ParseTree statement, String name) {
+ if (!identifierPattern.matcher(name).matches()) {
+
+ String message = ValidationUtil
+ .f("%s statement identifier:%s is not in required format:%s",
+ ValidationUtil.getSimpleStatementName(statement
+ .getClass()), name, identifierPattern
+ .toString());
+ String parent = ValidationUtil.getRootParentName(statement);
+ message = parent.equals(name) ? message : ValidationUtil.f(
+ "(In (sub)module:%s) %s", parent, message);
+
+ if(statement instanceof ParserRuleContext) {
+ message = "Error on line "+ ((ParserRuleContext)statement).getStart().getLine() + ": "+ message;
+ }
+
+ ValidationUtil.ex(message);
+ }
+ }
+
+ static Pattern prefixedIdentifierPattern = Pattern.compile("(.+):(.+)");
+
+ static void checkPrefixedIdentifier(ParseTree statement) {
+ checkPrefixedIdentifierInternal(statement,
+ ValidationUtil.getName(statement));
+ }
+
+ private static void checkPrefixedIdentifierInternal(ParseTree statement,
+ String id) {
+ Matcher matcher = prefixedIdentifierPattern.matcher(id);
+
+ if (matcher.matches()) {
+ try {
+ // check prefix
+ checkIdentifierInternal(statement, matcher.group(1));
+ // check ID
+ checkIdentifierInternal(statement, matcher.group(2));
+ } catch (YangValidationException e) {
+ ValidationUtil.ex(ValidationUtil.f(
+ "Prefixed id:%s not in required format, details:%s",
+ id, e.getMessage()));
+ }
+ } else
+ checkIdentifierInternal(statement, id);
+ }
+
+ static void checkSchemaNodeIdentifier(ParseTree statement) {
+ String id = ValidationUtil.getName(statement);
+
+ try {
+ for (String oneOfId : id.split("/")) {
+ if (oneOfId.isEmpty())
+ continue;
+ checkPrefixedIdentifierInternal(statement, oneOfId);
+ }
+ } catch (YangValidationException e) {
+ ValidationUtil.ex(ValidationUtil.f(
+ "Schema node id:%s not in required format, details:%s", id,
+ e.getMessage()));
+ }
+ }
+
+ private static interface MessageProvider {
+ String getMessage();
+ }
+
+ static void checkPresentChildOfTypeInternal(ParseTree parent,
+ Set<Class<? extends ParseTree>> expectedChildType,
+ MessageProvider message, boolean atMostOne) {
+ if (!checkPresentChildOfTypeSafe(parent, expectedChildType, atMostOne)) {
+ String str = atMostOne ? "(Expected exactly one statement) "
+ + message.getMessage() : message.getMessage();
+ ValidationUtil.ex(str);
+ }
+ }
+
+ static void checkPresentChildOfType(final ParseTree parent,
+ final Class<? extends ParseTree> expectedChildType,
+ boolean atMostOne) {
+
+ // Construct message in checkPresentChildOfTypeInternal only if
+ // validaiton fails, not in advance
+ MessageProvider message = new MessageProvider() {
+
+ @Override
+ public String getMessage() {
+ String message = ValidationUtil
+ .f("Missing %s statement in %s:%s", ValidationUtil
+ .getSimpleStatementName(expectedChildType),
+ ValidationUtil.getSimpleStatementName(parent
+ .getClass()), ValidationUtil
+ .getName(parent));
+
+ String root = ValidationUtil.getRootParentName(parent);
+ message = parent.equals(ValidationUtil
+ .getRootParentName(parent)) ? message : ValidationUtil
+ .f("(In (sub)module:%s) %s", root, message);
+ return message;
+ }
+ };
+
+ Set<Class<? extends ParseTree>> expectedChildTypeSet = Sets
+ .newHashSet();
+ expectedChildTypeSet.add(expectedChildType);
+
+ checkPresentChildOfTypeInternal(parent, expectedChildTypeSet, message,
+ atMostOne);
+ }
+
+ static void checkPresentChildOfTypes(final ParseTree parent,
+ final Set<Class<? extends ParseTree>> expectedChildTypes,
+ boolean atMostOne) {
+
+ // Construct message in checkPresentChildOfTypeInternal only if
+ // validaiton fails, not in advance
+ MessageProvider message = new MessageProvider() {
+
+ @Override
+ public String getMessage() {
+ StringBuilder childTypes = new StringBuilder();
+ String orStr = " OR ";
+ for (Class<? extends ParseTree> type : expectedChildTypes) {
+ childTypes.append(ValidationUtil
+ .getSimpleStatementName(type));
+ childTypes.append(orStr);
+ }
+
+ String message = ValidationUtil
+ .f("Missing %s statement in %s:%s", childTypes
+ .toString(), ValidationUtil
+ .getSimpleStatementName(parent.getClass()),
+ ValidationUtil.getName(parent));
+
+ String root = ValidationUtil.getRootParentName(parent);
+ message = parent.equals(ValidationUtil
+ .getRootParentName(parent)) ? message : ValidationUtil
+ .f("(In (sub)module:%s) %s", root, message);
+
+ return message;
+ }
+ };
+
+ checkPresentChildOfTypeInternal(parent, expectedChildTypes, message,
+ atMostOne);
+ }
+
+ static boolean checkPresentChildOfTypeSafe(ParseTree parent,
+ Set<Class<? extends ParseTree>> expectedChildType, boolean atMostOne) {
+
+ int foundChildrenOfType = ValidationUtil.countPresentChildrenOfType(
+ parent, expectedChildType);
+
+ return atMostOne ? foundChildrenOfType == 1 ? true : false
+ : foundChildrenOfType != 0 ? true : false;
+ }
+
+ static boolean checkPresentChildOfTypeSafe(ParseTree parent,
+ Class<? extends ParseTree> expectedChildType, boolean atMostOne) {
+
+ int foundChildrenOfType = ValidationUtil.countPresentChildrenOfType(
+ parent, expectedChildType);
+
+ return atMostOne ? foundChildrenOfType == 1 ? true : false
+ : foundChildrenOfType != 0 ? true : false;
+ }
+
+ static List<String> getAndCheckUniqueKeys(ParseTree ctx) {
+ String key = ValidationUtil.getName(ctx);
+ ParseTree parent = ctx.getParent();
+ String rootParentName = ValidationUtil.getRootParentName(ctx);
+
+ List<String> keyList = ValidationUtil.listKeysFromId(key);
+ Set<String> duplicates = ValidationUtil.getDuplicates(keyList);
+
+ if (duplicates.size() != 0)
+ ValidationUtil.ex(ValidationUtil.f(
+ "(In (sub)module:%s) %s:%s, %s:%s contains duplicates:%s",
+ rootParentName,
+ ValidationUtil.getSimpleStatementName(parent.getClass()),
+ ValidationUtil.getName(parent),
+ ValidationUtil.getSimpleStatementName(ctx.getClass()), key,
+ duplicates));
+ return keyList;
+ }
+}
--- /dev/null
+/*
+ * 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/eplv10.html
+ */
+package org.opendaylight.controller.yang.validator;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
+import org.opendaylight.controller.yang.parser.util.ParserListenerUtils;
+import org.opendaylight.controller.yang.parser.util.YangValidationException;
+
+/**
+ * Validation utilities
+ */
+final class ValidationUtil {
+
+ static void ex(String message) {
+ throw new YangValidationException(message);
+ }
+
+ static Set<String> getDuplicates(Collection<String> keyList) {
+ Set<String> all = new HashSet<String>();
+ Set<String> duplicates = new HashSet<String>();
+
+ for (String key : keyList) {
+ if (!all.add(key))
+ duplicates.add(key);
+ }
+ return duplicates;
+ }
+
+ static List<String> listKeysFromId(String keys) {
+ return Arrays.asList(keys.split(" "));
+ }
+
+ static String getRootParentName(ParseTree ctx) {
+ ParseTree root = getRootParent(ctx);
+ return ValidationUtil.getName(root);
+ }
+
+ private static ParseTree getRootParent(ParseTree ctx) {
+ ParseTree root = ctx;
+ while (root.getParent() != null) {
+ if (root.getClass().equals(Module_stmtContext.class)
+ || root.getClass().equals(Submodule_stmtContext.class))
+ break;
+ root = root.getParent();
+ }
+ return root;
+ }
+
+ static String getName(ParseTree child) {
+ return ParserListenerUtils.stringFromNode(child);
+ }
+
+ static String f(String base, Object... args) {
+ return String.format(base, args);
+ }
+
+ /**
+ * Get simple name from statement class e.g. Module from Module_stmt_context
+ */
+ static String getSimpleStatementName(
+ Class<? extends ParseTree> typeOfStatement) {
+
+ String className = typeOfStatement.getSimpleName();
+ int lastIndexOf = className.indexOf('$');
+ className = lastIndexOf == -1 ? className : className
+ .substring(lastIndexOf + 1);
+ int indexOfStmt = className.indexOf("_stmt");
+ int index = indexOfStmt == -1 ? className.indexOf("_arg") : indexOfStmt;
+ return className.substring(0, index).replace('_', '-');
+ }
+
+ static int countPresentChildrenOfType(ParseTree parent,
+ Set<Class<? extends ParseTree>> expectedChildTypes) {
+ int foundChildrenOfType = 0;
+
+ for (Class<? extends ParseTree> type : expectedChildTypes) {
+ foundChildrenOfType += countPresentChildrenOfType(parent, type);
+ }
+ return foundChildrenOfType;
+ }
+
+ static int countPresentChildrenOfType(ParseTree parent,
+ Class<? extends ParseTree> expectedChildType) {
+ int foundChildrenOfType = 0;
+
+ for (int i = 0; i < parent.getChildCount(); i++) {
+ ParseTree child = parent.getChild(i);
+ if (expectedChildType.isInstance(child))
+ foundChildrenOfType++;
+ }
+ return foundChildrenOfType;
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.validator;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Set;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Anyxml_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Augment_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Case_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Choice_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Container_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviation_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Extension_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Feature_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Grouping_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Identity_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.If_feature_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_list_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Notification_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Rpc_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Typedef_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Unique_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Uses_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener;
+import org.opendaylight.controller.yang.parser.impl.YangParserListenerImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Validation listener that validates yang statements according to RFC-6020.
+ * This validator expects only one module or submodule per file and performs
+ * only basic validation where context from all yang models is not present.
+ */
+final class YangModelBasicValidationListener extends YangParserBaseListener {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(YangModelBasicValidationListener.class);
+
+ private final Set<String> uniquePrefixes;
+ private final Set<String> uniqueImports;
+ private final Set<String> uniqueIncludes;
+
+ private String globalModuleId;
+
+ YangModelBasicValidationListener() {
+ super();
+ uniquePrefixes = Sets.newHashSet();
+ uniqueImports = Sets.newHashSet();
+ uniqueIncludes = Sets.newHashSet();
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Header statements present(mandatory prefix and namespace statements
+ * are in header)</li>
+ * <li>Only one module or submodule per file</li>
+ * </ol>
+ */
+ @Override
+ public void enterModule_stmt(Module_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx,
+ Module_header_stmtsContext.class, true);
+
+ String moduleName = ValidationUtil.getName(ctx);
+ BasicValidations.checkOnlyOneModulePresent(moduleName, globalModuleId);
+ globalModuleId = moduleName;
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Header statements present(mandatory belongs-to statement is in
+ * header)</li>
+ * <li>Only one module or submodule per file</li>
+ * </ol>
+ */
+ @Override
+ public void enterSubmodule_stmt(Submodule_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx,
+ Submodule_header_stmtsContext.class, true);
+
+ String submoduleName = ValidationUtil.getName(ctx);
+ BasicValidations.checkOnlyOneModulePresent(submoduleName,
+ globalModuleId);
+ globalModuleId = submoduleName;
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>One Belongs-to statement present</li>
+ * </ol>
+ */
+ @Override
+ public void enterSubmodule_header_stmts(Submodule_header_stmtsContext ctx) {
+ BasicValidations.checkPresentChildOfType(ctx,
+ Belongs_to_stmtContext.class, true);
+
+ // check Yang version present, if not log
+ try {
+ BasicValidations.checkPresentYangVersion(ctx,
+ ValidationUtil.getRootParentName(ctx));
+ } catch (Exception e) {
+ logger.debug(e.getMessage());
+ }
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>One Namespace statement present</li>
+ * <li>One Prefix statement present</li>
+ * </ol>
+ */
+ @Override
+ public void enterModule_header_stmts(Module_header_stmtsContext ctx) {
+ String moduleName = ValidationUtil.getRootParentName(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx,
+ Namespace_stmtContext.class, true);
+ BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class,
+ true);
+
+ // check Yang version present, if not log
+ try {
+ BasicValidations.checkPresentYangVersion(ctx, moduleName);
+ } catch (Exception e) {
+ logger.debug(e.getMessage());
+ }
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Date is in valid format</li>
+ * </ol>
+ */
+ @Override
+ public void enterRevision_stmt(Revision_stmtContext ctx) {
+ BasicValidations.checkDateFormat(ctx,
+ YangParserListenerImpl.simpleDateFormat);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>One Prefix statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterBelongs_to_stmt(Belongs_to_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class,
+ true);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Namespace string can be parsed as URI</li>
+ * </ol>
+ */
+ @Override
+ public void enterNamespace_stmt(Namespace_stmtContext ctx) {
+ String namespaceName = ValidationUtil.getName(ctx);
+ String rootParentName = ValidationUtil.getRootParentName(ctx);
+
+ try {
+ new URI(namespaceName);
+ } catch (URISyntaxException e) {
+ ValidationUtil.ex(ValidationUtil.f(
+ "(In module:%s) Namespace:%s cannot be parsed as URI",
+ rootParentName, namespaceName));
+ }
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Every import(identified by identifier) within a module/submodule is
+ * present only once</li>
+ * <li>One prefix statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterImport_stmt(Import_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkUniquenessInNamespace(ctx, uniqueImports);
+
+ BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class,
+ true);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Date is in valid format</li>
+ * </ol>
+ */
+ @Override
+ public void enterRevision_date_stmt(Revision_date_stmtContext ctx) {
+ BasicValidations.checkDateFormat(ctx,
+ YangParserListenerImpl.simpleDateFormat);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Every include(identified by identifier) within a module/submodule is
+ * present only once</li>
+ * </ol>
+ */
+ @Override
+ public void enterInclude_stmt(Include_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkUniquenessInNamespace(ctx, uniqueIncludes);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Yang-version is specified as 1</li>
+ * </ol>
+ */
+ @Override
+ public void enterYang_version_stmt(YangParser.Yang_version_stmtContext ctx) {
+ String version = ValidationUtil.getName(ctx);
+ String rootParentName = ValidationUtil.getRootParentName(ctx);
+ if (!version.equals(BasicValidations.SUPPORTED_YANG_VERSION)) {
+ ValidationUtil
+ .ex(ValidationUtil
+ .f("(In (sub)module:%s) Unsupported yang version:%s, supported version:%s",
+ rootParentName, version,
+ BasicValidations.SUPPORTED_YANG_VERSION));
+ }
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Every prefix(identified by identifier) within a module/submodule is
+ * presented only once</li>
+ * </ol>
+ */
+ @Override
+ public void enterPrefix_stmt(Prefix_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkUniquenessInNamespace(ctx, uniquePrefixes);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>One type statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterTypedef_stmt(Typedef_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class,
+ true);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>(Prefix):Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterType_stmt(Type_stmtContext ctx) {
+ BasicValidations.checkPrefixedIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterContainer_stmt(Container_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>One type statement child</li>
+ * <li>Default statement must not be present if mandatory statement is</li>
+ * </ol>
+ */
+ @Override
+ public void enterLeaf_stmt(Leaf_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class,
+ true);
+
+ BasicValidations.checkNotPresentBoth(ctx, Mandatory_stmtContext.class,
+ Default_stmtContext.class);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>One type statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class,
+ true);
+ }
+
+ private static final Set<String> permittedOrderByArgs = Sets.newHashSet(
+ "system", "user");
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: system, user</li>
+ * </ol>
+ */
+ @Override
+ public void enterOrdered_by_arg(Ordered_by_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedOrderByArgs);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterList_stmt(List_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ // TODO check: "if config==true then key must be present" could be
+ // performed
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>No duplicate keys</li>
+ * </ol>
+ */
+ @Override
+ public void enterKey_stmt(Key_stmtContext ctx) {
+ BasicValidations.getAndCheckUniqueKeys(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <liNo duplicate uniques</li>
+ * </ol>
+ */
+ @Override
+ public void enterUnique_stmt(Unique_stmtContext ctx) {
+ BasicValidations.getAndCheckUniqueKeys(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Default statement must not be present if mandatory statement is</li>
+ * </ol>
+ */
+ @Override
+ public void enterChoice_stmt(Choice_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkNotPresentBoth(ctx, Mandatory_stmtContext.class,
+ Default_stmtContext.class);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterCase_stmt(Case_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ private static final Set<String> permittedBooleanArgs = Sets.newHashSet(
+ "true", "false");
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: true, false</li>
+ * </ol>
+ */
+ @Override
+ public void enterMandatory_arg(Mandatory_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterAnyxml_stmt(Anyxml_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterGrouping_stmt(Grouping_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>(Prefix):Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterUses_stmt(Uses_stmtContext ctx) {
+ BasicValidations.checkPrefixedIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterRefine_stmt(Refine_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterRpc_stmt(Rpc_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterNotification_stmt(Notification_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Schema Node Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterAugment_stmt(Augment_stmtContext ctx) {
+ BasicValidations.checkSchemaNodeIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterIdentity_stmt(Identity_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>(Prefix):Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterBase_stmt(Base_stmtContext ctx) {
+ BasicValidations.checkPrefixedIdentifier(ctx);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: true, false</li>
+ * </ol>
+ */
+ @Override
+ public void enterYin_element_arg(Yin_element_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterExtension_stmt(Extension_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterArgument_stmt(Argument_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterFeature_stmt(Feature_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>(Prefix):Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterIf_feature_stmt(If_feature_stmtContext ctx) {
+ BasicValidations.checkPrefixedIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Schema Node Identifier is in required format</li>
+ * <li>At least one deviate-* statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterDeviation_stmt(Deviation_stmtContext ctx) {
+ BasicValidations.checkSchemaNodeIdentifier(ctx);
+
+ Set<Class<? extends ParseTree>> types = Sets.newHashSet();
+ types.add(Deviate_add_stmtContext.class);
+ types.add(Deviate_add_stmtContext.class);
+ BasicValidations.checkPresentChildOfTypes(ctx, types, false);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: true, false</li>
+ * </ol>
+ */
+ @Override
+ public void enterConfig_arg(Config_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs);
+ }
+
+ private static final Set<String> permittedStatusArgs = Sets.newHashSet(
+ "current", "deprecated", "obsolete");
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: "current", "deprecated", "obsolete"</li>
+ * </ol>
+ */
+ @Override
+ public void enterStatus_arg(Status_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedStatusArgs);
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.validator;
+
+import java.util.List;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.opendaylight.controller.yang.parser.util.YangValidationException;
+
+/**
+ * Exposed basic yang validation.
+ *
+ * Every file is validated using {@link YangModelBasicValidationListener}.
+ */
+public final class YangModelBasicValidator {
+
+ private final ParseTreeWalker walker;
+
+ public YangModelBasicValidator(ParseTreeWalker walker) {
+ this.walker = walker;
+ }
+
+ public YangModelBasicValidator() {
+ this.walker = new ParseTreeWalker();
+ }
+
+ public void validate(List<ParseTree> trees) {
+ for (int i = 0; i < trees.size(); i++) {
+ try {
+ final YangModelBasicValidationListener yangModelParser = new YangModelBasicValidationListener();
+ walker.walk(yangModelParser, trees.get(i));
+ } catch (YangValidationException e) {
+ // wrap exception to add information about which file failed
+ throw new YangValidationException(
+ "Yang validation failed for file" + e);
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.model.util.Leafref;
+
+import com.google.common.collect.Lists;
+
+public class AugmentTest {
+
+ private final URI types1NS = URI.create("urn:simple.nodes.test");
+ private final URI types2NS = URI.create("urn:simple.types.test");
+ private final URI types3NS = URI.create("urn:custom.nodes.test");
+ private Date types1Rev;
+ private Date types2Rev;
+ private Date types3Rev;
+ private final String t1 = "n";
+ private final String t2 = "t";
+ private final String t3 = "c";
+ private QName q0;
+ private QName q1;
+ private QName q2;
+
+ private final DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ private Set<Module> modules;
+
+ @Before
+ public void init() throws FileNotFoundException, ParseException {
+ types1Rev = simpleDateFormat.parse("2013-02-27");
+ types2Rev = simpleDateFormat.parse("2013-07-03");
+ types3Rev = simpleDateFormat.parse("2013-02-27");
+
+ q0 = new QName(types2NS, types2Rev, t2, "interfaces");
+ q1 = new QName(types2NS, types2Rev, t2, "ifEntry");
+ q2 = new QName(types3NS, types3Rev, t3, "augment-holder");
+
+ modules = TestUtils.loadModules(getClass().getResource("/model").getPath());
+ assertEquals(3, modules.size());
+ }
+
+ @Test
+ public void testAugmentParsing() {
+ SchemaPath expectedPath = null;
+ QName[] qnames = null;
+
+ // testfile1
+ Module module1 = TestUtils.findModule(modules, "nodes");
+ Set<AugmentationSchema> augmentations = module1.getAugmentations();
+ assertEquals(1, augmentations.size());
+ AugmentationSchema augment = augmentations.iterator().next();
+
+ Set<DataSchemaNode> augmentChildren = augment.getChildNodes();
+ assertEquals(5, augmentChildren.size());
+ for(DataSchemaNode dsn : augmentChildren) {
+ assertTrue(dsn.isAugmenting());
+ }
+
+ LeafSchemaNode ds0ChannelNumber = (LeafSchemaNode) augment.getDataChildByName("ds0ChannelNumber");
+ LeafSchemaNode interfaceId = (LeafSchemaNode) augment.getDataChildByName("interface-id");
+ LeafSchemaNode myType = (LeafSchemaNode) augment.getDataChildByName("my-type");
+ ContainerSchemaNode schemas = (ContainerSchemaNode) augment.getDataChildByName("schemas");
+ ChoiceNode odl = (ChoiceNode)augment.getDataChildByName("odl");
+
+ assertNotNull(ds0ChannelNumber);
+ assertNotNull(interfaceId);
+ assertNotNull(myType);
+ assertNotNull(schemas);
+ assertNotNull(odl);
+
+ qnames = new QName[4];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+
+ // leaf ds0ChannelNumber
+ qnames[3] = new QName(types1NS, types1Rev, t1, "ds0ChannelNumber");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, ds0ChannelNumber.getPath());
+
+ // leaf interface-id
+ qnames[3] = new QName(types1NS, types1Rev, t1, "interface-id");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, interfaceId.getPath());
+
+ // leaf my-type
+ qnames[3] = new QName(types1NS, types1Rev, t1, "my-type");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, myType.getPath());
+
+ // container schemas
+ qnames[3] = new QName(types1NS, types1Rev, t1, "schemas");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, schemas.getPath());
+
+ // choice odl
+ qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, odl.getPath());
+
+
+ // testfile3
+ Module module3 = TestUtils.findModule(modules, "custom");
+ augmentations = module3.getAugmentations();
+ assertEquals(3, augmentations.size());
+ AugmentationSchema augment1 = null;
+ AugmentationSchema augment2 = null;
+ AugmentationSchema augment3 = null;
+ for (AugmentationSchema as : augmentations) {
+ if("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
+ augment1 = as;
+ } else if("if:ifType='ds2'".equals(as.getWhenCondition().toString())) {
+ augment2 = as;
+ } else if ("if:leafType='ds1'".equals(as.getWhenCondition().toString())) {
+ augment3 = as;
+ }
+ }
+ assertNotNull(augment1);
+ assertNotNull(augment2);
+ assertNotNull(augment3);
+
+ assertEquals(1, augment1.getChildNodes().size());
+ ContainerSchemaNode augmentHolder = (ContainerSchemaNode) augment1.getDataChildByName("augment-holder");
+ assertTrue(augmentHolder.isAugmenting());
+
+ assertEquals(1, augment2.getChildNodes().size());
+ ContainerSchemaNode augmentHolder2 = (ContainerSchemaNode) augment2.getDataChildByName("augment-holder2");
+ assertTrue(augmentHolder2.isAugmenting());
+
+ assertEquals(1, augment3.getChildNodes().size());
+ LeafSchemaNode linkleaf = (LeafSchemaNode) augment3.getDataChildByName("linkleaf");
+ assertTrue(linkleaf.isAugmenting());
+ }
+
+ @Test
+ public void testAugmentResolving() throws ParseException {
+ SchemaPath expectedPath = null;
+ QName[] qnames = null;
+
+ Module module2 = TestUtils.findModule(modules, "types");
+ ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName("interfaces");
+ ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+ ContainerSchemaNode augmentedContainer = (ContainerSchemaNode) ifEntry.getDataChildByName("augment-holder");
+
+ // testfile1.yang
+ // augment "/data:interfaces/data:ifEntry/t3:augment-holder"
+ LeafSchemaNode ds0ChannelNumber = (LeafSchemaNode) augmentedContainer.getDataChildByName("ds0ChannelNumber");
+ LeafSchemaNode interfaceId = (LeafSchemaNode) augmentedContainer.getDataChildByName("interface-id");
+ LeafSchemaNode myType = (LeafSchemaNode) augmentedContainer.getDataChildByName("my-type");
+ ContainerSchemaNode schemas = (ContainerSchemaNode) augmentedContainer.getDataChildByName("schemas");
+ ChoiceNode odl = (ChoiceNode)augmentedContainer.getDataChildByName("odl");
+
+ assertNotNull(ds0ChannelNumber);
+ assertNotNull(interfaceId);
+ assertNotNull(myType);
+ assertNotNull(schemas);
+ assertNotNull(odl);
+
+ qnames = new QName[4];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+
+ // leaf ds0ChannelNumber
+ qnames[3] = new QName(types1NS, types1Rev, t1, "ds0ChannelNumber");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, ds0ChannelNumber.getPath());
+
+ // leaf interface-id
+ qnames[3] = new QName(types1NS, types1Rev, t1, "interface-id");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, interfaceId.getPath());
+
+ // leaf my-type
+ qnames[3] = new QName(types1NS, types1Rev, t1, "my-type");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, myType.getPath());
+
+ // container schemas
+ qnames[3] = new QName(types1NS, types1Rev, t1, "schemas");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, schemas.getPath());
+
+ // choice odl
+ qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, odl.getPath());
+
+ // testfile3.yang
+ // augment "/data:interfaces/data:ifEntry/t3:augment-holder/t1:schemas"
+ LeafSchemaNode linkleaf = (LeafSchemaNode) schemas.getDataChildByName("linkleaf");
+ assertNotNull(linkleaf);
+
+ qnames = new QName[5];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+ qnames[3] = new QName(types1NS, types1Rev, t1, "schemas");
+ qnames[4] = new QName(types3NS, types3Rev, t3, "linkleaf");
+ expectedPath = new SchemaPath(Arrays.asList(qnames), true);
+ assertEquals(expectedPath, linkleaf.getPath());
+ }
+
+ @Test
+ public void testAugmentChoice() throws ParseException {
+ SchemaPath expectedPath = null;
+ QName[] qnames = null;
+
+ Module module2 = TestUtils.findModule(modules, "types");
+ ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName("interfaces");
+ ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+ ContainerSchemaNode augmentedContainer = (ContainerSchemaNode) ifEntry.getDataChildByName("augment-holder");
+
+ // testfile1.yang
+ // augment "/data:interfaces/data:ifEntry/t3:augment-holder"
+ ChoiceNode odl = (ChoiceNode)augmentedContainer.getDataChildByName("odl");
+ assertNotNull(odl);
+ Set<ChoiceCaseNode> cases = odl.getCases();
+ assertEquals(4, cases.size());
+
+ ChoiceCaseNode id = null;
+ ChoiceCaseNode node1 = null;
+ ChoiceCaseNode node2 = null;
+ ChoiceCaseNode node3 = null;
+
+ for(ChoiceCaseNode ccn : cases) {
+ if("id".equals(ccn.getQName().getLocalName())) {
+ id = ccn;
+ } else if("node1".equals(ccn.getQName().getLocalName())) {
+ node1 = ccn;
+ } else if("node2".equals(ccn.getQName().getLocalName())) {
+ node2 = ccn;
+ } else if("node3".equals(ccn.getQName().getLocalName())) {
+ node3 = ccn;
+ }
+ }
+
+ assertNotNull(id);
+ assertNotNull(node1);
+ assertNotNull(node2);
+ assertNotNull(node3);
+
+ qnames = new QName[5];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+ qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+
+ // case id
+ qnames[4] = new QName(types1NS, types1Rev, t1, "id");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, id.getPath());
+ Set<DataSchemaNode> idChildren = id.getChildNodes();
+ assertEquals(1, idChildren.size());
+
+ // case node1
+ qnames[4] = new QName(types1NS, types1Rev, t1, "node1");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, node1.getPath());
+ Set<DataSchemaNode> node1Children = node1.getChildNodes();
+ assertTrue(node1Children.isEmpty());
+
+ // case node2
+ qnames[4] = new QName(types1NS, types1Rev, t1, "node2");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, node2.getPath());
+ Set<DataSchemaNode> node2Children = node2.getChildNodes();
+ assertTrue(node2Children.isEmpty());
+
+ // case node3
+ qnames[4] = new QName(types1NS, types1Rev, t1, "node3");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, node3.getPath());
+ Set<DataSchemaNode> node3Children = node3.getChildNodes();
+ assertEquals(1, node3Children.size());
+
+ // test cases
+ qnames = new QName[6];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+ qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+
+ // case id child
+ qnames[4] = new QName(types1NS, types1Rev, t1, "id");
+ qnames[5] = new QName(types1NS, types1Rev, t1, "id");
+ LeafSchemaNode caseIdChild = (LeafSchemaNode)idChildren.iterator().next();
+ assertNotNull(caseIdChild);
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, caseIdChild.getPath());
+
+ // case node3 child
+ qnames[4] = new QName(types1NS, types1Rev, t1, "node3");
+ qnames[5] = new QName(types1NS, types1Rev, t1, "node3");
+ ContainerSchemaNode caseNode3Child = (ContainerSchemaNode)node3Children.iterator().next();
+ assertNotNull(caseNode3Child);
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, caseNode3Child.getPath());
+ }
+
+ @Test
+ public void testAugmentNodesTypeSchemaPath() throws Exception {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ Set<AugmentationSchema> augments = testModule.getAugmentations();
+ assertEquals(1, augments.size());
+ AugmentationSchema augment = augments.iterator().next();
+
+ LeafSchemaNode ifcId = (LeafSchemaNode) augment.getDataChildByName("interface-id");
+ Leafref ifcIdType = (Leafref) ifcId.getType();
+ SchemaPath ifcIdTypeSchemaPath = ifcIdType.getPath();
+ List<QName> ifcIdTypePath = ifcIdTypeSchemaPath.getPath();
+
+ Date expectedDate = simpleDateFormat.parse("2013-02-27");
+
+ QName q3 = new QName(types1NS, expectedDate, "data", "interface-id");
+ assertEquals(q0, ifcIdTypePath.get(0));
+ assertEquals(q1, ifcIdTypePath.get(1));
+ assertEquals(q2, ifcIdTypePath.get(2));
+ assertEquals(q3, ifcIdTypePath.get(3));
+
+ LeafSchemaNode myType = (LeafSchemaNode) augment.getDataChildByName("my-type");
+ ExtendedType leafType = (ExtendedType) myType.getType();
+
+ testModule = TestUtils.findModule(modules, "types");
+ TypeDefinition<?> typedef = TestUtils.findTypedef(testModule.getTypeDefinitions(), "int32-ext2");
+
+ assertEquals(typedef, leafType);
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.MustDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+
+public class GroupingTest {
+ private Set<Module> modules;
+
+ @Before
+ public void init() throws FileNotFoundException {
+ modules = TestUtils.loadModules(getClass().getResource("/model").getPath());
+ assertEquals(3, modules.size());
+ }
+
+ @Test
+ public void testRefine() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+
+ ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("peer");
+ ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
+ Set<UsesNode> usesNodes = destination.getUses();
+ assertEquals(1, usesNodes.size());
+ UsesNode usesNode = usesNodes.iterator().next();
+ Map<SchemaPath, SchemaNode> refines = usesNode.getRefines();
+ assertEquals(5, refines.size());
+
+ LeafSchemaNode refineLeaf = null;
+ ContainerSchemaNode refineContainer = null;
+ ListSchemaNode refineList = null;
+ GroupingDefinition refineGrouping = null;
+ TypeDefinition<?> typedef = null;
+ for (Map.Entry<SchemaPath, SchemaNode> entry : refines.entrySet()) {
+ SchemaNode value = entry.getValue();
+ if (value instanceof LeafSchemaNode) {
+ refineLeaf = (LeafSchemaNode) value;
+ } else if (value instanceof ContainerSchemaNode) {
+ refineContainer = (ContainerSchemaNode) value;
+ } else if (value instanceof ListSchemaNode) {
+ refineList = (ListSchemaNode) value;
+ } else if (value instanceof GroupingDefinition) {
+ refineGrouping = (GroupingDefinition) value;
+ } else if (value instanceof TypeDefinition<?>) {
+ typedef = (TypeDefinition<?>) value;
+ }
+ }
+
+ // leaf address
+ assertNotNull(refineLeaf);
+ assertEquals("address", refineLeaf.getQName().getLocalName());
+ assertEquals("IP address of target node", refineLeaf.getDescription());
+ assertEquals("address reference added by refine", refineLeaf.getReference());
+ assertFalse(refineLeaf.isConfiguration());
+ assertTrue(refineLeaf.getConstraints().isMandatory());
+ Set<MustDefinition> leafMustConstraints = refineLeaf.getConstraints().getMustConstraints();
+ assertEquals(1, leafMustConstraints.size());
+ MustDefinition leafMust = leafMustConstraints.iterator().next();
+ assertEquals("\"ifType != 'ethernet' or (ifType = 'ethernet' and ifMTU = 1500)\"", leafMust.toString());
+
+ // container port
+ assertNotNull(refineContainer);
+ Set<MustDefinition> mustConstraints = refineContainer.getConstraints().getMustConstraints();
+ assertTrue(mustConstraints.isEmpty());
+ assertEquals("description of port defined by refine", refineContainer.getDescription());
+ assertEquals("port reference added by refine", refineContainer.getReference());
+ assertFalse(refineContainer.isConfiguration());
+ assertTrue(refineContainer.isPresenceContainer());
+
+ // list addresses
+ assertNotNull(refineList);
+ assertEquals("description of addresses defined by refine", refineList.getDescription());
+ assertEquals("addresses reference added by refine", refineList.getReference());
+ assertFalse(refineList.isConfiguration());
+ assertEquals(2, (int) refineList.getConstraints().getMinElements());
+ assertEquals(12, (int) refineList.getConstraints().getMaxElements());
+
+ // grouping target-inner
+ assertNotNull(refineGrouping);
+ Set<DataSchemaNode> refineGroupingChildren = refineGrouping.getChildNodes();
+ assertEquals(1, refineGroupingChildren.size());
+ LeafSchemaNode refineGroupingLeaf = (LeafSchemaNode) refineGroupingChildren.iterator().next();
+ assertEquals("inner-grouping-id", refineGroupingLeaf.getQName().getLocalName());
+ assertEquals("new target-inner grouping description", refineGrouping.getDescription());
+
+ // typedef group-type
+ assertNotNull(typedef);
+ assertEquals("new group-type description", typedef.getDescription());
+ assertEquals("new group-type reference", typedef.getReference());
+ assertTrue(typedef.getBaseType() instanceof ExtendedType);
+ }
+
+ @Test
+ public void testGrouping() {
+ Module testModule = TestUtils.findModule(modules, "custom");
+ Set<GroupingDefinition> groupings = testModule.getGroupings();
+ assertEquals(1, groupings.size());
+ GroupingDefinition grouping = groupings.iterator().next();
+ Set<DataSchemaNode> children = grouping.getChildNodes();
+ assertEquals(5, children.size());
+ }
+
+ @Test
+ public void testUses() {
+ // suffix _u = added by uses
+ // suffix _g = defined in grouping
+
+ Module testModule = TestUtils.findModule(modules, "custom");
+
+ // get grouping
+ Set<GroupingDefinition> groupings = testModule.getGroupings();
+ assertEquals(1, groupings.size());
+ GroupingDefinition grouping = groupings.iterator().next();
+
+ testModule = TestUtils.findModule(modules, "nodes");
+
+ // get node containing uses
+ ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("peer");
+ ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
+
+ // check uses
+ Set<UsesNode> uses = destination.getUses();
+ assertEquals(1, uses.size());
+
+ // check uses process
+ AnyXmlSchemaNode data_u = (AnyXmlSchemaNode) destination.getDataChildByName("data");
+ assertNotNull(data_u);
+ assertTrue(data_u.isAddedByUses());
+
+ AnyXmlSchemaNode data_g = (AnyXmlSchemaNode) grouping.getDataChildByName("data");
+ assertNotNull(data_g);
+ assertFalse(data_g.isAddedByUses());
+ assertFalse(data_u.equals(data_g));
+
+ ChoiceNode how_u = (ChoiceNode) destination.getDataChildByName("how");
+ assertNotNull(how_u);
+ assertTrue(how_u.isAddedByUses());
+
+ ChoiceNode how_g = (ChoiceNode) grouping.getDataChildByName("how");
+ assertNotNull(how_g);
+ assertFalse(how_g.isAddedByUses());
+ assertFalse(how_u.equals(how_g));
+
+ LeafSchemaNode address_u = (LeafSchemaNode) destination.getDataChildByName("address");
+ assertNotNull(address_u);
+ assertEquals("1.2.3.4", address_u.getDefault());
+ assertEquals("IP address of target node", address_u.getDescription());
+ assertEquals("address reference added by refine", address_u.getReference());
+ assertFalse(address_u.isConfiguration());
+ assertTrue(address_u.isAddedByUses());
+
+ LeafSchemaNode address_g = (LeafSchemaNode) grouping.getDataChildByName("address");
+ assertNotNull(address_g);
+ assertFalse(address_g.isAddedByUses());
+ assertNull(address_g.getDefault());
+ assertEquals("Target IP address", address_g.getDescription());
+ assertNull(address_g.getReference());
+ assertTrue(address_g.isConfiguration());
+ assertFalse(address_u.equals(address_g));
+
+ ContainerSchemaNode port_u = (ContainerSchemaNode) destination.getDataChildByName("port");
+ assertNotNull(port_u);
+ assertTrue(port_u.isAddedByUses());
+
+ ContainerSchemaNode port_g = (ContainerSchemaNode) grouping.getDataChildByName("port");
+ assertNotNull(port_g);
+ assertFalse(port_g.isAddedByUses());
+ assertFalse(port_u.equals(port_g));
+
+ ListSchemaNode addresses_u = (ListSchemaNode) destination.getDataChildByName("addresses");
+ assertNotNull(addresses_u);
+ assertTrue(addresses_u.isAddedByUses());
+
+ ListSchemaNode addresses_g = (ListSchemaNode) grouping.getDataChildByName("addresses");
+ assertNotNull(addresses_g);
+ assertFalse(addresses_g.isAddedByUses());
+ assertFalse(addresses_u.equals(addresses_g));
+
+ // grouping defined by 'uses'
+ Set<GroupingDefinition> groupings_u = destination.getGroupings();
+ assertEquals(1, groupings_u.size());
+ GroupingDefinition grouping_u = groupings_u.iterator().next();
+ assertTrue(grouping_u.isAddedByUses());
+
+ // grouping defined in 'grouping' node
+ Set<GroupingDefinition> groupings_g = grouping.getGroupings();
+ assertEquals(1, groupings_g.size());
+ GroupingDefinition grouping_g = groupings_g.iterator().next();
+ assertFalse(grouping_g.isAddedByUses());
+ assertFalse(grouping_u.equals(grouping_g));
+
+ List<UnknownSchemaNode> nodes_u = destination.getUnknownSchemaNodes();
+ assertEquals(1, nodes_u.size());
+ UnknownSchemaNode node_u = nodes_u.get(0);
+ assertTrue(node_u.isAddedByUses());
+
+ List<UnknownSchemaNode> nodes_g = grouping.getUnknownSchemaNodes();
+ assertEquals(1, nodes_g.size());
+ UnknownSchemaNode node_g = nodes_g.get(0);
+ assertFalse(node_g.isAddedByUses());
+ assertFalse(node_u.equals(node_g));
+ }
+
+ @Test
+ public void testUsesUnderModule() {
+ // suffix _u = added by uses
+ // suffix _g = defined in grouping
+
+ Module testModule = TestUtils.findModule(modules, "custom");
+
+ // get grouping
+ Set<GroupingDefinition> groupings = testModule.getGroupings();
+ assertEquals(1, groupings.size());
+ GroupingDefinition grouping = groupings.iterator().next();
+
+ // get node containing uses
+ Module destination = TestUtils.findModule(modules, "nodes");
+
+ // check uses
+ Set<UsesNode> uses = destination.getUses();
+ assertEquals(1, uses.size());
+
+ // check uses process
+ AnyXmlSchemaNode data_u = (AnyXmlSchemaNode) destination.getDataChildByName("data");
+ assertNotNull(data_u);
+ assertTrue(data_u.isAddedByUses());
+
+ AnyXmlSchemaNode data_g = (AnyXmlSchemaNode) grouping.getDataChildByName("data");
+ assertNotNull(data_g);
+ assertFalse(data_g.isAddedByUses());
+ assertFalse(data_u.equals(data_g));
+
+ ChoiceNode how_u = (ChoiceNode) destination.getDataChildByName("how");
+ assertNotNull(how_u);
+ assertTrue(how_u.isAddedByUses());
+
+ ChoiceNode how_g = (ChoiceNode) grouping.getDataChildByName("how");
+ assertNotNull(how_g);
+ assertFalse(how_g.isAddedByUses());
+ assertFalse(how_u.equals(how_g));
+
+ LeafSchemaNode address_u = (LeafSchemaNode) destination.getDataChildByName("address");
+ assertNotNull(address_u);
+ assertNull(address_u.getDefault());
+ assertEquals("Target IP address", address_u.getDescription());
+ assertNull(address_u.getReference());
+ assertTrue(address_u.isConfiguration());
+ assertTrue(address_u.isAddedByUses());
+
+ LeafSchemaNode address_g = (LeafSchemaNode) grouping.getDataChildByName("address");
+ assertNotNull(address_g);
+ assertFalse(address_g.isAddedByUses());
+ assertNull(address_g.getDefault());
+ assertEquals("Target IP address", address_g.getDescription());
+ assertNull(address_g.getReference());
+ assertTrue(address_g.isConfiguration());
+ assertFalse(address_u.equals(address_g));
+
+ ContainerSchemaNode port_u = (ContainerSchemaNode) destination.getDataChildByName("port");
+ assertNotNull(port_u);
+ assertTrue(port_u.isAddedByUses());
+
+ ContainerSchemaNode port_g = (ContainerSchemaNode) grouping.getDataChildByName("port");
+ assertNotNull(port_g);
+ assertFalse(port_g.isAddedByUses());
+ assertFalse(port_u.equals(port_g));
+
+ ListSchemaNode addresses_u = (ListSchemaNode) destination.getDataChildByName("addresses");
+ assertNotNull(addresses_u);
+ assertTrue(addresses_u.isAddedByUses());
+
+ ListSchemaNode addresses_g = (ListSchemaNode) grouping.getDataChildByName("addresses");
+ assertNotNull(addresses_g);
+ assertFalse(addresses_g.isAddedByUses());
+ assertFalse(addresses_u.equals(addresses_g));
+
+ // grouping defined by 'uses'
+ Set<GroupingDefinition> groupings_u = destination.getGroupings();
+ assertEquals(1, groupings_u.size());
+ GroupingDefinition grouping_u = groupings_u.iterator().next();
+ assertTrue(grouping_u.isAddedByUses());
+
+ // grouping defined in 'grouping' node
+ Set<GroupingDefinition> groupings_g = grouping.getGroupings();
+ assertEquals(1, groupings_g.size());
+ GroupingDefinition grouping_g = groupings_g.iterator().next();
+ assertFalse(grouping_g.isAddedByUses());
+ assertFalse(grouping_u.equals(grouping_g));
+
+ List<UnknownSchemaNode> nodes_u = destination.getUnknownSchemaNodes();
+ assertEquals(1, nodes_u.size());
+ UnknownSchemaNode node_u = nodes_u.get(0);
+ assertTrue(node_u.isAddedByUses());
+
+ List<UnknownSchemaNode> nodes_g = grouping.getUnknownSchemaNodes();
+ assertEquals(1, nodes_g.size());
+ UnknownSchemaNode node_g = nodes_g.get(0);
+ assertFalse(node_g.isAddedByUses());
+ assertFalse(node_u.equals(node_g));
+
+ UsesNode un = uses.iterator().next();
+ Set<AugmentationSchema> usesAugments = un.getAugmentations();
+ assertEquals(1, usesAugments.size());
+ AugmentationSchema augment = usesAugments.iterator().next();
+ assertEquals("inner augment", augment.getDescription());
+ Set<DataSchemaNode> children = augment.getChildNodes();
+ assertEquals(1, children.size());
+ DataSchemaNode leaf = children.iterator().next();
+ assertTrue(leaf instanceof LeafSchemaNode);
+ assertEquals("name", leaf.getQName().getLocalName());
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.ParseException;
+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;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.ModuleImport;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
+
+final class TestUtils {
+
+ private TestUtils() {
+ }
+
+ public static Set<Module> loadModules(String resourceDirectory) throws FileNotFoundException {
+ YangModelParser parser = new YangParserImpl();
+ final File testDir = new File(resourceDirectory);
+ final String[] fileList = testDir.list();
+ final List<File> testFiles = new ArrayList<File>();
+ if(fileList == null) {
+ throw new FileNotFoundException(resourceDirectory);
+ }
+ for (int i = 0; i < fileList.length; i++) {
+ String fileName = fileList[i];
+ testFiles.add(new File(testDir, fileName));
+ }
+ return parser.parseYangModels(testFiles);
+ }
+
+ public static Set<Module> loadModules(List<InputStream> input) throws IOException {
+ final YangModelParser parser = new YangParserImpl();
+ final Set<Module> modules = new HashSet<Module>(
+ parser.parseYangModelsFromStreams(input));
+ for(InputStream stream : input) {
+ stream.close();
+ }
+ return modules;
+ }
+
+ public static Module loadModule(final InputStream stream) throws
+ IOException {
+ final YangModelParser parser = new YangParserImpl();
+ final List<InputStream> input = Collections.singletonList(stream);
+ final Set<Module> modules = new HashSet<Module>(
+ parser.parseYangModelsFromStreams(input));
+ stream.close();
+ return modules.iterator().next();
+ }
+
+ public static Module loadModuleWithContext(final InputStream stream, final SchemaContext context) throws IOException {
+ final YangModelParser parser = new YangParserImpl();
+ final List<InputStream> input = Collections.singletonList(stream);
+ final Set<Module> modules = new HashSet<Module>(parser.parseYangModelsFromStreams(input, context));
+ stream.close();
+ return modules.iterator().next();
+ }
+
+ public static Set<Module> loadModulesWithContext(final List<InputStream> input, final SchemaContext context) throws IOException {
+ final YangModelParser parser = new YangParserImpl();
+ final Set<Module> modules = new HashSet<Module>(parser.parseYangModelsFromStreams(input, context));
+ for(InputStream is : input) {
+ if(is != null) {
+ is.close();
+ }
+ }
+ return modules;
+ }
+
+ public static Module findModule(Set<Module> modules, String moduleName) {
+ Module result = null;
+ for (Module module : modules) {
+ if (module.getName().equals(moduleName)) {
+ result = module;
+ break;
+ }
+ }
+ return result;
+ }
+
+ public static ModuleImport findImport(Set<ModuleImport> imports,
+ String prefix) {
+ ModuleImport result = null;
+ for (ModuleImport moduleImport : imports) {
+ if (moduleImport.getPrefix().equals(prefix)) {
+ result = moduleImport;
+ break;
+ }
+ }
+ return result;
+ }
+
+ public static TypeDefinition<?> findTypedef(
+ Set<TypeDefinition<?>> typedefs, String name) {
+ TypeDefinition<?> result = null;
+ for (TypeDefinition<?> td : typedefs) {
+ if (td.getQName().getLocalName().equals(name)) {
+ result = td;
+ break;
+ }
+ }
+ return result;
+ }
+
+ public static SchemaPath createPath(boolean absolute, URI namespace,
+ Date revision, String prefix, String... names) {
+ List<QName> path = new ArrayList<QName>();
+ for (String name : names) {
+ path.add(new QName(namespace, revision, prefix, name));
+ }
+ return new SchemaPath(path, absolute);
+ }
+
+ public static Date createDate(String date) {
+ Date result;
+ final DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ try {
+ result = simpleDateFormat.parse(date);
+ } catch (ParseException e) {
+ result = null;
+ }
+ return result;
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;
+import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
+import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition;
+import org.opendaylight.controller.yang.model.util.BitsType;
+import org.opendaylight.controller.yang.model.util.EnumerationType;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.model.util.IdentityrefType;
+import org.opendaylight.controller.yang.model.util.InstanceIdentifier;
+import org.opendaylight.controller.yang.model.util.UnionType;
+
+public class TypesResolutionTest {
+ private Set<Module> testedModules;
+
+ @Before
+ public void init() throws FileNotFoundException {
+ testedModules = TestUtils.loadModules(getClass().getResource("/types").getPath());
+ }
+
+ @Test
+ public void testIPVersion() {
+ Module tested = TestUtils.findModule(testedModules, "ietf-inet-types");
+ Set<TypeDefinition<?>> typedefs = tested.getTypeDefinitions();
+ assertEquals(14, typedefs.size());
+
+ TypeDefinition<?> type = TestUtils.findTypedef(typedefs, "ip-version");
+ assertTrue(type.getDescription().contains("This value represents the version of the IP protocol."));
+ assertTrue(type.getReference().contains("RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"));
+
+ EnumerationType enumType = (EnumerationType) type.getBaseType();
+ List<EnumPair> values = enumType.getValues();
+ assertEquals(3, values.size());
+
+ EnumPair value0 = values.get(0);
+ assertEquals("unknown", value0.getName());
+ assertEquals(0, (int) value0.getValue());
+ assertEquals("An unknown or unspecified version of the Internet protocol.", value0.getDescription());
+
+ EnumPair value1 = values.get(1);
+ assertEquals("ipv4", value1.getName());
+ assertEquals(1, (int) value1.getValue());
+ assertEquals("The IPv4 protocol as defined in RFC 791.", value1.getDescription());
+
+ EnumPair value2 = values.get(2);
+ assertEquals("ipv6", value2.getName());
+ assertEquals(2, (int) value2.getValue());
+ assertEquals("The IPv6 protocol as defined in RFC 2460.", value2.getDescription());
+ }
+
+ @Test
+ public void testEnumeration() {
+ Module tested = TestUtils.findModule(testedModules, "custom-types-test");
+ Set<TypeDefinition<?>> typedefs = tested.getTypeDefinitions();
+
+ TypeDefinition<?> type = TestUtils.findTypedef(typedefs, "ip-version");
+ EnumerationType enumType = (EnumerationType) type.getBaseType();
+ List<EnumPair> values = enumType.getValues();
+ assertEquals(4, values.size());
+
+ EnumPair value0 = values.get(0);
+ assertEquals("unknown", value0.getName());
+ assertEquals(0, (int) value0.getValue());
+ assertEquals("An unknown or unspecified version of the Internet protocol.", value0.getDescription());
+
+ EnumPair value1 = values.get(1);
+ assertEquals("ipv4", value1.getName());
+ assertEquals(19, (int) value1.getValue());
+ assertEquals("The IPv4 protocol as defined in RFC 791.", value1.getDescription());
+
+ EnumPair value2 = values.get(2);
+ assertEquals("ipv6", value2.getName());
+ assertEquals(7, (int) value2.getValue());
+ assertEquals("The IPv6 protocol as defined in RFC 2460.", value2.getDescription());
+
+ EnumPair value3 = values.get(3);
+ assertEquals("default", value3.getName());
+ assertEquals(20, (int) value3.getValue());
+ assertEquals("default ip", value3.getDescription());
+ }
+
+ @Test
+ public void testIpAddress() {
+ Module tested = TestUtils.findModule(testedModules, "ietf-inet-types");
+ Set<TypeDefinition<?>> typedefs = tested.getTypeDefinitions();
+ TypeDefinition<?> type = TestUtils.findTypedef(typedefs, "ip-address");
+ UnionType baseType = (UnionType) type.getBaseType();
+ List<TypeDefinition<?>> unionTypes = baseType.getTypes();
+
+ ExtendedType ipv4 = (ExtendedType) unionTypes.get(0);
+ assertTrue(ipv4.getBaseType() instanceof StringTypeDefinition);
+ String expectedPattern = "(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}"
+ + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" + "(%[\\p{N}\\p{L}]+)?";
+ assertEquals(expectedPattern, ipv4.getPatterns().get(0).getRegularExpression());
+
+ TypeDefinition<?> ipv4Address = TestUtils.findTypedef(typedefs, "ipv4-address");
+ assertEquals(ipv4Address, ipv4);
+
+ ExtendedType ipv6 = (ExtendedType) unionTypes.get(1);
+ assertTrue(ipv6.getBaseType() instanceof StringTypeDefinition);
+ List<PatternConstraint> ipv6Patterns = ipv6.getPatterns();
+ expectedPattern = "((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}"
+ + "((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|" + "(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}"
+ + "(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))" + "(%[\\p{N}\\p{L}]+)?";
+ assertEquals(expectedPattern, ipv6Patterns.get(0).getRegularExpression());
+
+ TypeDefinition<?> ipv6Address = TestUtils.findTypedef(typedefs, "ipv6-address");
+ assertEquals(ipv6Address, ipv6);
+
+ expectedPattern = "(([^:]+:){6}(([^:]+:[^:]+)|(.*\\..*)))|" + "((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)"
+ + "(%.+)?";
+ assertEquals(expectedPattern, ipv6Patterns.get(1).getRegularExpression());
+ }
+
+ @Test
+ public void testDomainName() {
+ Module tested = TestUtils.findModule(testedModules, "ietf-inet-types");
+ Set<TypeDefinition<?>> typedefs = tested.getTypeDefinitions();
+ ExtendedType type = (ExtendedType) TestUtils.findTypedef(typedefs, "domain-name");
+ assertTrue(type.getBaseType() instanceof StringTypeDefinition);
+ List<PatternConstraint> patterns = type.getPatterns();
+ assertEquals(1, patterns.size());
+ String expectedPattern = "((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*"
+ + "([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)" + "|\\.";
+ assertEquals(expectedPattern, patterns.get(0).getRegularExpression());
+
+ List<LengthConstraint> lengths = type.getLengths();
+ assertEquals(1, lengths.size());
+ LengthConstraint length = type.getLengths().get(0);
+ assertEquals(1L, length.getMin());
+ assertEquals(253L, length.getMax());
+ }
+
+ @Test
+ public void testInstanceIdentifier1() {
+ Module tested = TestUtils.findModule(testedModules, "custom-types-test");
+ LeafSchemaNode leaf = (LeafSchemaNode) tested.getDataChildByName("inst-id-leaf1");
+ InstanceIdentifier leafType = (InstanceIdentifier) leaf.getType();
+ assertFalse(leafType.requireInstance());
+ }
+
+ @Test
+ public void testInstanceIdentifier2() {
+ Module tested = TestUtils.findModule(testedModules, "custom-types-test");
+ LeafSchemaNode leaf = (LeafSchemaNode) tested.getDataChildByName("inst-id-leaf2");
+ InstanceIdentifier leafType = (InstanceIdentifier) leaf.getType();
+ assertTrue(leafType.requireInstance());
+ }
+
+ @Test
+ public void testIdentity() {
+ Module tested = TestUtils.findModule(testedModules, "custom-types-test");
+ Set<IdentitySchemaNode> identities = tested.getIdentities();
+ IdentitySchemaNode testedIdentity = null;
+ for (IdentitySchemaNode id : identities) {
+ if (id.getQName().getLocalName().equals("crypto-alg")) {
+ testedIdentity = id;
+ IdentitySchemaNode baseIdentity = id.getBaseIdentity();
+ assertEquals("crypto-base", baseIdentity.getQName().getLocalName());
+ assertNull(baseIdentity.getBaseIdentity());
+ }
+ }
+ assertNotNull(testedIdentity);
+ }
+
+ @Test
+ public void testBitsType1() {
+ Module tested = TestUtils.findModule(testedModules, "custom-types-test");
+ LeafSchemaNode leaf = (LeafSchemaNode) tested.getDataChildByName("mybits");
+ BitsType leafType = (BitsType) leaf.getType();
+ List<Bit> bits = leafType.getBits();
+ assertEquals(3, bits.size());
+
+ Bit bit1 = bits.get(0);
+ assertEquals("disable-nagle", bit1.getName());
+ assertEquals(0L, (long) bit1.getPosition());
+
+ Bit bit2 = bits.get(1);
+ assertEquals("auto-sense-speed", bit2.getName());
+ assertEquals(1L, (long) bit2.getPosition());
+
+ Bit bit3 = bits.get(2);
+ assertEquals("10-Mb-only", bit3.getName());
+ assertEquals(2L, (long) bit3.getPosition());
+ }
+
+ @Test
+ public void testBitsType2() {
+ Module tested = TestUtils.findModule(testedModules, "custom-types-test");
+ Set<TypeDefinition<?>> typedefs = tested.getTypeDefinitions();
+ TypeDefinition<?> testedType = TestUtils.findTypedef(typedefs, "access-operations-type");
+
+ BitsType bitsType = (BitsType) testedType.getBaseType();
+ List<Bit> bits = bitsType.getBits();
+ assertEquals(5, bits.size());
+
+ Bit bit0 = bits.get(0);
+ assertEquals(0L, (long) bit0.getPosition());
+
+ Bit bit1 = bits.get(1);
+ assertEquals(500L, (long) bit1.getPosition());
+
+ Bit bit2 = bits.get(2);
+ assertEquals(501L, (long) bit2.getPosition());
+
+ Bit bit3 = bits.get(3);
+ assertEquals(365L, (long) bit3.getPosition());
+
+ Bit bit4 = bits.get(4);
+ assertEquals(502L, (long) bit4.getPosition());
+ }
+
+ @Test
+ public void testIanaTimezones() {
+ Module tested = TestUtils.findModule(testedModules, "iana-timezones");
+ Set<TypeDefinition<?>> typedefs = tested.getTypeDefinitions();
+ TypeDefinition<?> testedType = TestUtils.findTypedef(typedefs, "iana-timezone");
+
+ String expectedDesc = "A timezone location as defined by the IANA timezone";
+ assertTrue(testedType.getDescription().contains(expectedDesc));
+ assertNull(testedType.getReference());
+ assertEquals(Status.CURRENT, testedType.getStatus());
+
+ QName testedTypeQName = testedType.getQName();
+ assertEquals(URI.create("urn:ietf:params:xml:ns:yang:iana-timezones"), testedTypeQName.getNamespace());
+ assertEquals(TestUtils.createDate("2012-07-09"), testedTypeQName.getRevision());
+ assertEquals("ianatz", testedTypeQName.getPrefix());
+ assertEquals("iana-timezone", testedTypeQName.getLocalName());
+
+ EnumerationType enumType = (EnumerationType) testedType.getBaseType();
+ List<EnumPair> values = enumType.getValues();
+ assertEquals(415, values.size()); // 0-414
+
+ EnumPair enum168 = values.get(168);
+ assertEquals("America/Danmarkshavn", enum168.getName());
+ assertEquals(168, (int) enum168.getValue());
+ assertEquals("east coast, north of Scoresbysund", enum168.getDescription());
+
+ EnumPair enum374 = values.get(374);
+ assertEquals("America/Indiana/Winamac", enum374.getName());
+ assertEquals(374, (int) enum374.getValue());
+ assertEquals("Eastern Time - Indiana - Pulaski County", enum374.getDescription());
+ }
+
+ @Test
+ public void testObjectId128() {
+ Module tested = TestUtils.findModule(testedModules, "ietf-yang-types");
+ Set<TypeDefinition<?>> typedefs = tested.getTypeDefinitions();
+ ExtendedType testedType = (ExtendedType) TestUtils.findTypedef(typedefs, "object-identifier-128");
+
+ List<PatternConstraint> patterns = testedType.getPatterns();
+ assertEquals(1, patterns.size());
+ PatternConstraint pattern = patterns.get(0);
+ assertEquals("\\d*(\\.\\d*){1,127}", pattern.getRegularExpression());
+
+ QName testedTypeQName = testedType.getQName();
+ assertEquals(URI.create("urn:ietf:params:xml:ns:yang:ietf-yang-types"), testedTypeQName.getNamespace());
+ assertEquals(TestUtils.createDate("2010-09-24"), testedTypeQName.getRevision());
+ assertEquals("yang", testedTypeQName.getPrefix());
+ assertEquals("object-identifier-128", testedTypeQName.getLocalName());
+
+ ExtendedType testedTypeBase = (ExtendedType) testedType.getBaseType();
+ patterns = testedTypeBase.getPatterns();
+ assertEquals(1, patterns.size());
+
+ pattern = patterns.get(0);
+ assertEquals("(([0-1](\\.[1-3]?[0-9]))|(2\\.(0|([1-9]\\d*))))(\\.(0|([1-9]\\d*)))*",
+ pattern.getRegularExpression());
+
+ QName testedTypeBaseQName = testedTypeBase.getQName();
+ assertEquals(URI.create("urn:ietf:params:xml:ns:yang:ietf-yang-types"), testedTypeBaseQName.getNamespace());
+ assertEquals(TestUtils.createDate("2010-09-24"), testedTypeBaseQName.getRevision());
+ assertEquals("yang", testedTypeBaseQName.getPrefix());
+ assertEquals("object-identifier", testedTypeBaseQName.getLocalName());
+ }
+
+ @Test
+ public void testIdentityref() {
+ Module tested = TestUtils.findModule(testedModules, "custom-types-test");
+ Set<TypeDefinition<?>> typedefs = tested.getTypeDefinitions();
+ TypeDefinition<?> testedType = TestUtils.findTypedef(typedefs, "service-type-ref");
+ IdentityrefType baseType = (IdentityrefType) testedType.getBaseType();
+ QName identity = baseType.getIdentity();
+ assertEquals(URI.create("urn:custom.types.demo"), identity.getNamespace());
+ assertEquals(TestUtils.createDate("2012-04-16"), identity.getRevision());
+ assertEquals("iit", identity.getPrefix());
+ assertEquals("service-type", identity.getLocalName());
+
+ LeafSchemaNode type = (LeafSchemaNode)tested.getDataChildByName("type");
+ assertNotNull(type);
+ TypeDefinition<?> leafType = type.getType();
+ assertEquals(testedType, leafType);
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
+import org.opendaylight.controller.yang.parser.util.YangValidationException;
+
+public class YangParserNegativeTest {
+
+ @Test
+ public void testInvalidImport() throws IOException {
+ try {
+ try (InputStream stream = new FileInputStream(getClass().getResource("/negative-scenario/testfile1.yang")
+ .getPath())) {
+ TestUtils.loadModule(stream);
+ fail("ValidationException should by thrown");
+ }
+ } catch (YangValidationException e) {
+ assertTrue(e.getMessage().contains("Not existing module imported"));
+ }
+ }
+
+ @Test
+ public void testTypeNotFound() throws IOException {
+ try {
+ try (InputStream stream = new FileInputStream(getClass().getResource("/negative-scenario/testfile2.yang")
+ .getPath())) {
+ TestUtils.loadModule(stream);
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ assertEquals(e.getMessage(), "Error in module 'test2' at line 24: Referenced type 'int-ext' not found.");
+ }
+ }
+
+ @Test
+ public void testInvalidAugmentTarget() throws IOException {
+ try {
+ final List<InputStream> streams = new ArrayList<>(2);
+ try (InputStream testFile0 = new FileInputStream(getClass()
+ .getResource("/negative-scenario/testfile0.yang").getPath())) {
+ streams.add(testFile0);
+ try (InputStream testFile3 = new FileInputStream(getClass().getResource(
+ "/negative-scenario/testfile3.yang").getPath())) {
+ streams.add(testFile3);
+ assertEquals("Expected loaded files count is 2", 2, streams.size());
+ TestUtils.loadModules(streams);
+ fail("YangParseException should by thrown");
+ }
+ }
+ } catch (YangParseException e) {
+ assertTrue(e.getMessage().contains("Failed to resolve augments in module 'test3'."));
+ }
+ }
+
+ @Test
+ public void testInvalidRefine() throws IOException {
+ try {
+ try (InputStream stream = new FileInputStream(getClass().getResource("/negative-scenario/testfile4.yang")
+ .getPath())) {
+ TestUtils.loadModule(stream);
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ assertTrue(e.getMessage().contains("Can not refine 'presence' for 'node'."));
+ }
+ }
+
+ @Test
+ public void testInvalidLength() throws IOException {
+ try {
+ try (InputStream stream = new FileInputStream(getClass().getResource("/negative-scenario/testfile5.yang")
+ .getPath())) {
+ TestUtils.loadModule(stream);
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ assertTrue(e.getMessage().contains("Invalid length constraint: <4, 10>"));
+ }
+ }
+
+ @Test
+ public void testInvalidRange() throws IOException {
+ try {
+ try (InputStream stream = new FileInputStream(getClass().getResource("/negative-scenario/testfile6.yang")
+ .getPath())) {
+ TestUtils.loadModule(stream);
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ assertTrue(e.getMessage().contains("Invalid range constraint: <5, 20>"));
+ }
+ }
+
+ @Test
+ public void testDuplicateContainer() throws IOException {
+ try {
+ try (InputStream stream = new FileInputStream(getClass().getResource(
+ "/negative-scenario/duplicity/container.yang").getPath())) {
+ TestUtils.loadModule(stream);
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ String expected = "Error in module 'container' at line 10: Can not add 'container foo': node with same name already declared at line 6";
+ assertEquals(expected, e.getMessage());
+ }
+ }
+
+ @Test
+ public void testDuplicateContainerList() throws IOException {
+ try {
+ try (InputStream stream = new FileInputStream(getClass().getResource(
+ "/negative-scenario/duplicity/container-list.yang").getPath())) {
+ TestUtils.loadModule(stream);
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ String expected = "Error in module 'container-list' at line 10: Can not add 'list foo': node with same name already declared at line 6";
+ assertEquals(expected, e.getMessage());
+ }
+ }
+
+ @Test
+ public void testDuplicateContainerLeaf() throws IOException {
+ try {
+ try (InputStream stream = new FileInputStream(getClass().getResource(
+ "/negative-scenario/duplicity/container-leaf.yang").getPath())) {
+ TestUtils.loadModule(stream);
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ String expected = "Error in module 'container-leaf' at line 10: Can not add 'leaf foo': node with same name already declared at line 6";
+ assertEquals(expected, e.getMessage());
+ }
+ }
+
+ @Test
+ public void testDuplicateTypedef() throws IOException {
+ try {
+ try (InputStream stream = new FileInputStream(getClass().getResource(
+ "/negative-scenario/duplicity/typedef.yang").getPath())) {
+ TestUtils.loadModule(stream);
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ String expected = "Error in module 'typedef' at line 10: typedef with same name 'int-ext' already declared at line 6";
+ assertEquals(expected, e.getMessage());
+ }
+ }
+
+ @Test
+ public void testDuplicityInAugmentTarget1() throws Exception {
+ try {
+ try (InputStream stream1 = new FileInputStream(getClass().getResource(
+ "/negative-scenario/duplicity/augment0.yang").getPath());
+ InputStream stream2 = new FileInputStream(getClass().getResource(
+ "/negative-scenario/duplicity/augment1.yang").getPath())) {
+ TestUtils.loadModules(Arrays.asList(stream1, stream2));
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ String expected = "Error in module 'augment1' at line 11: Can not add 'leaf id' to 'container bar' in module 'augment0': node with same name already declared at line 9";
+ assertEquals(expected, e.getMessage());
+ }
+ }
+
+ @Test
+ public void testDuplicityInAugmentTarget2() throws Exception {
+ try {
+ try (InputStream stream1 = new FileInputStream(getClass().getResource(
+ "/negative-scenario/duplicity/augment0.yang").getPath());
+ InputStream stream2 = new FileInputStream(getClass().getResource(
+ "/negative-scenario/duplicity/augment2.yang").getPath())) {
+ TestUtils.loadModules(Arrays.asList(stream1, stream2));
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ String expected = "Error in module 'augment2' at line 11: Can not add 'anyxml delta' to node 'choice-ext' in module 'augment0': case with same name already declared at line 18";
+ assertEquals(expected, e.getMessage());
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.Deviation;
+import org.opendaylight.controller.yang.model.api.Deviation.Deviate;
+import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
+import org.opendaylight.controller.yang.model.api.FeatureDefinition;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.ModuleImport;
+import org.opendaylight.controller.yang.model.api.NotificationDefinition;
+import org.opendaylight.controller.yang.model.api.RpcDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
+import org.opendaylight.controller.yang.model.util.Decimal64;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.model.util.Int16;
+import org.opendaylight.controller.yang.model.util.Int32;
+import org.opendaylight.controller.yang.model.util.StringType;
+import org.opendaylight.controller.yang.model.util.Uint32;
+import org.opendaylight.controller.yang.model.util.UnionType;
+
+public class YangParserTest {
+
+ private final URI nodesNS = URI.create("urn:simple.nodes.test");
+ private final URI typesNS = URI.create("urn:simple.types.test");
+ private final URI customNS = URI.create("urn:custom.nodes.test");
+ private Date nodesRev;
+ private Date typesRev;
+ private Date customRev;
+
+ private final DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ private Set<Module> modules;
+
+ @Before
+ public void init() throws FileNotFoundException, ParseException {
+ nodesRev = simpleDateFormat.parse("2013-02-27");
+ typesRev = simpleDateFormat.parse("2013-07-03");
+ customRev = simpleDateFormat.parse("2013-02-27");
+
+ modules = TestUtils.loadModules(getClass().getResource("/model").getPath());
+ assertEquals(3, modules.size());
+ }
+
+ @Test
+ public void testHeaders() throws ParseException {
+ Module test = TestUtils.findModule(modules, "nodes");
+
+ assertEquals("nodes", test.getName());
+ assertEquals("1", test.getYangVersion());
+ assertEquals(nodesNS, test.getNamespace());
+ assertEquals("n", test.getPrefix());
+
+ Set<ModuleImport> imports = test.getImports();
+ assertEquals(2, imports.size());
+
+ ModuleImport import2 = TestUtils.findImport(imports, "t");
+ assertEquals("types", import2.getModuleName());
+ assertEquals(typesRev, import2.getRevision());
+
+ ModuleImport import3 = TestUtils.findImport(imports, "c");
+ assertEquals("custom", import3.getModuleName());
+ assertEquals(customRev, import3.getRevision());
+
+ assertEquals("opendaylight", test.getOrganization());
+ assertEquals("http://www.opendaylight.org/", test.getContact());
+ Date expectedRevision = TestUtils.createDate("2013-02-27");
+ assertEquals(expectedRevision, test.getRevision());
+ assertEquals(" WILL BE DEFINED LATER", test.getReference());
+ }
+
+ @Test
+ public void testOrderingTypedef() {
+ Module test = TestUtils.findModule(modules, "types");
+ Set<TypeDefinition<?>> typedefs = test.getTypeDefinitions();
+ String[] expectedOrder = new String[] { "int32-ext1", "int32-ext2", "my-decimal-type", "my-union",
+ "my-union-ext", "nested-union2", "string-ext1", "string-ext2", "string-ext3", "string-ext4" };
+ String[] actualOrder = new String[typedefs.size()];
+
+ int i = 0;
+ for (TypeDefinition<?> type : typedefs) {
+ actualOrder[i] = type.getQName().getLocalName();
+ i++;
+ }
+ assertArrayEquals(expectedOrder, actualOrder);
+ }
+
+ @Test
+ public void testOrderingChildNodes() {
+ Module test = TestUtils.findModule(modules, "nodes");
+ AugmentationSchema augment1 = null;
+ for (AugmentationSchema as : test.getAugmentations()) {
+ if ("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
+ augment1 = as;
+ break;
+ }
+ }
+ assertNotNull(augment1);
+
+ String[] expectedOrder = new String[] { "ds0ChannelNumber", "interface-id", "my-type", "odl", "schemas" };
+ String[] actualOrder = new String[expectedOrder.length];
+
+ int i = 0;
+ for (DataSchemaNode augmentChild : augment1.getChildNodes()) {
+ actualOrder[i] = augmentChild.getQName().getLocalName();
+ i++;
+ }
+
+ assertArrayEquals(expectedOrder, actualOrder);
+ }
+
+ @Test
+ public void testOrderingNestedChildNodes1() {
+ Module test = TestUtils.findModule(modules, "nodes");
+
+ Set<DataSchemaNode> childNodes = test.getChildNodes();
+ String[] expectedOrder = new String[] { "address", "addresses", "custom-union-leaf", "data", "datas",
+ "decimal-leaf", "decimal-leaf2", "ext", "how", "int32-leaf", "length-leaf", "mycont", "peer", "port",
+ "string-leaf", "transfer", "union-leaf" };
+ String[] actualOrder = new String[childNodes.size()];
+
+ int i = 0;
+ for (DataSchemaNode child : childNodes) {
+ actualOrder[i] = child.getQName().getLocalName();
+ i++;
+ }
+ assertArrayEquals(expectedOrder, actualOrder);
+ }
+
+ @Test
+ public void testOrderingNestedChildNodes2() {
+ Module test = TestUtils.findModule(modules, "custom");
+ Set<GroupingDefinition> groupings = test.getGroupings();
+ assertEquals(1, groupings.size());
+ GroupingDefinition target = groupings.iterator().next();
+
+ Set<DataSchemaNode> childNodes = target.getChildNodes();
+ String[] expectedOrder = new String[] { "address", "addresses", "data", "how", "port" };
+ String[] actualOrder = new String[childNodes.size()];
+
+ int i = 0;
+ for (DataSchemaNode child : childNodes) {
+ actualOrder[i] = child.getQName().getLocalName();
+ i++;
+ }
+ assertArrayEquals(expectedOrder, actualOrder);
+ }
+
+ @Test
+ public void testParseContainer() {
+ Module test = TestUtils.findModule(modules, "types");
+ URI expectedNamespace = URI.create("urn:simple.types.test");
+ String expectedPrefix = "t";
+
+ ContainerSchemaNode interfaces = (ContainerSchemaNode) test.getDataChildByName("interfaces");
+ // test SchemaNode args
+ QName expectedQName = new QName(expectedNamespace, typesRev, expectedPrefix, "interfaces");
+ assertEquals(expectedQName, interfaces.getQName());
+ SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, typesRev, expectedPrefix, "interfaces");
+ assertEquals(expectedPath, interfaces.getPath());
+ assertNull(interfaces.getDescription());
+ assertNull(interfaces.getReference());
+ assertEquals(Status.CURRENT, interfaces.getStatus());
+ assertEquals(0, interfaces.getUnknownSchemaNodes().size());
+ // test DataSchemaNode args
+ assertFalse(interfaces.isAugmenting());
+ assertTrue(interfaces.isConfiguration());
+ ConstraintDefinition constraints = interfaces.getConstraints();
+ assertNull(constraints.getWhenCondition());
+ assertEquals(0, constraints.getMustConstraints().size());
+ assertFalse(constraints.isMandatory());
+ assertNull(constraints.getMinElements());
+ assertNull(constraints.getMaxElements());
+ // test AugmentationTarget args
+ assertEquals(0, interfaces.getAvailableAugmentations().size());
+ // test ContainerSchemaNode args
+ assertFalse(interfaces.isPresenceContainer());
+ // test DataNodeContainer args
+ assertEquals(0, interfaces.getTypeDefinitions().size());
+ assertEquals(1, interfaces.getChildNodes().size());
+ assertEquals(1, interfaces.getGroupings().size());
+ assertEquals(0, interfaces.getUses().size());
+
+ ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+ assertNotNull(ifEntry);
+ }
+
+ @Test
+ public void testParseList() {
+ Module test = TestUtils.findModule(modules, "types");
+ URI expectedNamespace = URI.create("urn:simple.types.test");
+ String expectedPrefix = "t";
+
+ ContainerSchemaNode interfaces = (ContainerSchemaNode) test.getDataChildByName("interfaces");
+
+ ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+ // test SchemaNode args
+ QName expectedQName = new QName(expectedNamespace, typesRev, expectedPrefix, "ifEntry");
+ assertEquals(expectedQName, ifEntry.getQName());
+ SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, typesRev, expectedPrefix, "interfaces",
+ "ifEntry");
+ assertEquals(expectedPath, ifEntry.getPath());
+ assertNull(ifEntry.getDescription());
+ assertNull(ifEntry.getReference());
+ assertEquals(Status.CURRENT, ifEntry.getStatus());
+ assertEquals(0, ifEntry.getUnknownSchemaNodes().size());
+ // test DataSchemaNode args
+ assertFalse(ifEntry.isAugmenting());
+ assertTrue(ifEntry.isConfiguration());
+ ConstraintDefinition constraints = ifEntry.getConstraints();
+ assertNull(constraints.getWhenCondition());
+ assertEquals(0, constraints.getMustConstraints().size());
+ assertFalse(constraints.isMandatory());
+ assertEquals(1, (int) constraints.getMinElements());
+ assertEquals(11, (int) constraints.getMaxElements());
+ // test AugmentationTarget args
+ Set<AugmentationSchema> availableAugmentations = ifEntry.getAvailableAugmentations();
+ assertEquals(2, availableAugmentations.size());
+ // test ListSchemaNode args
+ List<QName> expectedKey = new ArrayList<QName>();
+ expectedKey.add(new QName(expectedNamespace, typesRev, expectedPrefix, "ifIndex"));
+ assertEquals(expectedKey, ifEntry.getKeyDefinition());
+ assertFalse(ifEntry.isUserOrdered());
+ // test DataNodeContainer args
+ assertEquals(0, ifEntry.getTypeDefinitions().size());
+ assertEquals(4, ifEntry.getChildNodes().size());
+ assertEquals(0, ifEntry.getGroupings().size());
+ assertEquals(0, ifEntry.getUses().size());
+
+ LeafSchemaNode ifIndex = (LeafSchemaNode) ifEntry.getDataChildByName("ifIndex");
+ assertTrue(ifIndex.getType() instanceof Uint32);
+ LeafSchemaNode ifMtu = (LeafSchemaNode) ifEntry.getDataChildByName("ifMtu");
+ assertTrue(ifMtu.getType() instanceof Int32);
+ }
+
+ @Test
+ public void testTypedefRangesResolving() throws ParseException {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode int32Leaf = (LeafSchemaNode) testModule.getDataChildByName("int32-leaf");
+
+ ExtendedType leafType = (ExtendedType) int32Leaf.getType();
+ QName leafTypeQName = leafType.getQName();
+ assertEquals("int32-ext2", leafTypeQName.getLocalName());
+ assertEquals("n", leafTypeQName.getPrefix());
+ assertEquals(nodesNS, leafTypeQName.getNamespace());
+ assertEquals(nodesRev, leafTypeQName.getRevision());
+ assertNull(leafType.getUnits());
+ assertNull(leafType.getDefaultValue());
+ assertTrue(leafType.getLengths().isEmpty());
+ assertTrue(leafType.getPatterns().isEmpty());
+ List<RangeConstraint> ranges = leafType.getRanges();
+ assertEquals(1, ranges.size());
+ RangeConstraint range = ranges.get(0);
+ assertEquals(12L, range.getMin());
+ assertEquals(20L, range.getMax());
+
+ ExtendedType baseType = (ExtendedType) leafType.getBaseType();
+ QName baseTypeQName = baseType.getQName();
+ assertEquals("int32-ext2", baseTypeQName.getLocalName());
+ assertEquals("t", baseTypeQName.getPrefix());
+ assertEquals(typesNS, baseTypeQName.getNamespace());
+ assertEquals(typesRev, baseTypeQName.getRevision());
+ assertEquals("mile", baseType.getUnits());
+ assertEquals("11", baseType.getDefaultValue());
+ assertTrue(leafType.getLengths().isEmpty());
+ assertTrue(leafType.getPatterns().isEmpty());
+ List<RangeConstraint> baseTypeRanges = baseType.getRanges();
+ assertEquals(2, baseTypeRanges.size());
+ RangeConstraint baseTypeRange1 = baseTypeRanges.get(0);
+ assertEquals(3L, baseTypeRange1.getMin());
+ assertEquals(9L, baseTypeRange1.getMax());
+ RangeConstraint baseTypeRange2 = baseTypeRanges.get(1);
+ assertEquals(11L, baseTypeRange2.getMin());
+ assertEquals(20L, baseTypeRange2.getMax());
+
+ ExtendedType base = (ExtendedType) baseType.getBaseType();
+ QName baseQName = base.getQName();
+ assertEquals("int32-ext1", baseQName.getLocalName());
+ assertEquals("t", baseQName.getPrefix());
+ assertEquals(typesNS, baseQName.getNamespace());
+ assertEquals(typesRev, baseQName.getRevision());
+ assertNull(base.getUnits());
+ assertNull(base.getDefaultValue());
+ assertTrue(leafType.getLengths().isEmpty());
+ assertTrue(leafType.getPatterns().isEmpty());
+ List<RangeConstraint> baseRanges = base.getRanges();
+ assertEquals(1, baseRanges.size());
+ RangeConstraint baseRange = baseRanges.get(0);
+ assertEquals(2L, baseRange.getMin());
+ assertEquals(20L, baseRange.getMax());
+
+ assertTrue(base.getBaseType() instanceof Int32);
+ }
+
+ @Test
+ public void testTypedefPatternsResolving() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode stringleaf = (LeafSchemaNode) testModule.getDataChildByName("string-leaf");
+
+ ExtendedType type = (ExtendedType) stringleaf.getType();
+ QName typeQName = type.getQName();
+ assertEquals("string-ext4", typeQName.getLocalName());
+ assertEquals("t", typeQName.getPrefix());
+ assertEquals(typesNS, typeQName.getNamespace());
+ assertEquals(typesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ List<PatternConstraint> patterns = type.getPatterns();
+ assertEquals(1, patterns.size());
+ PatternConstraint pattern = patterns.iterator().next();
+ assertEquals("[e-z]*", pattern.getRegularExpression());
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
+
+ ExtendedType baseType1 = (ExtendedType) type.getBaseType();
+ QName baseType1QName = baseType1.getQName();
+ assertEquals("string-ext3", baseType1QName.getLocalName());
+ assertEquals("t", baseType1QName.getPrefix());
+ assertEquals(typesNS, baseType1QName.getNamespace());
+ assertEquals(typesRev, baseType1QName.getRevision());
+ assertNull(baseType1.getUnits());
+ assertNull(baseType1.getDefaultValue());
+ patterns = baseType1.getPatterns();
+ assertEquals(1, patterns.size());
+ pattern = patterns.iterator().next();
+ assertEquals("[b-u]*", pattern.getRegularExpression());
+ assertTrue(baseType1.getLengths().isEmpty());
+ assertTrue(baseType1.getRanges().isEmpty());
+
+ ExtendedType baseType2 = (ExtendedType) baseType1.getBaseType();
+ QName baseType2QName = baseType2.getQName();
+ assertEquals("string-ext2", baseType2QName.getLocalName());
+ assertEquals("t", baseType2QName.getPrefix());
+ assertEquals(typesNS, baseType2QName.getNamespace());
+ assertEquals(typesRev, baseType2QName.getRevision());
+ assertNull(baseType2.getUnits());
+ assertNull(baseType2.getDefaultValue());
+ assertTrue(baseType2.getPatterns().isEmpty());
+ List<LengthConstraint> baseType2Lengths = baseType2.getLengths();
+ assertEquals(1, baseType2Lengths.size());
+ LengthConstraint length = baseType2Lengths.get(0);
+ assertEquals(6L, length.getMin());
+ assertEquals(10L, length.getMax());
+ assertTrue(baseType2.getRanges().isEmpty());
+
+ ExtendedType baseType3 = (ExtendedType) baseType2.getBaseType();
+ QName baseType3QName = baseType3.getQName();
+ assertEquals("string-ext1", baseType3QName.getLocalName());
+ assertEquals("t", baseType3QName.getPrefix());
+ assertEquals(typesNS, baseType3QName.getNamespace());
+ assertEquals(typesRev, baseType3QName.getRevision());
+ assertNull(baseType3.getUnits());
+ assertNull(baseType3.getDefaultValue());
+ patterns = baseType3.getPatterns();
+ assertEquals(1, patterns.size());
+ pattern = patterns.iterator().next();
+ assertEquals("[a-k]*", pattern.getRegularExpression());
+ List<LengthConstraint> baseType3Lengths = baseType3.getLengths();
+ assertEquals(1, baseType3Lengths.size());
+ length = baseType3Lengths.get(0);
+ assertEquals(5L, length.getMin());
+ assertEquals(11L, length.getMax());
+ assertTrue(baseType3.getRanges().isEmpty());
+
+ assertTrue(baseType3.getBaseType() instanceof StringType);
+ }
+
+ @Test
+ public void testTypedefLengthsResolving() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+
+ LeafSchemaNode lengthLeaf = (LeafSchemaNode) testModule.getDataChildByName("length-leaf");
+ ExtendedType type = (ExtendedType) lengthLeaf.getType();
+
+ QName typeQName = type.getQName();
+ assertEquals("string-ext2", typeQName.getLocalName());
+ assertEquals("n", typeQName.getPrefix());
+ assertEquals(nodesNS, typeQName.getNamespace());
+ assertEquals(nodesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ assertTrue(type.getPatterns().isEmpty());
+ List<LengthConstraint> typeLengths = type.getLengths();
+ assertEquals(1, typeLengths.size());
+ LengthConstraint length = typeLengths.get(0);
+ assertEquals(7L, length.getMin());
+ assertEquals(10L, length.getMax());
+ assertTrue(type.getRanges().isEmpty());
+
+ ExtendedType baseType1 = (ExtendedType) type.getBaseType();
+ QName baseType1QName = baseType1.getQName();
+ assertEquals("string-ext2", baseType1QName.getLocalName());
+ assertEquals("t", baseType1QName.getPrefix());
+ assertEquals(typesNS, baseType1QName.getNamespace());
+ assertEquals(typesRev, baseType1QName.getRevision());
+ assertNull(baseType1.getUnits());
+ assertNull(baseType1.getDefaultValue());
+ assertTrue(baseType1.getPatterns().isEmpty());
+ List<LengthConstraint> baseType2Lengths = baseType1.getLengths();
+ assertEquals(1, baseType2Lengths.size());
+ length = baseType2Lengths.get(0);
+ assertEquals(6L, length.getMin());
+ assertEquals(10L, length.getMax());
+ assertTrue(baseType1.getRanges().isEmpty());
+
+ ExtendedType baseType2 = (ExtendedType) baseType1.getBaseType();
+ QName baseType2QName = baseType2.getQName();
+ assertEquals("string-ext1", baseType2QName.getLocalName());
+ assertEquals("t", baseType2QName.getPrefix());
+ assertEquals(typesNS, baseType2QName.getNamespace());
+ assertEquals(typesRev, baseType2QName.getRevision());
+ assertNull(baseType2.getUnits());
+ assertNull(baseType2.getDefaultValue());
+ List<PatternConstraint> patterns = baseType2.getPatterns();
+ assertEquals(1, patterns.size());
+ PatternConstraint pattern = patterns.iterator().next();
+ assertEquals("[a-k]*", pattern.getRegularExpression());
+ List<LengthConstraint> baseType3Lengths = baseType2.getLengths();
+ assertEquals(1, baseType3Lengths.size());
+ length = baseType3Lengths.get(0);
+ assertEquals(5L, length.getMin());
+ assertEquals(11L, length.getMax());
+ assertTrue(baseType2.getRanges().isEmpty());
+
+ assertTrue(baseType2.getBaseType() instanceof StringType);
+ }
+
+ @Test
+ public void testTypedefDecimal1() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("decimal-leaf");
+
+ ExtendedType type = (ExtendedType) testleaf.getType();
+ QName typeQName = type.getQName();
+ assertEquals("my-decimal-type", typeQName.getLocalName());
+ assertEquals("n", typeQName.getPrefix());
+ assertEquals(nodesNS, typeQName.getNamespace());
+ assertEquals(nodesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ assertEquals(4, (int) type.getFractionDigits());
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getPatterns().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
+
+ ExtendedType typeBase = (ExtendedType) type.getBaseType();
+ QName typeBaseQName = typeBase.getQName();
+ assertEquals("my-decimal-type", typeBaseQName.getLocalName());
+ assertEquals("t", typeBaseQName.getPrefix());
+ assertEquals(typesNS, typeBaseQName.getNamespace());
+ assertEquals(typesRev, typeBaseQName.getRevision());
+ assertNull(typeBase.getUnits());
+ assertNull(typeBase.getDefaultValue());
+ assertNull(typeBase.getFractionDigits());
+ assertTrue(typeBase.getLengths().isEmpty());
+ assertTrue(typeBase.getPatterns().isEmpty());
+ assertTrue(typeBase.getRanges().isEmpty());
+
+ Decimal64 decimal = (Decimal64) typeBase.getBaseType();
+ assertEquals(6, (int) decimal.getFractionDigits());
+ }
+
+ @Test
+ public void testTypedefDecimal2() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("decimal-leaf2");
+
+ ExtendedType type = (ExtendedType) testleaf.getType();
+ QName typeQName = type.getQName();
+ assertEquals("my-decimal-type", typeQName.getLocalName());
+ assertEquals("t", typeQName.getPrefix());
+ assertEquals(typesNS, typeQName.getNamespace());
+ assertEquals(typesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ assertNull(type.getFractionDigits());
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getPatterns().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
+
+ Decimal64 baseTypeDecimal = (Decimal64) type.getBaseType();
+ assertEquals(6, (int) baseTypeDecimal.getFractionDigits());
+ }
+
+ @Test
+ public void testTypedefUnion() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode unionleaf = (LeafSchemaNode) testModule.getDataChildByName("union-leaf");
+
+ ExtendedType type = (ExtendedType) unionleaf.getType();
+ QName typeQName = type.getQName();
+ assertEquals("my-union-ext", typeQName.getLocalName());
+ assertEquals("t", typeQName.getPrefix());
+ assertEquals(typesNS, typeQName.getNamespace());
+ assertEquals(typesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ assertNull(type.getFractionDigits());
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getPatterns().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
+
+ ExtendedType baseType = (ExtendedType) type.getBaseType();
+ QName baseTypeQName = baseType.getQName();
+ assertEquals("my-union", baseTypeQName.getLocalName());
+ assertEquals("t", baseTypeQName.getPrefix());
+ assertEquals(typesNS, baseTypeQName.getNamespace());
+ assertEquals(typesRev, baseTypeQName.getRevision());
+ assertNull(baseType.getUnits());
+ assertNull(baseType.getDefaultValue());
+ assertNull(baseType.getFractionDigits());
+ assertTrue(baseType.getLengths().isEmpty());
+ assertTrue(baseType.getPatterns().isEmpty());
+ assertTrue(baseType.getRanges().isEmpty());
+
+ UnionType unionType = (UnionType) baseType.getBaseType();
+ List<TypeDefinition<?>> unionTypes = unionType.getTypes();
+ assertEquals(2, unionTypes.size());
+
+ ExtendedType unionType1 = (ExtendedType) unionTypes.get(0);
+ QName unionType1QName = baseType.getQName();
+ assertEquals("my-union", unionType1QName.getLocalName());
+ assertEquals("t", unionType1QName.getPrefix());
+ assertEquals(typesNS, unionType1QName.getNamespace());
+ assertEquals(typesRev, unionType1QName.getRevision());
+ assertNull(unionType1.getUnits());
+ assertNull(unionType1.getDefaultValue());
+ assertNull(unionType1.getFractionDigits());
+ assertTrue(unionType1.getLengths().isEmpty());
+ assertTrue(unionType1.getPatterns().isEmpty());
+ List<RangeConstraint> ranges = unionType1.getRanges();
+ assertEquals(1, ranges.size());
+ RangeConstraint range = ranges.get(0);
+ assertEquals(1L, range.getMin());
+ assertEquals(100L, range.getMax());
+ assertTrue(unionType1.getBaseType() instanceof Int16);
+
+ assertTrue(unionTypes.get(1) instanceof Int32);
+ }
+
+ @Test
+ public void testNestedUnionResolving() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("custom-union-leaf");
+
+ ExtendedType type = (ExtendedType) testleaf.getType();
+ QName testleafTypeQName = type.getQName();
+ assertEquals(customNS, testleafTypeQName.getNamespace());
+ assertEquals(customRev, testleafTypeQName.getRevision());
+ assertEquals("c", testleafTypeQName.getPrefix());
+ assertEquals("union1", testleafTypeQName.getLocalName());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ assertNull(type.getFractionDigits());
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getPatterns().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
+
+ ExtendedType typeBase = (ExtendedType) type.getBaseType();
+ QName typeBaseQName = typeBase.getQName();
+ assertEquals(customNS, typeBaseQName.getNamespace());
+ assertEquals(customRev, typeBaseQName.getRevision());
+ assertEquals("c", typeBaseQName.getPrefix());
+ assertEquals("union2", typeBaseQName.getLocalName());
+ assertNull(typeBase.getUnits());
+ assertNull(typeBase.getDefaultValue());
+ assertNull(typeBase.getFractionDigits());
+ assertTrue(typeBase.getLengths().isEmpty());
+ assertTrue(typeBase.getPatterns().isEmpty());
+ assertTrue(typeBase.getRanges().isEmpty());
+
+ UnionType union = (UnionType) typeBase.getBaseType();
+ List<TypeDefinition<?>> unionTypes = union.getTypes();
+ assertEquals(2, unionTypes.size());
+ assertTrue(unionTypes.get(0) instanceof Int32);
+ assertTrue(unionTypes.get(1) instanceof ExtendedType);
+
+ ExtendedType unionType1 = (ExtendedType) unionTypes.get(1);
+ QName uniontType1QName = unionType1.getQName();
+ assertEquals(typesNS, uniontType1QName.getNamespace());
+ assertEquals(typesRev, uniontType1QName.getRevision());
+ assertEquals("t", uniontType1QName.getPrefix());
+ assertEquals("nested-union2", uniontType1QName.getLocalName());
+ assertNull(unionType1.getUnits());
+ assertNull(unionType1.getDefaultValue());
+ assertNull(unionType1.getFractionDigits());
+ assertTrue(unionType1.getLengths().isEmpty());
+ assertTrue(unionType1.getPatterns().isEmpty());
+ assertTrue(unionType1.getRanges().isEmpty());
+
+ UnionType nestedUnion = (UnionType) unionType1.getBaseType();
+ List<TypeDefinition<?>> nestedUnion2Types = nestedUnion.getTypes();
+ assertEquals(2, nestedUnion2Types.size());
+ assertTrue(nestedUnion2Types.get(0) instanceof StringType);
+ assertTrue(nestedUnion2Types.get(1) instanceof ExtendedType);
+
+ ExtendedType myUnionExt = (ExtendedType) nestedUnion2Types.get(1);
+ QName myUnionExtQName = myUnionExt.getQName();
+ assertEquals(typesNS, myUnionExtQName.getNamespace());
+ assertEquals(typesRev, myUnionExtQName.getRevision());
+ assertEquals("t", myUnionExtQName.getPrefix());
+ assertEquals("my-union-ext", myUnionExtQName.getLocalName());
+ assertNull(myUnionExt.getUnits());
+ assertNull(myUnionExt.getDefaultValue());
+ assertNull(myUnionExt.getFractionDigits());
+ assertTrue(myUnionExt.getLengths().isEmpty());
+ assertTrue(myUnionExt.getPatterns().isEmpty());
+ assertTrue(myUnionExt.getRanges().isEmpty());
+
+ ExtendedType myUnion = (ExtendedType) myUnionExt.getBaseType();
+ QName myUnionQName = myUnion.getQName();
+ assertEquals(typesNS, myUnionQName.getNamespace());
+ assertEquals(typesRev, myUnionQName.getRevision());
+ assertEquals("t", myUnionQName.getPrefix());
+ assertEquals("my-union", myUnionQName.getLocalName());
+ assertNull(myUnion.getUnits());
+ assertNull(myUnion.getDefaultValue());
+ assertNull(myUnion.getFractionDigits());
+ assertTrue(myUnion.getLengths().isEmpty());
+ assertTrue(myUnion.getPatterns().isEmpty());
+ assertTrue(myUnion.getRanges().isEmpty());
+
+ UnionType myUnionBase = (UnionType) myUnion.getBaseType();
+ List<TypeDefinition<?>> myUnionBaseTypes = myUnionBase.getTypes();
+ assertEquals(2, myUnionBaseTypes.size());
+ assertTrue(myUnionBaseTypes.get(0) instanceof ExtendedType);
+ assertTrue(myUnionBaseTypes.get(1) instanceof Int32);
+
+ ExtendedType int16Ext = (ExtendedType) myUnionBaseTypes.get(0);
+ QName int16ExtQName = int16Ext.getQName();
+ assertEquals(typesNS, int16ExtQName.getNamespace());
+ assertEquals(typesRev, int16ExtQName.getRevision());
+ assertEquals("t", int16ExtQName.getPrefix());
+ assertEquals("int16", int16ExtQName.getLocalName());
+ assertNull(int16Ext.getUnits());
+ assertNull(int16Ext.getDefaultValue());
+ assertNull(int16Ext.getFractionDigits());
+ assertTrue(int16Ext.getLengths().isEmpty());
+ assertTrue(int16Ext.getPatterns().isEmpty());
+ List<RangeConstraint> ranges = int16Ext.getRanges();
+ assertEquals(1, ranges.size());
+ RangeConstraint range = ranges.get(0);
+ assertEquals(1L, range.getMin());
+ assertEquals(100L, range.getMax());
+
+ assertTrue(int16Ext.getBaseType() instanceof Int16);
+ }
+
+ @Test
+ public void testChoice() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ ContainerSchemaNode transfer = (ContainerSchemaNode) testModule.getDataChildByName("transfer");
+ ChoiceNode how = (ChoiceNode) transfer.getDataChildByName("how");
+ Set<ChoiceCaseNode> cases = how.getCases();
+ assertEquals(5, cases.size());
+ ChoiceCaseNode input = null;
+ ChoiceCaseNode output = null;
+ for (ChoiceCaseNode caseNode : cases) {
+ if ("input".equals(caseNode.getQName().getLocalName())) {
+ input = caseNode;
+ } else if ("output".equals(caseNode.getQName().getLocalName())) {
+ output = caseNode;
+ }
+ }
+ assertNotNull(input);
+ assertNotNull(input.getPath());
+ assertNotNull(output);
+ assertNotNull(output.getPath());
+ }
+
+ @Test
+ public void testAnyXml() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ AnyXmlSchemaNode data = (AnyXmlSchemaNode) testModule.getDataChildByName("datas");
+ assertNotNull("anyxml data not found", data);
+
+ // test SchemaNode args
+ QName qname = data.getQName();
+ assertEquals("datas", qname.getLocalName());
+ assertEquals("n", qname.getPrefix());
+ assertEquals(nodesNS, qname.getNamespace());
+ assertEquals(nodesRev, qname.getRevision());
+ assertTrue(data.getDescription().contains("Copy of the source typesstore subset that matched"));
+ assertNull(data.getReference());
+ assertEquals(Status.OBSOLETE, data.getStatus());
+ assertEquals(0, data.getUnknownSchemaNodes().size());
+ // test DataSchemaNode args
+ assertFalse(data.isAugmenting());
+ assertTrue(data.isConfiguration());
+ ConstraintDefinition constraints = data.getConstraints();
+ assertNull(constraints.getWhenCondition());
+ assertEquals(0, constraints.getMustConstraints().size());
+ assertFalse(constraints.isMandatory());
+ assertNull(constraints.getMinElements());
+ assertNull(constraints.getMaxElements());
+ }
+
+ @Test
+ public void testDeviation() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ Set<Deviation> deviations = testModule.getDeviations();
+ assertEquals(1, deviations.size());
+ Deviation dev = deviations.iterator().next();
+
+ assertEquals("system/user ref", dev.getReference());
+
+ List<QName> path = new ArrayList<QName>();
+ path.add(new QName(typesNS, typesRev, "t", "interfaces"));
+ path.add(new QName(typesNS, typesRev, "t", "ifEntry"));
+ SchemaPath expectedPath = new SchemaPath(path, true);
+
+ assertEquals(expectedPath, dev.getTargetPath());
+ assertEquals(Deviate.ADD, dev.getDeviate());
+ }
+
+ @Test
+ public void testUnknownNode() {
+ Module testModule = TestUtils.findModule(modules, "custom");
+ ContainerSchemaNode network = (ContainerSchemaNode) testModule.getDataChildByName("network");
+ List<UnknownSchemaNode> unknownNodes = network.getUnknownSchemaNodes();
+ assertEquals(1, unknownNodes.size());
+ UnknownSchemaNode unknownNode = unknownNodes.get(0);
+ assertNotNull(unknownNode.getNodeType());
+ assertEquals("point", unknownNode.getNodeParameter());
+ }
+
+ @Test
+ public void testFeature() {
+ Module testModule = TestUtils.findModule(modules, "custom");
+ Set<FeatureDefinition> features = testModule.getFeatures();
+ assertEquals(1, features.size());
+ }
+
+ @Test
+ public void testExtension() {
+ Module testModule = TestUtils.findModule(modules, "custom");
+ List<ExtensionDefinition> extensions = testModule.getExtensionSchemaNodes();
+ assertEquals(1, extensions.size());
+ ExtensionDefinition extension = extensions.get(0);
+ assertEquals("name", extension.getArgument());
+ assertTrue(extension.isYinElement());
+ }
+
+ @Test
+ public void testNotification() {
+ Module testModule = TestUtils.findModule(modules, "custom");
+ String expectedPrefix = "c";
+
+ Set<NotificationDefinition> notifications = testModule.getNotifications();
+ assertEquals(1, notifications.size());
+
+ NotificationDefinition notification = notifications.iterator().next();
+ // test SchemaNode args
+ QName expectedQName = new QName(customNS, customRev, expectedPrefix, "event");
+ assertEquals(expectedQName, notification.getQName());
+ SchemaPath expectedPath = TestUtils.createPath(true, customNS, customRev, expectedPrefix, "event");
+ assertEquals(expectedPath, notification.getPath());
+ assertNull(notification.getDescription());
+ assertNull(notification.getReference());
+ assertEquals(Status.CURRENT, notification.getStatus());
+ assertEquals(0, notification.getUnknownSchemaNodes().size());
+ // test DataNodeContainer args
+ assertEquals(0, notification.getTypeDefinitions().size());
+ assertEquals(3, notification.getChildNodes().size());
+ assertEquals(0, notification.getGroupings().size());
+ assertEquals(0, notification.getUses().size());
+
+ LeafSchemaNode eventClass = (LeafSchemaNode) notification.getDataChildByName("event-class");
+ assertTrue(eventClass.getType() instanceof StringType);
+ AnyXmlSchemaNode reportingEntity = (AnyXmlSchemaNode) notification.getDataChildByName("reporting-entity");
+ assertNotNull(reportingEntity);
+ LeafSchemaNode severity = (LeafSchemaNode) notification.getDataChildByName("severity");
+ assertTrue(severity.getType() instanceof StringType);
+ }
+
+ @Test
+ public void testRpc() {
+ Module testModule = TestUtils.findModule(modules, "custom");
+
+ Set<RpcDefinition> rpcs = testModule.getRpcs();
+ assertEquals(1, rpcs.size());
+
+ RpcDefinition rpc = rpcs.iterator().next();
+ assertEquals("Retrieve all or part of a specified configuration.", rpc.getDescription());
+ assertEquals("RFC 6241, Section 7.1", rpc.getReference());
+
+ ContainerSchemaNode input = rpc.getInput();
+ assertNotNull(input.getDataChildByName("source"));
+ assertNotNull(input.getDataChildByName("filter"));
+ ContainerSchemaNode output = rpc.getOutput();
+ assertNotNull(output.getDataChildByName("data"));
+ }
+
+ @Test
+ public void testTypePath() throws ParseException {
+ Module test = TestUtils.findModule(modules, "types");
+ Set<TypeDefinition<?>> types = test.getTypeDefinitions();
+
+ // my-base-int32-type
+ ExtendedType int32Typedef = (ExtendedType) TestUtils.findTypedef(types, "int32-ext1");
+ QName int32TypedefQName = int32Typedef.getQName();
+
+ assertEquals(typesNS, int32TypedefQName.getNamespace());
+ assertEquals(typesRev, int32TypedefQName.getRevision());
+ assertEquals("t", int32TypedefQName.getPrefix());
+ assertEquals("int32-ext1", int32TypedefQName.getLocalName());
+
+ SchemaPath typeSchemaPath = int32Typedef.getPath();
+ List<QName> typePath = typeSchemaPath.getPath();
+ assertEquals(1, typePath.size());
+ assertEquals(int32TypedefQName, typePath.get(0));
+
+ // my-base-int32-type/int32
+ Int32 int32 = (Int32) int32Typedef.getBaseType();
+ QName int32QName = int32.getQName();
+ assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), int32QName.getNamespace());
+ assertNull(int32QName.getRevision());
+ assertEquals("", int32QName.getPrefix());
+ assertEquals("int32", int32QName.getLocalName());
+
+ SchemaPath int32SchemaPath = int32.getPath();
+ List<QName> int32Path = int32SchemaPath.getPath();
+ assertEquals(3, int32Path.size());
+ assertEquals(int32TypedefQName, int32Path.get(0));
+ assertEquals(int32QName, int32Path.get(2));
+ }
+
+ @Test
+ public void testTypePath2() throws ParseException {
+ Module test = TestUtils.findModule(modules, "types");
+ Set<TypeDefinition<?>> types = test.getTypeDefinitions();
+
+ // my-base-int32-type
+ ExtendedType myDecType = (ExtendedType) TestUtils.findTypedef(types, "my-decimal-type");
+ QName myDecTypeQName = myDecType.getQName();
+
+ assertEquals(typesNS, myDecTypeQName.getNamespace());
+ assertEquals(typesRev, myDecTypeQName.getRevision());
+ assertEquals("t", myDecTypeQName.getPrefix());
+ assertEquals("my-decimal-type", myDecTypeQName.getLocalName());
+
+ SchemaPath typeSchemaPath = myDecType.getPath();
+ List<QName> typePath = typeSchemaPath.getPath();
+ assertEquals(1, typePath.size());
+ assertEquals(myDecTypeQName, typePath.get(0));
+
+ // my-base-int32-type/int32
+ Decimal64 dec64 = (Decimal64) myDecType.getBaseType();
+ QName dec64QName = dec64.getQName();
+
+ assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), dec64QName.getNamespace());
+ assertNull(dec64QName.getRevision());
+ assertEquals("", dec64QName.getPrefix());
+ assertEquals("decimal64", dec64QName.getLocalName());
+
+ SchemaPath dec64SchemaPath = dec64.getPath();
+ List<QName> dec64Path = dec64SchemaPath.getPath();
+ assertEquals(2, dec64Path.size());
+ assertEquals(myDecTypeQName, dec64Path.get(0));
+ assertEquals(dec64QName, dec64Path.get(1));
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.Deviation;
+import org.opendaylight.controller.yang.model.api.Deviation.Deviate;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.MustDefinition;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+
+import com.google.common.collect.Lists;
+
+public class YangParserWithContextTest {
+ private final DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ private final YangParserImpl parser = new YangParserImpl();
+
+ @Test
+ public void testTypeFromContext() throws Exception {
+ SchemaContext context = null;
+ String resource = "/types/ietf-inet-types@2010-09-24.yang";
+ InputStream stream = new FileInputStream(getClass().getResource(resource).getPath());
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+ stream.close();
+
+ Module module = null;
+ resource = "/context-test/test1.yang";
+ InputStream stream2 = new FileInputStream(getClass().getResource(resource).getPath());
+ module = TestUtils.loadModuleWithContext(stream2, context);
+ stream2.close();
+ assertNotNull(module);
+
+ LeafSchemaNode leaf = (LeafSchemaNode) module.getDataChildByName("id");
+
+ ExtendedType leafType = (ExtendedType) leaf.getType();
+ QName qname = leafType.getQName();
+ assertEquals(URI.create("urn:simple.demo.test1"), qname.getNamespace());
+ assertEquals(simpleDateFormat.parse("2013-06-18"), qname.getRevision());
+ assertEquals("t1", qname.getPrefix());
+ assertEquals("port-number", qname.getLocalName());
+
+ ExtendedType leafBaseType = (ExtendedType) leafType.getBaseType();
+ qname = leafBaseType.getQName();
+ assertEquals(URI.create("urn:ietf:params:xml:ns:yang:ietf-inet-types"), qname.getNamespace());
+ assertEquals(simpleDateFormat.parse("2010-09-24"), qname.getRevision());
+ assertEquals("inet", qname.getPrefix());
+ assertEquals("port-number", qname.getLocalName());
+
+ ExtendedType dscpExt = (ExtendedType) TestUtils.findTypedef(module.getTypeDefinitions(), "dscp-ext");
+ List<RangeConstraint> ranges = dscpExt.getRanges();
+ assertEquals(1, ranges.size());
+ RangeConstraint range = ranges.get(0);
+ assertEquals(0L, range.getMin());
+ assertEquals(63L, range.getMax());
+ }
+
+ @Test
+ public void testUsesFromContext() throws Exception {
+ SchemaContext context = null;
+ try (InputStream stream1 = new FileInputStream(getClass().getResource("/model/custom.yang").getPath());
+ InputStream stream2 = new FileInputStream(getClass().getResource("/model/types.yang").getPath());
+ InputStream stream3 = new FileInputStream(getClass().getResource("/model/nodes.yang").getPath())) {
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream1, stream2, stream3)));
+ }
+ Module testModule = null;
+ try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/test2.yang").getPath())) {
+ testModule = TestUtils.loadModuleWithContext(stream, context);
+ }
+ assertNotNull(testModule);
+
+ // suffix _u = added by uses
+ // suffix _g = defined in grouping from context
+
+ // get grouping
+ Module contextModule = context.findModuleByNamespace(URI.create("urn:custom.nodes.test"));
+ assertNotNull(contextModule);
+ Set<GroupingDefinition> groupings = contextModule.getGroupings();
+ assertEquals(1, groupings.size());
+ GroupingDefinition grouping = groupings.iterator().next();
+
+ // get node containing uses
+ ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("peer");
+ ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
+
+ // check uses
+ Set<UsesNode> uses = destination.getUses();
+ assertEquals(1, uses.size());
+
+ // check uses process
+ AnyXmlSchemaNode data_u = (AnyXmlSchemaNode) destination.getDataChildByName("data");
+ assertNotNull(data_u);
+ assertTrue(data_u.isAddedByUses());
+
+ AnyXmlSchemaNode data_g = (AnyXmlSchemaNode) grouping.getDataChildByName("data");
+ assertNotNull(data_g);
+ assertFalse(data_g.isAddedByUses());
+ assertFalse(data_u.equals(data_g));
+
+ ChoiceNode how_u = (ChoiceNode) destination.getDataChildByName("how");
+ assertNotNull(how_u);
+ assertTrue(how_u.isAddedByUses());
+
+ ChoiceNode how_g = (ChoiceNode) grouping.getDataChildByName("how");
+ assertNotNull(how_g);
+ assertFalse(how_g.isAddedByUses());
+ assertFalse(how_u.equals(how_g));
+
+ LeafSchemaNode address_u = (LeafSchemaNode) destination.getDataChildByName("address");
+ assertNotNull(address_u);
+ assertTrue(address_u.isAddedByUses());
+
+ LeafSchemaNode address_g = (LeafSchemaNode) grouping.getDataChildByName("address");
+ assertNotNull(address_g);
+ assertFalse(address_g.isAddedByUses());
+ assertFalse(address_u.equals(address_g));
+
+ ContainerSchemaNode port_u = (ContainerSchemaNode) destination.getDataChildByName("port");
+ assertNotNull(port_u);
+ assertTrue(port_u.isAddedByUses());
+
+ ContainerSchemaNode port_g = (ContainerSchemaNode) grouping.getDataChildByName("port");
+ assertNotNull(port_g);
+ assertFalse(port_g.isAddedByUses());
+ assertFalse(port_u.equals(port_g));
+
+ ListSchemaNode addresses_u = (ListSchemaNode) destination.getDataChildByName("addresses");
+ assertNotNull(addresses_u);
+ assertTrue(addresses_u.isAddedByUses());
+
+ ListSchemaNode addresses_g = (ListSchemaNode) grouping.getDataChildByName("addresses");
+ assertNotNull(addresses_g);
+ assertFalse(addresses_g.isAddedByUses());
+ assertFalse(addresses_u.equals(addresses_g));
+
+ // grouping defined by 'uses'
+ Set<GroupingDefinition> groupings_u = destination.getGroupings();
+ assertEquals(1, groupings_u.size());
+ GroupingDefinition grouping_u = groupings_u.iterator().next();
+ assertTrue(grouping_u.isAddedByUses());
+
+ // grouping defined in 'grouping' node
+ Set<GroupingDefinition> groupings_g = grouping.getGroupings();
+ assertEquals(1, groupings_g.size());
+ GroupingDefinition grouping_g = groupings_g.iterator().next();
+ assertFalse(grouping_g.isAddedByUses());
+ assertFalse(grouping_u.equals(grouping_g));
+
+ List<UnknownSchemaNode> nodes_u = destination.getUnknownSchemaNodes();
+ assertEquals(1, nodes_u.size());
+ UnknownSchemaNode node_u = nodes_u.get(0);
+ assertTrue(node_u.isAddedByUses());
+
+ List<UnknownSchemaNode> nodes_g = grouping.getUnknownSchemaNodes();
+ assertEquals(1, nodes_g.size());
+ UnknownSchemaNode node_g = nodes_g.get(0);
+ assertFalse(node_g.isAddedByUses());
+ assertFalse(node_u.equals(node_g));
+ }
+
+ @Test
+ public void testUsesRefineFromContext() throws Exception {
+ SchemaContext context = null;
+ try (InputStream stream1 = new FileInputStream(getClass().getResource("/model/custom.yang").getPath());
+ InputStream stream2 = new FileInputStream(getClass().getResource("/model/types.yang").getPath());
+ InputStream stream3 = new FileInputStream(getClass().getResource("/model/nodes.yang").getPath())) {
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream1, stream2, stream3)));
+ }
+ Module module = null;
+ try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/test2.yang").getPath())) {
+ module = TestUtils.loadModuleWithContext(stream, context);
+ }
+ assertNotNull(module);
+
+ ContainerSchemaNode peer = (ContainerSchemaNode) module.getDataChildByName("peer");
+ ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
+ Set<UsesNode> usesNodes = destination.getUses();
+ assertEquals(1, usesNodes.size());
+ UsesNode usesNode = usesNodes.iterator().next();
+
+ // test grouping path
+ List<QName> path = new ArrayList<QName>();
+ QName qname = new QName(URI.create("urn:custom.nodes.test"), simpleDateFormat.parse("2013-02-27"), "c",
+ "target");
+ path.add(qname);
+ SchemaPath expectedPath = new SchemaPath(path, true);
+ assertEquals(expectedPath, usesNode.getGroupingPath());
+
+ // test refine
+ Map<SchemaPath, SchemaNode> refines = usesNode.getRefines();
+ assertEquals(5, refines.size());
+
+ LeafSchemaNode refineLeaf = null;
+ ContainerSchemaNode refineContainer = null;
+ ListSchemaNode refineList = null;
+ GroupingDefinition refineGrouping = null;
+ TypeDefinition<?> typedef = null;
+ for (Map.Entry<SchemaPath, SchemaNode> entry : refines.entrySet()) {
+ SchemaNode value = entry.getValue();
+ if (value instanceof LeafSchemaNode) {
+ refineLeaf = (LeafSchemaNode) value;
+ } else if (value instanceof ContainerSchemaNode) {
+ refineContainer = (ContainerSchemaNode) value;
+ } else if (value instanceof ListSchemaNode) {
+ refineList = (ListSchemaNode) value;
+ } else if (value instanceof GroupingDefinition) {
+ refineGrouping = (GroupingDefinition) value;
+ } else if (value instanceof TypeDefinition<?>) {
+ typedef = (TypeDefinition<?>) value;
+ }
+ }
+
+ // leaf address
+ assertNotNull(refineLeaf);
+ assertEquals("address", refineLeaf.getQName().getLocalName());
+ assertEquals("description of address defined by refine", refineLeaf.getDescription());
+ assertEquals("address reference added by refine", refineLeaf.getReference());
+ assertFalse(refineLeaf.isConfiguration());
+ assertTrue(refineLeaf.getConstraints().isMandatory());
+ Set<MustDefinition> leafMustConstraints = refineLeaf.getConstraints().getMustConstraints();
+ assertEquals(1, leafMustConstraints.size());
+ MustDefinition leafMust = leafMustConstraints.iterator().next();
+ assertEquals("\"ifType != 'ethernet' or (ifType = 'ethernet' and ifMTU = 1500)\"", leafMust.toString());
+
+ // container port
+ assertNotNull(refineContainer);
+ Set<MustDefinition> mustConstraints = refineContainer.getConstraints().getMustConstraints();
+ assertTrue(mustConstraints.isEmpty());
+ assertEquals("description of port defined by refine", refineContainer.getDescription());
+ assertEquals("port reference added by refine", refineContainer.getReference());
+ assertFalse(refineContainer.isConfiguration());
+ assertTrue(refineContainer.isPresenceContainer());
+
+ // list addresses
+ assertNotNull(refineList);
+ assertEquals("description of addresses defined by refine", refineList.getDescription());
+ assertEquals("addresses reference added by refine", refineList.getReference());
+ assertFalse(refineList.isConfiguration());
+ assertEquals(2, (int) refineList.getConstraints().getMinElements());
+ assertEquals(12, (int) refineList.getConstraints().getMaxElements());
+
+ // grouping target-inner
+ assertNotNull(refineGrouping);
+ Set<DataSchemaNode> refineGroupingChildren = refineGrouping.getChildNodes();
+ assertEquals(1, refineGroupingChildren.size());
+ LeafSchemaNode refineGroupingLeaf = (LeafSchemaNode) refineGroupingChildren.iterator().next();
+ assertEquals("inner-grouping-id", refineGroupingLeaf.getQName().getLocalName());
+ assertEquals("new target-inner grouping description", refineGrouping.getDescription());
+
+ // typedef group-type
+ assertNotNull(typedef);
+ assertEquals("new group-type description", typedef.getDescription());
+ assertEquals("new group-type reference", typedef.getReference());
+ assertTrue(typedef.getBaseType() instanceof ExtendedType);
+ }
+
+ @Test
+ public void testIdentity() throws Exception {
+ SchemaContext context = null;
+ try (InputStream stream = new FileInputStream(getClass().getResource("/types/custom-types-test@2012-4-4.yang")
+ .getPath())) {
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+ }
+ Module module = null;
+ try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/test3.yang").getPath())) {
+ module = TestUtils.loadModuleWithContext(stream, context);
+ }
+ assertNotNull(module);
+
+ Set<IdentitySchemaNode> identities = module.getIdentities();
+ assertEquals(1, identities.size());
+
+ IdentitySchemaNode identity = identities.iterator().next();
+ QName idQName = identity.getQName();
+ assertEquals(URI.create("urn:simple.demo.test3"), idQName.getNamespace());
+ assertEquals(simpleDateFormat.parse("2013-06-18"), idQName.getRevision());
+ assertEquals("t3", idQName.getPrefix());
+ assertEquals("pt", idQName.getLocalName());
+
+ IdentitySchemaNode baseIdentity = identity.getBaseIdentity();
+ QName idBaseQName = baseIdentity.getQName();
+ assertEquals(URI.create("urn:custom.types.demo"), idBaseQName.getNamespace());
+ assertEquals(simpleDateFormat.parse("2012-04-16"), idBaseQName.getRevision());
+ assertEquals("iit", idBaseQName.getPrefix());
+ assertEquals("service-type", idBaseQName.getLocalName());
+ }
+
+ @Test
+ public void testUnknownNodes() throws Exception {
+ SchemaContext context = null;
+ try (InputStream stream = new FileInputStream(getClass().getResource("/types/custom-types-test@2012-4-4.yang")
+ .getPath())) {
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+ }
+
+ Module module = null;
+ try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/test3.yang").getPath())) {
+ module = TestUtils.loadModuleWithContext(stream, context);
+ }
+
+ ContainerSchemaNode network = (ContainerSchemaNode) module.getDataChildByName("network");
+ List<UnknownSchemaNode> unknownNodes = network.getUnknownSchemaNodes();
+ assertEquals(1, unknownNodes.size());
+
+ UnknownSchemaNode un = unknownNodes.get(0);
+ QName unType = un.getNodeType();
+ assertEquals(URI.create("urn:custom.types.demo"), unType.getNamespace());
+ assertEquals(simpleDateFormat.parse("2012-04-16"), unType.getRevision());
+ assertEquals("custom", unType.getPrefix());
+ assertEquals("mountpoint", unType.getLocalName());
+ assertEquals("point", un.getNodeParameter());
+ }
+
+ @Test
+ public void testAugment() throws Exception {
+ // load first module
+ SchemaContext context = null;
+ String resource = "/context-augment-test/test4.yang";
+
+ try (InputStream stream = new FileInputStream(getClass().getResource(resource).getPath())) {
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+ }
+
+ Set<Module> contextModules = context.getModules();
+ Module t3 = TestUtils.findModule(contextModules, "test4");
+ ContainerSchemaNode interfaces = (ContainerSchemaNode) t3.getDataChildByName("interfaces");
+ ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+
+ // load another modules and parse them against already existing context
+ Set<Module> modules = null;
+ try (InputStream stream1 = new FileInputStream(getClass().getResource("/context-augment-test/test1.yang")
+ .getPath());
+ InputStream stream2 = new FileInputStream(getClass().getResource("/context-augment-test/test2.yang")
+ .getPath());
+ InputStream stream3 = new FileInputStream(getClass().getResource("/context-augment-test/test3.yang")
+ .getPath())) {
+ List<InputStream> input = Lists.newArrayList(stream1, stream2, stream3);
+ modules = TestUtils.loadModulesWithContext(input, context);
+ }
+ assertNotNull(modules);
+
+ // test augmentation process
+ ContainerSchemaNode augmentHolder = (ContainerSchemaNode) ifEntry.getDataChildByName("augment-holder");
+ assertNotNull(augmentHolder);
+ DataSchemaNode ds0 = augmentHolder.getDataChildByName("ds0ChannelNumber");
+ assertNotNull(ds0);
+ DataSchemaNode interfaceId = augmentHolder.getDataChildByName("interface-id");
+ assertNotNull(interfaceId);
+ DataSchemaNode higherLayerIf = augmentHolder.getDataChildByName("higher-layer-if");
+ assertNotNull(higherLayerIf);
+ ContainerSchemaNode schemas = (ContainerSchemaNode) augmentHolder.getDataChildByName("schemas");
+ assertNotNull(schemas);
+ assertNotNull(schemas.getDataChildByName("id"));
+
+ // test augment target after augmentation: check if it is same instance
+ ListSchemaNode ifEntryAfterAugment = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+ assertTrue(ifEntry == ifEntryAfterAugment);
+ }
+
+ @Test
+ public void testDeviation() throws Exception {
+ // load first module
+ SchemaContext context = null;
+ String resource = "/model/types.yang";
+
+ try (InputStream stream = new FileInputStream(getClass().getResource(resource).getPath())) {
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+ }
+
+ // load another modules and parse them against already existing context
+ Set<Module> modules = null;
+ try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/deviation-test.yang")
+ .getPath())) {
+ List<InputStream> input = Lists.newArrayList(stream);
+ modules = TestUtils.loadModulesWithContext(input, context);
+ }
+ assertNotNull(modules);
+
+ // test deviation
+ Module testModule = TestUtils.findModule(modules, "deviation-test");
+ Set<Deviation> deviations = testModule.getDeviations();
+ assertEquals(1, deviations.size());
+ Deviation dev = deviations.iterator().next();
+
+ assertEquals("system/user ref", dev.getReference());
+
+ URI expectedNS = URI.create("urn:simple.types.test");
+ DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ Date expectedRev = simpleDateFormat.parse("2013-07-03");
+ List<QName> path = new ArrayList<QName>();
+ path.add(new QName(expectedNS, expectedRev, "t", "interfaces"));
+ path.add(new QName(expectedNS, expectedRev, "t", "ifEntry"));
+ SchemaPath expectedPath = new SchemaPath(path, true);
+
+ assertEquals(expectedPath, dev.getTargetPath());
+ assertEquals(Deviate.ADD, dev.getDeviate());
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import static org.hamcrest.core.AnyOf.anyOf;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.*;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.ModuleImport;
+import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.controller.yang.parser.impl.YangParserListenerImpl;
+import org.opendaylight.controller.yang.parser.util.ModuleDependencySort.ModuleNodeImpl;
+import org.opendaylight.controller.yang.parser.util.TopologicalSort.Edge;
+
+import com.google.common.collect.Sets;
+
+public class ModuleDependencySortTest {
+
+ private ModuleBuilder a = mockModuleBuilder("a", null);
+ private ModuleBuilder b = mockModuleBuilder("b", null);
+ private ModuleBuilder c = mockModuleBuilder("c", null);
+ private ModuleBuilder d = mockModuleBuilder("d", null);
+
+ @Test
+ public void testValid() throws Exception {
+
+ mockDependency(a, b);
+ mockDependency(b, c);
+ mockDependency(b, d);
+
+ ModuleBuilder[] builders = new ModuleBuilder[] { d, b, c, a };
+
+ List<ModuleBuilder> l = ModuleDependencySort.sort(builders);
+
+ assertDependencyGraph(ModuleDependencySort.createModuleGraph(Arrays.asList(builders)));
+
+ @SuppressWarnings("unchecked")
+ Matcher<String> cOrD = anyOf(is(c.getName()), is(d.getName()));
+
+ assertThat(l.get(0).getName(), cOrD);
+ assertThat(l.get(1).getName(), cOrD);
+ assertThat(l.get(2).getName(), is(b.getName()));
+ assertThat(l.get(3).getName(), is(a.getName()));
+ }
+
+ @Test
+ public void testValidModule() throws Exception {
+
+ Date rev = new Date();
+ Module a = mockModule("a", rev);
+ Module b = mockModule("b", rev);
+ Module c = mockModule("c", rev);
+
+ mockDependency(a, b);
+ mockDependency(b, c);
+ mockDependency(a, c);
+
+ Module[] builders = new Module[] { a, b, c };
+
+ List<Module> l = ModuleDependencySort.sort(builders);
+
+ assertThat(l.get(0).getName(), is(c.getName()));
+ assertThat(l.get(1).getName(), is(b.getName()));
+ assertThat(l.get(2).getName(), is(a.getName()));
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testModuleTwice() throws Exception {
+ ModuleBuilder a2 = mockModuleBuilder("a", null);
+
+ ModuleBuilder[] builders = new ModuleBuilder[] { a, a2 };
+ try {
+ ModuleDependencySort.sort(builders);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(), containsString("Module:a with revision:default declared twice"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testImportNotExistingModule() throws Exception {
+ mockDependency(a, b);
+
+ ModuleBuilder[] builders = new ModuleBuilder[] { a };
+ try {
+ ModuleDependencySort.sort(builders);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(), containsString("Not existing module imported:b:default by:a:default"));
+ throw e;
+ }
+ }
+
+ @Test
+ public void testImportTwice() throws Exception {
+ mockDependency(a, b);
+ mockDependency(c, b);
+
+ ModuleBuilder[] builders = new ModuleBuilder[] { a, b, c };
+ ModuleDependencySort.sort(builders);
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testImportTwiceDifferentRevision() throws Exception {
+ Date date1 = new Date(463846463486L);
+ Date date2 = new Date(364896446683L);
+ b = mockModuleBuilder("b", date1);
+ ModuleBuilder b2 = mockModuleBuilder("b", date2);
+
+ mockDependency(a, b);
+ mockDependency(c, b2);
+
+ ModuleBuilder[] builders = new ModuleBuilder[] { a, c, b, b2 };
+ try {
+ ModuleDependencySort.sort(builders);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(), containsString("Module:b imported twice with different revisions:"
+ + YangParserListenerImpl.simpleDateFormat.format(date1) + ", "
+ + YangParserListenerImpl.simpleDateFormat.format(date2)));
+ throw e;
+ }
+ }
+
+ @Test
+ public void testModuleTwiceWithDifferentRevs() throws Exception {
+ ModuleBuilder a2 = mockModuleBuilder("a", new Date());
+
+ ModuleBuilder[] builders = new ModuleBuilder[] { a, a2 };
+ ModuleDependencySort.sort(builders);
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testModuleTwice2() throws Exception {
+ Date rev = new Date();
+ ModuleBuilder a2 = mockModuleBuilder("a", rev);
+ ModuleBuilder a3 = mockModuleBuilder("a", rev);
+
+ ModuleBuilder[] builders = new ModuleBuilder[] { a, a2, a3 };
+ try {
+ ModuleDependencySort.sort(builders);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(), containsString("Module:a with revision:"
+ + YangParserListenerImpl.simpleDateFormat.format(rev) + " declared twice"));
+ throw e;
+ }
+ }
+
+ private void assertDependencyGraph(Map<String, Map<Date, ModuleNodeImpl>> moduleGraph) {
+ for (Entry<String, Map<Date, ModuleNodeImpl>> node : moduleGraph.entrySet()) {
+ String name = node.getKey();
+
+ // Expects only one module revision
+
+ Set<Edge> inEdges = node.getValue().values().iterator().next().getInEdges();
+ Set<Edge> outEdges = node.getValue().values().iterator().next().getOutEdges();
+
+ if (name.equals("a")) {
+ assertEdgeCount(inEdges, 0, outEdges, 1);
+ } else if (name.equals("b")) {
+ assertEdgeCount(inEdges, 1, outEdges, 2);
+ } else {
+ assertEdgeCount(inEdges, 1, outEdges, 0);
+ }
+ }
+ }
+
+ private void assertEdgeCount(Set<Edge> inEdges, int i, Set<Edge> outEdges, int j) {
+ assertThat(inEdges.size(), is(i));
+ assertThat(outEdges.size(), is(j));
+ }
+
+ private void mockDependency(ModuleBuilder a, ModuleBuilder b) {
+ ModuleImport imprt = mock(ModuleImport.class);
+ doReturn(b.getName()).when(imprt).getModuleName();
+ doReturn(b.getRevision()).when(imprt).getRevision();
+ a.getModuleImports().add(imprt);
+ }
+
+ private void mockDependency(Module a, Module b) {
+ ModuleImport imprt = mock(ModuleImport.class);
+ doReturn(b.getName()).when(imprt).getModuleName();
+ doReturn(b.getRevision()).when(imprt).getRevision();
+ a.getImports().add(imprt);
+ }
+
+ private ModuleBuilder mockModuleBuilder(String name, Date rev) {
+ ModuleBuilder a = mock(ModuleBuilder.class);
+ doReturn(name).when(a).getName();
+ Set<ModuleImport> set = Sets.newHashSet();
+ doReturn(set).when(a).getModuleImports();
+ if (rev != null) {
+ doReturn(rev).when(a).getRevision();
+ }
+ return a;
+ }
+
+ private Module mockModule(String name, Date rev) {
+ Module a = mock(Module.class);
+ doReturn(name).when(a).getName();
+ Set<ModuleImport> set = Sets.newHashSet();
+ doReturn(set).when(a).getImports();
+ if (rev != null) {
+ doReturn(rev).when(a).getRevision();
+ }
+ return a;
+ }
+}
--- /dev/null
+/*
+ * 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.yang.parser.util;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import org.opendaylight.controller.yang.parser.util.TopologicalSort.Node;
+import org.opendaylight.controller.yang.parser.util.TopologicalSort.NodeImpl;
+
+import com.google.common.collect.Sets;
+
+public class TopologicalSortTest {
+
+ @Test(expected = IllegalStateException.class)
+ public void test() throws Exception {
+ Set<Node> nodes = Sets.newHashSet();
+
+ NodeImpl node1 = new NodeImpl();
+ nodes.add(node1);
+ NodeImpl node2 = new NodeImpl();
+ nodes.add(node2);
+ NodeImpl node3 = new NodeImpl();
+ nodes.add(node3);
+
+ node1.addEdge(node2);
+ node2.addEdge(node3);
+ node3.addEdge(node1);
+
+ try {
+ TopologicalSort.sort(nodes);
+ } catch (IllegalStateException e) {
+ throw e;
+ }
+ }
+
+ @Test
+ public void testValidSimple() throws Exception {
+ Set<Node> nodes = Sets.newHashSet();
+
+ Node node1 = new NodeImpl();
+ nodes.add(node1);
+ Node node2 = new NodeImpl();
+ nodes.add(node2);
+ Node node3 = new NodeImpl();
+ nodes.add(node3);
+ Node node4 = new NodeImpl();
+ nodes.add(node4);
+
+ ((NodeImpl) node1).addEdge(node2);
+ ((NodeImpl) node1).addEdge(node3);
+ ((NodeImpl) node2).addEdge(node4);
+ ((NodeImpl) node3).addEdge(node2);
+
+ List<Node> sorted = TopologicalSort.sort(nodes);
+
+ assertThat(sorted.get(0), is(node4));
+ assertThat(sorted.get(1), is(node2));
+ assertThat(sorted.get(2), is(node3));
+ assertThat(sorted.get(3), is(node1));
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.validator;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Unique_stmtContext;
+import org.opendaylight.controller.yang.parser.util.YangValidationException;
+
+public class YangModelValidationListTest {
+
+ private YangModelBasicValidationListener valid;
+
+ @Before
+ public void setUp() {
+ valid = new YangModelBasicValidationListener();
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testKeyValidationDuplicates() {
+
+ List_stmtContext list = YangModelValidationTest.mockStatement(
+ List_stmtContext.class, "list");
+ Key_stmtContext key = YangModelValidationTest.mockStatement(
+ Key_stmtContext.class, "leaf1 leaf2 leaf1 leaf1");
+ YangModelValidationTest.addChild(list, key);
+
+ try {
+ valid.enterKey_stmt(key);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("contains duplicates:[leaf1]"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testUniqueValidationDuplicates() {
+ List_stmtContext list = YangModelValidationTest.mockStatement(
+ List_stmtContext.class, "list");
+ Unique_stmtContext unique = YangModelValidationTest.mockStatement(
+ Unique_stmtContext.class, "leaf1/a leaf2/n leaf1/a leaf1");
+ YangModelValidationTest.addChild(list, unique);
+
+ try {
+ valid.enterUnique_stmt(unique);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("contains duplicates:[leaf1/a]"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testOrderBy() {
+ Ordered_by_argContext ctx = YangModelValidationTest.mockStatement(
+ Ordered_by_argContext.class, "unknown");
+
+ try {
+ valid.enterOrdered_by_arg(ctx);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Ordered-by:unknown, illegal value for Ordered-by statement, only permitted:"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testLeaf() {
+ Leaf_stmtContext ctx = YangModelValidationTest.mockStatement(
+ Leaf_stmtContext.class, "leaf1");
+ Default_stmtContext def = YangModelValidationTest.mockStatement(
+ Default_stmtContext.class, "default");
+ YangModelValidationTest.addChild(ctx, def);
+ Type_stmtContext typ = YangModelValidationTest.mockStatement(
+ Type_stmtContext.class, "type");
+ YangModelValidationTest.addChild(ctx, def);
+ YangModelValidationTest.addChild(ctx, typ);
+
+ Mandatory_stmtContext mand = YangModelValidationTest.mockStatement(
+ Mandatory_stmtContext.class, null);
+ YangModelValidationTest.addChild(ctx, mand);
+
+ try {
+ valid.enterLeaf_stmt(ctx);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Both Mandatory and Default statement present"));
+ throw e;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.validator;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.*;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
+import org.opendaylight.controller.yang.parser.util.YangValidationException;
+
+public class YangModelValidationModuleTest {
+
+ private YangModelBasicValidationListener valid;
+
+ @Before
+ public void setUp() {
+ valid = new YangModelBasicValidationListener();
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testRevisionInvalidDateFormat() {
+ Revision_stmtContext mockedRev = mockModuleWithRevision("badFormat",
+ "module1");
+
+ try {
+ valid.enterRevision_stmt(mockedRev);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Revision:badFormat, invalid date format expected date format is:"));
+ throw e;
+ }
+ }
+
+ @Test
+ public void testRevisionValidDateFormat() {
+ Revision_stmtContext mockedRev = mockModuleWithRevision(
+ YangModelValidationTest.getFormattedDate(), "module1");
+
+ valid.enterRevision_stmt(mockedRev);
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoHeaderStmts() {
+ Revision_stmtContext rev = mockModuleWithRevision("1999-4-5", "module1");
+
+ try {
+ valid.enterModule_stmt((Module_stmtContext) rev.getParent()
+ .getParent());
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Module-header statement in Module:module1"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testMultipleModulesPerSession() {
+ Module_stmtContext module1 = (Module_stmtContext) mockModuleWithRevision(
+ "1999-09-10", "m1").getParent().getParent();
+ YangModelValidationTest.addChild(module1, YangModelValidationTest
+ .mockStatement(Namespace_stmtContext.class, ""));
+
+ Module_stmtContext module2 = (Module_stmtContext) mockModuleWithRevision(
+ "1999-09-10", "m2").getParent().getParent();
+ YangModelValidationTest.addChild(module1, YangModelValidationTest
+ .mockStatement(Namespace_stmtContext.class, ""));
+ valid.enterModule_stmt(module1);
+
+ try {
+ valid.enterModule_stmt(module2);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("Multiple (sub)modules per file"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoNamespace() {
+ Module_header_stmtsContext header = YangModelValidationTest
+ .mockStatement(Module_header_stmtsContext.class, null);
+ Module_stmtContext mod = YangModelValidationTest.mockStatement(
+ Module_stmtContext.class, "module1");
+ YangModelValidationTest.addChild(mod, header);
+
+ try {
+ valid.enterModule_header_stmts(header);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Namespace statement in Module-header:"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoPrefix() {
+ Module_header_stmtsContext header = YangModelValidationTest
+ .mockStatement(Module_header_stmtsContext.class, null);
+ Namespace_stmtContext nmspc = YangModelValidationTest.mockStatement(
+ Namespace_stmtContext.class, "http://test");
+ Module_stmtContext mod = YangModelValidationTest.mockStatement(
+ Module_stmtContext.class, "module1");
+ YangModelValidationTest.addChild(mod, header);
+ YangModelValidationTest.addChild(header, nmspc);
+
+ try {
+ valid.enterModule_header_stmts(header);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Prefix statement in Module-header:"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testInvalidYangVersion() {
+
+ Yang_version_stmtContext yangVersion = YangModelValidationTest
+ .mockStatement(Yang_version_stmtContext.class, "55Unsup");
+
+ Module_stmtContext mod = YangModelValidationTest.mockStatement(
+ Module_stmtContext.class, "module1");
+ YangModelValidationTest.addChild(mod, yangVersion);
+
+ try {
+ valid.enterYang_version_stmt(yangVersion);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Unsupported yang version:55Unsup, supported version:"
+ + BasicValidations.SUPPORTED_YANG_VERSION));
+ throw e;
+ }
+ }
+
+ @Test
+ public void testValidYangVersion() {
+
+ Yang_version_stmtContext ctx = mock(Yang_version_stmtContext.class);
+ doReturn(1).when(ctx).getChildCount();
+ YangModelValidationTest.mockName(ctx, "1");
+
+ valid.enterYang_version_stmt(ctx);
+ }
+
+ private static Revision_stmtContext mockModuleWithRevision(String date,
+ String moduleName) {
+ Revision_stmtContext mockedRev = YangModelValidationTest.mockStatement(
+ Revision_stmtContext.class, date);
+ Revision_stmtsContext revs = YangModelValidationTest.mockStatement(
+ Revision_stmtsContext.class, null);
+ Module_stmtContext mod = YangModelValidationTest.mockStatement(
+ Module_stmtContext.class, moduleName);
+
+ YangModelValidationTest.addChild(revs, mockedRev);
+ YangModelValidationTest.addChild(mod, revs);
+ return mockedRev;
+ }
+}
--- /dev/null
+/*
+ * 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.yang.validator;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.mock;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
+import org.opendaylight.controller.yang.parser.util.YangValidationException;
+
+public class YangModelValidationSubModuleTest {
+
+ private YangModelBasicValidationListener valid;
+
+ @Before
+ public void setUp() {
+ valid = new YangModelBasicValidationListener();
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoRevision() {
+
+ Submodule_stmtContext ctx = YangModelValidationTest.mockStatement(
+ Submodule_stmtContext.class, "submodule1");
+
+ try {
+ valid.enterSubmodule_stmt(ctx);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Submodule-header statement in Submodule:submodule"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoBelongsTo() {
+ Submodule_header_stmtsContext header = mock(Submodule_header_stmtsContext.class);
+ mockSubmoduleParent(header, "submodule");
+
+ try {
+ valid.enterSubmodule_header_stmts(header);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Belongs-to statement in Submodule-header:"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testBelongsToNoPrefix() {
+ Belongs_to_stmtContext belongsTo = YangModelValidationTest
+ .mockStatement(Belongs_to_stmtContext.class, "supermodule");
+
+ mockSubmoduleParent(belongsTo, "submodule");
+
+ try {
+ valid.enterBelongs_to_stmt(belongsTo);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Prefix statement in Belongs-to:supermodule"));
+ throw e;
+ }
+ }
+
+ private Submodule_stmtContext mockSubmoduleParent(ParseTree child,
+ String moduleName) {
+ Submodule_stmtContext ctx = YangModelValidationTest.mockStatement(
+ Submodule_stmtContext.class, moduleName);
+ YangModelValidationTest.addChild(ctx, child);
+ return ctx;
+ }
+}
--- /dev/null
+/*
+ * 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.yang.validator;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Augment_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_delete_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviation_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext;
+import org.opendaylight.controller.yang.parser.impl.YangParserListenerImpl;
+import org.opendaylight.controller.yang.parser.util.YangValidationException;
+
+import com.google.common.collect.Sets;
+
+public class YangModelValidationTest {
+
+ private YangModelBasicValidationListener valid;
+
+ @Before
+ public void setUp() {
+
+ valid = new YangModelBasicValidationListener();
+ }
+
+ @Test
+ public void testPrefixes() {
+ Prefix_stmtContext pref = mockStatement(Prefix_stmtContext.class,
+ "unique1");
+ Module_stmtContext module = mockStatement(Module_stmtContext.class,
+ "module1");
+ addChild(module, pref);
+
+ valid.enterPrefix_stmt(pref);
+
+ pref = mockStatement(Prefix_stmtContext.class, "unique1");
+ module = mockStatement(Module_stmtContext.class, "module1");
+ addChild(module, pref);
+
+ try {
+ valid.enterPrefix_stmt(pref);
+ } catch (Exception e) {
+ return;
+ }
+
+ fail("Validation Exception should have occured");
+ }
+
+ @Test
+ public void testNamespace() {
+
+ Namespace_stmtContext namespace = mockStatement(
+ Namespace_stmtContext.class, "http://test.parsing.uri.com");
+ Module_stmtContext module = mockStatement(Module_stmtContext.class,
+ "module1");
+ addChild(module, namespace);
+
+ valid.enterNamespace_stmt(namespace);
+
+ namespace = mockStatement(Namespace_stmtContext.class, "invalid uri");
+ module = mockStatement(Module_stmtContext.class, "module1");
+ addChild(module, namespace);
+
+ try {
+ valid.enterNamespace_stmt(namespace);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Namespace:invalid uri cannot be parsed as URI"));
+ return;
+ }
+
+ fail("Validation Exception should have occured");
+ }
+
+ @Test
+ public void testImports() {
+ Import_stmtContext impor = mockImport("unique1", "p1");
+ Module_stmtContext mod = mockStatement(Module_stmtContext.class,
+ "module1");
+ addChild(mod, impor);
+
+ valid.enterImport_stmt(impor);
+
+ impor = mockImport("unique1", "p2");
+ mod = mockStatement(Module_stmtContext.class, "module1");
+ addChild(mod, impor);
+
+ try {
+ valid.enterImport_stmt(impor);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("Import:unique1 not unique"));
+ return;
+ }
+
+ fail("Validation Exception should have occured");
+ }
+
+ @Test
+ public void testIncludes() {
+ Include_stmtContext incl = mockInclude("unique1");
+ Module_stmtContext mod = mockStatement(Module_stmtContext.class,
+ "module1");
+ addChild(mod, incl);
+ valid.enterInclude_stmt(incl);
+
+ incl = mockInclude("unique1");
+ mod = mockStatement(Module_stmtContext.class, "module1");
+ addChild(mod, incl);
+
+ try {
+ valid.enterInclude_stmt(incl);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("Include:unique1 not unique in (sub)module"));
+ return;
+ }
+
+ fail("Validation Exception should have occured");
+ }
+
+ @Test
+ public void testIdentifierMatching() {
+ List<String> ids = new ArrayList<String>();
+ // valid
+ ids.add("_ok98-.87.-.8...88-asdAD");
+ ids.add("AA.bcd");
+ ids.add("a");
+ // invalid
+ ids.add("9aa");
+ ids.add("-");
+ ids.add(".");
+
+ int thrown = 0;
+ for (String id : ids) {
+ try {
+ Module_stmtContext module = mock(Module_stmtContext.class);
+ Token token = mock(Token.class);
+ when(module.getStart()).thenReturn(token);
+ BasicValidations.checkIdentifierInternal(
+ module, id);
+ } catch (YangValidationException e) {
+ thrown++;
+ }
+ }
+
+ assertThat(thrown, is(3));
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testAugument() {
+ Augment_stmtContext augument = mockStatement(Augment_stmtContext.class,
+ "/a:*abc/a:augument1");
+ Module_stmtContext mod1 = mockStatement(Module_stmtContext.class,
+ "mod1");
+ addChild(mod1, augument);
+
+ Token token = mock(Token.class);
+ when(augument.getStart()).thenReturn(token);
+
+ try {
+ valid.enterAugment_stmt(augument);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Schema node id:/a:*abc/a:augument1 not in required format, details:Prefixed id:a:*abc not in required format"));
+ throw e;
+ }
+ }
+
+ @Test
+ public void testDeviate() {
+ Deviation_stmtContext ctx = mockStatement(Deviation_stmtContext.class,
+ "deviations");
+ Deviate_add_stmtContext add = mockStatement(
+ Deviate_add_stmtContext.class, "add");
+ Deviate_delete_stmtContext del = mockStatement(
+ Deviate_delete_stmtContext.class, "delete");
+
+ addChild(ctx, add);
+ addChild(ctx, del);
+
+ valid.enterDeviation_stmt(ctx);
+
+ HashSet<Class<? extends ParseTree>> types = Sets.newHashSet();
+ types.add(Deviate_add_stmtContext.class);
+ types.add(Deviate_delete_stmtContext.class);
+
+ int count = ValidationUtil.countPresentChildrenOfType(ctx, types);
+ assertThat(count, is(2));
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testStatus() throws Exception {
+ Status_argContext status = mockStatement(Status_argContext.class,
+ "unknown");
+ try {
+ valid.enterStatus_arg(status);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("illegal value for Status statement, only permitted:"));
+ throw e;
+ }
+ }
+
+ private Import_stmtContext mockImport(String name, String prefixName) {
+ Import_stmtContext impor = mockStatement(Import_stmtContext.class, name);
+
+ Prefix_stmtContext prefix = mockStatement(Prefix_stmtContext.class,
+ prefixName);
+ Revision_date_stmtContext revDate = mockStatement(
+ Revision_date_stmtContext.class, getFormattedDate());
+
+ addChild(impor, prefix);
+ addChild(impor, revDate);
+ return impor;
+ }
+
+ static String getFormattedDate() {
+ return YangParserListenerImpl.simpleDateFormat.format(new Date());
+ }
+
+ private Include_stmtContext mockInclude(String name) {
+ Include_stmtContext incl = mockStatement(Include_stmtContext.class,
+ name);
+
+ Revision_date_stmtContext revDate = mockStatement(
+ Revision_date_stmtContext.class, getFormattedDate());
+
+ addChild(incl, revDate);
+ return incl;
+ }
+
+ static void mockName(ParseTree stmt, String name) {
+ StringContext nameCtx = mock(StringContext.class);
+ ParseTree internalName = mock(ParseTree.class);
+ doReturn(1).when(stmt).getChildCount();
+ doReturn(name).when(internalName).getText();
+ doReturn(internalName).when(nameCtx).getChild(0);
+ doReturn(nameCtx).when(stmt).getChild(0);
+ }
+
+ static <T extends ParseTree> T mockStatement(Class<T> stmtType, String name) {
+ T stmt = stmtType.cast(mock(stmtType));
+
+ doReturn(0).when(stmt).getChildCount();
+
+ if (name != null)
+ mockName(stmt, name);
+ return stmt;
+ }
+
+ static void addChild(ParseTree parent, ParseTree child) {
+ int childCount = parent.getChildCount() + 1;
+ doReturn(childCount).when(parent).getChildCount();
+ doReturn(child).when(parent).getChild(childCount - 1);
+ doReturn(parent).when(child).getParent();
+ }
+
+}
--- /dev/null
+module test1 {
+
+ yang-version 1;
+ namespace "urn:simple.demo.test1";
+ prefix "t1";
+
+ import test3 {
+ prefix "t3";
+ revision-date 2013-06-18;
+ }
+
+ import test2 {
+ prefix "t2";
+ revision-date 2013-06-18;
+ }
+
+ import test4 {
+ prefix "t4";
+ revision-date 2013-06-18;
+ }
+
+ organization "opendaylight";
+ contact "WILL-BE-DEFINED-LATER";
+ revision 2013-06-18 {
+ }
+
+ augment "/t4:interfaces/t4:ifEntry/t2:augment-holder/t3:schemas" {
+ when "if:ifType='ds0'";
+ leaf id {
+ type string;
+ }
+ }
+
+}
--- /dev/null
+module test2 {
+
+ yang-version 1;
+ namespace "urn:simple.demo.test2";
+ prefix "t2";
+
+ import test3 {
+ prefix "t3";
+ revision-date 2013-06-18;
+ }
+
+ import test4 {
+ prefix "t4";
+ revision-date 2013-06-18;
+ }
+
+ organization "opendaylight";
+ contact "WILL-BE-DEFINED-LATER";
+ revision 2013-06-18 {
+ }
+
+ augment "/t4:interfaces/t4:ifEntry/t3:augment-holder" {
+ when "if:ifType='ds0'";
+ leaf ds0ChannelNumber {
+ type string;
+ }
+ leaf interface-id {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ leaf-list higher-layer-if {
+ type leafref {
+ path "/if:interfaces/if:interface/if:higher-layer-if";
+ }
+ }
+ container schemas {
+ }
+ }
+
+}
--- /dev/null
+module test3 {
+
+ yang-version 1;
+ namespace "urn:simple.demo.test3";
+ prefix "t3";
+
+ import test4 {
+ prefix "t4";
+ revision-date 2013-06-18;
+ }
+
+ organization "opendaylight";
+ contact "WILL-BE-DEFINED-LATER";
+ revision 2013-06-18 {
+ }
+
+ augment "/t4:interfaces/t4:ifEntry" {
+ when "if:ifType='ds0'";
+ container augment-holder {
+ description "Description for augment holder";
+ }
+ }
+
+}
--- /dev/null
+module test4 {
+
+ yang-version 1;
+ namespace "urn:simple.demo.test4";
+ prefix "t4";
+
+ organization "opendaylight";
+ contact "WILL-BE-DEFINED-LATER";
+ revision 2013-06-18 {
+ }
+
+ container interfaces {
+ list ifEntry {
+ key "ifIndex";
+ leaf ifIndex {
+ type uint32;
+ units minutes;
+ }
+ leaf ifMtu {
+ type int32;
+ }
+ min-elements 1;
+ max-elements 11;
+ }
+ }
+
+}
--- /dev/null
+module deviation-test {
+ yang-version 1;
+ namespace "urn:simple.deviation.test";
+ prefix "dev";
+
+ import types {
+ prefix "t";
+ revision-date 2013-07-03;
+ }
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+
+ revision "2013-02-27" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+
+ deviation /t:interfaces/t:ifEntry {
+ deviate add {
+ default "admin"; // new users are 'admin' by default
+ config "true";
+ }
+ reference "system/user ref";
+ }
+
+}
--- /dev/null
+module test1 {
+
+ yang-version 1;
+ namespace "urn:simple.demo.test1";
+ prefix "t1";
+
+ import ietf-inet-types {
+ prefix "inet";
+ revision-date 2010-09-24;
+ }
+
+ organization "opendaylight";
+ contact "WILL-BE-DEFINED-LATER";
+ revision 2013-06-18 {
+ }
+
+ typedef dscp-ext {
+ type inet:dscp {
+ range "min..max";
+ }
+ }
+
+ leaf id {
+ type inet:port-number {
+ range "0..65536";
+ }
+ }
+
+}
--- /dev/null
+module test2 {
+
+ yang-version 1;
+ namespace "urn:simple.demo.test2";
+ prefix "t2";
+
+ import custom {
+ prefix "data";
+ }
+
+ organization "opendaylight";
+ contact "WILL-BE-DEFINED-LATER";
+ revision 2013-06-18 {
+ }
+
+ container peer {
+ container destination {
+ uses data:target {
+ refine address {
+ default "1.2.3.4";
+ description "description of address defined by refine";
+ reference "address reference added by refine";
+ config false;
+ mandatory true;
+ must "ifType != 'ethernet' or " +
+ "(ifType = 'ethernet' and ifMTU = 1500)" {
+ error-message "An ethernet MTU must be 1500";
+ }
+ }
+ refine port {
+ description "description of port defined by refine";
+ reference "port reference added by refine";
+ config false;
+ presence "presence is required";
+ }
+ refine addresses {
+ description "description of addresses defined by refine";
+ reference "addresses reference added by refine";
+ config false;
+ min-elements 2;
+ max-elements 12;
+ }
+ refine target-inner {
+ description "new target-inner grouping description";
+ }
+ refine group-type {
+ description "new group-type description";
+ reference "new group-type reference";
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+module test3 {
+
+ yang-version 1;
+ namespace "urn:simple.demo.test3";
+ prefix "t3";
+
+ import custom-types-test {
+ prefix "custom";
+ }
+
+ organization "opendaylight";
+ contact "WILL-BE-DEFINED-LATER";
+ revision 2013-06-18 {
+ }
+
+ identity pt {
+ base custom:service-type;
+ }
+
+ container network {
+ custom:mountpoint point {
+ mnt:target-ref target;
+ }
+
+ description "network-description";
+ reference "network-reference";
+ status obsolete;
+ config true;
+ presence "some presence text";
+ }
+
+}
--- /dev/null
+module custom {
+ yang-version 1;
+ namespace "urn:custom.nodes.test";
+ prefix "c";
+
+ import types {
+ prefix "types";
+ revision-date 2013-07-03;
+ }
+
+ 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 types:nested-union2;
+ }
+ }
+
+ augment "/types:interfaces/types:ifEntry" {
+ when "if:ifType='ds0'";
+ container augment-holder {
+ description "Description for augment holder";
+ }
+ }
+
+ augment "/types:interfaces/types:ifEntry" {
+ when "if:ifType='ds2'";
+ container augment-holder2 {
+ description "Description for augment holder";
+ }
+ }
+
+ augment "/types:interfaces/types:ifEntry/t3:augment-holder/t1:schemas" {
+ when "if:leafType='ds1'";
+ leaf linkleaf {
+ type binary;
+ }
+ }
+
+ 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" {
+ yin-element "true";
+ }
+ }
+
+ 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.";
+ }
+ }
+ }
+
+ grouping target {
+ anyxml data {
+ config true;
+ description "Copy of the source datastore subset.";
+ mandatory false;
+ must "test-condition-text";
+ reference "test-no-reference";
+ status "obsolete";
+ when "test-when-text";
+ }
+ choice how {
+ description "test choice description";
+ 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;
+ }
+ }
+ }
+ leaf address {
+ type string;
+ description "Target IP address";
+ }
+ container port {
+ description "Target port container";
+ }
+ list addresses {
+ key "id";
+ leaf id {
+ type int8;
+ }
+ }
+ grouping target-inner {
+ description "target-inner default description";
+ leaf inner-grouping-id {
+ type int8;
+ }
+ }
+ typedef group-type {
+ type types:my-decimal-type;
+ }
+
+ opendaylight;
+ }
+
+}
--- /dev/null
+module nodes {
+ yang-version 1;
+ namespace "urn:simple.nodes.test";
+ prefix "n";
+
+ import types {
+ prefix "t";
+ revision-date 2013-07-03;
+ }
+
+ import custom {
+ prefix "c";
+ revision-date 2013-02-27;
+ }
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+
+ revision "2013-02-27" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+ leaf int32-leaf {
+ type t:int32-ext2 {
+ range "12..max";
+ }
+ }
+
+ leaf string-leaf {
+ type t:string-ext4;
+ }
+
+ leaf length-leaf {
+ type t:string-ext2 {
+ length "7..max";
+ }
+ }
+
+ leaf decimal-leaf {
+ type t:my-decimal-type {
+ fraction-digits 4;
+ }
+ }
+
+ leaf decimal-leaf2 {
+ type t:my-decimal-type;
+ }
+
+ container ext {
+ types:c-define "MY_INTERFACES";
+ }
+
+ leaf union-leaf {
+ type t:my-union-ext;
+ }
+
+ deviation /t:interfaces/t:ifEntry {
+ deviate add {
+ default "admin"; // new users are 'admin' by default
+ config "true";
+ }
+ reference "system/user ref";
+ }
+
+ leaf custom-union-leaf {
+ type c:union1;
+ }
+
+ container transfer {
+ choice how {
+ default interval;
+ container input {
+ }
+ list output {
+ leaf id {
+ type string;
+ }
+ }
+ 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 datas {
+ description
+ "Copy of the source typesstore subset that matched
+ the filter criteria (if any). An empty types container
+ indicates that the request did not produce any results.";
+ status obsolete;
+ }
+
+ augment "/t:interfaces/t:ifEntry/c:augment-holder" {
+ when "if:ifType='ds0'";
+ leaf ds0ChannelNumber {
+ type string;
+ }
+ leaf interface-id {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ leaf my-type {
+ type t:int32-ext2;
+ }
+ container schemas {
+ }
+ choice odl {
+ leaf id {
+ type int8;
+ }
+ case node1 {
+ description "node1";
+ }
+ case node2 {
+ description "node2";
+ }
+ container node3 {
+ description "node3";
+ }
+ }
+ }
+
+ container mycont {
+ container innercont {
+ typedef mytype {
+ type string;
+ }
+ leaf myleaf {
+ type mytype;
+ }
+ }
+ }
+
+ uses c:target {
+ augment "/mycont/innercont" {
+ description "inner augment";
+ leaf name {
+ type string;
+ }
+ }
+ }
+
+ container peer {
+ container destination {
+ uses c:target {
+ refine address {
+ default "1.2.3.4";
+ description "IP address of target node";
+ reference "address reference added by refine";
+ config false;
+ mandatory true;
+ must "ifType != 'ethernet' or " +
+ "(ifType = 'ethernet' and ifMTU = 1500)" {
+ error-message "An ethernet MTU must be 1500";
+ }
+ }
+ refine port {
+ description "description of port defined by refine";
+ reference "port reference added by refine";
+ config false;
+ presence "presence is required";
+ }
+ refine addresses {
+ description "description of addresses defined by refine";
+ reference "addresses reference added by refine";
+ config false;
+ min-elements 2;
+ max-elements 12;
+ }
+ refine target-inner {
+ description "new target-inner grouping description";
+ }
+ refine group-type {
+ description "new group-type description";
+ reference "new group-type reference";
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+module types {
+ yang-version 1;
+ namespace "urn:simple.types.test";
+ prefix "t";
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+ description "This is types-data test description";
+
+ revision "2013-07-03" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+ typedef int32-ext1 {
+ type int32 {
+ range "2..20";
+ }
+ }
+
+ typedef int32-ext2 {
+ type int32-ext1 {
+ range "3..9|11..max";
+ }
+ units "mile";
+ default "11";
+ }
+
+ typedef string-ext1 {
+ type string {
+ pattern "[a-k]*";
+ length "5..11";
+ }
+ }
+
+ typedef string-ext2 {
+ type string-ext1 {
+ length "6..10";
+ }
+ }
+
+ typedef string-ext3 {
+ type string-ext2 {
+ pattern "[b-u]*";
+ }
+ }
+
+ typedef string-ext4 {
+ type string-ext3 {
+ pattern "[e-z]*";
+ }
+ }
+
+ typedef my-decimal-type {
+ type decimal64 {
+ fraction-digits 6;
+ }
+ }
+
+ typedef my-union {
+ type union {
+ type int16 {
+ range "1..100";
+ }
+ type int32;
+ }
+ }
+
+ typedef my-union-ext {
+ type my-union;
+ }
+
+ typedef nested-union2 {
+ type union {
+ type my-union-ext;
+ type string;
+ }
+ }
+
+ container interfaces {
+ grouping ifEntry {
+ container augment-holder;
+ }
+ list ifEntry {
+ key "ifIndex";
+
+ leaf ifIndex {
+ type uint32;
+ units minutes;
+ }
+
+ leaf ifMtu {
+ type int32;
+ }
+
+ min-elements 1;
+ max-elements 11;
+ }
+ }
+
+}
--- /dev/null
+module augment0 {
+ yang-version 1;
+ namespace "urn:simple.augment0.demo";
+ prefix "a0";
+
+ container foo {
+ description "foo container";
+ container bar {
+ leaf id {
+ type int8;
+ }
+ typedef int-ext {
+ type int8 {
+ range "5..10";
+ }
+ }
+ choice choice-ext {
+ leaf delta {
+ type int8;
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+module augment1 {
+ yang-version 1;
+ namespace "urn:simple.augment1.demo";
+ prefix "a1";
+
+ import augment0 {
+ prefix "a0";
+ }
+
+ augment "/a0:foo/a0:bar" {
+ leaf id {
+ type string;
+ }
+ }
+
+}
--- /dev/null
+module augment2 {
+ yang-version 1;
+ namespace "urn:simple.augment2.demo";
+ prefix "a2";
+
+ import augment0 {
+ prefix "a0";
+ }
+
+ augment "/a0:foo/a0:bar/a0:choice-ext" {
+ anyxml delta;
+ }
+
+}
--- /dev/null
+module container-leaf {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ container foo {
+ description "foo container";
+ }
+
+ leaf foo {
+ type int8;
+ }
+
+}
--- /dev/null
+module container-list {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ container foo {
+ description "foo container";
+ }
+
+ list foo {
+ description "foo list";
+ }
+
+}
--- /dev/null
+module container {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ container foo {
+ description "foo 1";
+ }
+
+ container foo {
+ description "foo 2";
+ }
+
+}
--- /dev/null
+module identity {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ identity id1;
+
+ identity id2;
+
+ identity id1 {
+ base id2;
+ }
+
+}
--- /dev/null
+module typedef {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ typedef int-ext {
+ type int32;
+ }
+
+ typedef int-ext {
+ type int16;
+ }
+
+}
--- /dev/null
+module test0 {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t0";
+
+ container interfaces {
+ }
+
+}
--- /dev/null
+module test1 {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ import some-module {
+ prefix "data";
+ revision-date 2013-02-27;
+ }
+
+}
--- /dev/null
+module test2 {
+ 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";
+ }
+
+ container c1 {
+ typedef int-ext {
+ type int32 {
+ range "10..20";
+ }
+ }
+ }
+
+ container top {
+ leaf id {
+ type int-ext;
+ }
+ }
+
+}
--- /dev/null
+module test3 {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ import test0 {
+ prefix "data";
+ }
+
+ augment "/data:unknown" {
+ when "if:ifType='ds0'";
+ leaf interface-id {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ }
+
+}
--- /dev/null
+module test4 {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ grouping tree {
+ leaf-list node {
+ type string;
+ }
+ container holder {
+
+ }
+ }
+
+ container schema {
+ uses tree {
+ refine node {
+ presence "true";
+ }
+ refine holder {
+ default "one";
+ }
+ }
+ }
+
+}
--- /dev/null
+module test5 {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ typedef my-custom-string {
+ type string {
+ pattern "[a-k]*";
+ length "5..11";
+ }
+ }
+
+ typedef my-string-type {
+ type my-custom-string {
+ length "4..10";
+ }
+ }
+
+}
--- /dev/null
+module test5 {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ typedef my-custom-int {
+ type int32 {
+ range "5..11 | 15..20";
+ }
+ }
+
+ typedef my-int-type {
+ type my-custom-int {
+ range "min..max";
+ }
+ }
+
+}
--- /dev/null
+module custom-types-test {
+
+ yang-version 1;
+ namespace "urn:custom.types.demo";
+ prefix "iit";
+
+ organization "opendaylight";
+ contact "WILL-BE-DEFINED-LATER";
+ revision 2012-04-16 {
+ }
+
+ typedef access-operations-type {
+ type bits {
+ bit create {
+ description "Any protocol operation that creates a new data node.";
+ }
+ bit read {
+ description "Any protocol operation or notification that returns the value of a data node.";
+ position 500;
+ }
+ bit update {
+ description "Any protocol operation that alters an existing data node.";
+ }
+ bit delete {
+ description "Any protocol operation that removes a data node.";
+ position 365;
+ }
+ bit exec {
+ description "Execution access to the specified protocol operation.";
+ }
+ }
+ description "NETCONF Access Operation.";
+ }
+
+ leaf inst-id-leaf1 {
+ type instance-identifier {
+ require-instance false;
+ }
+ }
+
+ leaf inst-id-leaf2 {
+ type instance-identifier;
+ }
+
+ leaf type {
+ type service-type-ref;
+ }
+
+ identity crypto-base {
+ description "crypto-base description";
+ }
+
+ identity crypto-alg {
+ base "crypto-base";
+ description "crypto-alg description";
+ }
+
+ leaf mybits {
+ type bits {
+ bit disable-nagle {
+ position 0;
+ }
+ bit auto-sense-speed {
+ position 1;
+ }
+ bit 10-Mb-only {
+ position 2;
+ }
+ }
+ default "auto-sense-speed";
+ }
+
+ typedef ip-version {
+ type enumeration {
+ enum unknown {
+ description "An unknown or unspecified version of the Internet protocol.";
+ }
+ enum ipv4 {
+ value "19";
+ description "The IPv4 protocol as defined in RFC 791.";
+ }
+ enum ipv6 {
+ value "7";
+ description "The IPv6 protocol as defined in RFC 2460.";
+ }
+ enum default {
+ description "default ip";
+ }
+ }
+ }
+
+ identity service-type {
+ description
+ "Service identity base type. All service identities must be
+ derived from this type. A service type uniquely defines a single
+ atomic API contract, such as a Java interface, a set of C
+ function declarations, or similar.
+
+ If the service type has a corresponding Java interface, the name
+ of that interface should be attached to the derived identity MUST
+ include a java-class keyword, whose name argument points to that
+ interface.";
+ }
+
+ typedef service-type-ref {
+ description
+ "Internal type of references to service type identity.";
+ type identityref {
+ base service-type;
+ }
+ }
+
+}
--- /dev/null
+module iana-afn-safi {
+ namespace "urn:ietf:params:xml:ns:yang:iana-afn-safi";
+ prefix "ianaaf";
+
+ organization
+ "IANA";
+ contact
+ " Internet Assigned Numbers Authority
+
+ Postal: ICANN
+ 4676 Admiralty Way, Suite 330
+ Marina del Rey, CA 90292
+
+ Tel: +1 310 823 9358
+ E-Mail: iana&iana.org";
+ description
+ "This YANG module provides two typedefs containing YANG
+ definitions for the following IANA-registered enumerations:
+
+ - Address Family Numbers (AFN)
+
+ - Subsequent Address Family Identifiers (SAFI)
+
+ The latest revision of this YANG module can be obtained from the
+ IANA web site.
+
+ Copyright (c) 2012 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject to
+ the license terms contained in, the Simplified BSD License set
+ forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC XXXX; see the
+ RFC itself for full legal notices.";
+ // RFC Ed.: replace XXXX with actual RFC number and remove this
+ // note.
+
+ // RFC Ed.: update the date below with the date of RFC publication
+ // and remove this note.
+ revision 2012-06-04 {
+ description
+ "Initial revision.";
+ reference
+ "RFC XXXX: TITLE";
+ }
+
+ typedef address-family {
+ type enumeration {
+ enum other {
+ value "0";
+ description
+ "none of the following";
+ }
+ enum ipv4 {
+ value "1";
+ description
+ "IP version 4";
+ }
+ enum ipv6 {
+ value "2";
+ description
+ "IP version 6";
+ }
+ enum nsap {
+ value "3";
+ description
+ "NSAP";
+ }
+ enum hdlc {
+ value "4";
+ description
+ "HDLC (8-bit multidrop)";
+ }
+ enum bbn1822 {
+ value "5";
+ description
+ "BBN 1822";
+ }
+ enum all802 {
+ value "6";
+ description
+ "802 (includes all 802 media plus Ethernet 'canonical
+ format')";
+ }
+ enum e163 {
+ value "7";
+ description
+ "E.163";
+ }
+ enum e164 {
+ value "8";
+ description
+ "E.164 (SMDS, FrameRelay, ATM)";
+ }
+ enum f69 {
+ value "9";
+ description
+ "F.69 (Telex)";
+ }
+ enum x121 {
+ value "10";
+ description
+ "X.121 (X.25, Frame Relay)";
+ }
+ enum ipx {
+ value "11";
+ description
+ "IPX (Internetwork Packet Exchange)";
+ }
+ enum appletalk {
+ value "12";
+ description
+ "Appletalk";
+ }
+ enum decnetIV {
+ value "13";
+ description
+ "DECnet IV";
+ }
+ enum banyanVines {
+ value "14";
+ description
+ "Banyan Vines";
+ }
+ enum e164withNsap {
+ value "15";
+ description
+ "E.164 with NSAP format subaddress";
+ reference
+ "ATM Forum UNI 3.1";
+ }
+ enum dns {
+ value "16";
+ description
+ "DNS (Domain Name System)";
+ }
+ enum distinguishedName {
+ value "17";
+ description
+ "Distinguished Name (per X.500)";
+ }
+ enum asNumber {
+ value "18";
+ description
+ "Autonomous System Number";
+ }
+ enum xtpOverIPv4 {
+ value "19";
+ description
+ "XTP over IP version 4";
+ }
+ enum xtpOverIpv6 {
+ value "20";
+ description
+ "XTP over IP version 6";
+ }
+ enum xtpNativeModeXTP {
+ value "21";
+ description
+ "XTP native mode XTP";
+ }
+ enum fibreChannelWWPN {
+ value "22";
+ description
+ "Fibre Channel World-Wide Port Name";
+ }
+ enum fibreChannelWWNN {
+ value "23";
+ description
+ "Fibre Channel World-Wide Node Name";
+ }
+ enum gwid {
+ value "24";
+ description
+ "Gateway Identifier";
+ }
+ enum l2vpn {
+ value "25";
+ description
+ "AFI for L2VPN information";
+ reference
+ "RFC 4761: Virtual Private LAN Service (VPLS): Using BGP
+ for Auto-Discovery and Signaling
+
+ RFC 6074: Provisioning, Auto-Discovery, and Signaling in
+ Layer 2 Virtual Private Networks (L2VPNs)
+ ";
+ }
+ enum eigrpCommon {
+ value "16384";
+ description
+ "EIGRP Common Service Family";
+ }
+ enum eigrpIPv4 {
+ value "16385";
+ description
+ "EIGRP IPv4 Service Family";
+ }
+ enum eigrpIPv6 {
+ value "16386";
+ description
+ "EIGRP IPv6 Service Family";
+ }
+ enum lcaf {
+ value "16387";
+ description
+ "LISP Canonical Address Format";
+ }
+ }
+ description
+ "This typedef is a YANG enumeration of IANA-registered address
+ family numbers (AFN).";
+ reference
+ "Address Family Numbers. IANA, 2011-01-20.
+ <http://www.iana.org/assignments/address-family-numbers/
+ address-family-numbers.xml>
+ ";
+ }
+
+ typedef subsequent-address-family {
+ type enumeration {
+ enum nlri-unicast {
+ value "1";
+ description
+ "Network Layer Reachability Information used for unicast
+ forwarding";
+ reference
+ "RFC 4760: Multiprotocol Extensions for BGP-4";
+ }
+ enum nlri-multicast {
+ value "2";
+ description
+ "Network Layer Reachability Information used for multicast
+ forwarding";
+ reference
+ "RFC 4760: Multiprotocol Extensions for BGP-4";
+ }
+ enum nlri-mpls {
+ value "4";
+ description
+ "Network Layer Reachability Information (NLRI) with MPLS
+ Labels";
+ reference
+ "RFC 3107: Carrying Label Information in BGP-4";
+ }
+ enum mcast-vpn {
+ value "5";
+ description
+ "MCAST-VPN";
+ reference
+ "RFC 6514: BGP Encodings and Procedures for Multicast in
+ MPLS/BGP IP VPNs";
+ }
+ enum nlri-dynamic-ms-pw {
+ value "6";
+ status "obsolete";
+ description
+ "Network Layer Reachability Information used for Dynamic
+ Placement of Multi-Segment Pseudowires (TEMPORARY -
+ Expires 2008-08-23)";
+ reference
+ "draft-ietf-pwe3-dynamic-ms-pw: Dynamic Placement of Multi
+ Segment Pseudowires";
+ }
+ enum encapsulation {
+ value "7";
+ description
+ "Encapsulation SAFI";
+ reference
+ "RFC 5512: The BGP Encapsulation Subsequent Address Family
+ Identifier (SAFI) and the BGP Tunnel Encapsulation
+ Attribute";
+ }
+ enum tunnel-safi {
+ value "64";
+ status "obsolete";
+ description
+ "Tunnel SAFI";
+ reference
+ "draft-nalawade-kapoor-tunnel-safi: BGP Tunnel SAFI";
+ }
+ enum vpls {
+ value "65";
+ description
+ "Virtual Private LAN Service (VPLS)";
+ reference
+ "RFC 4761: Virtual Private LAN Service (VPLS): Using BGP
+ for Auto-Discovery and Signaling
+
+ RFC 6074: Provisioning, Auto-Discovery, and Signaling in
+ Layer 2 Virtual Private Networks (L2VPNs)
+ ";
+ }
+ enum bgp-mdt {
+ value "66";
+ description
+ "BGP MDT SAFI";
+ reference
+ "RFC 6037: Cisco Systems' Solution for Multicast in
+ BGP/MPLS IP VPNs";
+ }
+ enum bgp-4over6 {
+ value "67";
+ description
+ "BGP 4over6 SAFI";
+ reference
+ "RFC 5747: 4over6 Transit Solution Using IP Encapsulation
+ and MP-BGP Extensions";
+ }
+ enum bgp-6over4 {
+ value "68";
+ description
+ "BGP 6over4 SAFI";
+ }
+ enum l1vpn-auto-discovery {
+ value "69";
+ description
+ "Layer-1 VPN auto-discovery information";
+ reference
+ "RFC 5195: BGP-Based Auto-Discovery for Layer-1 VPNs";
+ }
+ enum mpls-vpn {
+ value "128";
+ description
+ "MPLS-labeled VPN address";
+ reference
+ "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs)";
+ }
+ enum multicast-bgp-mpls-vpn {
+ value "129";
+ description
+ "Multicast for BGP/MPLS IP Virtual Private Networks
+ (VPNs)";
+ reference
+ "RFC 6513: Multicast in MPLS/BGP IP VPNs
+
+ RFC 6514: BGP Encodings and Procedures for Multicast in
+ MPLS/BGP IP VPNs
+ ";
+ }
+ enum route-target-constraints {
+ value "132";
+ description
+ "Route Target constraints";
+ reference
+ "RFC 4684: Constrained Route Distribution for Border
+ Gateway Protocol/MultiProtocol Label Switching (BGP/MPLS)
+ Internet Protocol (IP) Virtual Private Networks (VPNs)";
+ }
+ enum ipv4-diss-flow {
+ value "133";
+ description
+ "IPv4 dissemination of flow specification rules";
+ reference
+ "RFC 5575: Dissemination of Flow Specification Rules";
+ }
+ enum vpnv4-diss-flow {
+ value "134";
+ description
+ "IPv4 dissemination of flow specification rules";
+ reference
+ "RFC 5575: Dissemination of Flow Specification Rules";
+ }
+ enum vpn-auto-discovery {
+ value "140";
+ status "obsolete";
+ description
+ "VPN auto-discovery";
+ reference
+ "draft-ietf-l3vpn-bgpvpn-auto: Using BGP as an
+ Auto-Discovery Mechanism for VR-based Layer-3 VPNs";
+ }
+ }
+ description
+ "This typedef is a YANG enumeration of IANA-registered
+ subsequent address family identifiers (SAFI).";
+ reference
+ "Subsequent Address Family Identifiers (SAFI) Parameters. IANA,
+ 2012-02-22. <http://www.iana.org/assignments/safi-namespace/
+ safi-namespace.xml>
+ ";
+ }
+}
--- /dev/null
+module iana-if-type {
+ namespace "urn:ietf:params:xml:ns:yang:iana-if-type";
+ prefix ianaift;
+
+ organization "IANA";
+ contact
+ " Internet Assigned Numbers Authority
+
+ Postal: ICANN
+ 4676 Admiralty Way, Suite 330
+ Marina del Rey, CA 90292
+
+ Tel: +1 310 823 9358
+ E-Mail: iana&iana.org";
+ description
+ "This YANG module defines the iana-if-type typedef, which
+ contains YANG definitions for IANA-registered interface types.
+
+ This YANG module is maintained by IANA, and reflects the
+ 'ifType definitions' registry.
+
+ The latest revision of this YANG module can be obtained from
+ the IANA web site.
+
+ Copyright (c) 2011 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC XXXX; see
+ the RFC itself for full legal notices.";
+ // RFC Ed.: replace XXXX with actual RFC number and remove this
+ // note.
+
+ // RFC Ed.: update the date below with the date of RFC publication
+ // and remove this note.
+ revision 2012-06-05 {
+ description
+ "Initial revision.";
+ reference
+ "RFC XXXX: TITLE";
+ }
+
+ typedef iana-if-type {
+ type enumeration {
+ enum "other" {
+ value 1;
+ description
+ "None of the following";
+ }
+ enum "regular1822" {
+ value 2;
+ }
+ enum "hdh1822" {
+ value 3;
+ }
+ enum "ddnX25" {
+ value 4;
+ }
+ enum "rfc877x25" {
+ value 5;
+ reference
+ "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer";
+ }
+ enum "ethernetCsmacd" {
+ value 6;
+ description
+ "For all ethernet-like interfaces, regardless of speed,
+ as per RFC3635.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types.";
+ }
+ enum "iso88023Csmacd" {
+ value 7;
+ status deprecated;
+ description
+ "Deprecated via RFC3635.
+ Use ethernetCsmacd(6) instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types.";
+ }
+ enum "iso88024TokenBus" {
+ value 8;
+ }
+ enum "iso88025TokenRing" {
+ value 9;
+ }
+ enum "iso88026Man" {
+ value 10;
+ }
+ enum "starLan" {
+ value 11;
+ status deprecated;
+ description
+ "Deprecated via RFC3635.
+ Use ethernetCsmacd(6) instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types.";
+ }
+ enum "proteon10Mbit" {
+ value 12;
+ }
+ enum "proteon80Mbit" {
+ value 13;
+ }
+ enum "hyperchannel" {
+ value 14;
+ }
+ enum "fddi" {
+ value 15;
+ reference
+ "RFC 1512 - FDDI Management Information Base";
+ }
+ enum "lapb" {
+ value 16;
+ reference
+ "RFC 1381 - SNMP MIB Extension for X.25 LAPB";
+ }
+ enum "sdlc" {
+ value 17;
+ }
+ enum "ds1" {
+ value 18;
+ description
+ "DS1-MIB";
+ reference
+ "RFC 4805 - Definitions of Managed Objects for the
+ DS1, J1, E1, DS2, and E2 Interface Types";
+ }
+ enum "e1" {
+ value 19;
+ status obsolete;
+ description
+ "Obsolete see DS1-MIB";
+ reference
+ "RFC 4805 - Definitions of Managed Objects for the
+ DS1, J1, E1, DS2, and E2 Interface Types";
+ }
+ enum "basicISDN" {
+ value 20;
+ description
+ "see also RFC2127";
+ }
+ enum "primaryISDN" {
+ value 21;
+ }
+ enum "propPointToPointSerial" {
+ value 22;
+ description
+ "proprietary serial";
+ }
+ enum "ppp" {
+ value 23;
+ }
+ enum "softwareLoopback" {
+ value 24;
+ }
+ enum "eon" {
+ value 25;
+ description
+ "CLNP over IP";
+ }
+ enum "ethernet3Mbit" {
+ value 26;
+ }
+ enum "nsip" {
+ value 27;
+ description
+ "XNS over IP";
+ }
+ enum "slip" {
+ value 28;
+ description
+ "generic SLIP";
+ }
+ enum "ultra" {
+ value 29;
+ description
+ "ULTRA technologies";
+ }
+ enum "ds3" {
+ value 30;
+ description
+ "DS3-MIB";
+ reference
+ "RFC 3896 - Definitions of Managed Objects for the
+ DS3/E3 Interface Type";
+ }
+ enum "sip" {
+ value 31;
+ description
+ "SMDS, coffee";
+ reference
+ "RFC 1694 - Definitions of Managed Objects for SMDS
+ Interfaces using SMIv2";
+ }
+ enum "frameRelay" {
+ value 32;
+ description
+ "DTE only.";
+ reference
+ "RFC 2115 - Management Information Base for Frame Relay
+ DTEs Using SMIv2";
+ }
+ enum "rs232" {
+ value 33;
+ reference
+ "RFC 1659 - Definitions of Managed Objects for RS-232-like
+ Hardware Devices using SMIv2";
+ }
+ enum "para" {
+ value 34;
+ description
+ "parallel-port";
+ reference
+ "RFC 1660 - Definitions of Managed Objects for
+ Parallel-printer-like Hardware Devices using
+ SMIv2";
+ }
+ enum "arcnet" {
+ value 35;
+ description
+ "arcnet";
+ }
+ enum "arcnetPlus" {
+ value 36;
+ description
+ "arcnet plus";
+ }
+ enum "atm" {
+ value 37;
+ description
+ "ATM cells";
+ }
+ enum "miox25" {
+ value 38;
+ reference
+ "RFC 1461 - SNMP MIB extension for Multiprotocol
+ Interconnect over X.25";
+ }
+ enum "sonet" {
+ value 39;
+ description
+ "SONET or SDH";
+ }
+ enum "x25ple" {
+ value 40;
+ reference
+ "RFC 2127 - ISDN Management Information Base using SMIv2";
+ }
+ enum "iso88022llc" {
+ value 41;
+ }
+ enum "localTalk" {
+ value 42;
+ }
+ enum "smdsDxi" {
+ value 43;
+ }
+ enum "frameRelayService" {
+ value 44;
+ description
+ "FRNETSERV-MIB";
+ reference
+ "RFC 2954 - Definitions of Managed Objects for Frame
+ Relay Service";
+ }
+ enum "v35" {
+ value 45;
+ }
+ enum "hssi" {
+ value 46;
+ }
+ enum "hippi" {
+ value 47;
+ }
+ enum "modem" {
+ value 48;
+ description
+ "Generic modem";
+ }
+ enum "aal5" {
+ value 49;
+ description
+ "AAL5 over ATM";
+ }
+ enum "sonetPath" {
+ value 50;
+ }
+ enum "sonetVT" {
+ value 51;
+ }
+ enum "smdsIcip" {
+ value 52;
+ description
+ "SMDS InterCarrier Interface";
+ }
+ enum "propVirtual" {
+ value 53;
+ description
+ "proprietary virtual/internal";
+ reference
+ "RFC 2863 - The Interfaces Group MIB";
+ }
+ enum "propMultiplexor" {
+ value 54;
+ description
+ "proprietary multiplexing";
+ reference
+ "RFC 2863 - The Interfaces Group MIB";
+ }
+ enum "ieee80212" {
+ value 55;
+ description
+ "100BaseVG";
+ }
+ enum "fibreChannel" {
+ value 56;
+ description
+ "Fibre Channel";
+ }
+ enum "hippiInterface" {
+ value 57;
+ description
+ "HIPPI interfaces";
+ }
+ enum "frameRelayInterconnect" {
+ value 58;
+ status obsolete;
+ description
+ "Obsolete use either
+ frameRelay(32) or frameRelayService(44).";
+ }
+ enum "aflane8023" {
+ value 59;
+ description
+ "ATM Emulated LAN for 802.3";
+ }
+ enum "aflane8025" {
+ value 60;
+ description
+ "ATM Emulated LAN for 802.5";
+ }
+ enum "cctEmul" {
+ value 61;
+ description
+ "ATM Emulated circuit";
+ }
+ enum "fastEther" {
+ value 62;
+ status deprecated;
+ description
+ "Obsoleted via RFC3635.
+ ethernetCsmacd(6) should be used instead";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types.";
+ }
+ enum "isdn" {
+ value 63;
+ description
+ "ISDN and X.25";
+ reference
+ "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN
+ in the Packet Mode";
+ }
+ enum "v11" {
+ value 64;
+ description
+ "CCITT V.11/X.21";
+ }
+ enum "v36" {
+ value 65;
+ description
+ "CCITT V.36";
+ }
+ enum "g703at64k" {
+ value 66;
+ description
+ "CCITT G703 at 64Kbps";
+ }
+ enum "g703at2mb" {
+ value 67;
+ status obsolete;
+ description
+ "Obsolete see DS1-MIB";
+ }
+ enum "qllc" {
+ value 68;
+ description
+ "SNA QLLC";
+ }
+ enum "fastEtherFX" {
+ value 69;
+ status deprecated;
+ description
+ "Obsoleted via RFC3635
+ ethernetCsmacd(6) should be used instead";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types.";
+ }
+ enum "channel" {
+ value 70;
+ description
+ "channel";
+ }
+ enum "ieee80211" {
+ value 71;
+ description
+ "radio spread spectrum";
+ }
+ enum "ibm370parChan" {
+ value 72;
+ description
+ "IBM System 360/370 OEMI Channel";
+ }
+ enum "escon" {
+ value 73;
+ description
+ "IBM Enterprise Systems Connection";
+ }
+ enum "dlsw" {
+ value 74;
+ description
+ "Data Link Switching";
+ }
+ enum "isdns" {
+ value 75;
+ description
+ "ISDN S/T interface";
+ }
+ enum "isdnu" {
+ value 76;
+ description
+ "ISDN U interface";
+ }
+ enum "lapd" {
+ value 77;
+ description
+ "Link Access Protocol D";
+ }
+ enum "ipSwitch" {
+ value 78;
+ description
+ "IP Switching Objects";
+ }
+ enum "rsrb" {
+ value 79;
+ description
+ "Remote Source Route Bridging";
+ }
+ enum "atmLogical" {
+ value 80;
+ description
+ "ATM Logical Port";
+ reference
+ "RFC 3606 - Definitions of Supplemental Managed Objects
+ for ATM Interface";
+ }
+ enum "ds0" {
+ value 81;
+ description
+ "Digital Signal Level 0";
+ reference
+ "RFC 2494 - Definitions of Managed Objects for the DS0
+ and DS0 Bundle Interface Type";
+ }
+ enum "ds0Bundle" {
+ value 82;
+ description
+ "group of ds0s on the same ds1";
+ reference
+ "RFC 2494 - Definitions of Managed Objects for the DS0
+ and DS0 Bundle Interface Type";
+ }
+ enum "bsc" {
+ value 83;
+ description
+ "Bisynchronous Protocol";
+ }
+ enum "async" {
+ value 84;
+ description
+ "Asynchronous Protocol";
+ }
+ enum "cnr" {
+ value 85;
+ description
+ "Combat Net Radio";
+ }
+ enum "iso88025Dtr" {
+ value 86;
+ description
+ "ISO 802.5r DTR";
+ }
+ enum "eplrs" {
+ value 87;
+ description
+ "Ext Pos Loc Report Sys";
+ }
+ enum "arap" {
+ value 88;
+ description
+ "Appletalk Remote Access Protocol";
+ }
+ enum "propCnls" {
+ value 89;
+ description
+ "Proprietary Connectionless Protocol";
+ }
+ enum "hostPad" {
+ value 90;
+ description
+ "CCITT-ITU X.29 PAD Protocol";
+ }
+ enum "termPad" {
+ value 91;
+ description
+ "CCITT-ITU X.3 PAD Facility";
+ }
+ enum "frameRelayMPI" {
+ value 92;
+ description
+ "Multiproto Interconnect over FR";
+ }
+ enum "x213" {
+ value 93;
+ description
+ "CCITT-ITU X213";
+ }
+ enum "adsl" {
+ value 94;
+ description
+ "Asymmetric Digital Subscriber Loop";
+ }
+ enum "radsl" {
+ value 95;
+ description
+ "Rate-Adapt. Digital Subscriber Loop";
+ }
+ enum "sdsl" {
+ value 96;
+ description
+ "Symmetric Digital Subscriber Loop";
+ }
+ enum "vdsl" {
+ value 97;
+ description
+ "Very H-Speed Digital Subscrib. Loop";
+ }
+ enum "iso88025CRFPInt" {
+ value 98;
+ description
+ "ISO 802.5 CRFP";
+ }
+ enum "myrinet" {
+ value 99;
+ description
+ "Myricom Myrinet";
+ }
+ enum "voiceEM" {
+ value 100;
+ description
+ "voice recEive and transMit";
+ }
+ enum "voiceFXO" {
+ value 101;
+ description
+ "voice Foreign Exchange Office";
+ }
+ enum "voiceFXS" {
+ value 102;
+ description
+ "voice Foreign Exchange Station";
+ }
+ enum "voiceEncap" {
+ value 103;
+ description
+ "voice encapsulation";
+ }
+ enum "voiceOverIp" {
+ value 104;
+ description
+ "voice over IP encapsulation";
+ }
+ enum "atmDxi" {
+ value 105;
+ description
+ "ATM DXI";
+ }
+ enum "atmFuni" {
+ value 106;
+ description
+ "ATM FUNI";
+ }
+ enum "atmIma" {
+ value 107;
+ description
+ "ATM IMA";
+ }
+ enum "pppMultilinkBundle" {
+ value 108;
+ description
+ "PPP Multilink Bundle";
+ }
+ enum "ipOverCdlc" {
+ value 109;
+ description
+ "IBM ipOverCdlc";
+ }
+ enum "ipOverClaw" {
+ value 110;
+ description
+ "IBM Common Link Access to Workstn";
+ }
+ enum "stackToStack" {
+ value 111;
+ description
+ "IBM stackToStack";
+ }
+ enum "virtualIpAddress" {
+ value 112;
+ description
+ "IBM VIPA";
+ }
+ enum "mpc" {
+ value 113;
+ description
+ "IBM multi-protocol channel support";
+ }
+ enum "ipOverAtm" {
+ value 114;
+ description
+ "IBM ipOverAtm";
+ reference
+ "RFC 2320 - Definitions of Managed Objects for Classical IP
+ and ARP Over ATM Using SMIv2 (IPOA-MIB)";
+ }
+ enum "iso88025Fiber" {
+ value 115;
+ description
+ "ISO 802.5j Fiber Token Ring";
+ }
+ enum "tdlc" {
+ value 116;
+ description
+ "IBM twinaxial data link control";
+ }
+ enum "gigabitEthernet" {
+ value 117;
+ status deprecated;
+ description
+ "Obsoleted via RFC3635
+ ethernetCsmacd(6) should be used instead";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types.";
+ }
+ enum "hdlc" {
+ value 118;
+ description
+ "HDLC";
+ }
+ enum "lapf" {
+ value 119;
+ description
+ "LAP F";
+ }
+ enum "v37" {
+ value 120;
+ description
+ "V.37";
+ }
+ enum "x25mlp" {
+ value 121;
+ description
+ "Multi-Link Protocol";
+ }
+ enum "x25huntGroup" {
+ value 122;
+ description
+ "X25 Hunt Group";
+ }
+ enum "transpHdlc" {
+ value 123;
+ description
+ "Transp HDLC";
+ }
+ enum "interleave" {
+ value 124;
+ description
+ "Interleave channel";
+ }
+ enum "fast" {
+ value 125;
+ description
+ "Fast channel";
+ }
+ enum "ip" {
+ value 126;
+ description
+ "IP (for APPN HPR in IP networks)";
+ }
+ enum "docsCableMaclayer" {
+ value 127;
+ description
+ "CATV Mac Layer";
+ }
+ enum "docsCableDownstream" {
+ value 128;
+ description
+ "CATV Downstream interface";
+ }
+ enum "docsCableUpstream" {
+ value 129;
+ description
+ "CATV Upstream interface";
+ }
+ enum "a12MppSwitch" {
+ value 130;
+ description
+ "Avalon Parallel Processor";
+ }
+ enum "tunnel" {
+ value 131;
+ description
+ "Encapsulation interface";
+ }
+ enum "coffee" {
+ value 132;
+ description
+ "coffee pot";
+ reference
+ "RFC 2325 - Coffee MIB";
+ }
+ enum "ces" {
+ value 133;
+ description
+ "Circuit Emulation Service";
+ }
+ enum "atmSubInterface" {
+ value 134;
+ description
+ "ATM Sub Interface";
+ }
+ enum "l2vlan" {
+ value 135;
+ description
+ "Layer 2 Virtual LAN using 802.1Q";
+ }
+ enum "l3ipvlan" {
+ value 136;
+ description
+ "Layer 3 Virtual LAN using IP";
+ }
+ enum "l3ipxvlan" {
+ value 137;
+ description
+ "Layer 3 Virtual LAN using IPX";
+ }
+ enum "digitalPowerline" {
+ value 138;
+ description
+ "IP over Power Lines";
+ }
+ enum "mediaMailOverIp" {
+ value 139;
+ description
+ "Multimedia Mail over IP";
+ }
+ enum "dtm" {
+ value 140;
+ description
+ "Dynamic syncronous Transfer Mode";
+ }
+ enum "dcn" {
+ value 141;
+ description
+ "Data Communications Network";
+ }
+ enum "ipForward" {
+ value 142;
+ description
+ "IP Forwarding Interface";
+ }
+ enum "msdsl" {
+ value 143;
+ description
+ "Multi-rate Symmetric DSL";
+ }
+ enum "ieee1394" {
+ value 144;
+ description
+ "IEEE1394 High Performance Serial Bus";
+ }
+ enum "if-gsn" {
+ value 145;
+ description
+ "HIPPI-6400";
+ }
+ enum "dvbRccMacLayer" {
+ value 146;
+ description
+ "DVB-RCC MAC Layer";
+ }
+ enum "dvbRccDownstream" {
+ value 147;
+ description
+ "DVB-RCC Downstream Channel";
+ }
+ enum "dvbRccUpstream" {
+ value 148;
+ description
+ "DVB-RCC Upstream Channel";
+ }
+ enum "atmVirtual" {
+ value 149;
+ description
+ "ATM Virtual Interface";
+ }
+ enum "mplsTunnel" {
+ value 150;
+ description
+ "MPLS Tunnel Virtual Interface";
+ }
+ enum "srp" {
+ value 151;
+ description
+ "Spatial Reuse Protocol ";
+ }
+ enum "voiceOverAtm" {
+ value 152;
+ description
+ "Voice Over ATM";
+ }
+ enum "voiceOverFrameRelay" {
+ value 153;
+ description
+ "Voice Over Frame Relay";
+ }
+ enum "idsl" {
+ value 154;
+ description
+ "Digital Subscriber Loop over ISDN";
+ }
+ enum "compositeLink" {
+ value 155;
+ description
+ "Avici Composite Link Interface";
+ }
+ enum "ss7SigLink" {
+ value 156;
+ description
+ "SS7 Signaling Link";
+ }
+ enum "propWirelessP2P" {
+ value 157;
+ description
+ "Prop. P2P wireless interface";
+ }
+ enum "frForward" {
+ value 158;
+ description
+ "Frame Forward Interface";
+ }
+ enum "rfc1483" {
+ value 159;
+ description
+ "Multiprotocol over ATM AAL5";
+ reference
+ "RFC 1483 - Multiprotocol Encapsulation over ATM
+ Adaptation Layer 5";
+ }
+ enum "usb" {
+ value 160;
+ description
+ "USB Interface";
+ }
+ enum "ieee8023adLag" {
+ value 161;
+ description
+ "IEEE 802.3ad Link Aggregate";
+ }
+ enum "bgppolicyaccounting" {
+ value 162;
+ description
+ "BGP Policy Accounting";
+ }
+ enum "frf16MfrBundle" {
+ value 163;
+ description
+ "FRF .16 Multilink Frame Relay";
+ }
+ enum "h323Gatekeeper" {
+ value 164;
+ description
+ "H323 Gatekeeper";
+ }
+ enum "h323Proxy" {
+ value 165;
+ description
+ "H323 Voice and Video Proxy";
+ }
+ enum "mpls" {
+ value 166;
+ description
+ "MPLS";
+ }
+ enum "mfSigLink" {
+ value 167;
+ description
+ "Multi-frequency signaling link";
+ }
+ enum "hdsl2" {
+ value 168;
+ description
+ "High Bit-Rate DSL - 2nd generation";
+ }
+ enum "shdsl" {
+ value 169;
+ description
+ "Multirate HDSL2";
+ }
+ enum "ds1FDL" {
+ value 170;
+ description
+ "Facility Data Link 4Kbps on a DS1";
+ }
+ enum "pos" {
+ value 171;
+ description
+ "Packet over SONET/SDH Interface";
+ }
+ enum "dvbAsiIn" {
+ value 172;
+ description
+ "DVB-ASI Input";
+ }
+ enum "dvbAsiOut" {
+ value 173;
+ description
+ "DVB-ASI Output";
+ }
+ enum "plc" {
+ value 174;
+ description
+ "Power Line Communtications";
+ }
+ enum "nfas" {
+ value 175;
+ description
+ "Non Facility Associated Signaling";
+ }
+ enum "tr008" {
+ value 176;
+ description
+ "TR008";
+ }
+ enum "gr303RDT" {
+ value 177;
+ description
+ "Remote Digital Terminal";
+ }
+ enum "gr303IDT" {
+ value 178;
+ description
+ "Integrated Digital Terminal";
+ }
+ enum "isup" {
+ value 179;
+ description
+ "ISUP";
+ }
+ enum "propDocsWirelessMaclayer" {
+ value 180;
+ description
+ "Cisco proprietary Maclayer";
+ }
+ enum "propDocsWirelessDownstream" {
+ value 181;
+ description
+ "Cisco proprietary Downstream";
+ }
+ enum "propDocsWirelessUpstream" {
+ value 182;
+ description
+ "Cisco proprietary Upstream";
+ }
+ enum "hiperlan2" {
+ value 183;
+ description
+ "HIPERLAN Type 2 Radio Interface";
+ }
+ enum "propBWAp2Mp" {
+ value 184;
+ description
+ "PropBroadbandWirelessAccesspt2multipt use of this value
+ for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f
+ is deprecated and ieee80216WMAN(237) should be used
+ instead.";
+ }
+ enum "sonetOverheadChannel" {
+ value 185;
+ description
+ "SONET Overhead Channel";
+ }
+ enum "digitalWrapperOverheadChannel" {
+ value 186;
+ description
+ "Digital Wrapper";
+ }
+ enum "aal2" {
+ value 187;
+ description
+ "ATM adaptation layer 2";
+ }
+ enum "radioMAC" {
+ value 188;
+ description
+ "MAC layer over radio links";
+ }
+ enum "atmRadio" {
+ value 189;
+ description
+ "ATM over radio links";
+ }
+ enum "imt" {
+ value 190;
+ description
+ "Inter Machine Trunks";
+ }
+ enum "mvl" {
+ value 191;
+ description
+ "Multiple Virtual Lines DSL";
+ }
+ enum "reachDSL" {
+ value 192;
+ description
+ "Long Reach DSL";
+ }
+ enum "frDlciEndPt" {
+ value 193;
+ description
+ "Frame Relay DLCI End Point";
+ }
+ enum "atmVciEndPt" {
+ value 194;
+ description
+ "ATM VCI End Point";
+ }
+ enum "opticalChannel" {
+ value 195;
+ description
+ "Optical Channel";
+ }
+ enum "opticalTransport" {
+ value 196;
+ description
+ "Optical Transport";
+ }
+ enum "propAtm" {
+ value 197;
+ description
+ "Proprietary ATM";
+ }
+ enum "voiceOverCable" {
+ value 198;
+ description
+ "Voice Over Cable Interface";
+ }
+ enum "infiniband" {
+ value 199;
+ description
+ "Infiniband";
+ }
+ enum "teLink" {
+ value 200;
+ description
+ "TE Link";
+ }
+ enum "q2931" {
+ value 201;
+ description
+ "Q.2931";
+ }
+ enum "virtualTg" {
+ value 202;
+ description
+ "Virtual Trunk Group";
+ }
+ enum "sipTg" {
+ value 203;
+ description
+ "SIP Trunk Group";
+ }
+ enum "sipSig" {
+ value 204;
+ description
+ "SIP Signaling";
+ }
+ enum "docsCableUpstreamChannel" {
+ value 205;
+ description
+ "CATV Upstream Channel";
+ }
+ enum "econet" {
+ value 206;
+ description
+ "Acorn Econet";
+ }
+ enum "pon155" {
+ value 207;
+ description
+ "FSAN 155Mb Symetrical PON interface";
+ }
+ enum "pon622" {
+ value 208;
+ description
+ "FSAN622Mb Symetrical PON interface";
+ }
+ enum "bridge" {
+ value 209;
+ description
+ "Transparent bridge interface";
+ }
+ enum "linegroup" {
+ value 210;
+ description
+ "Interface common to multiple lines";
+ }
+ enum "voiceEMFGD" {
+ value 211;
+ description
+ "voice E&M Feature Group D";
+ }
+ enum "voiceFGDEANA" {
+ value 212;
+ description
+ "voice FGD Exchange Access North American";
+ }
+ enum "voiceDID" {
+ value 213;
+ description
+ "voice Direct Inward Dialing";
+ }
+ enum "mpegTransport" {
+ value 214;
+ description
+ "MPEG transport interface";
+ }
+ enum "sixToFour" {
+ value 215;
+ status deprecated;
+ description
+ "6to4 interface (DEPRECATED)";
+ reference
+ "RFC 4087 - IP Tunnel MIB";
+ }
+ enum "gtp" {
+ value 216;
+ description
+ "GTP (GPRS Tunneling Protocol)";
+ }
+ enum "pdnEtherLoop1" {
+ value 217;
+ description
+ "Paradyne EtherLoop 1";
+ }
+ enum "pdnEtherLoop2" {
+ value 218;
+ description
+ "Paradyne EtherLoop 2";
+ }
+ enum "opticalChannelGroup" {
+ value 219;
+ description
+ "Optical Channel Group";
+ }
+ enum "homepna" {
+ value 220;
+ description
+ "HomePNA ITU-T G.989";
+ }
+ enum "gfp" {
+ value 221;
+ description
+ "Generic Framing Procedure (GFP)";
+ }
+ enum "ciscoISLvlan" {
+ value 222;
+ description
+ "Layer 2 Virtual LAN using Cisco ISL";
+ }
+ enum "actelisMetaLOOP" {
+ value 223;
+ description
+ "Acteleis proprietary MetaLOOP High Speed Link";
+ }
+ enum "fcipLink" {
+ value 224;
+ description
+ "FCIP Link";
+ }
+ enum "rpr" {
+ value 225;
+ description
+ "Resilient Packet Ring Interface Type";
+ }
+ enum "qam" {
+ value 226;
+ description
+ "RF Qam Interface";
+ }
+ enum "lmp" {
+ value 227;
+ description
+ "Link Management Protocol";
+ reference
+ "RFC 4327 - Link Management Protocol (LMP) Management
+ Information Base (MIB)";
+ }
+ enum "cblVectaStar" {
+ value 228;
+ description
+ "Cambridge Broadband Networks Limited VectaStar";
+ }
+ enum "docsCableMCmtsDownstream" {
+ value 229;
+ description
+ "CATV Modular CMTS Downstream Interface";
+ }
+ enum "adsl2" {
+ value 230;
+ status deprecated;
+ description
+ "Asymmetric Digital Subscriber Loop Version 2
+ (DEPRECATED/OBSOLETED - please use adsl2plus(238)
+ instead)";
+ reference
+ "RFC 4706 - Definitions of Managed Objects for Asymmetric
+ Digital Subscriber Line 2 (ADSL2)";
+ }
+ enum "macSecControlledIF" {
+ value 231;
+ description
+ "MACSecControlled";
+ }
+ enum "macSecUncontrolledIF" {
+ value 232;
+ description
+ "MACSecUncontrolled";
+ }
+ enum "aviciOpticalEther" {
+ value 233;
+ description
+ "Avici Optical Ethernet Aggregate";
+ }
+ enum "atmbond" {
+ value 234;
+ description
+ "atmbond";
+ }
+ enum "voiceFGDOS" {
+ value 235;
+ description
+ "voice FGD Operator Services";
+ }
+ enum "mocaVersion1" {
+ value 236;
+ description
+ "MultiMedia over Coax Alliance (MoCA) Interface
+ as documented in information provided privately to IANA";
+ }
+ enum "ieee80216WMAN" {
+ value 237;
+ description
+ "IEEE 802.16 WMAN interface";
+ }
+ enum "adsl2plus" {
+ value 238;
+ description
+ "Asymmetric Digital Subscriber Loop Version 2,
+ Version 2 Plus and all variants";
+ }
+ enum "dvbRcsMacLayer" {
+ value 239;
+ description
+ "DVB-RCS MAC Layer";
+ reference
+ "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+ }
+ enum "dvbTdm" {
+ value 240;
+ description
+ "DVB Satellite TDM";
+ reference
+ "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+ }
+ enum "dvbRcsTdma" {
+ value 241;
+ description
+ "DVB-RCS TDMA";
+ reference
+ "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+ }
+ enum "x86Laps" {
+ value 242;
+ description
+ "LAPS based on ITU-T X.86/Y.1323";
+ }
+ enum "wwanPP" {
+ value 243;
+ description
+ "3GPP WWAN";
+ }
+ enum "wwanPP2" {
+ value 244;
+ description
+ "3GPP2 WWAN";
+ }
+ enum "voiceEBS" {
+ value 245;
+ description
+ "voice P-phone EBS physical interface";
+ }
+ enum "ifPwType" {
+ value 246;
+ description
+ "Pseudowire interface type";
+ reference
+ "RFC 5601 - Pseudowire (PW) Management Information Base";
+ }
+ enum "ilan" {
+ value 247;
+ description
+ "Internal LAN on a bridge per IEEE 802.1ap";
+ }
+ enum "pip" {
+ value 248;
+ description
+ "Provider Instance Port on a bridge per IEEE 802.1ah PBB";
+ }
+ enum "aluELP" {
+ value 249;
+ description
+ "Alcatel-Lucent Ethernet Link Protection";
+ }
+ enum "gpon" {
+ value 250;
+ description
+ "Gigabit-capable passive optical networks (G-PON) as per
+ ITU-T G.948";
+ }
+ enum "vdsl2" {
+ value 251;
+ description
+ "Very high speed digital subscriber line Version 2
+ (as per ITU-T Recommendation G.993.2)";
+ reference
+ "RFC 5650 - Definitions of Managed Objects for Very High
+ Speed Digital Subscriber Line 2 (VDSL2)";
+ }
+ enum "capwapDot11Profile" {
+ value 252;
+ description
+ "WLAN Profile Interface";
+ reference
+ "RFC 5834 - Control and Provisioning of Wireless Access
+ Points (CAPWAP) Protocol Binding MIB for
+ IEEE 802.11";
+ }
+ enum "capwapDot11Bss" {
+ value 253;
+ description
+ "WLAN BSS Interface";
+ reference
+ "RFC 5834 - Control and Provisioning of Wireless Access
+ Points (CAPWAP) Protocol Binding MIB for
+ IEEE 802.11";
+ }
+ enum "capwapWtpVirtualRadio" {
+ value 254;
+ description
+ "WTP Virtual Radio Interface";
+ reference
+ "RFC 5833 - Control and Provisioning of Wireless Access
+ Points (CAPWAP) Protocol Base MIB";
+ }
+ enum "bits" {
+ value 255;
+ description
+ "bitsport";
+ }
+ enum "docsCableUpstreamRfPort" {
+ value 256;
+ description
+ "DOCSIS CATV Upstream RF Port";
+ }
+ enum "cableDownstreamRfPort" {
+ value 257;
+ description
+ "CATV downstream RF port";
+ }
+ enum "vmwareVirtualNic" {
+ value 258;
+ description
+ "VMware Virtual Network Interface";
+ }
+ enum "ieee802154" {
+ value 259;
+ description
+ "IEEE 802.15.4 WPAN interface";
+ reference
+ "IEEE 802.15.4-2006";
+ }
+ enum "otnOdu" {
+ value 260;
+ description
+ "OTN Optical Data Unit";
+ }
+ enum "otnOtu" {
+ value 261;
+ description
+ "OTN Optical channel Transport Unit";
+ }
+ enum "ifVfiType" {
+ value 262;
+ description
+ "VPLS Forwarding Instance Interface Type";
+ }
+ enum "g9981" {
+ value 263;
+ description
+ "G.998.1 bonded interface";
+ }
+ enum "g9982" {
+ value 264;
+ description
+ "G.998.2 bonded interface";
+ }
+ enum "g9983" {
+ value 265;
+ description
+ "G.998.3 bonded interface";
+ }
+ enum "aluEpon" {
+ value 266;
+ description
+ "Ethernet Passive Optical Networks (E-PON)";
+ }
+ enum "aluEponOnu" {
+ value 267;
+ description
+ "EPON Optical Network Unit";
+ }
+ enum "aluEponPhysicalUni" {
+ value 268;
+ description
+ "EPON physical User to Network interface";
+ }
+ enum "aluEponLogicalLink" {
+ value 269;
+ description
+ "The emulation of a point-to-point link over the EPON
+ layer";
+ }
+ enum "aluGponOnu" {
+ value 270;
+ description
+ "GPON Optical Network Unit";
+ reference
+ "ITU-T G.984.2";
+ }
+ enum "aluGponPhysicalUni" {
+ value 271;
+ description
+ "GPON physical User to Network interface";
+ reference
+ "ITU-T G.984.2";
+ }
+ enum "vmwareNicTeam" {
+ value 272;
+ description
+ "VMware NIC Team";
+ }
+ }
+ description
+ "This data type is used as the syntax of the 'type'
+ leaf in the 'interface' list in the YANG module
+ ietf-interface.
+
+ The definition of this typedef with the
+ addition of newly assigned values is published
+ periodically by the IANA, in either the Assigned
+ Numbers RFC, or some derivative of it specific to
+ Internet Network Management number assignments. (The
+ latest arrangements can be obtained by contacting the
+ IANA.)
+
+ Requests for new values should be made to IANA via
+ email (iana&iana.org).";
+ reference
+ "ifType definitions registry.
+ <http://www.iana.org/assignments/smi-numbers>";
+ }
+}
--- /dev/null
+module iana-timezones {
+ namespace "urn:ietf:params:xml:ns:yang:iana-timezones";
+ prefix ianatz;
+
+ organization "IANA";
+ contact
+ " Internet Assigned Numbers Authority
+
+ Postal: ICANN
+ 4676 Admiralty Way, Suite 330
+ Marina del Rey, CA 90292
+
+ Tel: +1 310 823 9358
+ E-Mail: iana&iana.org";
+ description
+ "This YANG module defines the iana-timezone typedef, which
+ contains YANG definitions for IANA-registered timezones.
+
+ This YANG module is maintained by IANA, and reflects the
+ IANA Time Zone Database.
+ (http://www.iana.org/time-zones)
+
+ The latest revision of this YANG module can be obtained from
+ the IANA web site.
+
+ Copyright (c) 2011 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC XXXX; see
+ the RFC itself for full legal notices.";
+
+ revision 2012-07-09 {
+ description
+ "Initial revision. Using IANA Time Zone Data v. 2012c
+ (Released 2012-03-27)";
+ reference "RFC XXXX: TITLE";
+ }
+ typedef iana-timezone {
+ description
+ "A timezone location as defined by the IANA timezone
+ database (http://www.iana.org/time-zones)";
+ type enumeration {
+ enum "Europe/Andorra" {
+ value 0;
+ }
+ enum "Asia/Dubai" {
+ value 1;
+ }
+ enum "Asia/Kabul" {
+ value 2;
+ }
+ enum "America/Antigua" {
+ value 3;
+ }
+ enum "America/Anguilla" {
+ value 4;
+ }
+ enum "Europe/Tirane" {
+ value 5;
+ }
+ enum "Asia/Yerevan" {
+ value 6;
+ }
+ enum "Africa/Luanda" {
+ value 7;
+ }
+ enum "Antarctica/McMurdo" {
+ value 8;
+ description
+ "McMurdo Station, Ross Island";
+ }
+ enum "Antarctica/South_Pole" {
+ value 9;
+ description
+ "Amundsen-Scott Station, South Pole";
+ }
+ enum "Antarctica/Rothera" {
+ value 10;
+ description
+ "Rothera Station, Adelaide Island";
+ }
+ enum "Antarctica/Palmer" {
+ value 11;
+ description
+ "Palmer Station, Anvers Island";
+ }
+ enum "Antarctica/Mawson" {
+ value 12;
+ description
+ "Mawson Station, Holme Bay";
+ }
+ enum "Antarctica/Davis" {
+ value 13;
+ description
+ "Davis Station, Vestfold Hills";
+ }
+ enum "Antarctica/Casey" {
+ value 14;
+ description
+ "Casey Station, Bailey Peninsula";
+ }
+ enum "Antarctica/Vostok" {
+ value 15;
+ description
+ "Vostok Station, Lake Vostok";
+ }
+ enum "Antarctica/DumontDUrville" {
+ value 16;
+ description
+ "Dumont-d'Urville Station, Terre Adelie";
+ }
+ enum "Antarctica/Syowa" {
+ value 17;
+ description
+ "Syowa Station, E Ongul I";
+ }
+ enum "Antarctica/Macquarie" {
+ value 18;
+ description
+ "Macquarie Island Station, Macquarie Island";
+ }
+ enum "America/Argentina/Buenos_Aires" {
+ value 19;
+ description
+ "Buenos Aires (BA, CF)";
+ }
+ enum "America/Argentina/Cordoba" {
+ value 20;
+ description
+ "most locations (CB, CC, CN, ER, FM, MN, SE, SF)";
+ }
+ enum "America/Argentina/Salta" {
+ value 21;
+ description
+ "(SA, LP, NQ, RN)";
+ }
+ enum "America/Argentina/Jujuy" {
+ value 22;
+ description
+ "Jujuy (JY)";
+ }
+ enum "America/Argentina/Tucuman" {
+ value 23;
+ description
+ "Tucuman (TM)";
+ }
+ enum "America/Argentina/Catamarca" {
+ value 24;
+ description
+ "Catamarca (CT), Chubut (CH)";
+ }
+ enum "America/Argentina/La_Rioja" {
+ value 25;
+ description
+ "La Rioja (LR)";
+ }
+ enum "America/Argentina/San_Juan" {
+ value 26;
+ description
+ "San Juan (SJ)";
+ }
+ enum "America/Argentina/Mendoza" {
+ value 27;
+ description
+ "Mendoza (MZ)";
+ }
+ enum "America/Argentina/San_Luis" {
+ value 28;
+ description
+ "San Luis (SL)";
+ }
+ enum "America/Argentina/Rio_Gallegos" {
+ value 29;
+ description
+ "Santa Cruz (SC)";
+ }
+ enum "America/Argentina/Ushuaia" {
+ value 30;
+ description
+ "Tierra del Fuego (TF)";
+ }
+ enum "Pacific/Pago_Pago" {
+ value 31;
+ }
+ enum "Europe/Vienna" {
+ value 32;
+ }
+ enum "Australia/Lord_Howe" {
+ value 33;
+ description
+ "Lord Howe Island";
+ }
+ enum "Australia/Hobart" {
+ value 34;
+ description
+ "Tasmania - most locations";
+ }
+ enum "Australia/Currie" {
+ value 35;
+ description
+ "Tasmania - King Island";
+ }
+ enum "Australia/Melbourne" {
+ value 36;
+ description
+ "Victoria";
+ }
+ enum "Australia/Sydney" {
+ value 37;
+ description
+ "New South Wales - most locations";
+ }
+ enum "Australia/Broken_Hill" {
+ value 38;
+ description
+ "New South Wales - Yancowinna";
+ }
+ enum "Australia/Brisbane" {
+ value 39;
+ description
+ "Queensland - most locations";
+ }
+ enum "Australia/Lindeman" {
+ value 40;
+ description
+ "Queensland - Holiday Islands";
+ }
+ enum "Australia/Adelaide" {
+ value 41;
+ description
+ "South Australia";
+ }
+ enum "Australia/Darwin" {
+ value 42;
+ description
+ "Northern Territory";
+ }
+ enum "Australia/Perth" {
+ value 43;
+ description
+ "Western Australia - most locations";
+ }
+ enum "Australia/Eucla" {
+ value 44;
+ description
+ "Western Australia - Eucla area";
+ }
+ enum "America/Aruba" {
+ value 45;
+ }
+ enum "Europe/Mariehamn" {
+ value 46;
+ }
+ enum "Asia/Baku" {
+ value 47;
+ }
+ enum "Europe/Sarajevo" {
+ value 48;
+ }
+ enum "America/Barbados" {
+ value 49;
+ }
+ enum "Asia/Dhaka" {
+ value 50;
+ }
+ enum "Europe/Brussels" {
+ value 51;
+ }
+ enum "Africa/Ouagadougou" {
+ value 52;
+ }
+ enum "Europe/Sofia" {
+ value 53;
+ }
+ enum "Asia/Bahrain" {
+ value 54;
+ }
+ enum "Africa/Bujumbura" {
+ value 55;
+ }
+ enum "Africa/Porto-Novo" {
+ value 56;
+ }
+ enum "America/St_Barthelemy" {
+ value 57;
+ }
+ enum "Atlantic/Bermuda" {
+ value 58;
+ }
+ enum "Asia/Brunei" {
+ value 59;
+ }
+ enum "America/La_Paz" {
+ value 60;
+ }
+ enum "America/Kralendijk" {
+ value 61;
+ }
+ enum "America/Noronha" {
+ value 62;
+ description
+ "Atlantic islands";
+ }
+ enum "America/Belem" {
+ value 63;
+ description
+ "Amapa, E Para";
+ }
+ enum "America/Fortaleza" {
+ value 64;
+ description
+ "NE Brazil (MA, PI, CE, RN, PB)";
+ }
+ enum "America/Recife" {
+ value 65;
+ description
+ "Pernambuco";
+ }
+ enum "America/Araguaina" {
+ value 66;
+ description
+ "Tocantins";
+ }
+ enum "America/Maceio" {
+ value 67;
+ description
+ "Alagoas, Sergipe";
+ }
+ enum "America/Bahia" {
+ value 68;
+ description
+ "Bahia";
+ }
+ enum "America/Sao_Paulo" {
+ value 69;
+ description
+ "S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)";
+ }
+ enum "America/Campo_Grande" {
+ value 70;
+ description
+ "Mato Grosso do Sul";
+ }
+ enum "America/Cuiaba" {
+ value 71;
+ description
+ "Mato Grosso";
+ }
+ enum "America/Santarem" {
+ value 72;
+ description
+ "W Para";
+ }
+ enum "America/Porto_Velho" {
+ value 73;
+ description
+ "Rondonia";
+ }
+ enum "America/Boa_Vista" {
+ value 74;
+ description
+ "Roraima";
+ }
+ enum "America/Manaus" {
+ value 75;
+ description
+ "E Amazonas";
+ }
+ enum "America/Eirunepe" {
+ value 76;
+ description
+ "W Amazonas";
+ }
+ enum "America/Rio_Branco" {
+ value 77;
+ description
+ "Acre";
+ }
+ enum "America/Nassau" {
+ value 78;
+ }
+ enum "Asia/Thimphu" {
+ value 79;
+ }
+ enum "Africa/Gaborone" {
+ value 80;
+ }
+ enum "Europe/Minsk" {
+ value 81;
+ }
+ enum "America/Belize" {
+ value 82;
+ }
+ enum "America/St_Johns" {
+ value 83;
+ description
+ "Newfoundland Time, including SE Labrador";
+ }
+ enum "America/Halifax" {
+ value 84;
+ description
+ "Atlantic Time - Nova Scotia (most places), PEI";
+ }
+ enum "America/Glace_Bay" {
+ value 85;
+ description
+ "Atlantic Time - Nova Scotia - places that did not observe
+ DST 1966-1971";
+ }
+ enum "America/Moncton" {
+ value 86;
+ description
+ "Atlantic Time - New Brunswick";
+ }
+ enum "America/Goose_Bay" {
+ value 87;
+ description
+ "Atlantic Time - Labrador - most locations";
+ }
+ enum "America/Blanc-Sablon" {
+ value 88;
+ description
+ "Atlantic Standard Time - Quebec - Lower North Shore";
+ }
+ enum "America/Montreal" {
+ value 89;
+ description
+ "Eastern Time - Quebec - most locations";
+ }
+ enum "America/Toronto" {
+ value 90;
+ description
+ "Eastern Time - Ontario - most locations";
+ }
+ enum "America/Nipigon" {
+ value 91;
+ description
+ "Eastern Time - Ontario & Quebec - places that did not
+ observe DST 1967-1973";
+ }
+ enum "America/Thunder_Bay" {
+ value 92;
+ description
+ "Eastern Time - Thunder Bay, Ontario";
+ }
+ enum "America/Iqaluit" {
+ value 93;
+ description
+ "Eastern Time - east Nunavut - most locations";
+ }
+ enum "America/Pangnirtung" {
+ value 94;
+ description
+ "Eastern Time - Pangnirtung, Nunavut";
+ }
+ enum "America/Resolute" {
+ value 95;
+ description
+ "Central Standard Time - Resolute, Nunavut";
+ }
+ enum "America/Atikokan" {
+ value 96;
+ description
+ "Eastern Standard Time - Atikokan, Ontario and Southampton I,
+ Nunavut";
+ }
+ enum "America/Rankin_Inlet" {
+ value 97;
+ description
+ "Central Time - central Nunavut";
+ }
+ enum "America/Winnipeg" {
+ value 98;
+ description
+ "Central Time - Manitoba & west Ontario";
+ }
+ enum "America/Rainy_River" {
+ value 99;
+ description
+ "Central Time - Rainy River & Fort Frances, Ontario";
+ }
+ enum "America/Regina" {
+ value 100;
+ description
+ "Central Standard Time - Saskatchewan - most locations";
+ }
+ enum "America/Swift_Current" {
+ value 101;
+ description
+ "Central Standard Time - Saskatchewan - midwest";
+ }
+ enum "America/Edmonton" {
+ value 102;
+ description
+ "Mountain Time - Alberta, east British Columbia & west
+ Saskatchewan";
+ }
+ enum "America/Cambridge_Bay" {
+ value 103;
+ description
+ "Mountain Time - west Nunavut";
+ }
+ enum "America/Yellowknife" {
+ value 104;
+ description
+ "Mountain Time - central Northwest Territories";
+ }
+ enum "America/Inuvik" {
+ value 105;
+ description
+ "Mountain Time - west Northwest Territories";
+ }
+ enum "America/Creston" {
+ value 106;
+ description
+ "Mountain Standard Time - Creston, British Columbia";
+ }
+ enum "America/Dawson_Creek" {
+ value 107;
+ description
+ "Mountain Standard Time - Dawson Creek & Fort Saint John,
+ British Columbia";
+ }
+ enum "America/Vancouver" {
+ value 108;
+ description
+ "Pacific Time - west British Columbia";
+ }
+ enum "America/Whitehorse" {
+ value 109;
+ description
+ "Pacific Time - south Yukon";
+ }
+ enum "America/Dawson" {
+ value 110;
+ description
+ "Pacific Time - north Yukon";
+ }
+ enum "Indian/Cocos" {
+ value 111;
+ }
+ enum "Africa/Kinshasa" {
+ value 112;
+ description
+ "west Dem. Rep. of Congo";
+ }
+ enum "Africa/Lubumbashi" {
+ value 113;
+ description
+ "east Dem. Rep. of Congo";
+ }
+ enum "Africa/Bangui" {
+ value 114;
+ }
+ enum "Africa/Brazzaville" {
+ value 115;
+ }
+ enum "Europe/Zurich" {
+ value 116;
+ }
+ enum "Africa/Abidjan" {
+ value 117;
+ }
+ enum "Pacific/Rarotonga" {
+ value 118;
+ }
+ enum "America/Santiago" {
+ value 119;
+ description
+ "most locations";
+ }
+ enum "Pacific/Easter" {
+ value 120;
+ description
+ "Easter Island & Sala y Gomez";
+ }
+ enum "Africa/Douala" {
+ value 121;
+ }
+ enum "Asia/Shanghai" {
+ value 122;
+ description
+ "east China - Beijing, Guangdong, Shanghai, etc.";
+ }
+ enum "Asia/Harbin" {
+ value 123;
+ description
+ "Heilongjiang (except Mohe), Jilin";
+ }
+ enum "Asia/Chongqing" {
+ value 124;
+ description
+ "central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou,
+ etc.";
+ }
+ enum "Asia/Urumqi" {
+ value 125;
+ description
+ "most of Tibet & Xinjiang";
+ }
+ enum "Asia/Kashgar" {
+ value 126;
+ description
+ "west Tibet & Xinjiang";
+ }
+ enum "America/Bogota" {
+ value 127;
+ }
+ enum "America/Costa_Rica" {
+ value 128;
+ }
+ enum "America/Havana" {
+ value 129;
+ }
+ enum "Atlantic/Cape_Verde" {
+ value 130;
+ }
+ enum "America/Curacao" {
+ value 131;
+ }
+ enum "Indian/Christmas" {
+ value 132;
+ }
+ enum "Asia/Nicosia" {
+ value 133;
+ }
+ enum "Europe/Prague" {
+ value 134;
+ }
+ enum "Europe/Berlin" {
+ value 135;
+ }
+ enum "Africa/Djibouti" {
+ value 136;
+ }
+ enum "Europe/Copenhagen" {
+ value 137;
+ }
+ enum "America/Dominica" {
+ value 138;
+ }
+ enum "America/Santo_Domingo" {
+ value 139;
+ }
+ enum "Africa/Algiers" {
+ value 140;
+ }
+ enum "America/Guayaquil" {
+ value 141;
+ description
+ "mainland";
+ }
+ enum "Pacific/Galapagos" {
+ value 142;
+ description
+ "Galapagos Islands";
+ }
+ enum "Europe/Tallinn" {
+ value 143;
+ }
+ enum "Africa/Cairo" {
+ value 144;
+ }
+ enum "Africa/El_Aaiun" {
+ value 145;
+ }
+ enum "Africa/Asmara" {
+ value 146;
+ }
+ enum "Europe/Madrid" {
+ value 147;
+ description
+ "mainland";
+ }
+ enum "Africa/Ceuta" {
+ value 148;
+ description
+ "Ceuta & Melilla";
+ }
+ enum "Atlantic/Canary" {
+ value 149;
+ description
+ "Canary Islands";
+ }
+ enum "Africa/Addis_Ababa" {
+ value 150;
+ }
+ enum "Europe/Helsinki" {
+ value 151;
+ }
+ enum "Pacific/Fiji" {
+ value 152;
+ }
+ enum "Atlantic/Stanley" {
+ value 153;
+ }
+ enum "Pacific/Chuuk" {
+ value 154;
+ description
+ "Chuuk (Truk) and Yap";
+ }
+ enum "Pacific/Pohnpei" {
+ value 155;
+ description
+ "Pohnpei (Ponape)";
+ }
+ enum "Pacific/Kosrae" {
+ value 156;
+ description
+ "Kosrae";
+ }
+ enum "Atlantic/Faroe" {
+ value 157;
+ }
+ enum "Europe/Paris" {
+ value 158;
+ }
+ enum "Africa/Libreville" {
+ value 159;
+ }
+ enum "Europe/London" {
+ value 160;
+ }
+ enum "America/Grenada" {
+ value 161;
+ }
+ enum "Asia/Tbilisi" {
+ value 162;
+ }
+ enum "America/Cayenne" {
+ value 163;
+ }
+ enum "Europe/Guernsey" {
+ value 164;
+ }
+ enum "Africa/Accra" {
+ value 165;
+ }
+ enum "Europe/Gibraltar" {
+ value 166;
+ }
+ enum "America/Godthab" {
+ value 167;
+ description
+ "most locations";
+ }
+ enum "America/Danmarkshavn" {
+ value 168;
+ description
+ "east coast, north of Scoresbysund";
+ }
+ enum "America/Scoresbysund" {
+ value 169;
+ description
+ "Scoresbysund / Ittoqqortoormiit";
+ }
+ enum "America/Thule" {
+ value 170;
+ description
+ "Thule / Pituffik";
+ }
+ enum "Africa/Banjul" {
+ value 171;
+ }
+ enum "Africa/Conakry" {
+ value 172;
+ }
+ enum "America/Guadeloupe" {
+ value 173;
+ }
+ enum "Africa/Malabo" {
+ value 174;
+ }
+ enum "Europe/Athens" {
+ value 175;
+ }
+ enum "Atlantic/South_Georgia" {
+ value 176;
+ }
+ enum "America/Guatemala" {
+ value 177;
+ }
+ enum "Pacific/Guam" {
+ value 178;
+ }
+ enum "Africa/Bissau" {
+ value 179;
+ }
+ enum "America/Guyana" {
+ value 180;
+ }
+ enum "Asia/Hong_Kong" {
+ value 181;
+ }
+ enum "America/Tegucigalpa" {
+ value 182;
+ }
+ enum "Europe/Zagreb" {
+ value 183;
+ }
+ enum "America/Port-au-Prince" {
+ value 184;
+ }
+ enum "Europe/Budapest" {
+ value 185;
+ }
+ enum "Asia/Jakarta" {
+ value 186;
+ description
+ "Java & Sumatra";
+ }
+ enum "Asia/Pontianak" {
+ value 187;
+ description
+ "west & central Borneo";
+ }
+ enum "Asia/Makassar" {
+ value 188;
+ description
+ "east & south Borneo, Sulawesi (Celebes), Bali, Nusa
+ Tengarra, west Timor";
+ }
+ enum "Asia/Jayapura" {
+ value 189;
+ description
+ "west New Guinea (Irian Jaya) & Malukus (Moluccas)";
+ }
+ enum "Europe/Dublin" {
+ value 190;
+ }
+ enum "Asia/Jerusalem" {
+ value 191;
+ }
+ enum "Europe/Isle_of_Man" {
+ value 192;
+ }
+ enum "Asia/Kolkata" {
+ value 193;
+ }
+ enum "Indian/Chagos" {
+ value 194;
+ }
+ enum "Asia/Baghdad" {
+ value 195;
+ }
+ enum "Asia/Tehran" {
+ value 196;
+ }
+ enum "Atlantic/Reykjavik" {
+ value 197;
+ }
+ enum "Europe/Rome" {
+ value 198;
+ }
+ enum "Europe/Jersey" {
+ value 199;
+ }
+ enum "America/Jamaica" {
+ value 200;
+ }
+ enum "Asia/Amman" {
+ value 201;
+ }
+ enum "Asia/Tokyo" {
+ value 202;
+ }
+ enum "Africa/Nairobi" {
+ value 203;
+ }
+ enum "Asia/Bishkek" {
+ value 204;
+ }
+ enum "Asia/Phnom_Penh" {
+ value 205;
+ }
+ enum "Pacific/Tarawa" {
+ value 206;
+ description
+ "Gilbert Islands";
+ }
+ enum "Pacific/Enderbury" {
+ value 207;
+ description
+ "Phoenix Islands";
+ }
+ enum "Pacific/Kiritimati" {
+ value 208;
+ description
+ "Line Islands";
+ }
+ enum "Indian/Comoro" {
+ value 209;
+ }
+ enum "America/St_Kitts" {
+ value 210;
+ }
+ enum "Asia/Pyongyang" {
+ value 211;
+ }
+ enum "Asia/Seoul" {
+ value 212;
+ }
+ enum "Asia/Kuwait" {
+ value 213;
+ }
+ enum "America/Cayman" {
+ value 214;
+ }
+ enum "Asia/Almaty" {
+ value 215;
+ description
+ "most locations";
+ }
+ enum "Asia/Qyzylorda" {
+ value 216;
+ description
+ "Qyzylorda (Kyzylorda, Kzyl-Orda)";
+ }
+ enum "Asia/Aqtobe" {
+ value 217;
+ description
+ "Aqtobe (Aktobe)";
+ }
+ enum "Asia/Aqtau" {
+ value 218;
+ description
+ "Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)";
+ }
+ enum "Asia/Oral" {
+ value 219;
+ description
+ "West Kazakhstan";
+ }
+ enum "Asia/Vientiane" {
+ value 220;
+ }
+ enum "Asia/Beirut" {
+ value 221;
+ }
+ enum "America/St_Lucia" {
+ value 222;
+ }
+ enum "Europe/Vaduz" {
+ value 223;
+ }
+ enum "Asia/Colombo" {
+ value 224;
+ }
+ enum "Africa/Monrovia" {
+ value 225;
+ }
+ enum "Africa/Maseru" {
+ value 226;
+ }
+ enum "Europe/Vilnius" {
+ value 227;
+ }
+ enum "Europe/Luxembourg" {
+ value 228;
+ }
+ enum "Europe/Riga" {
+ value 229;
+ }
+ enum "Africa/Tripoli" {
+ value 230;
+ }
+ enum "Africa/Casablanca" {
+ value 231;
+ }
+ enum "Europe/Monaco" {
+ value 232;
+ }
+ enum "Europe/Chisinau" {
+ value 233;
+ }
+ enum "Europe/Podgorica" {
+ value 234;
+ }
+ enum "America/Marigot" {
+ value 235;
+ }
+ enum "Indian/Antananarivo" {
+ value 236;
+ }
+ enum "Pacific/Majuro" {
+ value 237;
+ description
+ "most locations";
+ }
+ enum "Pacific/Kwajalein" {
+ value 238;
+ description
+ "Kwajalein";
+ }
+ enum "Europe/Skopje" {
+ value 239;
+ }
+ enum "Africa/Bamako" {
+ value 240;
+ }
+ enum "Asia/Rangoon" {
+ value 241;
+ }
+ enum "Asia/Ulaanbaatar" {
+ value 242;
+ description
+ "most locations";
+ }
+ enum "Asia/Hovd" {
+ value 243;
+ description
+ "Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan";
+ }
+ enum "Asia/Choibalsan" {
+ value 244;
+ description
+ "Dornod, Sukhbaatar";
+ }
+ enum "Asia/Macau" {
+ value 245;
+ }
+ enum "Pacific/Saipan" {
+ value 246;
+ }
+ enum "America/Martinique" {
+ value 247;
+ }
+ enum "Africa/Nouakchott" {
+ value 248;
+ }
+ enum "America/Montserrat" {
+ value 249;
+ }
+ enum "Europe/Malta" {
+ value 250;
+ }
+ enum "Indian/Mauritius" {
+ value 251;
+ }
+ enum "Indian/Maldives" {
+ value 252;
+ }
+ enum "Africa/Blantyre" {
+ value 253;
+ }
+ enum "America/Mexico_City" {
+ value 254;
+ description
+ "Central Time - most locations";
+ }
+ enum "America/Cancun" {
+ value 255;
+ description
+ "Central Time - Quintana Roo";
+ }
+ enum "America/Merida" {
+ value 256;
+ description
+ "Central Time - Campeche, Yucatan";
+ }
+ enum "America/Monterrey" {
+ value 257;
+ description
+ "Mexican Central Time - Coahuila, Durango, Nuevo Leon,
+ Tamaulipas away from US border";
+ }
+ enum "America/Matamoros" {
+ value 258;
+ description
+ "US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas
+ near US border";
+ }
+ enum "America/Mazatlan" {
+ value 259;
+ description
+ "Mountain Time - S Baja, Nayarit, Sinaloa";
+ }
+ enum "America/Chihuahua" {
+ value 260;
+ description
+ "Mexican Mountain Time - Chihuahua away from US border";
+ }
+ enum "America/Ojinaga" {
+ value 261;
+ description
+ "US Mountain Time - Chihuahua near US border";
+ }
+ enum "America/Hermosillo" {
+ value 262;
+ description
+ "Mountain Standard Time - Sonora";
+ }
+ enum "America/Tijuana" {
+ value 263;
+ description
+ "US Pacific Time - Baja California near US border";
+ }
+ enum "America/Santa_Isabel" {
+ value 264;
+ description
+ "Mexican Pacific Time - Baja California away from US border";
+ }
+ enum "America/Bahia_Banderas" {
+ value 265;
+ description
+ "Mexican Central Time - Bahia de Banderas";
+ }
+ enum "Asia/Kuala_Lumpur" {
+ value 266;
+ description
+ "peninsular Malaysia";
+ }
+ enum "Asia/Kuching" {
+ value 267;
+ description
+ "Sabah & Sarawak";
+ }
+ enum "Africa/Maputo" {
+ value 268;
+ }
+ enum "Africa/Windhoek" {
+ value 269;
+ }
+ enum "Pacific/Noumea" {
+ value 270;
+ }
+ enum "Africa/Niamey" {
+ value 271;
+ }
+ enum "Pacific/Norfolk" {
+ value 272;
+ }
+ enum "Africa/Lagos" {
+ value 273;
+ }
+ enum "America/Managua" {
+ value 274;
+ }
+ enum "Europe/Amsterdam" {
+ value 275;
+ }
+ enum "Europe/Oslo" {
+ value 276;
+ }
+ enum "Asia/Kathmandu" {
+ value 277;
+ }
+ enum "Pacific/Nauru" {
+ value 278;
+ }
+ enum "Pacific/Niue" {
+ value 279;
+ }
+ enum "Pacific/Auckland" {
+ value 280;
+ description
+ "most locations";
+ }
+ enum "Pacific/Chatham" {
+ value 281;
+ description
+ "Chatham Islands";
+ }
+ enum "Asia/Muscat" {
+ value 282;
+ }
+ enum "America/Panama" {
+ value 283;
+ }
+ enum "America/Lima" {
+ value 284;
+ }
+ enum "Pacific/Tahiti" {
+ value 285;
+ description
+ "Society Islands";
+ }
+ enum "Pacific/Marquesas" {
+ value 286;
+ description
+ "Marquesas Islands";
+ }
+ enum "Pacific/Gambier" {
+ value 287;
+ description
+ "Gambier Islands";
+ }
+ enum "Pacific/Port_Moresby" {
+ value 288;
+ }
+ enum "Asia/Manila" {
+ value 289;
+ }
+ enum "Asia/Karachi" {
+ value 290;
+ }
+ enum "Europe/Warsaw" {
+ value 291;
+ }
+ enum "America/Miquelon" {
+ value 292;
+ }
+ enum "Pacific/Pitcairn" {
+ value 293;
+ }
+ enum "America/Puerto_Rico" {
+ value 294;
+ }
+ enum "Asia/Gaza" {
+ value 295;
+ description
+ "Gaza Strip";
+ }
+ enum "Asia/Hebron" {
+ value 296;
+ description
+ "West Bank";
+ }
+ enum "Europe/Lisbon" {
+ value 297;
+ description
+ "mainland";
+ }
+ enum "Atlantic/Madeira" {
+ value 298;
+ description
+ "Madeira Islands";
+ }
+ enum "Atlantic/Azores" {
+ value 299;
+ description
+ "Azores";
+ }
+ enum "Pacific/Palau" {
+ value 300;
+ }
+ enum "America/Asuncion" {
+ value 301;
+ }
+ enum "Asia/Qatar" {
+ value 302;
+ }
+ enum "Indian/Reunion" {
+ value 303;
+ }
+ enum "Europe/Bucharest" {
+ value 304;
+ }
+ enum "Europe/Belgrade" {
+ value 305;
+ }
+ enum "Europe/Kaliningrad" {
+ value 306;
+ description
+ "Moscow-01 - Kaliningrad";
+ }
+ enum "Europe/Moscow" {
+ value 307;
+ description
+ "Moscow+00 - west Russia";
+ }
+ enum "Europe/Volgograd" {
+ value 308;
+ description
+ "Moscow+00 - Caspian Sea";
+ }
+ enum "Europe/Samara" {
+ value 309;
+ description
+ "Moscow+00 - Samara, Udmurtia";
+ }
+ enum "Asia/Yekaterinburg" {
+ value 310;
+ description
+ "Moscow+02 - Urals";
+ }
+ enum "Asia/Omsk" {
+ value 311;
+ description
+ "Moscow+03 - west Siberia";
+ }
+ enum "Asia/Novosibirsk" {
+ value 312;
+ description
+ "Moscow+03 - Novosibirsk";
+ }
+ enum "Asia/Novokuznetsk" {
+ value 313;
+ description
+ "Moscow+03 - Novokuznetsk";
+ }
+ enum "Asia/Krasnoyarsk" {
+ value 314;
+ description
+ "Moscow+04 - Yenisei River";
+ }
+ enum "Asia/Irkutsk" {
+ value 315;
+ description
+ "Moscow+05 - Lake Baikal";
+ }
+ enum "Asia/Yakutsk" {
+ value 316;
+ description
+ "Moscow+06 - Lena River";
+ }
+ enum "Asia/Vladivostok" {
+ value 317;
+ description
+ "Moscow+07 - Amur River";
+ }
+ enum "Asia/Sakhalin" {
+ value 318;
+ description
+ "Moscow+07 - Sakhalin Island";
+ }
+ enum "Asia/Magadan" {
+ value 319;
+ description
+ "Moscow+08 - Magadan";
+ }
+ enum "Asia/Kamchatka" {
+ value 320;
+ description
+ "Moscow+08 - Kamchatka";
+ }
+ enum "Asia/Anadyr" {
+ value 321;
+ description
+ "Moscow+08 - Bering Sea";
+ }
+ enum "Africa/Kigali" {
+ value 322;
+ }
+ enum "Asia/Riyadh" {
+ value 323;
+ }
+ enum "Pacific/Guadalcanal" {
+ value 324;
+ }
+ enum "Indian/Mahe" {
+ value 325;
+ }
+ enum "Africa/Khartoum" {
+ value 326;
+ }
+ enum "Europe/Stockholm" {
+ value 327;
+ }
+ enum "Asia/Singapore" {
+ value 328;
+ }
+ enum "Atlantic/St_Helena" {
+ value 329;
+ }
+ enum "Europe/Ljubljana" {
+ value 330;
+ }
+ enum "Arctic/Longyearbyen" {
+ value 331;
+ }
+ enum "Europe/Bratislava" {
+ value 332;
+ }
+ enum "Africa/Freetown" {
+ value 333;
+ }
+ enum "Europe/San_Marino" {
+ value 334;
+ }
+ enum "Africa/Dakar" {
+ value 335;
+ }
+ enum "Africa/Mogadishu" {
+ value 336;
+ }
+ enum "America/Paramaribo" {
+ value 337;
+ }
+ enum "Africa/Juba" {
+ value 338;
+ }
+ enum "Africa/Sao_Tome" {
+ value 339;
+ }
+ enum "America/El_Salvador" {
+ value 340;
+ }
+ enum "America/Lower_Princes" {
+ value 341;
+ }
+ enum "Asia/Damascus" {
+ value 342;
+ }
+ enum "Africa/Mbabane" {
+ value 343;
+ }
+ enum "America/Grand_Turk" {
+ value 344;
+ }
+ enum "Africa/Ndjamena" {
+ value 345;
+ }
+ enum "Indian/Kerguelen" {
+ value 346;
+ }
+ enum "Africa/Lome" {
+ value 347;
+ }
+ enum "Asia/Bangkok" {
+ value 348;
+ }
+ enum "Asia/Dushanbe" {
+ value 349;
+ }
+ enum "Pacific/Fakaofo" {
+ value 350;
+ }
+ enum "Asia/Dili" {
+ value 351;
+ }
+ enum "Asia/Ashgabat" {
+ value 352;
+ }
+ enum "Africa/Tunis" {
+ value 353;
+ }
+ enum "Pacific/Tongatapu" {
+ value 354;
+ }
+ enum "Europe/Istanbul" {
+ value 355;
+ }
+ enum "America/Port_of_Spain" {
+ value 356;
+ }
+ enum "Pacific/Funafuti" {
+ value 357;
+ }
+ enum "Asia/Taipei" {
+ value 358;
+ }
+ enum "Africa/Dar_es_Salaam" {
+ value 359;
+ }
+ enum "Europe/Kiev" {
+ value 360;
+ description
+ "most locations";
+ }
+ enum "Europe/Uzhgorod" {
+ value 361;
+ description
+ "Ruthenia";
+ }
+ enum "Europe/Zaporozhye" {
+ value 362;
+ description
+ "Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk";
+ }
+ enum "Europe/Simferopol" {
+ value 363;
+ description
+ "central Crimea";
+ }
+ enum "Africa/Kampala" {
+ value 364;
+ }
+ enum "Pacific/Johnston" {
+ value 365;
+ description
+ "Johnston Atoll";
+ }
+ enum "Pacific/Midway" {
+ value 366;
+ description
+ "Midway Islands";
+ }
+ enum "Pacific/Wake" {
+ value 367;
+ description
+ "Wake Island";
+ }
+ enum "America/New_York" {
+ value 368;
+ description
+ "Eastern Time";
+ }
+ enum "America/Detroit" {
+ value 369;
+ description
+ "Eastern Time - Michigan - most locations";
+ }
+ enum "America/Kentucky/Louisville" {
+ value 370;
+ description
+ "Eastern Time - Kentucky - Louisville area";
+ }
+ enum "America/Kentucky/Monticello" {
+ value 371;
+ description
+ "Eastern Time - Kentucky - Wayne County";
+ }
+ enum "America/Indiana/Indianapolis" {
+ value 372;
+ description
+ "Eastern Time - Indiana - most locations";
+ }
+ enum "America/Indiana/Vincennes" {
+ value 373;
+ description
+ "Eastern Time - Indiana - Daviess, Dubois, Knox & Martin
+ Counties";
+ }
+ enum "America/Indiana/Winamac" {
+ value 374;
+ description
+ "Eastern Time - Indiana - Pulaski County";
+ }
+ enum "America/Indiana/Marengo" {
+ value 375;
+ description
+ "Eastern Time - Indiana - Crawford County";
+ }
+ enum "America/Indiana/Petersburg" {
+ value 376;
+ description
+ "Eastern Time - Indiana - Pike County";
+ }
+ enum "America/Indiana/Vevay" {
+ value 377;
+ description
+ "Eastern Time - Indiana - Switzerland County";
+ }
+ enum "America/Chicago" {
+ value 378;
+ description
+ "Central Time";
+ }
+ enum "America/Indiana/Tell_City" {
+ value 379;
+ description
+ "Central Time - Indiana - Perry County";
+ }
+ enum "America/Indiana/Knox" {
+ value 380;
+ description
+ "Central Time - Indiana - Starke County";
+ }
+ enum "America/Menominee" {
+ value 381;
+ description
+ "Central Time - Michigan - Dickinson, Gogebic, Iron &
+ Menominee Counties";
+ }
+ enum "America/North_Dakota/Center" {
+ value 382;
+ description
+ "Central Time - North Dakota - Oliver County";
+ }
+ enum "America/North_Dakota/New_Salem" {
+ value 383;
+ description
+ "Central Time - North Dakota - Morton County (except Mandan
+ area)";
+ }
+ enum "America/North_Dakota/Beulah" {
+ value 384;
+ description
+ "Central Time - North Dakota - Mercer County";
+ }
+ enum "America/Denver" {
+ value 385;
+ description
+ "Mountain Time";
+ }
+ enum "America/Boise" {
+ value 386;
+ description
+ "Mountain Time - south Idaho & east Oregon";
+ }
+ enum "America/Shiprock" {
+ value 387;
+ description
+ "Mountain Time - Navajo";
+ }
+ enum "America/Phoenix" {
+ value 388;
+ description
+ "Mountain Standard Time - Arizona";
+ }
+ enum "America/Los_Angeles" {
+ value 389;
+ description
+ "Pacific Time";
+ }
+ enum "America/Anchorage" {
+ value 390;
+ description
+ "Alaska Time";
+ }
+ enum "America/Juneau" {
+ value 391;
+ description
+ "Alaska Time - Alaska panhandle";
+ }
+ enum "America/Sitka" {
+ value 392;
+ description
+ "Alaska Time - southeast Alaska panhandle";
+ }
+ enum "America/Yakutat" {
+ value 393;
+ description
+ "Alaska Time - Alaska panhandle neck";
+ }
+ enum "America/Nome" {
+ value 394;
+ description
+ "Alaska Time - west Alaska";
+ }
+ enum "America/Adak" {
+ value 395;
+ description
+ "Aleutian Islands";
+ }
+ enum "America/Metlakatla" {
+ value 396;
+ description
+ "Metlakatla Time - Annette Island";
+ }
+ enum "Pacific/Honolulu" {
+ value 397;
+ description
+ "Hawaii";
+ }
+ enum "America/Montevideo" {
+ value 398;
+ }
+ enum "Asia/Samarkand" {
+ value 399;
+ description
+ "west Uzbekistan";
+ }
+ enum "Asia/Tashkent" {
+ value 400;
+ description
+ "east Uzbekistan";
+ }
+ enum "Europe/Vatican" {
+ value 401;
+ }
+ enum "America/St_Vincent" {
+ value 402;
+ }
+ enum "America/Caracas" {
+ value 403;
+ }
+ enum "America/Tortola" {
+ value 404;
+ }
+ enum "America/St_Thomas" {
+ value 405;
+ }
+ enum "Asia/Ho_Chi_Minh" {
+ value 406;
+ }
+ enum "Pacific/Efate" {
+ value 407;
+ }
+ enum "Pacific/Wallis" {
+ value 408;
+ }
+ enum "Pacific/Apia" {
+ value 409;
+ }
+ enum "Asia/Aden" {
+ value 410;
+ }
+ enum "Indian/Mayotte" {
+ value 411;
+ }
+ enum "Africa/Johannesburg" {
+ value 412;
+ }
+ enum "Africa/Lusaka" {
+ value 413;
+ }
+ enum "Africa/Harare" {
+ value 414;
+ }
+ }
+ }
+}
--- /dev/null
+ module ietf-inet-types {
+
+ namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+ prefix "inet";
+
+ organization
+ "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+ contact
+ "WG Web: <http://tools.ietf.org/wg/netmod/>
+ WG List: <mailto:netmod@ietf.org>
+
+ WG Chair: David Partain
+ <mailto:david.partain@ericsson.com>
+
+ WG Chair: David Kessens
+ <mailto:david.kessens@nsn.com>
+
+ Editor: Juergen Schoenwaelder
+ <mailto:j.schoenwaelder@jacobs-university.de>";
+
+ description
+ "This module contains a collection of generally useful derived
+ YANG data types for Internet addresses and related things.
+
+ Copyright (c) 2010 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, is permitted pursuant to, and subject to the license
+ terms contained in, the Simplified BSD License set forth in Section
+ 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 6021; see
+ the RFC itself for full legal notices.";
+
+ revision 2010-09-24 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 6021: Common YANG Data Types";
+ }
+
+ /*** collection of protocol field related types ***/
+
+ typedef ip-version {
+ type enumeration {
+ enum unknown {
+ value "0";
+ description
+ "An unknown or unspecified version of the Internet protocol.";
+ }
+ enum ipv4 {
+ value "1";
+ description
+ "The IPv4 protocol as defined in RFC 791.";
+ }
+ enum ipv6 {
+ value "2";
+ description
+ "The IPv6 protocol as defined in RFC 2460.";
+ }
+ }
+ description
+ "This value represents the version of the IP protocol.
+
+ In the value set and its semantics, this type is equivalent
+ to the InetVersion textual convention of the SMIv2.";
+ reference
+ "RFC 791: Internet Protocol
+ RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+ RFC 4001: Textual Conventions for Internet Network Addresses";
+ }
+
+ typedef dscp {
+ type uint8 {
+ range "0..63";
+ }
+ description
+ "The dscp type represents a Differentiated Services Code-Point
+ that may be used for marking packets in a traffic stream.
+
+ In the value set and its semantics, this type is equivalent
+ to the Dscp textual convention of the SMIv2.";
+ reference
+ "RFC 3289: Management Information Base for the Differentiated
+ Services Architecture
+ RFC 2474: Definition of the Differentiated Services Field
+ (DS Field) in the IPv4 and IPv6 Headers
+ RFC 2780: IANA Allocation Guidelines For Values In
+ the Internet Protocol and Related Headers";
+ }
+
+ typedef ipv6-flow-label {
+ type uint32 {
+ range "0..1048575";
+ }
+ description
+ "The flow-label type represents flow identifier or Flow Label
+ in an IPv6 packet header that may be used to discriminate
+ traffic flows.
+
+ In the value set and its semantics, this type is equivalent
+ to the IPv6FlowLabel textual convention of the SMIv2.";
+ reference
+ "RFC 3595: Textual Conventions for IPv6 Flow Label
+ RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+ }
+
+ typedef port-number {
+ type uint16 {
+ range "0..65535";
+ }
+ description
+ "The port-number type represents a 16-bit port number of an
+ Internet transport layer protocol such as UDP, TCP, DCCP, or
+ SCTP. Port numbers are assigned by IANA. A current list of
+ all assignments is available from <http://www.iana.org/>.
+
+ Note that the port number value zero is reserved by IANA. In
+ situations where the value zero does not make sense, it can
+ be excluded by subtyping the port-number type.
+
+ In the value set and its semantics, this type is equivalent
+ to the InetPortNumber textual convention of the SMIv2.";
+ reference
+ "RFC 768: User Datagram Protocol
+ RFC 793: Transmission Control Protocol
+ RFC 4960: Stream Control Transmission Protocol
+ RFC 4340: Datagram Congestion Control Protocol (DCCP)
+ RFC 4001: Textual Conventions for Internet Network Addresses";
+ }
+
+ /*** collection of autonomous system related types ***/
+
+ typedef as-number {
+ type uint32;
+ description
+ "The as-number type represents autonomous system numbers
+ which identify an Autonomous System (AS). An AS is a set
+ of routers under a single technical administration, using
+ an interior gateway protocol and common metrics to route
+ packets within the AS, and using an exterior gateway
+ protocol to route packets to other ASs'. IANA maintains
+ the AS number space and has delegated large parts to the
+ regional registries.
+
+ Autonomous system numbers were originally limited to 16
+ bits. BGP extensions have enlarged the autonomous system
+ number space to 32 bits. This type therefore uses an uint32
+ base type without a range restriction in order to support
+ a larger autonomous system number space.
+
+ In the value set and its semantics, this type is equivalent
+ to the InetAutonomousSystemNumber textual convention of
+ the SMIv2.";
+ reference
+ "RFC 1930: Guidelines for creation, selection, and registration
+ of an Autonomous System (AS)
+ RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+ RFC 4893: BGP Support for Four-octet AS Number Space
+ RFC 4001: Textual Conventions for Internet Network Addresses";
+ }
+
+ /*** collection of IP address and hostname related types ***/
+
+ typedef ip-address {
+ type union {
+ type inet:ipv4-address;
+ type inet:ipv6-address;
+ }
+ description
+ "The ip-address type represents an IP address and is IP
+ version neutral. The format of the textual representations
+ implies the IP version.";
+ }
+
+ typedef ipv4-address {
+ type string {
+ pattern
+ '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+ + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+ + '(%[\p{N}\p{L}]+)?';
+ }
+ description
+ "The ipv4-address type represents an IPv4 address in
+ dotted-quad notation. The IPv4 address may include a zone
+ index, separated by a % sign.
+
+ The zone index is used to disambiguate identical address
+ values. For link-local addresses, the zone index will
+ typically be the interface index number or the name of an
+ interface. If the zone index is not present, the default
+ zone of the device will be used.
+
+ The canonical format for the zone index is the numerical
+ format";
+ }
+
+ typedef ipv6-address {
+ type string {
+ pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+ + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+ + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+ + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+ + '(%[\p{N}\p{L}]+)?';
+ pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+ + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+ + '(%.+)?';
+ }
+ description
+ "The ipv6-address type represents an IPv6 address in full,
+ mixed, shortened, and shortened-mixed notation. The IPv6
+ address may include a zone index, separated by a % sign.
+
+ The zone index is used to disambiguate identical address
+ values. For link-local addresses, the zone index will
+ typically be the interface index number or the name of an
+ interface. If the zone index is not present, the default
+ zone of the device will be used.
+
+ The canonical format of IPv6 addresses uses the compressed
+ format described in RFC 4291, Section 2.2, item 2 with the
+ following additional rules: the :: substitution must be
+ applied to the longest sequence of all-zero 16-bit chunks
+ in an IPv6 address. If there is a tie, the first sequence
+ of all-zero 16-bit chunks is replaced by ::. Single
+ all-zero 16-bit chunks are not compressed. The canonical
+ format uses lowercase characters and leading zeros are
+ not allowed. The canonical format for the zone index is
+ the numerical format as described in RFC 4007, Section
+ 11.2.";
+ reference
+ "RFC 4291: IP Version 6 Addressing Architecture
+ RFC 4007: IPv6 Scoped Address Architecture
+ RFC 5952: A Recommendation for IPv6 Address Text Representation";
+ }
+
+ typedef ip-prefix {
+ type union {
+ type inet:ipv4-prefix;
+ type inet:ipv6-prefix;
+ }
+ description
+ "The ip-prefix type represents an IP prefix and is IP
+ version neutral. The format of the textual representations
+ implies the IP version.";
+ }
+
+ typedef ipv4-prefix {
+ type string {
+ pattern
+ '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+ + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+ + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+ }
+ description
+ "The ipv4-prefix type represents an IPv4 address prefix.
+ The prefix length is given by the number following the
+ slash character and must be less than or equal to 32.
+
+ A prefix length value of n corresponds to an IP address
+ mask that has n contiguous 1-bits from the most
+ significant bit (MSB) and all other bits set to 0.
+
+ The canonical format of an IPv4 prefix has all bits of
+ the IPv4 address set to zero that are not part of the
+ IPv4 prefix.";
+ }
+
+ typedef ipv6-prefix {
+ type string {
+ pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+ + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+ + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+ + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+ + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+ pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+ + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+ + '(/.+)';
+ }
+ description
+ "The ipv6-prefix type represents an IPv6 address prefix.
+ The prefix length is given by the number following the
+ slash character and must be less than or equal 128.
+
+ A prefix length value of n corresponds to an IP address
+ mask that has n contiguous 1-bits from the most
+ significant bit (MSB) and all other bits set to 0.
+
+ The IPv6 address should have all bits that do not belong
+ to the prefix set to zero.
+
+ The canonical format of an IPv6 prefix has all bits of
+ the IPv6 address set to zero that are not part of the
+ IPv6 prefix. Furthermore, IPv6 address is represented
+ in the compressed format described in RFC 4291, Section
+ 2.2, item 2 with the following additional rules: the ::
+ substitution must be applied to the longest sequence of
+ all-zero 16-bit chunks in an IPv6 address. If there is
+ a tie, the first sequence of all-zero 16-bit chunks is
+ replaced by ::. Single all-zero 16-bit chunks are not
+ compressed. The canonical format uses lowercase
+ characters and leading zeros are not allowed.";
+ reference
+ "RFC 4291: IP Version 6 Addressing Architecture";
+ }
+
+ /*** collection of domain name and URI types ***/
+
+ typedef domain-name {
+ type string {
+ pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+ + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+ + '|\.';
+ length "1..253";
+ }
+ description
+ "The domain-name type represents a DNS domain name. The
+ name SHOULD be fully qualified whenever possible.
+
+ Internet domain names are only loosely specified. Section
+ 3.5 of RFC 1034 recommends a syntax (modified in Section
+ 2.1 of RFC 1123). The pattern above is intended to allow
+ for current practice in domain name use, and some possible
+ future expansion. It is designed to hold various types of
+ domain names, including names used for A or AAAA records
+ (host names) and other records, such as SRV records. Note
+ that Internet host names have a stricter syntax (described
+ in RFC 952) than the DNS recommendations in RFCs 1034 and
+ 1123, and that systems that want to store host names in
+ schema nodes using the domain-name type are recommended to
+ adhere to this stricter standard to ensure interoperability.
+
+ The encoding of DNS names in the DNS protocol is limited
+ to 255 characters. Since the encoding consists of labels
+ prefixed by a length bytes and there is a trailing NULL
+ byte, only 253 characters can appear in the textual dotted
+ notation.
+
+ The description clause of schema nodes using the domain-name
+ type MUST describe when and how these names are resolved to
+ IP addresses. Note that the resolution of a domain-name value
+ may require to query multiple DNS records (e.g., A for IPv4
+ and AAAA for IPv6). The order of the resolution process and
+ which DNS record takes precedence can either be defined
+ explicitely or it may depend on the configuration of the
+ resolver.
+
+ Domain-name values use the US-ASCII encoding. Their canonical
+ format uses lowercase US-ASCII characters. Internationalized
+ domain names MUST be encoded in punycode as described in RFC
+ 3492";
+ reference
+ "RFC 952: DoD Internet Host Table Specification
+ RFC 1034: Domain Names - Concepts and Facilities
+ RFC 1123: Requirements for Internet Hosts -- Application
+ and Support
+ RFC 2782: A DNS RR for specifying the location of services
+ (DNS SRV)
+ RFC 3492: Punycode: A Bootstring encoding of Unicode for
+ Internationalized Domain Names in Applications
+ (IDNA)
+ RFC 5891: Internationalizing Domain Names in Applications
+ (IDNA): Protocol";
+ }
+
+ typedef host {
+ type union {
+ type inet:ip-address;
+ type inet:domain-name;
+ }
+ description
+ "The host type represents either an IP address or a DNS
+ domain name.";
+ }
+
+ typedef uri {
+ type string;
+ description
+ "The uri type represents a Uniform Resource Identifier
+ (URI) as defined by STD 66.
+
+ Objects using the uri type MUST be in US-ASCII encoding,
+ and MUST be normalized as described by RFC 3986 Sections
+ 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary
+ percent-encoding is removed, and all case-insensitive
+ characters are set to lowercase except for hexadecimal
+ digits, which are normalized to uppercase as described in
+ Section 6.2.2.1.
+
+ The purpose of this normalization is to help provide
+ unique URIs. Note that this normalization is not
+ sufficient to provide uniqueness. Two URIs that are
+ textually distinct after this normalization may still be
+ equivalent.
+
+ Objects using the uri type may restrict the schemes that
+ they permit. For example, 'data:' and 'urn:' schemes
+ might not be appropriate.
+
+ A zero-length URI is not a valid URI. This can be used to
+ express 'URI absent' where required.
+
+ In the value set and its semantics, this type is equivalent
+ to the Uri SMIv2 textual convention defined in RFC 5017.";
+ reference
+ "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+ RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+ Group: Uniform Resource Identifiers (URIs), URLs,
+ and Uniform Resource Names (URNs): Clarifications
+ and Recommendations
+ RFC 5017: MIB Textual Conventions for Uniform Resource
+ Identifiers (URIs)";
+ }
+
+ }
--- /dev/null
+ module ietf-yang-types {
+
+ namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types";
+ prefix "yang";
+
+ organization
+ "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+ contact
+ "WG Web: <http://tools.ietf.org/wg/netmod/>
+ WG List: <mailto:netmod@ietf.org>
+
+ WG Chair: David Partain
+ <mailto:david.partain@ericsson.com>
+
+ WG Chair: David Kessens
+ <mailto:david.kessens@nsn.com>
+
+ Editor: Juergen Schoenwaelder
+ <mailto:j.schoenwaelder@jacobs-university.de>";
+
+ description
+ "This module contains a collection of generally useful derived
+ YANG data types.
+
+ Copyright (c) 2010 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, is permitted pursuant to, and subject to the license
+ terms contained in, the Simplified BSD License set forth in Section
+ 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 6021; see
+ the RFC itself for full legal notices.";
+
+ revision 2010-09-24 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 6021: Common YANG Data Types";
+ }
+
+ /*** collection of counter and gauge types ***/
+
+ typedef counter32 {
+ type uint32;
+ description
+ "The counter32 type represents a non-negative integer
+ that monotonically increases until it reaches a
+ maximum value of 2^32-1 (4294967295 decimal), when it
+ wraps around and starts increasing again from zero.
+
+ Counters have no defined 'initial' value, and thus, a
+ single value of a counter has (in general) no information
+ content. Discontinuities in the monotonically increasing
+ value normally occur at re-initialization of the
+ management system, and at other times as specified in the
+ description of a schema node using this type. If such
+ other times can occur, for example, the creation of
+ a schema node of type counter32 at times other than
+ re-initialization, then a corresponding schema node
+ should be defined, with an appropriate type, to indicate
+ the last discontinuity.
+
+ The counter32 type should not be used for configuration
+ schema nodes. A default statement SHOULD NOT be used in
+ combination with the type counter32.
+
+ In the value set and its semantics, this type is equivalent
+ to the Counter32 type of the SMIv2.";
+ reference
+ "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+ }
+
+ typedef zero-based-counter32 {
+ type yang:counter32;
+ default "0";
+ description
+ "The zero-based-counter32 type represents a counter32
+ that has the defined 'initial' value zero.
+
+ A schema node of this type will be set to zero (0) on creation
+ and will thereafter increase monotonically until it reaches
+ a maximum value of 2^32-1 (4294967295 decimal), when it
+ wraps around and starts increasing again from zero.
+
+ Provided that an application discovers a new schema node
+ of this type within the minimum time to wrap, it can use the
+ 'initial' value as a delta. It is important for a management
+ station to be aware of this minimum time and the actual time
+ between polls, and to discard data if the actual time is too
+ long or there is no defined minimum time.
+
+ In the value set and its semantics, this type is equivalent
+ to the ZeroBasedCounter32 textual convention of the SMIv2.";
+ reference
+ "RFC 4502: Remote Network Monitoring Management Information
+ Base Version 2";
+ }
+
+ typedef counter64 {
+ type uint64;
+ description
+ "The counter64 type represents a non-negative integer
+ that monotonically increases until it reaches a
+ maximum value of 2^64-1 (18446744073709551615 decimal),
+ when it wraps around and starts increasing again from zero.
+
+ Counters have no defined 'initial' value, and thus, a
+ single value of a counter has (in general) no information
+ content. Discontinuities in the monotonically increasing
+ value normally occur at re-initialization of the
+ management system, and at other times as specified in the
+ description of a schema node using this type. If such
+ other times can occur, for example, the creation of
+ a schema node of type counter64 at times other than
+ re-initialization, then a corresponding schema node
+ should be defined, with an appropriate type, to indicate
+ the last discontinuity.
+
+ The counter64 type should not be used for configuration
+ schema nodes. A default statement SHOULD NOT be used in
+ combination with the type counter64.
+
+ In the value set and its semantics, this type is equivalent
+ to the Counter64 type of the SMIv2.";
+ reference
+ "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+ }
+
+ typedef zero-based-counter64 {
+ type yang:counter64;
+ default "0";
+ description
+ "The zero-based-counter64 type represents a counter64 that
+ has the defined 'initial' value zero.
+
+ A schema node of this type will be set to zero (0) on creation
+ and will thereafter increase monotonically until it reaches
+ a maximum value of 2^64-1 (18446744073709551615 decimal),
+ when it wraps around and starts increasing again from zero.
+
+ Provided that an application discovers a new schema node
+ of this type within the minimum time to wrap, it can use the
+ 'initial' value as a delta. It is important for a management
+ station to be aware of this minimum time and the actual time
+ between polls, and to discard data if the actual time is too
+ long or there is no defined minimum time.
+
+ In the value set and its semantics, this type is equivalent
+ to the ZeroBasedCounter64 textual convention of the SMIv2.";
+ reference
+ "RFC 2856: Textual Conventions for Additional High Capacity
+ Data Types";
+ }
+
+ typedef gauge32 {
+ type uint32;
+ description
+ "The gauge32 type represents a non-negative integer, which
+ may increase or decrease, but shall never exceed a maximum
+ value, nor fall below a minimum value. The maximum value
+ cannot be greater than 2^32-1 (4294967295 decimal), and
+ the minimum value cannot be smaller than 0. The value of
+ a gauge32 has its maximum value whenever the information
+ being modeled is greater than or equal to its maximum
+ value, and has its minimum value whenever the information
+ being modeled is smaller than or equal to its minimum value.
+ If the information being modeled subsequently decreases
+ below (increases above) the maximum (minimum) value, the
+ gauge32 also decreases (increases).
+
+ In the value set and its semantics, this type is equivalent
+ to the Gauge32 type of the SMIv2.";
+ reference
+ "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+ }
+
+ typedef gauge64 {
+ type uint64;
+ description
+ "The gauge64 type represents a non-negative integer, which
+ may increase or decrease, but shall never exceed a maximum
+ value, nor fall below a minimum value. The maximum value
+ cannot be greater than 2^64-1 (18446744073709551615), and
+ the minimum value cannot be smaller than 0. The value of
+ a gauge64 has its maximum value whenever the information
+ being modeled is greater than or equal to its maximum
+ value, and has its minimum value whenever the information
+ being modeled is smaller than or equal to its minimum value.
+ If the information being modeled subsequently decreases
+ below (increases above) the maximum (minimum) value, the
+ gauge64 also decreases (increases).
+
+ In the value set and its semantics, this type is equivalent
+ to the CounterBasedGauge64 SMIv2 textual convention defined
+ in RFC 2856";
+ reference
+ "RFC 2856: Textual Conventions for Additional High Capacity
+ Data Types";
+ }
+
+ /*** collection of identifier related types ***/
+
+ typedef object-identifier {
+ type string {
+ pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))'
+ + '(\.(0|([1-9]\d*)))*';
+ }
+ description
+ "The object-identifier type represents administratively
+ assigned names in a registration-hierarchical-name tree.
+
+ Values of this type are denoted as a sequence of numerical
+ non-negative sub-identifier values. Each sub-identifier
+ value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers
+ are separated by single dots and without any intermediate
+ whitespace.
+
+ The ASN.1 standard restricts the value space of the first
+ sub-identifier to 0, 1, or 2. Furthermore, the value space
+ of the second sub-identifier is restricted to the range
+ 0 to 39 if the first sub-identifier is 0 or 1. Finally,
+ the ASN.1 standard requires that an object identifier
+ has always at least two sub-identifier. The pattern
+ captures these restrictions.
+
+ Although the number of sub-identifiers is not limited,
+ module designers should realize that there may be
+ implementations that stick with the SMIv2 limit of 128
+ sub-identifiers.
+
+ This type is a superset of the SMIv2 OBJECT IDENTIFIER type
+ since it is not restricted to 128 sub-identifiers. Hence,
+ this type SHOULD NOT be used to represent the SMIv2 OBJECT
+ IDENTIFIER type, the object-identifier-128 type SHOULD be
+ used instead.";
+ reference
+ "ISO9834-1: Information technology -- Open Systems
+ Interconnection -- Procedures for the operation of OSI
+ Registration Authorities: General procedures and top
+ arcs of the ASN.1 Object Identifier tree";
+ }
+
+
+
+
+ typedef object-identifier-128 {
+ type object-identifier {
+ pattern '\d*(\.\d*){1,127}';
+ }
+ description
+ "This type represents object-identifiers restricted to 128
+ sub-identifiers.
+
+ In the value set and its semantics, this type is equivalent
+ to the OBJECT IDENTIFIER type of the SMIv2.";
+ reference
+ "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+ }
+
+ /*** collection of date and time related types ***/
+
+ typedef date-and-time {
+ type string {
+ pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
+ + '(Z|[\+\-]\d{2}:\d{2})';
+ }
+ description
+ "The date-and-time type is a profile of the ISO 8601
+ standard for representation of dates and times using the
+ Gregorian calendar. The profile is defined by the
+ date-time production in Section 5.6 of RFC 3339.
+
+ The date-and-time type is compatible with the dateTime XML
+ schema type with the following notable exceptions:
+
+ (a) The date-and-time type does not allow negative years.
+
+ (b) The date-and-time time-offset -00:00 indicates an unknown
+ time zone (see RFC 3339) while -00:00 and +00:00 and Z all
+ represent the same time zone in dateTime.
+
+ (c) The canonical format (see below) of data-and-time values
+ differs from the canonical format used by the dateTime XML
+ schema type, which requires all times to be in UTC using the
+ time-offset 'Z'.
+
+ This type is not equivalent to the DateAndTime textual
+ convention of the SMIv2 since RFC 3339 uses a different
+ separator between full-date and full-time and provides
+ higher resolution of time-secfrac.
+
+ The canonical format for date-and-time values with a known time
+ zone uses a numeric time zone offset that is calculated using
+ the device's configured known offset to UTC time. A change of
+ the device's offset to UTC time will cause date-and-time values
+ to change accordingly. Such changes might happen periodically
+ in case a server follows automatically daylight saving time
+ (DST) time zone offset changes. The canonical format for
+ date-and-time values with an unknown time zone (usually referring
+ to the notion of local time) uses the time-offset -00:00.";
+ reference
+ "RFC 3339: Date and Time on the Internet: Timestamps
+ RFC 2579: Textual Conventions for SMIv2
+ XSD-TYPES: XML Schema Part 2: Datatypes Second Edition";
+ }
+
+ typedef timeticks {
+ type uint32;
+ description
+ "The timeticks type represents a non-negative integer that
+ represents the time, modulo 2^32 (4294967296 decimal), in
+ hundredths of a second between two epochs. When a schema
+ node is defined that uses this type, the description of
+ the schema node identifies both of the reference epochs.
+
+ In the value set and its semantics, this type is equivalent
+ to the TimeTicks type of the SMIv2.";
+ reference
+ "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+ }
+
+ typedef timestamp {
+ type yang:timeticks;
+ description
+ "The timestamp type represents the value of an associated
+ timeticks schema node at which a specific occurrence happened.
+ The specific occurrence must be defined in the description
+ of any schema node defined using this type. When the specific
+ occurrence occurred prior to the last time the associated
+ timeticks attribute was zero, then the timestamp value is
+ zero. Note that this requires all timestamp values to be
+ reset to zero when the value of the associated timeticks
+ attribute reaches 497+ days and wraps around to zero.
+
+ The associated timeticks schema node must be specified
+ in the description of any schema node using this type.
+
+ In the value set and its semantics, this type is equivalent
+ to the TimeStamp textual convention of the SMIv2.";
+ reference
+ "RFC 2579: Textual Conventions for SMIv2";
+ }
+
+ /*** collection of generic address types ***/
+
+ typedef phys-address {
+ type string {
+ pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
+ }
+ description
+ "Represents media- or physical-level addresses represented
+ as a sequence octets, each octet represented by two hexadecimal
+ numbers. Octets are separated by colons. The canonical
+ representation uses lowercase characters.
+
+ In the value set and its semantics, this type is equivalent
+ to the PhysAddress textual convention of the SMIv2.";
+ reference
+ "RFC 2579: Textual Conventions for SMIv2";
+ }
+
+ typedef mac-address {
+ type string {
+ pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
+ }
+ description
+ "The mac-address type represents an IEEE 802 MAC address.
+ The canonical representation uses lowercase characters.
+
+ In the value set and its semantics, this type is equivalent
+ to the MacAddress textual convention of the SMIv2.";
+ reference
+ "IEEE 802: IEEE Standard for Local and Metropolitan Area
+ Networks: Overview and Architecture
+ RFC 2579: Textual Conventions for SMIv2";
+ }
+
+ /*** collection of XML specific types ***/
+
+ typedef xpath1.0 {
+ type string;
+ description
+ "This type represents an XPATH 1.0 expression.
+
+ When a schema node is defined that uses this type, the
+ description of the schema node MUST specify the XPath
+ context in which the XPath expression is evaluated.";
+ reference
+ "XPATH: XML Path Language (XPath) Version 1.0";
+ }
+
+ }
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
- <modelVersion>4.0.0</modelVersion>\r
- <parent>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>yang</artifactId>\r
- <version>0.5.4-SNAPSHOT</version>\r
- </parent>\r
- <artifactId>yang-model-util</artifactId>\r
- <dependencies>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>yang-model-api</artifactId>\r
- </dependency>\r
- </dependencies>\r
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+\r
+ <parent>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang</artifactId>\r
+ <version>0.5.4-SNAPSHOT</version>\r
+ </parent>\r
+\r
+ <modelVersion>4.0.0</modelVersion>\r
+ <artifactId>yang-model-util</artifactId>\r
+ <name>${project.artifactId}</name>\r
+ <description>${project.artifactId}</description>\r
+\r
+ <dependencies>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang-model-api</artifactId>\r
+ </dependency>\r
+ </dependencies>\r
+\r
</project>\r
/**
*
- * @param actualPath
- * @param namespace
- * @param revision
- * @param name
+ * @param path uint type schema path
+ * @param name qname
* @param description
- * @param MIN_VALUE
* @param maxRange
* @param units
*/
}
/**
- * @param name
+ *
+ * @param path uint type schema path
+ * @param name qname
* @param description
* @param rangeStatements
* @param units
/**
* Default constructor. <br>
* Instantiates Bits type as empty bits list.
+ *
+ * @param path
*/
public BitsType(final SchemaPath path) {
super();
/**
* Constructor with explicit definition of bits assigned to BitsType.
*
- * @param actualPath
- * @param namespace
- * @param revision
+ * @param path
* @param bits
- * The bits assigned for Bits Type
*/
public BitsType(final SchemaPath path, final List<Bit> bits) {
super();
final int prime = 31;
int result = 1;
result = prime * result + ((bits == null) ? 0 : bits.hashCode());
- result = prime * result
- + ((description == null) ? 0 : description.hashCode());
+ result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((path == null) ? 0 : path.hashCode());
- result = prime * result
- + ((reference == null) ? 0 : reference.hashCode());
+ result = prime * result + ((reference == null) ? 0 : reference.hashCode());
result = prime * result + ((units == null) ? 0 : units.hashCode());
return result;
}