Bug 6183 - Shorthand case should create case node in schema tree 39/53139/11
authorPeter Kajsa <pkajsa@cisco.com>
Fri, 10 Mar 2017 13:10:56 +0000 (14:10 +0100)
committerRobert Varga <nite@hq.sk>
Mon, 27 Mar 2017 14:44:24 +0000 (14:44 +0000)
According to Rfc7950, if a case statement is omitted and implicit case
node is created, schema node identifiers MUST always explicitly include
the implicit case node identifiers.

This patch deals with both Yang 1.1 and Yang 1 in the same way.

Change-Id: I64fef2aee85855cb6300318f7c97e694b3105a0a
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
12 files changed:
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/AbstractStatementSupport.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupport.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/StatementContextBase.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextWriter.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementDefinitionContext.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/ChoiceStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ChoiceStatementRfc7950Support.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6183Test.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang10/foo.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang11/foo.yang [new file with mode: 0644]

index 02374622dd40c2b28918824679a5fc3fbc0970bd..4f5c6b3a412cf0a11b6a152f894a47d56804531a 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.parser.spi.meta;
 
 import com.google.common.base.Preconditions;
+import java.util.Optional;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -15,6 +16,9 @@ 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.parser.spi.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementDefinitionContext;
 
 /**
  *
@@ -68,6 +72,14 @@ public abstract class AbstractStatementSupport<A, D extends DeclaredStatement<A>
         return type;
     }
 
+    @Override
+    public Optional<StatementContextBase<?, ?, ?>> beforeSubStatementCreated(final StmtContext.Mutable<?, ?, ?> stmt,
+            final int offset, final StatementDefinitionContext<?, ?, ?> def, final StatementSourceReference ref,
+            final String argument) {
+        // NOOP for most implementations and also no implicit statements
+        return Optional.empty();
+    }
+
     @Override
     public void onStatementAdded(final StmtContext.Mutable<A, D, E> stmt) {
         // NOOP for most implementations
index d8555dea68da82d54624d4beef204e2f80b824ae..4ccffedb2c18a1ad7c1398e98bf065fcb675d78c 100644 (file)
@@ -8,10 +8,15 @@
 
 package org.opendaylight.yangtools.yang.parser.spi.meta;
 
+import java.util.Optional;
 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.parser.spi.meta.StmtContext.Mutable;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementDefinitionContext;
 
 /**
  *
@@ -69,6 +74,29 @@ public interface StatementSupport<A, D extends DeclaredStatement<A>, E extends E
      */
     void onStatementAdded(StmtContext.Mutable<A, D, E> stmt);
 
+    /**
+     * Invoked before a substatement with specified offset, definition,
+     * reference and argument is created and added to parent statement. This
+     * allows implementations of this interface perform any modifications to the
+     * build context hierarchy before a substatement is created. One such use is
+     * creating an implicit statement.
+     *
+     * @param stmt
+     *            Context of parent statement where a new substatement should be
+     *            created. No substatements are available.
+     * @param offset
+     *            substatement offset
+     * @param def
+     *            definition context
+     * @param ref
+     *            source reference
+     * @param argument
+     *            substatement argument
+     * @return optional of an implicit substatement
+     */
+    Optional<StatementContextBase<?, ?, ?>> beforeSubStatementCreated(final Mutable<?, ?, ?> stmt, final int offset,
+            final StatementDefinitionContext<?, ?, ?> def, final StatementSourceReference ref, final String argument);
+
     /**
      * Invoked when statement is closed during
      * {@link ModelProcessingPhase#SOURCE_PRE_LINKAGE} phase, only substatements
index 5c1fa6329c87aa8436bf697c53dd7697eb2e0432..cfbd93377cf5e4adecc7db49bf2b040031e07b83 100644 (file)
@@ -34,6 +34,7 @@ import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 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;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
@@ -130,7 +131,10 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
             QName name, final String argument, final StatementSourceReference ref) {
         if (current != null) {
             // Fast path: we are entering a statement which was emitted in previous phase
-            final StatementContextBase<?, ?, ?> existing = current.lookupSubstatement(childId);
+            StatementContextBase<?, ?, ?> existing = current.lookupSubstatement(childId);
+            while (existing != null && StatementSource.CONTEXT == existing.getStatementSource()) {
+                existing = existing.lookupSubstatement(childId);
+            }
             if (existing != null) {
                 return existing;
             }
index d478818e2abeeef3c9836bb9e31d60ed74512038..31c9333e560442318779726453759f9ad02906ca 100644 (file)
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.EnumMap;
 import java.util.EventListener;
 import java.util.Iterator;
+import java.util.Optional;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
@@ -356,13 +357,19 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
      * @param argument statement argument
      * @return A new substatement
      */
-    public final <CA, CD extends DeclaredStatement<CA>, CE extends EffectiveStatement<CA, CD>> StatementContextBase<CA, CD, CE>
-            createSubstatement(final int offset, final StatementDefinitionContext<CA, CD, CE> def,
-                    final StatementSourceReference ref, final String argument) {
+    public final <CA, CD extends DeclaredStatement<CA>, CE extends EffectiveStatement<CA, CD>> StatementContextBase<CA, CD, CE> createSubstatement(
+            final int offset, final StatementDefinitionContext<CA, CD, CE> def, final StatementSourceReference ref,
+            final String argument) {
         final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase();
         Preconditions.checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
                 "Declared statement cannot be added in effective phase at: %s", getStatementSourceReference());
 
+        final Optional<StatementContextBase<?, ?, ?>> implicitStatement = definition.beforeSubStatementCreated(this, offset, def, ref, argument);
+        if(implicitStatement.isPresent()) {
+            final StatementContextBase<?, ?, ?> presentImplicitStmt = implicitStatement.get();
+            return presentImplicitStmt.createSubstatement(offset, def, ref, argument);
+        }
+
         final StatementContextBase<CA, CD, CE> ret = new SubstatementContext<>(this, def, ref, argument);
         substatements = substatements.put(offset, ret);
         def.onStatementAdded(ret);
index 9b6bda04299aa19355d54b9c4df833525ede1544..1eddffd82789234e10857290c460726031d5ef36 100644 (file)
@@ -11,6 +11,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
@@ -36,7 +37,12 @@ final class StatementContextWriter implements StatementWriter {
     public void endStatement(@Nonnull final StatementSourceReference ref) {
         Preconditions.checkState(current != null);
         current.endDeclared(ref, phase);
-        current = current.getParentContext();
+        StatementContextBase<?, ?, ?> parentContext = current.getParentContext();
+        while (parentContext != null && StatementSource.CONTEXT == parentContext.getStatementSource()) {
+            parentContext.endDeclared(ref, phase);
+            parentContext = parentContext.getParentContext();
+        }
+        current = parentContext;
     }
 
     @Nonnull
index 08a97419b66fae2c766edf9862c28d6ce0f92698..c1a1d2581aab85209b5184e6c2ddf742c42c8e2b 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Preconditions;
+import java.util.Optional;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
@@ -20,6 +21,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StatementFactory;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
 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.spi.source.StatementSourceReference;
 
 public class StatementDefinitionContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> {
     private final StatementSupport<A, D, E> support;
@@ -44,6 +46,11 @@ public class StatementDefinitionContext<A, D extends DeclaredStatement<A>, E ext
         return support.getPublicView();
     }
 
+    public Optional<StatementContextBase<?, ?, ?>> beforeSubStatementCreated(final Mutable<?, ?, ?> stmt, final int offset, final StatementDefinitionContext<?, ?, ?> def, final StatementSourceReference ref,
+            final String argument) {
+        return support.beforeSubStatementCreated(stmt, offset, def, ref, argument);
+    }
+
     public boolean onStatementAdded(final Mutable<A, D, E> stmt) {
         support.onStatementAdded(stmt);
         return false;
index 24a45628f3944a9e2c87705b682cdb476aba189d..5a009523e788c049e3876675f4d34dc201c5f727 100644 (file)
@@ -141,7 +141,7 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
     public StatementContextBase<A, D, E> createCopy(final QNameModule newQNameModule,
             final StatementContextBase<?, ?, ?> newParent, final CopyType typeOfCopy) {
         Preconditions.checkState(getCompletedPhase() == ModelProcessingPhase.EFFECTIVE_MODEL,
-                "Attempted to copy statement {} which has completed phase {}", this, getCompletedPhase());
+                "Attempted to copy statement %s which has completed phase %s", this, getCompletedPhase());
 
         final SubstatementContext<A, D, E> copy = new SubstatementContext<>(this, newQNameModule, newParent, typeOfCopy);
 
index b45fc9238d49aad2f4a904ff98932a3095cb7365..5918274c6a041885d166871fed2c96e835283ab9 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
 
 import java.util.Collection;
+import java.util.Optional;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -26,8 +27,13 @@ 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.StatementSupport;
 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.spi.source.ImplicitSubstatement;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementDefinitionContext;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.ChoiceEffectiveStatementImpl;
 
 public class ChoiceStatementImpl extends AbstractDeclaredStatement<QName>
@@ -54,9 +60,9 @@ public class ChoiceStatementImpl extends AbstractDeclaredStatement<QName>
         super(context);
     }
 
-    public static class Definition
-            extends
+    public static class Definition extends
             AbstractStatementSupport<QName, ChoiceStatement, EffectiveStatement<QName, ChoiceStatement>> {
+        private static final StatementSupport<?, ?, ?> IMPLICIT_CASE = new CaseStatementImpl.Definition();
 
         public Definition() {
             super(YangStmtMapping.CHOICE);
@@ -68,13 +74,24 @@ public class ChoiceStatementImpl extends AbstractDeclaredStatement<QName>
         }
 
         @Override
-        public void onStatementAdded(final Mutable<QName, ChoiceStatement, EffectiveStatement<QName, ChoiceStatement>> stmt) {
+        public Optional<StatementContextBase<?, ?, ?>> beforeSubStatementCreated(
+                final StmtContext.Mutable<?, ?, ?> stmt, final int offset,
+                final StatementDefinitionContext<?, ?, ?> def, final StatementSourceReference ref, final String argument) {
+
+            if (YangValidationBundles.SUPPORTED_CASE_SHORTHANDS.contains(def.getPublicView())) {
+                return Optional.of(createImplicitCase((StatementContextBase<?, ?, ?>) stmt, offset, ref, argument));
+            }
+            return Optional.empty();
+        }
+
+        @Override
+        public void onStatementAdded(
+                final Mutable<QName, ChoiceStatement, EffectiveStatement<QName, ChoiceStatement>> stmt) {
             stmt.getParentContext().addToNs(ChildSchemaNodes.class, stmt.getStatementArgument(), stmt);
         }
 
         @Override
-        public ChoiceStatement createDeclared(
-                final StmtContext<QName, ChoiceStatement, ?> ctx) {
+        public ChoiceStatement createDeclared(final StmtContext<QName, ChoiceStatement, ?> ctx) {
             return new ChoiceStatementImpl(ctx);
         }
 
@@ -88,6 +105,17 @@ public class ChoiceStatementImpl extends AbstractDeclaredStatement<QName>
         protected SubstatementValidator getSubstatementValidator() {
             return SUBSTATEMENT_VALIDATOR;
         }
+
+        protected StatementSupport<?, ?, ?> implictCase() {
+            return IMPLICIT_CASE;
+        }
+
+        private StatementContextBase<?, ?, ?> createImplicitCase(final StmtContext.Mutable<?, ?, ?> stmt,
+                final int offset, final StatementSourceReference ref, final String argument) {
+            final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implictCase());
+            return ((StatementContextBase<?, ?, ?>) stmt).createSubstatement(offset, def, ImplicitSubstatement.of(ref),
+                    argument);
+        }
     }
 
     @Nonnull
index 23f830ed80aeabb0adae53db54ee826607ae7538..15e79b032861cc12956533d288f83f3c8dbd12ec 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc7950;
 import com.google.common.annotations.Beta;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.ChoiceStatementImpl;
 
 /**
@@ -36,6 +37,13 @@ public final class ChoiceStatementRfc7950Support extends ChoiceStatementImpl.Def
             .addOptional(YangStmtMapping.WHEN)
             .build();
 
+    private static final StatementSupport<?, ?, ?> IMPLICIT_CASE = new CaseStatementRfc7950Support();
+
+    @Override
+    protected StatementSupport<?, ?, ?> implictCase() {
+        return IMPLICIT_CASE;
+    }
+
     @Override
     protected SubstatementValidator getSubstatementValidator() {
         return SUBSTATEMENT_VALIDATOR;
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6183Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6183Test.java
new file mode 100644 (file)
index 0000000..c1b0c31
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017 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.stmt;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class Bug6183Test {
+    private static final String FOO_NS = "foo";
+    private static final String FOO_REV = "1970-01-01";
+
+    @Test
+    public void testYang10() throws Exception {
+        assertSchemaContext(StmtTestUtils.parseYangSources("/bugs/bug6183/yang10"));
+    }
+
+    @Test
+    public void testYang11() throws Exception {
+        assertSchemaContext(StmtTestUtils.parseYangSources("/bugs/bug6183/yang11"));
+    }
+
+    public void assertSchemaContext(final SchemaContext context) throws Exception {
+        assertNotNull(context);
+        assertEquals(3, context.getChildNodes().size());
+        assertEquals(1, context.getModules().size());
+        assertEquals(4, context.getModules().iterator().next().getAugmentations().size());
+
+        assertTrue(context.getDataChildByName(foo("before")) instanceof ContainerSchemaNode);
+        assertTrue(context.getDataChildByName(foo("after")) instanceof ContainerSchemaNode);
+
+        final DataSchemaNode dataChildByName = context.getDataChildByName(foo("my-choice"));
+        assertTrue(dataChildByName instanceof ChoiceSchemaNode);
+        final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) dataChildByName;
+
+        assertEquals(4, myChoice.getCases().size());
+
+        final ChoiceCaseNode implCase = myChoice.getCaseNodeByName(foo("implicit-case-container"));
+        assertNotNull(implCase);
+        final ChoiceCaseNode declCaseOne = myChoice.getCaseNodeByName(foo("declared-case-one"));
+        assertNotNull(declCaseOne);
+        final ChoiceCaseNode secondImplCase = myChoice.getCaseNodeByName(foo("second-implicit-case-container"));
+        assertNotNull(secondImplCase);
+        final ChoiceCaseNode declCaseTwo = myChoice.getCaseNodeByName(foo("declared-case-two"));
+        assertNotNull(declCaseTwo);
+
+        assertEquals(1, declCaseOne.getChildNodes().size());
+        assertFalse(getLeafSchemaNode(declCaseOne, "leaf-in-declare-case-one").isAugmenting());
+        assertEquals(1, declCaseTwo.getChildNodes().size());
+        assertFalse(getLeafSchemaNode(declCaseTwo, "leaf-in-declare-case-two").isAugmenting());
+
+        assertEquals(2, implCase.getChildNodes().size());
+        assertTrue(getLeafSchemaNode(implCase, "leaf-after-container").isAugmenting());
+        final ContainerSchemaNode implCaseContainer = getContainerSchemaNode(implCase, "implicit-case-container");
+
+        assertEquals(3, implCaseContainer.getChildNodes().size());
+        assertTrue(getLeafSchemaNode(implCaseContainer, "leaf-inside-container").isAugmenting());
+        assertFalse(getLeafSchemaNode(implCaseContainer, "declared-leaf-in-case-container").isAugmenting());
+        final ContainerSchemaNode declContInCaseCont = getContainerSchemaNode(implCaseContainer,
+                "declared-container-in-case-container");
+
+        assertEquals(1, declContInCaseCont.getChildNodes().size());
+        assertFalse(getLeafSchemaNode(declContInCaseCont, "declared-leaf").isAugmenting());
+
+        assertEquals(2, secondImplCase.getChildNodes().size());
+        assertTrue(getLeafSchemaNode(secondImplCase, "leaf-after-second-container").isAugmenting());
+        final ContainerSchemaNode secondImplCaseContainer = getContainerSchemaNode(secondImplCase,
+                "second-implicit-case-container");
+
+        assertEquals(2, secondImplCaseContainer.getChildNodes().size());
+        assertTrue(getLeafSchemaNode(secondImplCaseContainer, "leaf-inside-second-container").isAugmenting());
+        assertFalse(getLeafSchemaNode(secondImplCaseContainer, "declared-leaf-in-second-case-container").isAugmenting());
+    }
+
+    private static ContainerSchemaNode getContainerSchemaNode(final DataNodeContainer parent, final String containerName) {
+        final DataSchemaNode dataChildByName = parent.getDataChildByName(foo(containerName));
+        assertTrue(dataChildByName instanceof ContainerSchemaNode);
+        return (ContainerSchemaNode) dataChildByName;
+    }
+
+    private static LeafSchemaNode getLeafSchemaNode(final DataNodeContainer parent, final String leafName) {
+        final DataSchemaNode dataChildByName = parent.getDataChildByName(foo(leafName));
+        assertTrue(dataChildByName instanceof LeafSchemaNode);
+        return (LeafSchemaNode) dataChildByName;
+    }
+
+    private static QName foo(final String localName) {
+        return QName.create(FOO_NS, FOO_REV, localName);
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang10/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang10/foo.yang
new file mode 100644 (file)
index 0000000..1b1961b
--- /dev/null
@@ -0,0 +1,62 @@
+module foo {
+    namespace "foo";
+    prefix "foo";
+
+    container before {
+    }
+
+    choice my-choice {
+        container implicit-case-container {
+            container declared-container-in-case-container {
+                leaf declared-leaf {
+                    type empty;
+                }
+            }
+            leaf declared-leaf-in-case-container {
+                type empty;
+            }
+        }
+        case declared-case-one {
+            leaf leaf-in-declare-case-one {
+                type empty;
+            }
+        }
+        container second-implicit-case-container {
+            leaf declared-leaf-in-second-case-container {
+                type empty;
+            }
+        }
+        case declared-case-two {
+            leaf leaf-in-declare-case-two {
+                type empty;
+            }
+        }
+    }
+
+    container after {
+    }
+
+    augment "/my-choice/implicit-case-container" {
+        leaf leaf-after-container {
+            type empty;
+        }
+    }
+
+    augment "/my-choice/implicit-case-container/implicit-case-container" {
+        leaf leaf-inside-container {
+            type empty;
+        }
+    }
+
+    augment "/my-choice/second-implicit-case-container" {
+        leaf leaf-after-second-container {
+            type empty;
+        }
+    }
+
+    augment "/my-choice/second-implicit-case-container/second-implicit-case-container" {
+        leaf leaf-inside-second-container {
+            type empty;
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang11/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang11/foo.yang
new file mode 100644 (file)
index 0000000..f1aa472
--- /dev/null
@@ -0,0 +1,63 @@
+module foo {
+    namespace "foo";
+    prefix "foo";
+    yang-version 1.1;
+
+    container before {
+    }
+
+    choice my-choice {
+        container implicit-case-container {
+            container declared-container-in-case-container {
+                leaf declared-leaf {
+                    type empty;
+                }
+            }
+            leaf declared-leaf-in-case-container {
+                type empty;
+            }
+        }
+        case declared-case-one {
+            leaf leaf-in-declare-case-one {
+                type empty;
+            }
+        }
+        container second-implicit-case-container {
+            leaf declared-leaf-in-second-case-container {
+                type empty;
+            }
+        }
+        case declared-case-two {
+            leaf leaf-in-declare-case-two {
+                type empty;
+            }
+        }
+    }
+
+    container after {
+    }
+
+    augment "/my-choice/implicit-case-container" {
+        leaf leaf-after-container {
+            type empty;
+        }
+    }
+
+    augment "/my-choice/implicit-case-container/implicit-case-container" {
+        leaf leaf-inside-container {
+            type empty;
+        }
+    }
+
+    augment "/my-choice/second-implicit-case-container" {
+        leaf leaf-after-second-container {
+            type empty;
+        }
+    }
+
+    augment "/my-choice/second-implicit-case-container/second-implicit-case-container" {
+        leaf leaf-inside-second-container {
+            type empty;
+        }
+    }
+}