From: Robert Varga Date: Wed, 30 Jan 2019 15:39:35 +0000 (+0100) Subject: Fix automatic lifecycle delete stacking X-Git-Tag: v2.0.17~38 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F28%2F80028%2F1;hp=8968f26659e4bffeb354f6940575f466f459cf65;p=yangtools.git Fix automatic lifecycle delete stacking Nodes with automatic lifecycle have the strange property that their delete operations may actually stack with other operations. Unfortunately delete operation itself has no semantics of having underlying modifications, as it has no baseline to which to apply them. In order to fix this, we need to turn deletes into empty writes for these constructs and once we are performing disappearing, undo this trick. This effectively means that both empty writes and deletes result in a delete operation, if they ended up modifying the tree, or into a no-op if they did not. JIRA: YANGTOOLS-938 Change-Id: I68b9f304e76d6b1bdb707f411a87cd6085ed8bc7 Signed-off-by: Robert Varga --- diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractNodeContainerModificationStrategy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractNodeContainerModificationStrategy.java index 5ea52b1686..b0b6cecba8 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractNodeContainerModificationStrategy.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractNodeContainerModificationStrategy.java @@ -78,9 +78,8 @@ abstract class AbstractNodeContainerModificationStrategy extends SchemaAwareAppl } @Override - protected TreeNode applyWrite(final ModifiedNode modification, + protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue, final Optional currentMeta, final Version version) { - final NormalizedNode newValue = modification.getWrittenValue(); final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version); if (modification.getChildren().isEmpty()) { diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractValueNodeModificationStrategy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractValueNodeModificationStrategy.java index 2cd8bbdac3..ff50d991af 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractValueNodeModificationStrategy.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractValueNodeModificationStrategy.java @@ -57,15 +57,16 @@ abstract class AbstractValueNodeModificationStrategy e protected final TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta, final Version version) { // Just overwrite whatever was there, but be sure to run validation - verifyStructure(modification.getWrittenValue(), true); + final NormalizedNode newValue = modification.getWrittenValue(); + verifyStructure(newValue, true); modification.resolveModificationType(ModificationType.WRITE); - return applyWrite(modification, null, version); + return applyWrite(modification, newValue, null, version); } @Override - protected final TreeNode applyWrite(final ModifiedNode modification, + protected final TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue, final Optional currentMeta, final Version version) { - return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), version); + return TreeNodeFactory.createTreeNode(newValue, version); } @Override diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ChoiceModificationStrategy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ChoiceModificationStrategy.java index ddf81930e1..568bf4c0dc 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ChoiceModificationStrategy.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ChoiceModificationStrategy.java @@ -131,9 +131,9 @@ final class ChoiceModificationStrategy extends AbstractNodeContainerModification } @Override - protected TreeNode applyWrite(final ModifiedNode modification, final Optional currentMeta, - final Version version) { - final TreeNode ret = super.applyWrite(modification, currentMeta, version); + protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue, + final Optional currentMeta, final Version version) { + final TreeNode ret = super.applyWrite(modification, newValue, currentMeta, version); enforceCases(ret); return ret; } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ListEntryModificationStrategy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ListEntryModificationStrategy.java index d64442ba57..9b44410f08 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ListEntryModificationStrategy.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ListEntryModificationStrategy.java @@ -43,9 +43,9 @@ final class ListEntryModificationStrategy extends AbstractDataNodeContainerModif } @Override - protected TreeNode applyWrite(final ModifiedNode modification, final Optional currentMeta, - final Version version) { - final TreeNode ret = super.applyWrite(modification, currentMeta, version); + protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue, + final Optional currentMeta, final Version version) { + final TreeNode ret = super.applyWrite(modification, newValue, currentMeta, version); enforcer.enforceOnTreeNode(ret); return ret; } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MinMaxElementsValidation.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MinMaxElementsValidation.java index 92f96c9e76..02335ff676 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MinMaxElementsValidation.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MinMaxElementsValidation.java @@ -166,15 +166,15 @@ final class MinMaxElementsValidation extends SchemaAwareApplyOperation { } @Override - protected TreeNode applyWrite(final ModifiedNode modification, final Optional currentMeta, - final Version version) { + protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue, + final Optional currentMeta, final Version version) { final TreeNode validated = modification.getValidatedNode(this, currentMeta); if (validated != null) { return validated; } // FIXME: the result moved, make sure we enforce again - return delegate.applyWrite(modification, currentMeta, version); + return delegate.applyWrite(modification, newValue, currentMeta, version); } @Override diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java index 9e163f538a..699a785bd8 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java @@ -7,6 +7,7 @@ */ package org.opendaylight.yangtools.yang.data.impl.schema.tree; +import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; import java.util.Collection; @@ -101,8 +102,9 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode getWrittenValue() { - return value; + return verifyNotNull(value); } /** diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/PresenceContainerModificationStrategy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/PresenceContainerModificationStrategy.java index 578c50de24..5be8745cad 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/PresenceContainerModificationStrategy.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/PresenceContainerModificationStrategy.java @@ -44,9 +44,9 @@ final class PresenceContainerModificationStrategy extends ContainerModificationS } @Override - protected TreeNode applyWrite(final ModifiedNode modification, final Optional currentMeta, - final Version version) { - final TreeNode ret = super.applyWrite(modification, currentMeta, version); + protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue, + final Optional currentMeta, final Version version) { + final TreeNode ret = super.applyWrite(modification, newValue, currentMeta, version); enforcer.enforceOnTreeNode(ret); return ret; } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java index 03654a6197..d50ad5a7c6 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java @@ -13,6 +13,7 @@ import java.util.Optional; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; @@ -217,7 +218,7 @@ abstract class SchemaAwareApplyOperation extends ModificationApplyOperation { // structure is usually verified when the transaction is sealed. To preserve correctness, we have // to run that validation here. modification.resolveModificationType(ModificationType.WRITE); - result = applyWrite(modification, currentMeta, version); + result = applyWrite(modification, modification.getWrittenValue(), currentMeta, version); verifyStructure(result.getData(), true); } else { result = applyMerge(modification, currentMeta.get(), version); @@ -226,7 +227,8 @@ abstract class SchemaAwareApplyOperation extends ModificationApplyOperation { return modification.setSnapshot(Optional.of(result)); case WRITE: modification.resolveModificationType(ModificationType.WRITE); - return modification.setSnapshot(Optional.of(applyWrite(modification, currentMeta, version))); + return modification.setSnapshot(Optional.of(applyWrite(modification, modification.getWrittenValue(), + currentMeta, version))); case NONE: modification.resolveModificationType(ModificationType.UNMODIFIED); return currentMeta; @@ -247,7 +249,8 @@ abstract class SchemaAwareApplyOperation extends ModificationApplyOperation { */ protected abstract TreeNode applyMerge(ModifiedNode modification, TreeNode currentMeta, Version version); - protected abstract TreeNode applyWrite(ModifiedNode modification, Optional currentMeta, Version version); + protected abstract TreeNode applyWrite(ModifiedNode modification, NormalizedNode newValue, + Optional currentMeta, Version version); /** * Apply a nested operation. Since there may not actually be a nested operation diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StructuralContainerModificationStrategy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StructuralContainerModificationStrategy.java index 877f994faf..d5df4716f6 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StructuralContainerModificationStrategy.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StructuralContainerModificationStrategy.java @@ -12,6 +12,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; @@ -54,42 +55,24 @@ final class StructuralContainerModificationStrategy extends ModificationApplyOpe @Override Optional apply(final ModifiedNode modification, final Optional storeMeta, final Version version) { - final Optional ret; - if (modification.getOperation() == LogicalOperation.TOUCH && !storeMeta.isPresent()) { - // Container is not present, let's take care of the 'magically appear' part of our job - ret = delegate.apply(modification, fakeMeta(version), version); - - // Fake container got removed: that is a no-op - if (!ret.isPresent()) { - modification.resolveModificationType(ModificationType.UNMODIFIED); - return ret; - } - - // If the delegate indicated SUBTREE_MODIFIED, account for the fake and report APPEARED - if (modification.getModificationType() == ModificationType.SUBTREE_MODIFIED) { - modification.resolveModificationType(ModificationType.APPEARED); + // The only way a tree node can disappear is through delete (which we handle here explicitly) or through + // actions of disappearResult(). It is therefore safe to perform Optional.get() on the results of + // delegate.apply() + final TreeNode ret; + if (modification.getOperation() == LogicalOperation.DELETE) { + if (modification.getChildren().isEmpty()) { + return delegate.apply(modification, storeMeta, version); } + // Delete with children, implies it really is an empty write + ret = delegate.applyWrite(modification, emptyNode, storeMeta, version); + } else if (modification.getOperation() == LogicalOperation.TOUCH && !storeMeta.isPresent()) { + ret = applyTouch(modification, storeMeta, version); } else { - // Container is present, run normal apply operation - ret = delegate.apply(modification, storeMeta, version); - - // Container was explicitly deleted, no magic required - if (!ret.isPresent()) { - return ret; - } - } - - /* - * At this point ret is guaranteed to be present. We need to take care of the 'magically disappear' part of - * our job. Check if there are any child nodes left. If there are none, remove this container and turn the - * modification into a DISAPPEARED. - */ - if (((NormalizedNodeContainer) ret.get().getData()).getValue().isEmpty()) { - modification.resolveModificationType(ModificationType.DISAPPEARED); - return Optional.empty(); + // No special handling required here, run normal apply operation + ret = delegate.apply(modification, storeMeta, version).get(); } - return ret; + return disappearResult(modification, ret, storeMeta); } @Override @@ -128,4 +111,50 @@ final class StructuralContainerModificationStrategy extends ModificationApplyOpe public Optional getChild(final PathArgument child) { return delegate.getChild(child); } + + private TreeNode applyTouch(final ModifiedNode modification, final Optional storeMeta, + final Version version) { + // Container is not present, let's take care of the 'magically appear' part of our job + final Optional ret = delegate.apply(modification, fakeMeta(version), version); + + // If the delegate indicated SUBTREE_MODIFIED, account for the fake and report APPEARED + if (modification.getModificationType() == ModificationType.SUBTREE_MODIFIED) { + modification.resolveModificationType(ModificationType.APPEARED); + } + return ret.get(); + } + + private static Optional disappearResult(final ModifiedNode modification, final TreeNode result, + final Optional storeMeta) { + // Check if the result is in fact empty before pulling any tricks + if (!isEmpty(result)) { + return Optional.of(result); + } + + // We are pulling the 'disappear' trick, but what we report can be three different things + final ModificationType finalType; + if (!storeMeta.isPresent()) { + // ... there was nothing in the datastore, no change + finalType = ModificationType.UNMODIFIED; + } else if (modification.getModificationType() == ModificationType.WRITE) { + // ... this was an empty write, possibly originally a delete + finalType = ModificationType.DELETE; + } else { + // ... it really disappeared + finalType = ModificationType.DISAPPEARED; + } + modification.resolveModificationType(finalType); + return Optional.empty(); + } + + private static boolean isEmpty(final TreeNode treeNode) { + final NormalizedNode data = treeNode.getData(); + if (data instanceof NormalizedNodeContainer) { + return ((NormalizedNodeContainer) data).getValue().isEmpty(); + } + if (data instanceof OrderedNodeContainer) { + return ((OrderedNodeContainer) data).getSize() == 0; + } + throw new IllegalStateException("Unhandled data " + data); + } } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListModificationStrategy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListModificationStrategy.java index 076f9df776..646222cf1b 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListModificationStrategy.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListModificationStrategy.java @@ -48,9 +48,8 @@ final class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation { } @Override - protected TreeNode applyWrite(final ModifiedNode modification, + protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue, final Optional currentMeta, final Version version) { - final NormalizedNode newValue = modification.getWrittenValue(); final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version); if (modification.getChildren().isEmpty()) { diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/Bug2690Test.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/Bug2690Test.java index fd19f5bdae..518f6eb641 100644 --- a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/Bug2690Test.java +++ b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/Bug2690Test.java @@ -14,6 +14,7 @@ import java.util.Optional; import org.junit.Before; import org.junit.Test; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; @@ -30,6 +31,9 @@ import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; public class Bug2690Test { + private static final YangInstanceIdentifier NAME_PATH = YangInstanceIdentifier.of(TestModel.NON_PRESENCE_QNAME) + .node(TestModel.NAME_QNAME); + private DataTree inMemoryDataTree; @Before @@ -43,28 +47,24 @@ public class Bug2690Test { final MapEntryNode fooEntryNode = ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1); final MapEntryNode barEntryNode = ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 2); final MapNode mapNode1 = ImmutableNodes.mapNodeBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.OUTER_LIST_QNAME)) + .withNodeIdentifier(new NodeIdentifier(TestModel.OUTER_LIST_QNAME)) .withChild(fooEntryNode).build(); final MapNode mapNode2 = ImmutableNodes.mapNodeBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.OUTER_LIST_QNAME)) + .withNodeIdentifier(new NodeIdentifier(TestModel.OUTER_LIST_QNAME)) .withChild(barEntryNode).build(); final ContainerNode cont1 = Builders.containerBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME)) + .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME)) .withChild(mapNode1).build(); final ContainerNode cont2 = Builders.containerBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME)) + .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME)) .withChild(mapNode2).build(); final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification(); modificationTree.write(TestModel.TEST_PATH, cont1); modificationTree.merge(TestModel.TEST_PATH, cont2); - modificationTree.ready(); - - inMemoryDataTree.validate(modificationTree); - final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree); - inMemoryDataTree.commit(prepare); + commit(modificationTree); final DataTreeSnapshot snapshotAfterTx = inMemoryDataTree.takeSnapshot(); final DataTreeModification modificationAfterTx = snapshotAfterTx.newModification(); @@ -72,4 +72,38 @@ public class Bug2690Test { assertTrue(readNode.isPresent()); assertEquals(2, ((NormalizedNodeContainer)readNode.get()).getValue().size()); } + + @Test + public void testDeleteStructuralAndWriteChild() throws DataValidationFailedException { + final DataTreeModification modificationTree = setupTestDeleteStructuralAndWriteChild(); + verifyTestDeleteStructuralAndWriteChild(modificationTree); + } + + @Test + public void testDeleteStructuralAndWriteChildWithCommit() throws DataValidationFailedException { + final DataTreeModification modificationTree = setupTestDeleteStructuralAndWriteChild(); + commit(modificationTree); + verifyTestDeleteStructuralAndWriteChild(inMemoryDataTree.takeSnapshot()); + } + + private DataTreeModification setupTestDeleteStructuralAndWriteChild() { + final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification(); + modificationTree.delete(YangInstanceIdentifier.of(TestModel.NON_PRESENCE_QNAME)); + modificationTree.write(NAME_PATH, Builders.leafBuilder() + .withNodeIdentifier(new NodeIdentifier(TestModel.NAME_QNAME)).withValue("abc").build()); + return modificationTree; + } + + private static void verifyTestDeleteStructuralAndWriteChild(final DataTreeSnapshot snapshot) { + final Optional> readNode = snapshot.readNode(NAME_PATH); + assertTrue(readNode.isPresent()); + } + + private void commit(final DataTreeModification modificationTree) throws DataValidationFailedException { + modificationTree.ready(); + + inMemoryDataTree.validate(modificationTree); + final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree); + inMemoryDataTree.commit(prepare); + } } diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TestModel.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TestModel.java index 664d7d6561..f98d9d2bb0 100644 --- a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TestModel.java +++ b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TestModel.java @@ -25,6 +25,11 @@ public final class TestModel { public static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value"); private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang"; + public static final QName NON_PRESENCE_QNAME = QName.create(TEST_QNAME, "non-presence"); + public static final QName DEEP_CHOICE_QNAME = QName.create(TEST_QNAME, "deep-choice"); + public static final QName A_LIST_QNAME = QName.create(TEST_QNAME, "a-list"); + public static final QName A_NAME_QNAME = QName.create(TEST_QNAME, "a-name"); + public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME); public static final YangInstanceIdentifier OUTER_LIST_PATH = YangInstanceIdentifier.builder(TEST_PATH) .node(OUTER_LIST_QNAME).build(); diff --git a/yang/yang-data-impl/src/test/resources/odl-datastore-test.yang b/yang/yang-data-impl/src/test/resources/odl-datastore-test.yang index 7241758eaa..43143f20cb 100644 --- a/yang/yang-data-impl/src/test/resources/odl-datastore-test.yang +++ b/yang/yang-data-impl/src/test/resources/odl-datastore-test.yang @@ -7,6 +7,30 @@ module odl-datastore-test { description "Initial revision."; } + container non-presence { + description "Deep structure of (structural) nodes to test structural "; + + leaf name { + type string; + } + + choice deep-choice { + list a-list { + key "a-name"; + + leaf a-name { + type string; + } + } + + container b-container { + leaf b-name { + type string; + } + } + } + } + container test { presence true; choice choice1 {