Bug 6867: Extend yang statement parser to support different yang versions 68/48368/28
authorPeter Kajsa <pkajsa@cisco.com>
Thu, 1 Dec 2016 13:57:24 +0000 (14:57 +0100)
committerRobert Varga <rovarga@cisco.com>
Wed, 14 Dec 2016 14:33:36 +0000 (15:33 +0100)
This patch extends statement parser in order to support different versions
of yang, yin or other statement based languages. Statement parser is able
to distinguish version of each yang, yin or other source and it performs
parsing of the source according to the specific version. Mixed-version
schemacontext (i.e. imports across versions) is supported too.

More in detail, StatementSupportBundle must be initialized by
SupportedVersionBundle, which defines set of supported versions.
In consequence, StatementSupportBundle allows to add version specific
StatementSupport into bundle. Furthermore each RootStatementContext
allows to set its version based on which corresponding StatementSupports
are invoked. For yang models, RootStatementContext version is set based
on a value of yang version statement.

Change-Id: I06bbcbfee091a0f54480d5f5f588a9ed18a84b55
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
Signed-off-by: Robert Varga <rovarga@cisco.com>
50 files changed:
yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/YangVersion.java [new file with mode: 0644]
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/Rfc6020Mapping.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/YangVersionStatement.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/AbstractDeclaredStatement.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupportBundle.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/CustomStatementParserBuilder.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/NamespaceStorageSupport.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/RootStatementContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ContainerStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ModuleStatementSupport.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangVersionStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/AbstractEffectiveDataSchemaNode.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/AbstractEffectiveModule.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/YangVersionEffectiveStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/AnydataStatementImpl.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ContainerStatementRfc7950Support.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ModuleStatementRfc7950Support.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/effective/AnyDataEffectiveStatementImpl.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6867BasicTest.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/StmtTestUtils.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/semver/SemanticVersionComplexTest.java
yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/anydata-10.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/anydata-11.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/invalid-10.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/invalid-11.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/unsupported-version.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/valid-10.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/valid-11.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/model/bar.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/model/baz.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/model/foo.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/model/subfoo.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/bar@2016-01-03.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/bar@2016-01-04.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/foo.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/foobar@2016-01-31.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/foobar@2016-02-28.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/semantic-version.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/bar@2016-01-03.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/bar@2016-01-04.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foo.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foobar@2016-01-31.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foobar@2016-02-27.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foobar@2016-02-28.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/semantic-version.yang [new file with mode: 0644]

diff --git a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/YangVersion.java b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/YangVersion.java
new file mode 100644 (file)
index 0000000..cfde8ca
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.common;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+
+/**
+ * Enumeration of supported YANG versions.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public enum YangVersion {
+    /**
+     * Version 1, as defined in RFC6020.
+     */
+    VERSION_1("1", "RFC6020"),
+    /**
+     * Version 1.1, as defined in RFC7950.
+     */
+    VERSION_1_1("1.1", "RFC7950");
+
+    private final String str;
+    private String reference;
+
+    private YangVersion(final String str, final String reference) {
+        this.str = Preconditions.checkNotNull(str);
+        this.reference = Preconditions.checkNotNull(reference);
+    }
+
+    /**
+     * Parse a YANG version from its textual representation.
+     *
+     * @param str String to parse
+     * @return YANG version
+     * @throws IllegalArgumentException if the string is malformed
+     * @throws NullPointerException if the string is null
+     */
+    public static YangVersion parse(@Nonnull final String str) {
+        switch (str) {
+            case "1":
+                return VERSION_1;
+            case "1.1":
+                return VERSION_1_1;
+            default:
+                throw new IllegalArgumentException("Invalid YANG version '" + str + "'");
+        }
+    }
+
+    /**
+     * Return the normative reference defining this YANG version.
+     *
+     * @return Normative reference.
+     */
+    @Nonnull public String getReference() {
+        return reference;
+    }
+
+    /**
+     * Return the canonical string represetation of this YANG version.
+     * @return Canonical string
+     */
+    @Nonnull public String toCanonicalString() {
+        return str;
+    }
+}
index f1c25fcbe2da37ef8832a076b61751335f4c1f53..d37ebb15f6fdc74f1ff54fbf6b0192e297ba57da 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.yangtools.yang.common.YangConstants;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ArgumentStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
@@ -82,9 +83,9 @@ import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.YangVersionStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.YinElementStatement;
 
-
 @Beta
 public enum Rfc6020Mapping implements StatementDefinition {
+    ANYDATA(AnydataStatement.class, "anydata", "name"),
     ANYXML(AnyxmlStatement.class, "anyxml", "name"),
     ARGUMENT(ArgumentStatement.class, "argument", "name"),
     AUGMENT(AugmentStatement.class, "augment", "target-node"),
@@ -157,7 +158,7 @@ public enum Rfc6020Mapping implements StatementDefinition {
     private final QName argument;
     private final boolean yinElement;
 
-    Rfc6020Mapping(Class<? extends DeclaredStatement<?>> clz, final String nameStr) {
+    Rfc6020Mapping(final Class<? extends DeclaredStatement<?>> clz, final String nameStr) {
         type = Preconditions.checkNotNull(clz);
         //FIXME: fill up effective type correctly
         effectiveType = null;
@@ -166,7 +167,7 @@ public enum Rfc6020Mapping implements StatementDefinition {
         yinElement = false;
     }
 
-    Rfc6020Mapping(Class<? extends DeclaredStatement<?>> clz, final String nameStr, final String argumentStr) {
+    Rfc6020Mapping(final Class<? extends DeclaredStatement<?>> clz, final String nameStr, final String argumentStr) {
         type = Preconditions.checkNotNull(clz);
         //FIXME: fill up effective type correctly
         effectiveType = null;
@@ -175,7 +176,7 @@ public enum Rfc6020Mapping implements StatementDefinition {
         this.yinElement = false;
     }
 
-    Rfc6020Mapping(Class<? extends DeclaredStatement<?>> clz, final String nameStr, final String argumentStr,
+    Rfc6020Mapping(final Class<? extends DeclaredStatement<?>> clz, final String nameStr, final String argumentStr,
             final boolean yinElement) {
         type = Preconditions.checkNotNull(clz);
         //FIXME: fill up effective type correctly
@@ -185,7 +186,7 @@ public enum Rfc6020Mapping implements StatementDefinition {
         this.yinElement = yinElement;
     }
 
-    @Nonnull private static QName yinQName(String nameStr) {
+    @Nonnull private static QName yinQName(final String nameStr) {
         return QName.create(YangConstants.RFC6020_YIN_MODULE, nameStr).intern();
     }
 
index da972c46c52ef50e42841296a9ab257b2861a4ba..2133c7d4e19fb7a3d69bec23cc3ac9dece7a4ecf 100644 (file)
@@ -8,10 +8,11 @@
 package org.opendaylight.yangtools.yang.model.api.stmt;
 
 import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 
-public interface YangVersionStatement extends DeclaredStatement<String> {
+public interface YangVersionStatement extends DeclaredStatement<YangVersion> {
 
-    @Nonnull String getValue();
+    @Nonnull YangVersion getValue();
 }
 
index 5150b8505b223c75f9f8cbf197408e2c2fa6e23b..6069d4b5d47d2a614dd26548ff5cf8fa3c2cc94a 100644 (file)
@@ -43,7 +43,7 @@ public abstract class AbstractDeclaredStatement<A> implements DeclaredStatement<
          * Perform an explicit copy, because Collections2.transform() is lazily transformed and retains pointer to
          * original collection, which may contains references to mutable context.
          */
-        Collection<StatementContextBase<?, ?, ?>> declaredSubstatements = context.declaredSubstatements();
+        final Collection<StatementContextBase<?, ?, ?>> declaredSubstatements = context.declaredSubstatements();
         substatements = ImmutableList.copyOf(Collections2.transform(declaredSubstatements, StatementContextBase::buildDeclared));
     }
 
index badd2b6bccd7b1f728748a2f236df79003d796cf..3d9c9375f92b03c265049ede136da8ecf30e2e3c 100644 (file)
@@ -8,48 +8,95 @@
 package org.opendaylight.yangtools.yang.parser.spi.meta;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.HashBasedTable;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.Table;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
 
-public final class StatementSupportBundle implements Immutable,NamespaceBehaviour.Registry {
+public final class StatementSupportBundle implements Immutable, NamespaceBehaviour.Registry {
 
-    private static final StatementSupportBundle EMPTY = new StatementSupportBundle(null, ImmutableMap.of(), ImmutableMap.of());
+    private static final StatementSupportBundle EMPTY = new StatementSupportBundle(null, null, ImmutableMap.of(),
+            ImmutableMap.of(), ImmutableTable.of());
 
     private final StatementSupportBundle parent;
-    private final ImmutableMap<QName, StatementSupport<?,?,?>> definitions;
+    private final ImmutableMap<QName, StatementSupport<?, ?, ?>> commonDefinitions;
+    private final ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificDefinitions;
     private final ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaceDefinitions;
+    private final Set<YangVersion> supportedVersions;
 
     private StatementSupportBundle(final StatementSupportBundle parent,
-                                   final ImmutableMap<QName, StatementSupport<?, ?, ?>> statements,
-                                   final ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces) {
+            final Set<YangVersion> supportedVersions,
+            final ImmutableMap<QName, StatementSupport<?, ?, ?>> commonStatements,
+            final ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces,
+            final ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificStatements) {
         this.parent = parent;
-        this.definitions = statements;
+        this.supportedVersions = supportedVersions;
+        this.commonDefinitions = commonStatements;
         this.namespaceDefinitions = namespaces;
+        this.versionSpecificDefinitions = versionSpecificStatements;
     }
 
-    public ImmutableMap<QName, StatementSupport<?, ?, ?>> getDefinitions() {
-        return definitions;
+    /**
+     * Returns statement definitions common for all versions
+     *
+     * @return map of common statement definitions
+     */
+    public ImmutableMap<QName, StatementSupport<?, ?, ?>> getCommonDefinitions() {
+        return commonDefinitions;
+    }
+
+    /**
+     * Returns statement definitions specific for requested version. Result of
+     * this method doesn't include common statement definitions.
+     *
+     * @param version
+     *            requested version
+     * @return map of statement definitions specific for requested version, it
+     *         doesn't include common statement definitions.
+     */
+    public ImmutableMap<QName, StatementSupport<?, ?, ?>> getDefinitionsSpecificForVersion(final YangVersion version) {
+        return versionSpecificDefinitions.row(version);
+    }
+
+    /**
+     * Returns all version specific statement definitions. Result of this method
+     * doesn't include common statement definitions.
+     *
+     * @return table of all version specific statement definitions, it doesn't
+     *         include common statement definitions.
+     */
+    public ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> getAllVersionSpecificDefinitions() {
+        return versionSpecificDefinitions;
     }
 
     public ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> getNamespaceDefinitions() {
         return namespaceDefinitions;
     }
 
-    public static Builder builder() {
-        return new Builder(EMPTY);
+    public static Builder builder(final Set<YangVersion> supportedVersions) {
+        return new Builder(supportedVersions, EMPTY);
     }
 
     public static Builder derivedFrom(final StatementSupportBundle parent) {
-        return new Builder(parent);
+        Preconditions.checkNotNull(parent);
+        return new Builder(parent.getSupportedVersions(), parent);
+    }
+
+    public Set<YangVersion> getSupportedVersions() {
+        return supportedVersions;
     }
 
     @Override
-    public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(final Class<N> namespace)
-            throws NamespaceNotAvailableException {
+    public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(
+            final Class<N> namespace) throws NamespaceNotAvailableException {
         final NamespaceBehaviour<?, ?, ?> potential = namespaceDefinitions.get(namespace);
         if (potential != null) {
             Preconditions.checkState(namespace.equals(potential.getIdentifier()));
@@ -76,33 +123,79 @@ public final class StatementSupportBundle implements Immutable,NamespaceBehaviou
         return false;
     }
 
-    public StatementSupport<?, ?,?> getStatementDefinition(final QName stmtName) {
-        final StatementSupport<?,?, ?> potential = definitions.get(stmtName);
+    public StatementSupport<?, ?, ?> getStatementDefinition(final YangVersion version, final QName stmtName) {
+        StatementSupport<?, ?, ?> result = getVersionSpecificStatementDefinition(version, stmtName);
+        if (result == null) {
+            result = getCommonStatementDefinition(stmtName);
+        }
+
+        return result;
+    }
+
+    private StatementSupport<?, ?, ?> getCommonStatementDefinition(final QName stmtName) {
+        final StatementSupport<?, ?, ?> potential = commonDefinitions.get(stmtName);
+        if (potential != null) {
+            return potential;
+        }
+        if (parent != null) {
+            return parent.getCommonStatementDefinition(stmtName);
+        }
+        return null;
+    }
+
+    private StatementSupport<?, ?, ?> getVersionSpecificStatementDefinition(final YangVersion version,
+            final QName stmtName) {
+        final StatementSupport<?, ?, ?> potential = versionSpecificDefinitions.get(version, stmtName);
         if (potential != null) {
             return potential;
         }
+
         if (parent != null) {
-            return parent.getStatementDefinition(stmtName);
+            return parent.getVersionSpecificStatementDefinition(version, stmtName);
         }
         return null;
     }
 
     public static class Builder implements org.opendaylight.yangtools.concepts.Builder<StatementSupportBundle> {
-        private final Map<QName, StatementSupport<?, ?, ?>> statements = new HashMap<>();
+        private final Map<QName, StatementSupport<?, ?, ?>> commonStatements = new HashMap<>();
+        private final Table<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificStatements = HashBasedTable
+                .create();
         private final Map<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces = new HashMap<>();
 
+        private final Set<YangVersion> supportedVersions;
         private StatementSupportBundle parent;
 
-        Builder(final StatementSupportBundle parent) {
-            this.parent = parent;
+        Builder(final Set<YangVersion> supportedVersions, final StatementSupportBundle parent) {
+            this.parent = Preconditions.checkNotNull(parent);
+            this.supportedVersions = ImmutableSet.copyOf(supportedVersions);
         }
 
         public Builder addSupport(final StatementSupport<?, ?, ?> definition) {
             final QName identifier = definition.getStatementName();
-            Preconditions.checkState(!statements.containsKey(identifier), "Statement %s already defined.", identifier);
-            Preconditions.checkState(parent.getStatementDefinition(identifier) == null,
+            Preconditions.checkState(!commonStatements.containsKey(identifier),
+                    "Statement %s already defined in common statement bundle.", identifier);
+            Preconditions.checkState(parent.getCommonStatementDefinition(identifier) == null,
                     "Statement %s already defined.", identifier);
-            statements.put(identifier, definition);
+            commonStatements.put(identifier, definition);
+            return this;
+        }
+
+        public Builder addVersionSpecificSupport(final YangVersion version,
+                final StatementSupport<?, ?, ?> definition) {
+            Preconditions.checkNotNull(version);
+            Preconditions.checkNotNull(definition);
+            Preconditions.checkArgument(supportedVersions.contains(version));
+
+            final QName identifier = definition.getStatementName();
+            Preconditions.checkState(!commonStatements.containsKey(identifier),
+                    "Statement %s already defined in common statement bundle.", identifier);
+            Preconditions.checkState(!versionSpecificStatements.contains(version, identifier),
+                    "Statement %s already defined for version %s.", identifier, version);
+            Preconditions.checkState(parent.getCommonStatementDefinition(identifier) == null,
+                    "Statement %s already defined in parent's common statement bundle.", identifier);
+            Preconditions.checkState(parent.getVersionSpecificStatementDefinition(version, identifier) == null,
+                    "Statement %s already defined for version %s in parent's statement bundle.", identifier, version);
+            versionSpecificStatements.put(version, identifier, definition);
             return this;
         }
 
@@ -115,6 +208,10 @@ public final class StatementSupportBundle implements Immutable,NamespaceBehaviou
             return this;
         }
 
+        public Set<YangVersion> getSupportedVersions() {
+            return supportedVersions;
+        }
+
         public Builder setParent(final StatementSupportBundle parent) {
             this.parent = parent;
             return this;
@@ -122,8 +219,9 @@ public final class StatementSupportBundle implements Immutable,NamespaceBehaviou
 
         @Override
         public StatementSupportBundle build() {
-            return new StatementSupportBundle(parent, ImmutableMap.copyOf(statements), ImmutableMap.copyOf(namespaces));
+            Preconditions.checkState(parent != null, "Parent must not be null");
+            return new StatementSupportBundle(parent, supportedVersions, ImmutableMap.copyOf(commonStatements),
+                    ImmutableMap.copyOf(namespaces), ImmutableTable.copyOf(versionSpecificStatements));
         }
     }
-
 }
index 62b48676e5afe20562952c1a1940ecf871e58fc8..e9828717c40752d3d863c4ed936624ff61c290ac 100644 (file)
@@ -13,6 +13,7 @@ import java.util.Map;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
@@ -130,6 +131,13 @@ public interface StmtContext<A, D extends DeclaredStatement<A>, E extends Effect
 
     ModelProcessingPhase getCompletedPhase();
 
+    /**
+     * Return version of root statement context.
+     *
+     * @return version of root statement context
+     */
+    @Nonnull YangVersion getRootVersion();
+
     interface Mutable<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
             extends StmtContext<A, D, E> {
 
@@ -150,6 +158,14 @@ public interface StmtContext<A, D extends DeclaredStatement<A>, E extends Effect
                 Class<N> namespace, KT key, StmtContext<?, ?, ?> stmt);
 
         void setSupportedByFeatures(boolean isSupported);
+
+        /**
+         * Set version of root statement context.
+         *
+         * @param version
+         *            of root statement context
+         */
+        void setRootVersion(YangVersion version);
     }
 
 }
index 5947639c2631ea4046babc153b4fba867bbc71dd..8781a3a442a6a4041b7748c36bd9d818a00d6192 100644 (file)
@@ -9,8 +9,12 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
+import com.google.common.collect.HashBasedTable;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Table;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -25,6 +29,7 @@ import java.util.Set;
 import java.util.function.Predicate;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
@@ -61,7 +66,7 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh
             .add(ModelProcessingPhase.SOURCE_LINKAGE).add(ModelProcessingPhase.STATEMENT_DEFINITION)
             .add(ModelProcessingPhase.FULL_DECLARATION).add(ModelProcessingPhase.EFFECTIVE_MODEL).build();
 
-    private final Map<QName, StatementDefinitionContext<?, ?, ?>> definitions = new HashMap<>();
+    private final Table<YangVersion, QName, StatementDefinitionContext<?, ?, ?>> definitions = HashBasedTable.create();
     private final Map<Class<?>, NamespaceBehaviourWithListeners<?, ?, ?>> supportedNamespaces = new HashMap<>();
 
     private final Map<ModelProcessingPhase, StatementSupportBundle> supports;
@@ -71,16 +76,11 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh
     private ModelProcessingPhase finishedPhase = ModelProcessingPhase.INIT;
 
     private final boolean enabledSemanticVersions;
+    private final Set<YangVersion> supportedVersions;
 
     BuildGlobalContext(final Map<ModelProcessingPhase, StatementSupportBundle> supports,
             final StatementParserMode statementParserMode, final Predicate<QName> isFeatureSupported) {
-        super();
-        this.supports = Preconditions.checkNotNull(supports, "BuildGlobalContext#supports cannot be null");
-        Preconditions.checkNotNull(statementParserMode, "Statement parser mode must not be null.");
-        this.enabledSemanticVersions = statementParserMode == StatementParserMode.SEMVER_MODE;
-
-        addToNs(SupportedFeaturesNamespace.class, SupportedFeatures.SUPPORTED_FEATURES,
-                Preconditions.checkNotNull(isFeatureSupported, "Supported feature predicate must not be null."));
+        this(supports, ImmutableMap.of(), statementParserMode, isFeatureSupported);
     }
 
     BuildGlobalContext(final Map<ModelProcessingPhase, StatementSupportBundle> supports,
@@ -97,6 +97,7 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh
 
         addToNs(SupportedFeaturesNamespace.class, SupportedFeatures.SUPPORTED_FEATURES,
                 Preconditions.checkNotNull(isFeatureSupported, "Supported feature predicate must not be null."));
+        this.supportedVersions = ImmutableSet.copyOf(supports.get(ModelProcessingPhase.INIT).getSupportedVersions());
     }
 
     boolean isEnabledSemanticVersioning() {
@@ -162,13 +163,14 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh
         return new SimpleNamespaceContext<>(potentialRaw);
     }
 
-    StatementDefinitionContext<?, ?, ?> getStatementDefinition(final QName name) {
-        StatementDefinitionContext<?, ?, ?> potential = definitions.get(name);
+    StatementDefinitionContext<?, ?, ?> getStatementDefinition(final YangVersion version, final QName name) {
+        StatementDefinitionContext<?, ?, ?> potential = definitions.get(version, name);
         if (potential == null) {
-            final StatementSupport<?, ?, ?> potentialRaw = supports.get(currentPhase).getStatementDefinition(name);
+            final StatementSupport<?, ?, ?> potentialRaw = supports.get(currentPhase).getStatementDefinition(version,
+                    name);
             if (potentialRaw != null) {
                 potential = new StatementDefinitionContext<>(potentialRaw);
-                definitions.put(name, potential);
+                definitions.put(version, name, potential);
             }
         }
         return potential;
@@ -343,4 +345,8 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh
     Set<SourceSpecificContext> getSources() {
         return sources;
     }
+
+    public Set<YangVersion> getSupportedVersions() {
+        return supportedVersions;
+    }
 }
index 7c648e46a9ce776c60b3d5d0dba03e3247e6cd56..d85044b7b14abfd6f3e5119dc7ec5fa9f66eb513 100644 (file)
@@ -8,10 +8,15 @@
 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Table;
+import com.google.common.collect.Table.Cell;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
@@ -22,16 +27,37 @@ import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementR
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
 
 public class CustomStatementParserBuilder {
-    private final Map<ModelProcessingPhase, StatementSupportBundle.Builder> reactorSupportBundles = ImmutableMap
-            .<ModelProcessingPhase, StatementSupportBundle.Builder> builder()
-            .put(ModelProcessingPhase.INIT, StatementSupportBundle.builder())
-            .put(ModelProcessingPhase.SOURCE_PRE_LINKAGE, StatementSupportBundle.builder())
-            .put(ModelProcessingPhase.SOURCE_LINKAGE, StatementSupportBundle.builder())
-            .put(ModelProcessingPhase.STATEMENT_DEFINITION, StatementSupportBundle.builder())
-            .put(ModelProcessingPhase.FULL_DECLARATION, StatementSupportBundle.builder())
-            .put(ModelProcessingPhase.EFFECTIVE_MODEL, StatementSupportBundle.builder()).build();
+    private final Map<ModelProcessingPhase, StatementSupportBundle.Builder> reactorSupportBundles;
     private final Map<ValidationBundleType, Collection<StatementDefinition>> reactorValidationBundles = new HashMap<>();
 
+    /**
+     * Creates a new CustomStatementParserBuilder object initialized by
+     * YangInferencePipeline.SUPPORTED_VERSION_BUNDLE. Statement parser will
+     * support the same versions as defined in
+     * YangInferencePipeline.SUPPORTED_VERSION_BUNDLE.
+     */
+    public CustomStatementParserBuilder() {
+        this(YangInferencePipeline.SUPPORTED_VERSIONS);
+    }
+
+    /**
+     * Creates a new CustomStatementParserBuilder object initialized by specific
+     * version bundle. Statement parser will support all versions defined in
+     * given version bundle.
+     *
+     * @param supportedVersions
+     *            bundle of supported verions
+     */
+    public CustomStatementParserBuilder(final Set<YangVersion> supportedVersions) {
+        reactorSupportBundles = ImmutableMap.<ModelProcessingPhase, StatementSupportBundle.Builder> builder()
+                .put(ModelProcessingPhase.INIT, StatementSupportBundle.builder(supportedVersions))
+                .put(ModelProcessingPhase.SOURCE_PRE_LINKAGE, StatementSupportBundle.builder(supportedVersions))
+                .put(ModelProcessingPhase.SOURCE_LINKAGE, StatementSupportBundle.builder(supportedVersions))
+                .put(ModelProcessingPhase.STATEMENT_DEFINITION, StatementSupportBundle.builder(supportedVersions))
+                .put(ModelProcessingPhase.FULL_DECLARATION, StatementSupportBundle.builder(supportedVersions))
+                .put(ModelProcessingPhase.EFFECTIVE_MODEL, StatementSupportBundle.builder(supportedVersions)).build();
+    }
+
     public CustomStatementParserBuilder addStatementSupport(final ModelProcessingPhase phase,
             final StatementSupport<?, ?, ?> stmtSupport) {
         reactorSupportBundles.get(phase).addSupport(stmtSupport);
@@ -69,7 +95,8 @@ public class CustomStatementParserBuilder {
 
     public CustomStatementParserBuilder addAllSupports(final ModelProcessingPhase phase,
             final StatementSupportBundle stmtSupportBundle) {
-        addAllStatementSupports(phase, stmtSupportBundle.getDefinitions().values());
+        addAllCommonStatementSupports(phase, stmtSupportBundle.getCommonDefinitions().values());
+        addAllVersionSpecificSupports(phase, stmtSupportBundle.getAllVersionSpecificDefinitions());
         addAllNamespaceSupports(phase, stmtSupportBundle.getNamespaceDefinitions().values());
         return this;
     }
@@ -83,8 +110,19 @@ public class CustomStatementParserBuilder {
         return this;
     }
 
+    /**
+     * Use
+     * {@link #addAllCommonStatementSupports(ModelProcessingPhase, Collection)
+     * addAllCommonStatementSupports} method instead.
+     */
+    @Deprecated
     public CustomStatementParserBuilder addAllStatementSupports(final ModelProcessingPhase phase,
             final Collection<StatementSupport<?, ?, ?>> statementSupports) {
+        return addAllCommonStatementSupports(phase, statementSupports);
+    }
+
+    public CustomStatementParserBuilder addAllCommonStatementSupports(final ModelProcessingPhase phase,
+            final Collection<StatementSupport<?, ?, ?>> statementSupports) {
         final StatementSupportBundle.Builder stmtBundleBuilder = reactorSupportBundles.get(phase);
         for (final StatementSupport<?, ?, ?> statementSupport : statementSupports) {
             stmtBundleBuilder.addSupport(statementSupport);
@@ -92,6 +130,15 @@ public class CustomStatementParserBuilder {
         return this;
     }
 
+    public CustomStatementParserBuilder addAllVersionSpecificSupports(final ModelProcessingPhase phase,
+            final Table<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificSupports) {
+        final StatementSupportBundle.Builder stmtBundleBuilder = reactorSupportBundles.get(phase);
+        for (final Cell<YangVersion, QName, StatementSupport<?, ?, ?>> cell : versionSpecificSupports.cellSet()) {
+            stmtBundleBuilder.addVersionSpecificSupport(cell.getRowKey(), cell.getValue());
+        }
+        return this;
+    }
+
     public CrossSourceStatementReactor build() {
         final StatementSupportBundle initBundle = reactorSupportBundles.get(ModelProcessingPhase.INIT).build();
         final StatementSupportBundle preLinkageBundle = reactorSupportBundles
index 0fe03bec79a97db2aa2a59bbd6da39dcc8fa292d..4c36df37062c192f7b2a50d714c0e9a382458d14 100644 (file)
@@ -68,7 +68,7 @@ abstract class NamespaceStorageSupport implements NamespaceStorageNode {
     @SuppressWarnings("unchecked")
     @Override
     public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
-        Map<K, V> localNamespace = (Map<K,V>) namespaces.get(type);
+        final Map<K, V> localNamespace = (Map<K,V>) namespaces.get(type);
 
         V potential = null;
         if (localNamespace != null) {
@@ -89,9 +89,9 @@ abstract class NamespaceStorageSupport implements NamespaceStorageNode {
             return null;
         }
 
-        Set<Entry<ModuleIdentifier, V>> entrySet = localNamespace.entrySet();
-        for (Entry<ModuleIdentifier, V> entry : entrySet) {
-            ModuleIdentifier moduleIdentifierInMap = entry.getKey();
+        final Set<Entry<ModuleIdentifier, V>> entrySet = localNamespace.entrySet();
+        for (final Entry<ModuleIdentifier, V> entry : entrySet) {
+            final ModuleIdentifier moduleIdentifierInMap = entry.getKey();
             if (moduleIdentifierInMap.getName().equals(key.getName())) {
                 return entry.getValue();
             }
@@ -103,7 +103,7 @@ abstract class NamespaceStorageSupport implements NamespaceStorageNode {
     @Override
     public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
         @SuppressWarnings("unchecked")
-        Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
+        final Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
         return localNamespace;
     }
 
index ff139209b2f5964228d9391c52972e2c06579468..7c8b2d5877d44e16bba09744e3fbe44dd4568467 100644 (file)
@@ -17,6 +17,7 @@ import java.util.Map;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
@@ -36,9 +37,13 @@ import org.opendaylight.yangtools.yang.parser.spi.source.IncludedModuleContext;
 public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> extends
         StatementContextBase<A, D, E> {
 
+    public static final YangVersion DEFAULT_VERSION = YangVersion.VERSION_1;
+
     private final SourceSpecificContext sourceContext;
     private final A argument;
 
+    private YangVersion version;
+
     /**
      * References to RootStatementContext of submodules which are included in this source.
      */
@@ -50,6 +55,12 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
         this.argument = builder.getDefinition().parseArgumentValue(this, builder.getRawArgument());
     }
 
+    RootStatementContext(final ContextBuilder<A, D, E> builder, final SourceSpecificContext sourceContext,
+            final YangVersion version) {
+        this(builder, sourceContext);
+        this.setRootVersion(version);
+    }
+
     RootStatementContext(final RootStatementContext<A, D, E> original, final QNameModule newQNameModule,
         final CopyType typeOfCopy) {
         super(original);
@@ -218,4 +229,18 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
         }
         return null;
     }
+
+    @Override
+    public YangVersion getRootVersion() {
+        return version == null ? DEFAULT_VERSION : version;
+    }
+
+    @Override
+    public void setRootVersion(final YangVersion version) {
+        Preconditions.checkArgument(sourceContext.getSupportedVersions().contains(version),
+                "Unsupported yang version %s in %s", version, getStatementSourceReference());
+        Preconditions.checkState(this.version == null, "Version of root %s has been already set to %s", argument,
+                this.version);
+        this.version = Preconditions.checkNotNull(version);
+    }
 }
index 7b30b53f3932d434a7a34ae22e9027e3a543c485..680b7f379cdef5d5b07c2060877edd14961eef18 100644 (file)
@@ -21,11 +21,13 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import javax.annotation.Nullable;
 import org.opendaylight.yangtools.concepts.Mutable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.YangConstants;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
@@ -39,6 +41,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Namesp
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementDefinitionNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToModuleContext;
 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleIdentifier;
 import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
@@ -82,11 +85,18 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
 
         @Override
         public StatementContextBase build() {
+            /*
+             * If root is null or root version is other than default,
+             * we need to create new root.
+             */
             if (root == null) {
                 root = new RootStatementContext(this, SourceSpecificContext.this);
+            } else if (!RootStatementContext.DEFAULT_VERSION.equals(root.getRootVersion())
+                    && inProgressPhase == ModelProcessingPhase.SOURCE_LINKAGE) {
+                root = new RootStatementContext(this, SourceSpecificContext.this, root.getRootVersion());
             } else {
                 Preconditions.checkState(root.getIdentifier().equals(createIdentifier()),
-                    "Root statement was already defined as %s.", root.getIdentifier());
+                        "Root statement was already defined as %s.", root.getIdentifier());
             }
             root.resetLists();
             return root;
@@ -147,7 +157,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
             }
         }
 
-        StatementDefinitionContext<?, ?, ?> def = currentContext.getStatementDefinition(name);
+        StatementDefinitionContext<?, ?, ?> def = currentContext.getStatementDefinition(getRootVersion(), name);
 
         if (def == null) {
             final StatementSupport<?, ?, ?> extension = qNameToStmtDefMap.get(name);
@@ -190,6 +200,15 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return root;
     }
 
+    /**
+     * Return version of root statement context.
+     *
+     * @return version of root statement context
+     */
+    YangVersion getRootVersion() {
+        return root != null ? root.getRootVersion() : RootStatementContext.DEFAULT_VERSION;
+    }
+
     DeclaredStatement<?> buildDeclared() {
         return root.buildDeclared();
     }
@@ -396,7 +415,9 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
 
     private QNameToStatementDefinition stmtDef() {
         // regular YANG statements and extension supports added
-        qNameToStmtDefMap.putAll(currentContext.getSupportsForPhase(inProgressPhase).getDefinitions());
+        final StatementSupportBundle supportsForPhase = currentContext.getSupportsForPhase(inProgressPhase);
+        qNameToStmtDefMap.putAll(supportsForPhase.getCommonDefinitions());
+        qNameToStmtDefMap.putAll(supportsForPhase.getDefinitionsSpecificForVersion(getRootVersion()));
 
         // No further actions needed
         if (inProgressPhase != ModelProcessingPhase.FULL_DECLARATION) {
@@ -419,4 +440,8 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
 
         return qNameToStmtDefMap;
     }
+
+    public Set<YangVersion> getSupportedVersions() {
+        return currentContext.getSupportedVersions();
+    }
 }
index 1c78ae16c096664129221ca05b7e18452e9fa0ed..aa64a559364d48fb31858e6573cd9e81787421ae 100644 (file)
@@ -17,6 +17,7 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
@@ -306,4 +307,14 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
     public boolean isEnabledSemanticVersioning() {
         return parent.isEnabledSemanticVersioning();
     }
+
+    @Override
+    public YangVersion getRootVersion() {
+        return getRoot().getRootVersion();
+    }
+
+    @Override
+    public void setRootVersion(final YangVersion version) {
+        getRoot().setRootVersion(version);
+    }
 }
index 605ab3c28bb2371f55cf99cd079d9c068e3b0b92..aadf2fd8445f39d9d3ecd5375001376985adfa84 100644 (file)
@@ -88,7 +88,11 @@ public class ContainerStatementImpl extends AbstractDeclaredStatement<QName> imp
         public void onFullDefinitionDeclared(final Mutable<QName, ContainerStatement,
                 EffectiveStatement<QName, ContainerStatement>> stmt) {
             super.onFullDefinitionDeclared(stmt);
-            SUBSTATEMENT_VALIDATOR.validate(stmt);
+            getSubstatementValidator().validate(stmt);
+        }
+
+        protected SubstatementValidator getSubstatementValidator() {
+            return SUBSTATEMENT_VALIDATOR;
         }
     }
 
index 05c390c1187fcc0151105ed8d02346f228f0c971..0622dad4f6565e14dfd9bb7da4a6643b91ea4847 100644 (file)
@@ -122,7 +122,7 @@ public class ModuleStatementSupport extends
             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
         }
 
-        QNameModule qNameModule = QNameModule.create(moduleNs, revisionDate.orElse(null)).intern();
+        final QNameModule qNameModule = QNameModule.create(moduleNs, revisionDate.orElse(null)).intern();
 
         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule);
     }
@@ -130,7 +130,7 @@ public class ModuleStatementSupport extends
     @Override
     public void onLinkageDeclared(final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
 
-        Optional<URI> moduleNs = Optional.ofNullable(firstAttributeOf(stmt.declaredSubstatements(),
+        final Optional<URI> moduleNs = Optional.ofNullable(firstAttributeOf(stmt.declaredSubstatements(),
                 NamespaceStatement.class));
         SourceException.throwIf(!moduleNs.isPresent(), stmt.getStatementSourceReference(),
             "Namespace of the module [%s] is missing", stmt.getStatementArgument());
@@ -140,8 +140,8 @@ public class ModuleStatementSupport extends
             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
         }
 
-        QNameModule qNameModule = QNameModule.create(moduleNs.get(), revisionDate.orElse(null)).intern();
-        ModuleIdentifier moduleIdentifier = ModuleIdentifierImpl.create(stmt.getStatementArgument(),
+        final QNameModule qNameModule = QNameModule.create(moduleNs.get(), revisionDate.orElse(null)).intern();
+        final ModuleIdentifier moduleIdentifier = ModuleIdentifierImpl.create(stmt.getStatementArgument(),
                 Optional.empty(), revisionDate);
 
         stmt.addContext(ModuleNamespace.class, moduleIdentifier, stmt);
@@ -185,6 +185,10 @@ public class ModuleStatementSupport extends
     public void onFullDefinitionDeclared(final Mutable<String, ModuleStatement,
             EffectiveStatement<String, ModuleStatement>> stmt) {
         super.onFullDefinitionDeclared(stmt);
-        SUBSTATEMENT_VALIDATOR.validate(stmt);
+        getSubstatementValidator().validate(stmt);
+    }
+
+    protected SubstatementValidator getSubstatementValidator() {
+        return SUBSTATEMENT_VALIDATOR;
     }
 }
index a24dd487d5b8ec445d2590c7a6618d28d521d0be..98f04c6e181d3e422159bbbda76f2c15751475bd 100644 (file)
@@ -12,8 +12,11 @@ import static org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour
 import static org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.treeScoped;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
 import java.util.Collection;
 import java.util.Map;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.parser.spi.ExtensionNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.GroupingNamespace;
@@ -55,17 +58,23 @@ import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamesp
 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.AnydataStatementImpl;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ContainerStatementRfc7950Support;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.ModuleStatementRfc7950Support;
 
 public final class YangInferencePipeline {
+    public static final Set<YangVersion> SUPPORTED_VERSIONS =
+            Sets.immutableEnumSet(YangVersion.VERSION_1, YangVersion.VERSION_1_1);
 
     public static final StatementSupportBundle INIT_BUNDLE = StatementSupportBundle
-            .builder().addSupport(global(ValidationBundlesNamespace.class))
+            .builder(SUPPORTED_VERSIONS).addSupport(global(ValidationBundlesNamespace.class))
             .addSupport(global(SupportedFeaturesNamespace.class))
             .build();
 
     public static final StatementSupportBundle PRE_LINKAGE_BUNDLE = StatementSupportBundle
             .derivedFrom(INIT_BUNDLE)
-            .addSupport(new ModuleStatementSupport())
+            .addVersionSpecificSupport(YangVersion.VERSION_1, new ModuleStatementSupport())
+            .addVersionSpecificSupport(YangVersion.VERSION_1_1, new ModuleStatementRfc7950Support())
             .addSupport(new SubmoduleStatementImpl.Definition())
             .addSupport(new NamespaceStatementImpl.Definition())
             .addSupport(new ImportStatementDefinition())
@@ -135,7 +144,8 @@ public final class YangInferencePipeline {
             .addSupport(new LengthStatementImpl.Definition())
             .addSupport(new PatternStatementImpl.Definition())
             .addSupport(new RangeStatementImpl.Definition())
-            .addSupport(new ContainerStatementImpl.Definition())
+            .addVersionSpecificSupport(YangVersion.VERSION_1, new ContainerStatementImpl.Definition())
+            .addVersionSpecificSupport(YangVersion.VERSION_1_1, new ContainerStatementRfc7950Support())
             .addSupport(new GroupingStatementImpl.Definition())
             .addSupport(new ListStatementImpl.Definition())
             .addSupport(new UniqueStatementImpl.Definition())
@@ -160,6 +170,7 @@ public final class YangInferencePipeline {
             .addSupport(new MustStatementImpl.Definition())
             .addSupport(new MandatoryStatementImpl.Definition())
             .addSupport(new AnyxmlStatementImpl.Definition())
+            .addVersionSpecificSupport(YangVersion.VERSION_1_1, new AnydataStatementImpl.Definition())
             .addSupport(new IfFeatureStatementImpl.Definition())
             .addSupport(new UsesStatementImpl.Definition())
             .addSupport(treeScoped(GroupingNamespace.class)) //treeScoped
index 2a6a14a54e7c18ee07a9fe181d3e911af95cc914..34619c698de700fee7bac293805340db4ca2c2f3 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
 
 import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.YangVersionStatement;
@@ -15,50 +16,61 @@ import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.YangVersionEffectiveStatementImpl;
 
-public class YangVersionStatementImpl extends AbstractDeclaredStatement<String> implements YangVersionStatement {
+public class YangVersionStatementImpl extends AbstractDeclaredStatement<YangVersion> implements YangVersionStatement {
     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(Rfc6020Mapping
             .YANG_VERSION)
             .build();
 
-    protected YangVersionStatementImpl(StmtContext<String, YangVersionStatement, ?> context) {
+    protected YangVersionStatementImpl(final StmtContext<YangVersion, YangVersionStatement, ?> context) {
         super(context);
     }
 
-    public static class Definition extends AbstractStatementSupport<String,YangVersionStatement,
-            EffectiveStatement<String,YangVersionStatement>> {
+    public static class Definition extends AbstractStatementSupport<YangVersion, YangVersionStatement,
+            EffectiveStatement<YangVersion, YangVersionStatement>> {
 
         public Definition() {
             super(Rfc6020Mapping.YANG_VERSION);
         }
 
         @Override
-        public String parseArgumentValue(StmtContext<?, ?, ?> ctx, String value) {
-            return value;
+        public YangVersion parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
+            try {
+                return YangVersion.parse(value);
+            } catch (IllegalArgumentException e) {
+                throw new SourceException("Unsupported YANG version " + value, ctx.getStatementSourceReference(), e);
+            }
         }
 
         @Override
-        public YangVersionStatement createDeclared(StmtContext<String, YangVersionStatement, ?> ctx) {
+        public YangVersionStatement createDeclared(final StmtContext<YangVersion, YangVersionStatement, ?> ctx) {
             return new YangVersionStatementImpl(ctx);
         }
 
         @Override
-        public EffectiveStatement<String, YangVersionStatement> createEffective
-                (StmtContext<String, YangVersionStatement, EffectiveStatement<String, YangVersionStatement>> ctx) {
+        public void onPreLinkageDeclared(
+                final StmtContext.Mutable<YangVersion, YangVersionStatement, EffectiveStatement<YangVersion, YangVersionStatement>> stmt) {
+            stmt.setRootVersion(stmt.getStatementArgument());
+        }
+
+        @Override
+        public EffectiveStatement<YangVersion, YangVersionStatement> createEffective
+                (final StmtContext<YangVersion, YangVersionStatement, EffectiveStatement<YangVersion, YangVersionStatement>> ctx) {
             return new YangVersionEffectiveStatementImpl(ctx);
         }
 
         @Override
-        public void onFullDefinitionDeclared(StmtContext.Mutable<String, YangVersionStatement,
-                EffectiveStatement<String, YangVersionStatement>> stmt) {
+        public void onFullDefinitionDeclared(final StmtContext.Mutable<YangVersion, YangVersionStatement,
+                EffectiveStatement<YangVersion, YangVersionStatement>> stmt) {
             super.onFullDefinitionDeclared(stmt);
             SUBSTATEMENT_VALIDATOR.validate(stmt);
         }
     }
 
     @Nonnull @Override
-    public String getValue() {
-        return rawArgument();
+    public YangVersion getValue() {
+        return argument();
     }
 }
index c82beb5a1eda33fc41deff6fcbd6817e16c7ec95..37a355756258c28ba84c1a96599ee2b78c98e026 100644 (file)
@@ -12,13 +12,13 @@ import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 
-abstract class AbstractEffectiveDataSchemaNode<D extends DeclaredStatement<QName>> extends
+public abstract class AbstractEffectiveDataSchemaNode<D extends DeclaredStatement<QName>> extends
         AbstractEffectiveSchemaNode<D> implements DataSchemaNode {
 
-    // :FIXME should be private and final
+    // :FIXME Bug-7277
     boolean augmenting;
     private final boolean addedByUses;
     private final boolean configuration;
index 117392261fd7e39501203ff0608a59e5ce2e5af9..7ae2adc5528caf70ae20e5f74c589ff8d31bde54 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.yangtools.concepts.SemVer;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Deviation;
@@ -57,7 +58,7 @@ abstract class AbstractEffectiveModule<D extends DeclaredStatement<String>> exte
     private final String name;
     private final String sourcePath;
     private final String prefix;
-    private final String yangVersion;
+    private final YangVersion yangVersion;
     private final String organization;
     private final String contact;
     private final Set<ModuleImport> imports;
@@ -86,7 +87,7 @@ abstract class AbstractEffectiveModule<D extends DeclaredStatement<String>> exte
         this.prefix = (prefixStmt == null) ? null : prefixStmt.argument();
 
         YangVersionEffectiveStatementImpl yangVersionStmt = firstEffective(YangVersionEffectiveStatementImpl.class);
-        this.yangVersion = (yangVersionStmt == null) ? "1" : yangVersionStmt.argument();
+        this.yangVersion = (yangVersionStmt == null) ? YangVersion.VERSION_1 : yangVersionStmt.argument();
 
         SemanticVersionEffectiveStatementImpl semanticVersionStmt = firstEffective(SemanticVersionEffectiveStatementImpl.class);
         this.semanticVersion = (semanticVersionStmt == null) ? DEFAULT_SEMANTIC_VERSION : semanticVersionStmt.argument();
@@ -285,7 +286,7 @@ abstract class AbstractEffectiveModule<D extends DeclaredStatement<String>> exte
 
     @Override
     public String getYangVersion() {
-        return yangVersion;
+        return yangVersion.toCanonicalString();
     }
 
     @Override
index 835e2cbc3a1e06e02d1e8c9d71da1d83d86e8b49..b4dace9c49a64d44b1335b9511789b489ef29abc 100644 (file)
@@ -7,11 +7,12 @@
  */
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective;
 
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.stmt.YangVersionStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 
-public final class YangVersionEffectiveStatementImpl extends DeclaredEffectiveStatementBase<String, YangVersionStatement> {
-    public YangVersionEffectiveStatementImpl(final StmtContext<String, YangVersionStatement, ?> ctx) {
+public final class YangVersionEffectiveStatementImpl extends DeclaredEffectiveStatementBase<YangVersion, YangVersionStatement> {
+    public YangVersionEffectiveStatementImpl(final StmtContext<YangVersion, YangVersionStatement, ?> ctx) {
         super(ctx);
     }
 }
\ No newline at end of file
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/AnydataStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/AnydataStatementImpl.java
new file mode 100644 (file)
index 0000000..da20a49
--- /dev/null
@@ -0,0 +1,130 @@
+/**
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.stmt.rfc7950;
+
+import java.util.Collection;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ConfigStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement;
+import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.ChildSchemaNodes;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.effective.AnyDataEffectiveStatementImpl;
+
+public class AnydataStatementImpl extends AbstractDeclaredStatement<QName> implements AnydataStatement {
+    private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(Rfc6020Mapping
+            .ANYDATA)
+            .addOptional(Rfc6020Mapping.CONFIG)
+            .addOptional(Rfc6020Mapping.DESCRIPTION)
+            .addAny(Rfc6020Mapping.IF_FEATURE)
+            .addOptional(Rfc6020Mapping.MANDATORY)
+            .addAny(Rfc6020Mapping.MUST)
+            .addOptional(Rfc6020Mapping.REFERENCE)
+            .addOptional(Rfc6020Mapping.STATUS)
+            .addOptional(Rfc6020Mapping.WHEN)
+            .build();
+
+    protected AnydataStatementImpl(final StmtContext<QName, AnydataStatement, ?> context) {
+        super(context);
+    }
+
+    public static class Definition extends
+            AbstractStatementSupport<QName, AnydataStatement, EffectiveStatement<QName, AnydataStatement>> {
+
+        public Definition() {
+            super(Rfc6020Mapping.ANYDATA);
+        }
+
+        @Override
+        public QName parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
+            return Utils.qNameFromArgument(ctx, value);
+        }
+
+        @Override
+        public void onStatementAdded(final Mutable<QName, AnydataStatement, EffectiveStatement<QName, AnydataStatement>> stmt) {
+            stmt.getParentContext().addToNs(ChildSchemaNodes.class, stmt.getStatementArgument(), stmt);
+        }
+
+        @Override
+        public AnydataStatement createDeclared(final StmtContext<QName, AnydataStatement, ?> ctx) {
+            return new AnydataStatementImpl(ctx);
+        }
+
+        @Override
+        public EffectiveStatement<QName, AnydataStatement> createEffective(
+                final StmtContext<QName, AnydataStatement, EffectiveStatement<QName, AnydataStatement>> ctx) {
+            return new AnyDataEffectiveStatementImpl(ctx);
+        }
+
+        @Override
+        public void onFullDefinitionDeclared(final Mutable<QName, AnydataStatement,
+                EffectiveStatement<QName, AnydataStatement>> stmt) {
+            super.onFullDefinitionDeclared(stmt);
+            SUBSTATEMENT_VALIDATOR.validate(stmt);
+        }
+    }
+
+    @Override
+    public QName getName() {
+        return argument();
+    }
+
+    @Override
+    public WhenStatement getWhenStatement() {
+        return firstDeclared(WhenStatement.class);
+    }
+
+    @Override
+    public Collection<? extends IfFeatureStatement> getIfFeatures() {
+        return allDeclared(IfFeatureStatement.class);
+    }
+
+    @Override
+    public Collection<? extends MustStatement> getMusts() {
+        return allDeclared(MustStatement.class);
+    }
+
+    @Override
+    public ConfigStatement getConfig() {
+        return firstDeclared(ConfigStatement.class);
+    }
+
+    @Override
+    public StatusStatement getStatus() {
+        return firstDeclared(StatusStatement.class);
+    }
+
+    @Override
+    public DescriptionStatement getDescription() {
+        return firstDeclared(DescriptionStatement.class);
+    }
+
+    @Override
+    public ReferenceStatement getReference() {
+        return firstDeclared(ReferenceStatement.class);
+    }
+
+    @Override
+    public MandatoryStatement getMandatory() {
+        return firstDeclared(MandatoryStatement.class);
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ContainerStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ContainerStatementRfc7950Support.java
new file mode 100644 (file)
index 0000000..9208e37
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.stmt.rfc7950;
+
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.ContainerStatementImpl;
+
+public class ContainerStatementRfc7950Support extends ContainerStatementImpl.Definition {
+    private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(Rfc6020Mapping
+            .CONTAINER)
+            .addAny(Rfc6020Mapping.ANYXML)
+            .addAny(Rfc6020Mapping.CHOICE)
+            .addOptional(Rfc6020Mapping.CONFIG)
+            .addAny(Rfc6020Mapping.CONTAINER)
+            .addOptional(Rfc6020Mapping.DESCRIPTION)
+            .addAny(Rfc6020Mapping.GROUPING)
+            .addAny(Rfc6020Mapping.IF_FEATURE)
+            .addAny(Rfc6020Mapping.LEAF)
+            .addAny(Rfc6020Mapping.LEAF_LIST)
+            .addAny(Rfc6020Mapping.LIST)
+            .addAny(Rfc6020Mapping.MUST)
+            .addOptional(Rfc6020Mapping.PRESENCE)
+            .addOptional(Rfc6020Mapping.REFERENCE)
+            .addOptional(Rfc6020Mapping.STATUS)
+            .addAny(Rfc6020Mapping.TYPEDEF)
+            .addAny(Rfc6020Mapping.USES)
+            .addOptional(Rfc6020Mapping.WHEN)
+            .addAny(Rfc6020Mapping.NOTIFICATION)
+            .build();
+
+    @Override
+    protected SubstatementValidator getSubstatementValidator() {
+        return SUBSTATEMENT_VALIDATOR;
+    }
+}
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ModuleStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ModuleStatementRfc7950Support.java
new file mode 100644 (file)
index 0000000..70623f6
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.stmt.rfc7950;
+
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.ModuleStatementSupport;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.SupportedExtensionsMapping;
+
+public class ModuleStatementRfc7950Support extends ModuleStatementSupport {
+    private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(Rfc6020Mapping
+            .MODULE)
+            .addAny(Rfc6020Mapping.ANYXML)
+            .addAny(Rfc6020Mapping.ANYDATA)
+            .addAny(Rfc6020Mapping.AUGMENT)
+            .addAny(Rfc6020Mapping.CHOICE)
+            .addOptional(Rfc6020Mapping.CONTACT)
+            .addAny(Rfc6020Mapping.CONTAINER)
+            .addOptional(Rfc6020Mapping.DESCRIPTION)
+            .addAny(Rfc6020Mapping.DEVIATION)
+            .addAny(Rfc6020Mapping.EXTENSION)
+            .addAny(Rfc6020Mapping.FEATURE)
+            .addAny(Rfc6020Mapping.GROUPING)
+            .addAny(Rfc6020Mapping.IDENTITY)
+            .addAny(Rfc6020Mapping.IMPORT)
+            .addAny(Rfc6020Mapping.INCLUDE)
+            .addAny(Rfc6020Mapping.LEAF)
+            .addAny(Rfc6020Mapping.LEAF_LIST)
+            .addAny(Rfc6020Mapping.LIST)
+            .addMandatory(Rfc6020Mapping.NAMESPACE)
+            .addAny(Rfc6020Mapping.NOTIFICATION)
+            .addOptional(Rfc6020Mapping.ORGANIZATION)
+            .addMandatory(Rfc6020Mapping.PREFIX)
+            .addOptional(Rfc6020Mapping.REFERENCE)
+            .addAny(Rfc6020Mapping.REVISION)
+            .addAny(Rfc6020Mapping.RPC)
+            .addAny(Rfc6020Mapping.TYPEDEF)
+            .addAny(Rfc6020Mapping.USES)
+            .addMandatory(Rfc6020Mapping.YANG_VERSION)
+            .addOptional(SupportedExtensionsMapping.SEMANTIC_VERSION)
+            .build();
+
+    @Override
+    protected SubstatementValidator getSubstatementValidator() {
+        return SUBSTATEMENT_VALIDATOR;
+    }
+}
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/effective/AnyDataEffectiveStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/effective/AnyDataEffectiveStatementImpl.java
new file mode 100644 (file)
index 0000000..7b1920d
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.stmt.rfc7950.effective;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Optional;
+import java.util.Objects;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.AbstractEffectiveDataSchemaNode;
+
+public class AnyDataEffectiveStatementImpl extends AbstractEffectiveDataSchemaNode<AnydataStatement> implements
+        AnyDataSchemaNode, DerivableSchemaNode {
+
+    private final AnyDataSchemaNode original;
+
+    public AnyDataEffectiveStatementImpl(
+            final StmtContext<QName, AnydataStatement, EffectiveStatement<QName, AnydataStatement>> ctx) {
+        super(ctx);
+        this.original = ctx.getOriginalCtx() == null ? null : (AnyDataSchemaNode) ctx.getOriginalCtx().buildEffective();
+    }
+
+    @Override
+    public Optional<AnyDataSchemaNode> getOriginal() {
+        return Optional.fromNullable(original);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getQName(),getPath());
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        final AnyDataEffectiveStatementImpl other = (AnyDataEffectiveStatementImpl) obj;
+        return Objects.equals(getQName(), other.getQName()) && Objects.equals(getPath(), other.getPath());
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this).add("qname", getQName()).add("path", getPath()).toString();
+    }
+
+    @Override
+    public ContainerSchemaNode getSchemaOfAnyData() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6867BasicTest.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6867BasicTest.java
new file mode 100644 (file)
index 0000000..54cc314
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.yangtools.yang.parser.stmt.rfc7950;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.stmt.StmtTestUtils;
+
+public class Bug6867BasicTest {
+
+    @Test
+    public void valid10Test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException {
+        final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/basic-test/valid-10.yang");
+        assertNotNull(schemaContext);
+    }
+
+    @Test
+    public void valid11Test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException {
+        final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/basic-test/valid-11.yang");
+        assertNotNull(schemaContext);
+    }
+
+    @Test
+    public void invalid10Test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException {
+        try {
+            StmtTestUtils.parseYangSource("/rfc7950/basic-test/invalid-10.yang");
+            fail("Test should fail due to invalid Yang 1.0");
+        } catch (final SomeModifiersUnresolvedException e) {
+            assertTrue(e.getCause().getMessage().startsWith("NOTIFICATION is not valid for CONTAINER"));
+        }
+    }
+
+    @Test
+    public void invalid11Test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException {
+        try {
+            StmtTestUtils.parseYangSource("/rfc7950/basic-test/invalid-11.yang");
+            fail("Test should fail due to invalid Yang 1.1");
+        } catch (final SomeModifiersUnresolvedException e) {
+            assertTrue(e.getCause().getMessage().startsWith("RPC is not valid for CONTAINER"));
+        }
+    }
+
+    @Test
+    public void anyData11Test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException {
+        final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/basic-test/anydata-11.yang");
+        assertNotNull(schemaContext);
+    }
+
+    @Test
+    public void anyData10Test() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException {
+        try {
+            StmtTestUtils.parseYangSource("/rfc7950/basic-test/anydata-10.yang");
+            fail("Test should fail due to invalid Yang 1.0");
+        } catch (final SomeModifiersUnresolvedException e) {
+            assertTrue(e.getCause().getMessage().startsWith("anydata is not a YANG statement or use of extension"));
+        }
+    }
+
+    @Test
+    public void yangModelTest() throws ReactorException, SourceException, FileNotFoundException, URISyntaxException {
+        final SchemaContext schemaContext = StmtTestUtils.parseYangSources("/rfc7950/model");
+        assertNotNull(schemaContext);
+    }
+
+    @Test
+    public void unsupportedVersionTest() throws ReactorException, SourceException, FileNotFoundException,
+            URISyntaxException {
+        try {
+            StmtTestUtils.parseYangSource("/rfc7950/basic-test/unsupported-version.yang");
+            fail("Test should fail due to unsupported Yang version");
+        } catch (final SomeModifiersUnresolvedException e) {
+            final Throwable cause = e.getCause();
+            assertNotNull(cause);
+            assertTrue(cause.getMessage().startsWith("Unsupported YANG version 2.3"));
+        }
+    }
+}
index 5ee247647199d5e0a67f34aa02caefa410372eda..e6336f273b31e682bd4119f82315136a95944a53 100644 (file)
@@ -37,12 +37,12 @@ import org.slf4j.LoggerFactory;
 public class StmtTestUtils {
 
     final public static FileFilter YANG_FILE_FILTER = file -> {
-        String name = file.getName().toLowerCase();
+        final String name = file.getName().toLowerCase();
         return name.endsWith(".yang") && file.isFile();
     };
 
     final public static FileFilter YIN_FILE_FILTER = file -> {
-        String name = file.getName().toLowerCase();
+        final String name = file.getName().toLowerCase();
         return name.endsWith(".xml") && file.isFile();
     };
 
@@ -52,18 +52,18 @@ public class StmtTestUtils {
 
     }
 
-    public static void log(Throwable e, String indent) {
+    public static void log(final Throwable e, final String indent) {
         LOG.debug(indent + e.getMessage());
 
-        Throwable[] suppressed = e.getSuppressed();
-        for (Throwable throwable : suppressed) {
+        final Throwable[] suppressed = e.getSuppressed();
+        for (final Throwable throwable : suppressed) {
             log(throwable, indent + "        ");
         }
     }
 
     public static List<Module> findModules(final Set<Module> modules, final String moduleName) {
-        List<Module> result = new ArrayList<>();
-        for (Module module : modules) {
+        final List<Module> result = new ArrayList<>();
+        for (final Module module : modules) {
             if (module.getName().equals(moduleName)) {
                 result.add(module);
             }
@@ -71,24 +71,24 @@ public class StmtTestUtils {
         return result;
     }
 
-    public static void addSources(CrossSourceStatementReactor.BuildAction reactor, YangStatementSourceImpl... sources) {
-        for (YangStatementSourceImpl source : sources) {
+    public static void addSources(final CrossSourceStatementReactor.BuildAction reactor, final YangStatementSourceImpl... sources) {
+        for (final YangStatementSourceImpl source : sources) {
             reactor.addSource(source);
         }
     }
 
-    public static void printReferences(Module module, boolean isSubmodule, String indent) {
+    public static void printReferences(final Module module, final boolean isSubmodule, final String indent) {
         LOG.debug(indent + (isSubmodule ? "Submodule " : "Module ") + module.getName());
-        Set<Module> submodules = module.getSubmodules();
-        for (Module submodule : submodules) {
+        final Set<Module> submodules = module.getSubmodules();
+        for (final Module submodule : submodules) {
             printReferences(submodule, true, indent + "      ");
             printChilds(submodule.getChildNodes(), indent + "            ");
         }
     }
 
-    public static void printChilds(Collection<DataSchemaNode> childNodes, String indent) {
+    public static void printChilds(final Collection<DataSchemaNode> childNodes, final String indent) {
 
-        for (DataSchemaNode child : childNodes) {
+        for (final DataSchemaNode child : childNodes) {
             LOG.debug(indent + "Child " + child.getQName().getLocalName());
             if (child instanceof DataNodeContainer) {
                 printChilds(((DataNodeContainer) child).getChildNodes(), indent + "      ");
@@ -96,29 +96,29 @@ public class StmtTestUtils {
         }
     }
 
-    public static SchemaContext parseYangSources(StatementStreamSource... sources) throws SourceException,
+    public static SchemaContext parseYangSources(final StatementStreamSource... sources) throws SourceException,
             ReactorException {
         return parseYangSources(StatementParserMode.DEFAULT_MODE, sources);
     }
 
-    public static SchemaContext parseYangSources(StatementParserMode statementParserMode, StatementStreamSource... sources)
+    public static SchemaContext parseYangSources(final StatementParserMode statementParserMode, final StatementStreamSource... sources)
             throws SourceException, ReactorException {
 
-        CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(statementParserMode);
+        final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(statementParserMode);
         reactor.addSources(sources);
 
         return reactor.buildEffective();
     }
 
-    public static SchemaContext parseYangSources(File... files) throws SourceException, ReactorException,
+    public static SchemaContext parseYangSources(final File... files) throws SourceException, ReactorException,
             FileNotFoundException {
         return parseYangSources(StatementParserMode.DEFAULT_MODE, files);
     }
 
-    public static SchemaContext parseYangSources(StatementParserMode statementParserMode, File... files) throws SourceException,
+    public static SchemaContext parseYangSources(final StatementParserMode statementParserMode, final File... files) throws SourceException,
             ReactorException, FileNotFoundException {
 
-        StatementStreamSource[] sources = new StatementStreamSource[files.length];
+        final StatementStreamSource[] sources = new StatementStreamSource[files.length];
 
         for (int i = 0; i < files.length; i++) {
             sources[i] = new YangStatementSourceImpl(new NamedFileInputStream(files[i], files[i].getPath()));
@@ -127,43 +127,55 @@ public class StmtTestUtils {
         return parseYangSources(statementParserMode, sources);
     }
 
-    public static SchemaContext parseYangSources(Collection<File> files) throws SourceException, ReactorException,
+    public static SchemaContext parseYangSources(final Collection<File> files) throws SourceException, ReactorException,
             FileNotFoundException {
         return parseYangSources(files, StatementParserMode.DEFAULT_MODE);
     }
 
-    public static SchemaContext parseYangSources(Collection<File> files, StatementParserMode statementParserMode)
+    public static SchemaContext parseYangSources(final Collection<File> files, final StatementParserMode statementParserMode)
             throws SourceException, ReactorException, FileNotFoundException {
         return parseYangSources(statementParserMode, files.toArray(new File[files.size()]));
     }
 
-    public static SchemaContext parseYangSources(String yangSourcesDirectoryPath) throws SourceException,
+    public static SchemaContext parseYangSources(final String yangSourcesDirectoryPath) throws SourceException,
             ReactorException, FileNotFoundException, URISyntaxException {
         return parseYangSources(yangSourcesDirectoryPath, StatementParserMode.DEFAULT_MODE);
     }
 
-    public static SchemaContext parseYangSources(String yangSourcesDirectoryPath, StatementParserMode statementParserMode)
+    public static SchemaContext parseYangSource(final String yangSourcePath) throws SourceException, ReactorException,
+            FileNotFoundException, URISyntaxException {
+        return parseYangSource(yangSourcePath, StatementParserMode.DEFAULT_MODE);
+    }
+
+    public static SchemaContext parseYangSource(final String yangSourcePath, final StatementParserMode statementParserMode)
+            throws SourceException, ReactorException, FileNotFoundException, URISyntaxException {
+        final URL source = StmtTestUtils.class.getResource(yangSourcePath);
+        final File sourceFile = new File(source.toURI());
+        return parseYangSources(statementParserMode, sourceFile);
+    }
+
+    public static SchemaContext parseYangSources(final String yangSourcesDirectoryPath, final StatementParserMode statementParserMode)
             throws SourceException, ReactorException, FileNotFoundException, URISyntaxException {
 
-        URL resourceDir = StmtTestUtils.class.getResource(yangSourcesDirectoryPath);
-        File testSourcesDir = new File(resourceDir.toURI());
+        final URL resourceDir = StmtTestUtils.class.getResource(yangSourcesDirectoryPath);
+        final File testSourcesDir = new File(resourceDir.toURI());
 
         return parseYangSources(statementParserMode, testSourcesDir.listFiles(YANG_FILE_FILTER));
     }
 
-    public static SchemaContext parseYinSources(String yinSourcesDirectoryPath, StatementParserMode statementParserMode)
+    public static SchemaContext parseYinSources(final String yinSourcesDirectoryPath, final StatementParserMode statementParserMode)
             throws SourceException, ReactorException, FileNotFoundException, URISyntaxException {
 
-        URL resourceDir = StmtTestUtils.class.getResource(yinSourcesDirectoryPath);
-        File testSourcesDir = new File(resourceDir.toURI());
+        final URL resourceDir = StmtTestUtils.class.getResource(yinSourcesDirectoryPath);
+        final File testSourcesDir = new File(resourceDir.toURI());
 
         return parseYinSources(statementParserMode, testSourcesDir.listFiles(YIN_FILE_FILTER));
     }
 
-    public static SchemaContext parseYinSources(StatementParserMode statementParserMode, File... files) throws SourceException,
+    public static SchemaContext parseYinSources(final StatementParserMode statementParserMode, final File... files) throws SourceException,
             ReactorException, FileNotFoundException {
 
-        StatementStreamSource[] sources = new StatementStreamSource[files.length];
+        final StatementStreamSource[] sources = new StatementStreamSource[files.length];
 
         for (int i = 0; i < files.length; i++) {
             sources[i] = new YinStatementSourceImpl(new NamedFileInputStream(files[i], files[i].getPath()));
@@ -172,26 +184,26 @@ public class StmtTestUtils {
         return parseYinSources(statementParserMode, sources);
     }
 
-    public static SchemaContext parseYinSources(StatementParserMode statementParserMode, StatementStreamSource... sources)
+    public static SchemaContext parseYinSources(final StatementParserMode statementParserMode, final StatementStreamSource... sources)
             throws SourceException, ReactorException {
 
-        CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(statementParserMode);
+        final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild(statementParserMode);
         reactor.addSources(sources);
 
         return reactor.buildEffective();
     }
 
-    public static Module findImportedModule(SchemaContext context, Module rootModule, String importedModuleName) {
+    public static Module findImportedModule(final SchemaContext context, final Module rootModule, final String importedModuleName) {
         ModuleImport requestedModuleImport = null;
-        Set<ModuleImport> rootImports = rootModule.getImports();
-        for (ModuleImport moduleImport : rootImports) {
+        final Set<ModuleImport> rootImports = rootModule.getImports();
+        for (final ModuleImport moduleImport : rootImports) {
             if (moduleImport.getModuleName().equals(importedModuleName)) {
                 requestedModuleImport = moduleImport;
                 break;
             }
         }
 
-        Module importedModule = context.findModuleByName(requestedModuleImport.getModuleName(),
+        final Module importedModule = context.findModuleByName(requestedModuleImport.getModuleName(),
                 requestedModuleImport.getRevision());
         return importedModule;
     }
index 44205743c6e781e0eacbee3ddd2b56b9e190c5da..6a04bf1fdf721e060f5a9cf87ad4bec7915c1088 100644 (file)
@@ -11,8 +11,6 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
-
 import java.io.FileNotFoundException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -21,6 +19,7 @@ import org.junit.Test;
 import org.opendaylight.yangtools.concepts.SemVer;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
 import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
@@ -32,22 +31,34 @@ public class SemanticVersionComplexTest {
     @Test
     public void complexTest1() throws SourceException, FileNotFoundException, ReactorException, URISyntaxException,
             ParseException {
-        SchemaContext context = StmtTestUtils.parseYangSources("/semantic-version/complex/complex-1",
+        final SchemaContext context = StmtTestUtils.parseYangSources("/semantic-version/complex/complex-1",
                 StatementParserMode.SEMVER_MODE);
+        verifySchemaContextTest1(context);
+    }
+
+    @Test
+    public void complexTest1Yang1_1() throws SourceException, FileNotFoundException, ReactorException, URISyntaxException,
+            ParseException {
+        final SchemaContext context = StmtTestUtils.parseYangSources("/rfc7950/semantic-version/complex-1",
+                StatementParserMode.SEMVER_MODE);
+        verifySchemaContextTest1(context);
+    }
+
+    private void verifySchemaContextTest1(final SchemaContext context) throws URISyntaxException {
         assertNotNull(context);
 
-        Module foo = context.findModuleByNamespace(new URI("foo")).iterator().next();
-        Module semVer = context.findModuleByNamespace(new URI("urn:opendaylight:yang:extension:semantic-version"))
+        final Module foo = context.findModuleByNamespace(new URI("foo")).iterator().next();
+        final Module semVer = context.findModuleByNamespace(new URI("urn:opendaylight:yang:extension:semantic-version"))
                 .iterator().next();
 
         // check module versions
         assertEquals(SemVer.valueOf("1.3.95"), semVer.getSemanticVersion());
         assertEquals(SemVer.valueOf("1.50.2"), foo.getSemanticVersion());
 
-        Module bar = StmtTestUtils.findImportedModule(context, foo, "bar");
+        final Module bar = StmtTestUtils.findImportedModule(context, foo, "bar");
         assertEquals(SemVer.valueOf("1.2.6"), bar.getSemanticVersion());
 
-        Module foobar = StmtTestUtils.findImportedModule(context, bar, "foobar");
+        final Module foobar = StmtTestUtils.findImportedModule(context, bar, "foobar");
         assertEquals(SemVer.valueOf("2.26.465"), foobar.getSemanticVersion());
 
         // check imported components
@@ -68,22 +79,34 @@ public class SemanticVersionComplexTest {
     @Test
     public void complexTest2() throws SourceException, FileNotFoundException, ReactorException, URISyntaxException,
             ParseException {
-        SchemaContext context = StmtTestUtils.parseYangSources("/semantic-version/complex/complex-2",
+        final SchemaContext context = StmtTestUtils.parseYangSources("/semantic-version/complex/complex-2",
+                StatementParserMode.SEMVER_MODE);
+        verifySchemaContextTest2(context);
+    }
+
+    @Test
+    public void complexTest2Yang1_1() throws SourceException, FileNotFoundException, ReactorException, URISyntaxException,
+            ParseException {
+        final SchemaContext context = StmtTestUtils.parseYangSources("/rfc7950/semantic-version/complex-2",
                 StatementParserMode.SEMVER_MODE);
+        verifySchemaContextTest2(context);
+    }
+
+    private void verifySchemaContextTest2(final SchemaContext context) throws URISyntaxException {
         assertNotNull(context);
 
-        Module foo = context.findModuleByNamespace(new URI("foo")).iterator().next();
-        Module semVer = context.findModuleByNamespace(new URI("urn:opendaylight:yang:extension:semantic-version"))
+        final Module foo = context.findModuleByNamespace(new URI("foo")).iterator().next();
+        final Module semVer = context.findModuleByNamespace(new URI("urn:opendaylight:yang:extension:semantic-version"))
                 .iterator().next();
 
         // check module versions
         assertEquals(SemVer.valueOf("2.5.50"), semVer.getSemanticVersion());
         assertEquals(SemVer.valueOf("2.32.2"), foo.getSemanticVersion());
 
-        Module bar = StmtTestUtils.findImportedModule(context, foo, "bar");
+        final Module bar = StmtTestUtils.findImportedModule(context, foo, "bar");
         assertEquals(SemVer.valueOf("4.9.8"), bar.getSemanticVersion());
 
-        Module foobar = StmtTestUtils.findImportedModule(context, bar, "foobar");
+        final Module foobar = StmtTestUtils.findImportedModule(context, bar, "foobar");
         assertEquals(SemVer.valueOf("7.13.99"), foobar.getSemanticVersion());
 
         // check used augmentations
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/anydata-10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/anydata-10.yang
new file mode 100644 (file)
index 0000000..7bbeac5
--- /dev/null
@@ -0,0 +1,11 @@
+module anydata-10 {
+    namespace "anydata-10";
+    prefix a;
+    yang-version 1;
+
+    anydata my-data {
+    }
+
+    container root {
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/anydata-11.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/anydata-11.yang
new file mode 100644 (file)
index 0000000..7201150
--- /dev/null
@@ -0,0 +1,13 @@
+module anydata-11 {
+    namespace "anydata-11";
+    prefix a;
+    yang-version 1.1;
+
+    anydata my-data {
+    }
+
+    container root {
+        notification root-notification {
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/invalid-10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/invalid-10.yang
new file mode 100644 (file)
index 0000000..b0cc012
--- /dev/null
@@ -0,0 +1,9 @@
+module invalid-10 {
+    namespace "invalid-10";
+    prefix v;
+
+    container root {
+        notification root-notification {
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/invalid-11.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/invalid-11.yang
new file mode 100644 (file)
index 0000000..8ccc3ad
--- /dev/null
@@ -0,0 +1,14 @@
+module invalid-11 {
+    namespace "invalid-11";
+    prefix v;
+    yang-version 1.1;
+
+    container root {
+        rpc root-rpc {
+            input {
+            }
+            output {
+            }
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/unsupported-version.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/unsupported-version.yang
new file mode 100644 (file)
index 0000000..1785f93
--- /dev/null
@@ -0,0 +1,8 @@
+module unsupported-version {
+    namespace "version-test";
+    prefix un;
+    yang-version 2.3;
+
+    container root {
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/valid-10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/valid-10.yang
new file mode 100644 (file)
index 0000000..8cdabef
--- /dev/null
@@ -0,0 +1,7 @@
+module valid-10 {
+    namespace "valid-10";
+    prefix v;
+
+    container root {
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/valid-11.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/basic-test/valid-11.yang
new file mode 100644 (file)
index 0000000..9fa1962
--- /dev/null
@@ -0,0 +1,10 @@
+module valid-11 {
+    namespace "valid-11";
+    prefix v;
+    yang-version 1.1;
+
+    container root {
+        notification root-notification {
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/model/bar.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/model/bar.yang
new file mode 100644 (file)
index 0000000..aa8643a
--- /dev/null
@@ -0,0 +1,119 @@
+module bar {
+    yang-version 1.1;
+    namespace "urn:opendaylight.bar";
+    prefix "bar";
+
+    organization "opendaylight";
+    contact "http://www.opendaylight.org/";
+    description "This model define custom type definitions";
+
+    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 invalid-string-pattern {
+        type string {
+            pattern "[[A-1*-%22!^^}";
+        }
+    }
+
+    typedef multiple-pattern-string {
+        type string {
+            pattern "[[A-1*-%22!^^}";
+            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;
+        }
+    }
+
+    extension opendaylight {
+        argument "name" {
+            yin-element "true";
+        }
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/model/baz.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/model/baz.yang
new file mode 100644 (file)
index 0000000..b7b9c02
--- /dev/null
@@ -0,0 +1,194 @@
+module baz {
+    yang-version 1.1;
+    namespace "urn:opendaylight.baz";
+    prefix "baz";
+
+    import bar {
+        prefix "br";
+        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 br:nested-union2;
+        }
+    }
+
+    augment "/br:interfaces/br:ifEntry" {
+        when "if:ifType='ds0'";
+        container augment-holder {
+            description "Description for augment holder";
+        }
+    }
+
+    augment "/br:interfaces/br:ifEntry" {
+        when "if:ifType='ds2'";
+        container augment-holder2 {
+            description "Description for augment holder";
+        }
+    }
+
+    container network {
+        baz:c-define point {
+        }
+
+        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.";
+                baz:c-define 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";
+            mandatory true;
+        }
+        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 br:my-decimal-type;
+        }
+        
+        br:opendaylight;
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/model/foo.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/model/foo.yang
new file mode 100644 (file)
index 0000000..83ced67
--- /dev/null
@@ -0,0 +1,235 @@
+module foo {
+    yang-version 1.1;
+    namespace "urn:opendaylight.foo";
+    prefix "foo";
+
+    import bar {
+        prefix "br";
+        revision-date 2013-07-03;
+    }
+
+    import baz {
+        prefix "bz";
+        revision-date 2013-02-27;
+    }
+
+    include subfoo {
+        revision-date "2013-02-27";
+    }
+
+    organization "opendaylight";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-02-27" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    typedef identifier {
+        type int32;
+    }
+
+    leaf int32-leaf {
+        type br:int32-ext2 {
+            range "12..max";
+        }
+    }
+
+    leaf string-leaf {
+        type br:string-ext4;
+    }
+
+    leaf invalid-pattern-string-leaf {
+        type br:invalid-string-pattern;
+    }
+
+    leaf invalid-direct-string-pattern-def-leaf {
+        type string {
+            pattern "[[A-1*-%22!^^}";
+        }
+    }
+
+    leaf multiple-pattern-string-leaf {
+        type br:multiple-pattern-string;
+    }
+
+    leaf multiple-pattern-direct-string-def-leaf {
+        type string {
+            pattern "[e-z]*";
+            pattern "[[A-1*-%22!^^}";
+            pattern "[a-d]*";
+        }
+    }
+
+    leaf length-leaf {
+        type br:string-ext2 {
+            length "7..max";
+        }
+    }
+
+    leaf decimal-leaf {
+        type br:my-decimal-type {
+            fraction-digits 4;
+        }
+    }
+
+    leaf decimal-leaf2 {
+        type br:my-decimal-type;
+    }
+
+    container ext {
+        bz:c-define "MY_INTERFACES";
+    }
+
+    leaf union-leaf {
+        type br:my-union-ext;
+    }
+
+    deviation /br:interfaces/br:ifEntry {
+        deviate add {
+            default "admin";
+            config "true";
+        }
+        reference "system/user ref";
+    }
+
+    leaf custom-union-leaf {
+        type bz: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 "/br:interfaces/br:ifEntry/bz: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 br: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 bz:target {
+        augment "how/interval" {
+            description "inner augment";
+            leaf name {
+                type string;
+            }
+        }
+    }
+
+    container peer {
+        container destination {
+            uses bz:target {
+                refine address {
+                    default "1.2.3.4";
+                    description "IP address of target node";
+                    reference "address reference added by refine";
+                    config false;
+                    mandatory false;
+                    must "ifType != 'ethernet' or " +
+                            "(ifType = 'ethernet' and ifMTU = 1500)" {
+                        error-message "An ethernet MTU must be 1500";
+                    }
+                    foo:mountpoint "mnt-extension";
+                }
+                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 unbounded;
+                }
+                refine addresses/id {
+                    description "id of address";
+                }
+            }
+        }
+    }
+
+    extension mountpoint {
+        description "enter point";
+        argument "name" {
+            yin-element "true";
+        }
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/model/subfoo.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/model/subfoo.yang
new file mode 100644 (file)
index 0000000..e0008de
--- /dev/null
@@ -0,0 +1,70 @@
+submodule subfoo {
+    yang-version 1.1;
+
+    belongs-to foo {
+        prefix f;
+    }
+
+    import bar {
+        prefix "br";
+        revision-date 2013-07-03;
+    }
+
+    import baz {
+        prefix "bz";
+        revision-date 2013-02-27;
+    }
+
+    revision "2013-02-27" {
+    }
+
+    leaf id {
+        type br:int32-ext2 {
+            range "12..max";
+        }
+    }
+
+    leaf foo-id {
+        type f:identifier;
+    }
+
+    container sub-ext {
+        bz:c-define "MY_INTERFACES";
+    }
+
+    container sub-transfer {
+        choice how {
+            default interval;
+            container input {
+            }
+            list output {
+                leaf id {
+                    type string;
+                }
+            }
+            case manual {
+                leaf manual {
+                    type empty;
+                }
+            }
+        }
+    }
+
+    anyxml sub-datas {
+        status obsolete;
+    }
+
+    augment "/br:interfaces/br:ifEntry/bz:augment-holder" {
+        when "if:ifType='ds0'";
+        leaf subleaf {
+            type string;
+        }
+    }
+
+    extension sub-mountpoint {
+        argument "name" {
+            yin-element "true";
+        }
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/bar@2016-01-03.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/bar@2016-01-03.yang
new file mode 100644 (file)
index 0000000..207b4bd
--- /dev/null
@@ -0,0 +1,24 @@
+module bar {
+    namespace "bar";
+    prefix bar;
+    yang-version 1.1;
+
+    import semantic-version { prefix sv; sv:semantic-version "1.2.012"; }
+    import foobar { prefix foobar; sv:semantic-version "2.25.3"; }
+
+    revision "2016-01-03" {
+        description "Imported version";
+    }
+    sv:semantic-version "1.2.6";
+
+    container root {
+        container test-container {
+            uses foobar:test-grouping;
+        }
+    }
+
+    leaf-list should-present {
+        type string;
+        description "List of strings";
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/bar@2016-01-04.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/bar@2016-01-04.yang
new file mode 100644 (file)
index 0000000..8328cbe
--- /dev/null
@@ -0,0 +1,24 @@
+module bar {
+    namespace "bar";
+    prefix bar;
+    yang-version 1.1;
+
+    import semantic-version { prefix sv; sv:semantic-version "1.2.210"; }
+    import foobar { prefix foobar; sv:semantic-version "2.25.3"; }
+
+    revision "2016-01-04" {
+        description "Not-imported version";
+    }
+    sv:semantic-version "2.200.200";
+
+    container root {
+        container test-container {
+            uses foobar:test-grouping;
+        }
+    }
+
+    leaf-list should-not-be-present {
+        type uint32;
+        description "List of integers";
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/foo.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/foo.yang
new file mode 100644 (file)
index 0000000..e3828f0
--- /dev/null
@@ -0,0 +1,13 @@
+module foo {
+    namespace "foo";
+    prefix foo;
+    yang-version 1.1;
+
+    import semantic-version { prefix sv; sv:semantic-version "1.0.0"; }
+    import bar { prefix bar; sv:semantic-version "1.2.5"; }
+
+    revision "2016-02-01" {
+        description "Initial version";
+    }
+    sv:semantic-version "1.50.02";
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/foobar@2016-01-31.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/foobar@2016-01-31.yang
new file mode 100644 (file)
index 0000000..773bc65
--- /dev/null
@@ -0,0 +1,23 @@
+module foobar {
+    namespace "foobar";
+    prefix foobar;
+    yang-version 1.1;
+
+    import semantic-version { prefix sv; sv:semantic-version "1.2.95"; }
+
+    revision "2016-01-31" {
+        description "Not-imported version";
+    }
+    sv:semantic-version "2.25.2";
+
+    grouping test-grouping {
+        leaf name {
+            type string;
+            description "Name";
+        }
+        leaf oldnumber {
+            type uint8;
+            description "Old number";
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/foobar@2016-02-28.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/foobar@2016-02-28.yang
new file mode 100644 (file)
index 0000000..4c92e9f
--- /dev/null
@@ -0,0 +1,23 @@
+module foobar {
+    namespace "foobar";
+    prefix foobar;
+    yang-version 1.1;
+
+    import semantic-version { prefix sv; sv:semantic-version "1.3.95"; }
+
+    revision "2016-02-28" {
+        description "Imported version";
+    }
+    sv:semantic-version "2.26.465";
+
+    grouping test-grouping {
+        leaf name {
+            type string;
+            description "Name";
+        }
+        leaf number {
+            type uint32;
+            description "Number";
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/semantic-version.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-1/semantic-version.yang
new file mode 100644 (file)
index 0000000..14dc274
--- /dev/null
@@ -0,0 +1,47 @@
+module semantic-version {
+    namespace "urn:opendaylight:yang:extension:semantic-version";
+    prefix sv;
+    yang-version 1.1;
+
+    revision 2016-02-02 {
+        description "Initial verison";
+    }
+    sv:semantic-version "1.3.95";
+
+    extension semantic-version {
+        argument "semantic-version" {
+            yin-element false;
+        }
+        description
+            "The OpenConfig version number for the module. This is
+            expressed as a semantic version number of the form:
+              x.y.z
+            where:
+              * x corresponds to the major version,
+              * y corresponds to a minor version,
+              * z corresponds to a patch version.
+            This version corresponds to the model file within which it is
+            defined, and does not cover the whole set of OpenConfig models.
+            Where several modules are used to build up a single block of
+            functionality, the same module version is specified across each
+            file that makes up the module.
+
+            A major version number of 0 indicates that this model is still
+            in development (whether within OpenConfig or with industry
+            partners), and is potentially subject to change.
+
+            Following a release of major version 1, all modules will
+            increment major revision number where backwards incompatible
+            changes to the model are made.
+
+            The minor version is changed when features are added to the
+            model that do not impact current clients use of the model.
+
+            The patch-level version is incremented when non-feature changes
+            (such as bugfixes or clarifications to human-readable
+            descriptions that do not impact model functionality) are made
+            that maintain backwards compatibility.
+
+            The version number is stored in the module meta-data.";
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/bar@2016-01-03.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/bar@2016-01-03.yang
new file mode 100644 (file)
index 0000000..f11bdb0
--- /dev/null
@@ -0,0 +1,23 @@
+module bar {
+    namespace "bar";
+    prefix bar;
+    yang-version 1;
+
+    import semantic-version { prefix sv; sv:semantic-version "2.0.40"; }
+    import foobar { prefix foobar; sv:semantic-version "7.12.54"; }
+
+    revision "2016-01-03" {
+        description "Imported version";
+    }
+    sv:semantic-version "4.9.8";
+
+    augment "/foobar:root/foobar:test-container" {
+        leaf should-present-leaf-1 {
+            type string;
+        }
+        leaf should-present-leaf-2 {
+            type uint8;
+            default 0;
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/bar@2016-01-04.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/bar@2016-01-04.yang
new file mode 100644 (file)
index 0000000..712b379
--- /dev/null
@@ -0,0 +1,23 @@
+module bar {
+    namespace "bar";
+    prefix bar;
+    yang-version 1.1;
+
+    import semantic-version { prefix sv; sv:semantic-version "2.0.50"; }
+    import foobar { prefix foobar; sv:semantic-version "7.12.54"; }
+
+    revision "2016-01-04" {
+        description "Not-imported version";
+    }
+    sv:semantic-version "3.0.5";
+
+    augment "/foobar:root/foobar:test-container" {
+        leaf should-not-be-present-leaf-1 {
+            type string;
+        }
+        leaf should-not-be-present-leaf-2 {
+            type uint8;
+            default 0;
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foo.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foo.yang
new file mode 100644 (file)
index 0000000..3955eb5
--- /dev/null
@@ -0,0 +1,13 @@
+module foo {
+    namespace "foo";
+    prefix foo;
+    yang-version 1.1;
+
+    import semantic-version { prefix sv; sv:semantic-version "2.5.40"; }
+    import bar { prefix bar; sv:semantic-version "4.1.1"; }
+
+    revision "2016-02-01" {
+        description "Initial version";
+    }
+    sv:semantic-version "2.32.2";
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foobar@2016-01-31.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foobar@2016-01-31.yang
new file mode 100644 (file)
index 0000000..435bea6
--- /dev/null
@@ -0,0 +1,20 @@
+module foobar {
+    namespace "foobar";
+    prefix foobar;
+    yang-version 1;
+
+    import semantic-version { prefix sv; sv:semantic-version "2.1.950"; }
+
+    revision "2016-01-31" {
+        description "Not-imported version";
+    }
+    sv:semantic-version "8.0.0";
+
+    container root {
+        leaf included-not-correct-mark {
+            type empty;
+        }
+        container test-container {
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foobar@2016-02-27.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foobar@2016-02-27.yang
new file mode 100644 (file)
index 0000000..8b8f48e
--- /dev/null
@@ -0,0 +1,20 @@
+module foobar {
+    namespace "foobar";
+    prefix foobar;
+    yang-version 1;
+
+    import semantic-version { prefix sv; sv:semantic-version "2.5.50"; }
+
+    revision "2016-02-27" {
+        description "Not-imported version";
+    }
+    sv:semantic-version "7.13.0";
+
+    container root {
+        leaf included-not-correct-mark {
+            type empty;
+        }
+        container test-container {
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foobar@2016-02-28.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/foobar@2016-02-28.yang
new file mode 100644 (file)
index 0000000..c45a020
--- /dev/null
@@ -0,0 +1,20 @@
+module foobar {
+    namespace "foobar";
+    prefix foobar;
+    yang-version 1;
+
+    import semantic-version { prefix sv; sv:semantic-version "2.5.50"; }
+
+    revision "2016-02-28" {
+        description "Imported version";
+    }
+    sv:semantic-version "7.13.99";
+
+    container root {
+        leaf included-correct-mark {
+            type empty;
+        }
+        container test-container {
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/semantic-version.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/semantic-version/complex-2/semantic-version.yang
new file mode 100644 (file)
index 0000000..a7e5ba2
--- /dev/null
@@ -0,0 +1,47 @@
+module semantic-version {
+    namespace "urn:opendaylight:yang:extension:semantic-version";
+    prefix sv;
+    yang-version 1;
+
+    revision 2016-02-02 {
+        description "Initial verison";
+    }
+    sv:semantic-version "2.5.50";
+
+    extension semantic-version {
+        argument "semantic-version" {
+            yin-element false;
+        }
+        description
+            "The OpenConfig version number for the module. This is
+            expressed as a semantic version number of the form:
+              x.y.z
+            where:
+              * x corresponds to the major version,
+              * y corresponds to a minor version,
+              * z corresponds to a patch version.
+            This version corresponds to the model file within which it is
+            defined, and does not cover the whole set of OpenConfig models.
+            Where several modules are used to build up a single block of
+            functionality, the same module version is specified across each
+            file that makes up the module.
+
+            A major version number of 0 indicates that this model is still
+            in development (whether within OpenConfig or with industry
+            partners), and is potentially subject to change.
+
+            Following a release of major version 1, all modules will
+            increment major revision number where backwards incompatible
+            changes to the model are made.
+
+            The minor version is changed when features are added to the
+            model that do not impact current clients use of the model.
+
+            The patch-level version is incremented when non-feature changes
+            (such as bugfixes or clarifications to human-readable
+            descriptions that do not impact model functionality) are made
+            that maintain backwards compatibility.
+
+            The version number is stored in the module meta-data.";
+    }
+}