summaryrefslogtreecommitdiffstats
path: root/infra
diff options
context:
space:
mode:
Diffstat (limited to 'infra')
-rw-r--r--infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java2
-rw-r--r--infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModificationDiff.java34
-rw-r--r--infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModificationDiffTest.java32
-rw-r--r--infra/data-impl/src/test/resources/test-diff.yang4
4 files changed, 66 insertions, 6 deletions
diff --git a/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java b/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java
index 7af9847d7..7f8b53919 100644
--- a/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java
+++ b/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModifiableDataTreeDelegator.java
@@ -115,7 +115,7 @@ public final class ModifiableDataTreeDelegator extends ModifiableDataTreeManager
rootPath, rootNode, rootNode.getDataBefore(), rootNode.getDataAfter());
final ModificationDiff modificationDiff =
- ModificationDiff.recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, rootNode);
+ ModificationDiff.recursivelyFromCandidateRoot(rootNode);
LOG.debug("ConfigDataTree.modify() diff: {}", modificationDiff);
// Distinguish between updates (create + update) and deletes
diff --git a/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModificationDiff.java b/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModificationDiff.java
index 1c87bc03a..e78bb876b 100644
--- a/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModificationDiff.java
+++ b/infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModificationDiff.java
@@ -41,7 +41,8 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
final class ModificationDiff {
private static final ModificationDiff EMPTY_DIFF = new ModificationDiff(Collections.emptyMap());
- private static final EnumSet LEAF_MODIFICATIONS = EnumSet.of(ModificationType.WRITE, ModificationType.DELETE);
+ private static final EnumSet VALID_MODIFICATIONS = EnumSet.of(ModificationType.WRITE, ModificationType.DELETE);
+ private static final EnumSet IGNORED_MODIFICATIONS = EnumSet.of(ModificationType.APPEARED, ModificationType.DISAPPEARED);
private final Map<YangInstanceIdentifier, NormalizedNodeUpdate> updates;
@@ -98,12 +99,25 @@ final class ModificationDiff {
}
/**
+ * Same as {@link #recursivelyFromCandidate(YangInstanceIdentifier, DataTreeCandidateNode)} but does not process
+ * the root node for modifications, since it's the artificial data root, that has no child leaves but always is
+ * marked as SUBTREE_MODIFIED.
+ */
+ @Nonnull
+ static ModificationDiff recursivelyFromCandidateRoot(@Nonnull final DataTreeCandidateNode currentCandidate) {
+ return recursivelyChildrenFromCandidate(YangInstanceIdentifier.EMPTY, currentCandidate);
+ }
+
+ /**
* Check whether current node was modified. {@link MixinNode}s are ignored
* and only nodes which direct leaves(or choices) are modified are considered a modification.
*/
private static Boolean isModification(@Nonnull final DataTreeCandidateNode currentCandidate) {
+ // Disappear is not a modification
+ if (IGNORED_MODIFICATIONS.contains(currentCandidate.getModificationType())) {
+ return false;
// Mixin nodes are not considered modifications
- if (isMixin(currentCandidate) && !isAugment(currentCandidate)) {
+ } else if (isMixin(currentCandidate) && !isAugment(currentCandidate)) {
return false;
} else {
return isCurrentModified(currentCandidate);
@@ -111,13 +125,18 @@ final class ModificationDiff {
}
private static Boolean isCurrentModified(final @Nonnull DataTreeCandidateNode currentCandidate) {
+ // First check if it's an empty presence node
+ if (isEmptyPresenceNode(currentCandidate)) {
+ return true;
+ }
+
// Check if there are any modified leaves and if so, consider current node as modified
final Boolean directLeavesModified = currentCandidate.getChildNodes().stream()
.filter(ModificationDiff::isLeaf)
// For some reason, we get modifications on unmodified list keys
// and that messes up our modifications collection here, so we need to skip
.filter(ModificationDiff::isBeforeAndAfterDifferent)
- .filter(child -> LEAF_MODIFICATIONS.contains(child.getModificationType()))
+ .filter(child -> VALID_MODIFICATIONS.contains(child.getModificationType()))
.findFirst()
.isPresent();
@@ -133,6 +152,15 @@ final class ModificationDiff {
}
/**
+ * Check if new data are empty but still to be considered as a modification, meaning it's presence has a meaning
+ * e.g. containers with presence statement.
+ */
+ private static boolean isEmptyPresenceNode(final @Nonnull DataTreeCandidateNode currentCandidate) {
+ return currentCandidate.getChildNodes().isEmpty()
+ && VALID_MODIFICATIONS.contains(currentCandidate.getModificationType());
+ }
+
+ /**
* Process all non-leaf child nodes recursively, creating aggregated {@link ModificationDiff}.
*/
private static ModificationDiff recursivelyChildrenFromCandidate(final @Nonnull YangInstanceIdentifier yangIid,
diff --git a/infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModificationDiffTest.java b/infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModificationDiffTest.java
index 2fa82043b..cc00f2dc6 100644
--- a/infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModificationDiffTest.java
+++ b/infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModificationDiffTest.java
@@ -1,9 +1,12 @@
package io.fd.honeycomb.data.impl;
+import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import com.google.common.base.Optional;
import java.util.Map;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;
@@ -45,10 +48,11 @@ public class ModificationDiffTest {
static final QName IN_CASE1_LEAF_QNAME = QName.create(WITH_CHOICE_CONTAINER_QNAME, "in-case1");
static final QName IN_CASE2_LEAF_QNAME = QName.create(WITH_CHOICE_CONTAINER_QNAME, "in-case2");
+ static final QName PRESENCE_CONTAINER_QNAME = QName.create(TOP_CONTAINER_QNAME, "presence");
+
static final YangInstanceIdentifier TOP_CONTAINER_ID = YangInstanceIdentifier.of(TOP_CONTAINER_QNAME);
static final YangInstanceIdentifier NESTED_LIST_ID = TOP_CONTAINER_ID.node(new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME));
-
@Test
public void testInitialWrite() throws Exception {
final TipProducingDataTree dataTree = getDataTree();
@@ -66,6 +70,30 @@ public class ModificationDiffTest {
}
@Test
+ public void testWritePresenceEmptyContainer() throws Exception {
+ final TipProducingDataTree dataTree = getDataTree();
+ final DataTreeModification dataTreeModification = getModification(dataTree);
+ final NormalizedNode<?, ?> presenceContainer = Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(PRESENCE_CONTAINER_QNAME))
+ .build();
+ final YangInstanceIdentifier PRESENCE_CONTAINER_ID = YangInstanceIdentifier.of(PRESENCE_CONTAINER_QNAME);
+ dataTreeModification.write(PRESENCE_CONTAINER_ID, presenceContainer);
+ final DataTreeCandidateTip prepare = prepareModification(dataTree, dataTreeModification);
+
+ final ModificationDiff modificationDiff = getModificationDiff(prepare);
+
+ dataTree.commit(prepare);
+
+ final Optional<NormalizedNode<?, ?>> presenceAfter = getModification(dataTree).readNode(PRESENCE_CONTAINER_ID);
+ assertTrue(presenceAfter.isPresent());
+ assertThat(presenceAfter.get(), equalTo(presenceContainer));
+
+ assertThat(modificationDiff.getUpdates().size(), is(1));
+ assertThat(modificationDiff.getUpdates().values().size(), is(1));
+ assertUpdate(modificationDiff.getUpdates().values().iterator().next(), PRESENCE_CONTAINER_ID, null, presenceContainer);
+ }
+
+ @Test
public void testInitialWriteForContainerWithChoice() throws Exception {
final TipProducingDataTree dataTree = getDataTree();
final DataTreeModification dataTreeModification = getModification(dataTree);
@@ -132,7 +160,7 @@ public class ModificationDiffTest {
}
private ModificationDiff getModificationDiff(final DataTreeCandidateTip prepare) {
- return ModificationDiff.recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode());
+ return ModificationDiff.recursivelyFromCandidateRoot(prepare.getRootNode());
}
@Test
diff --git a/infra/data-impl/src/test/resources/test-diff.yang b/infra/data-impl/src/test/resources/test-diff.yang
index 5cccc8718..6c27ddc17 100644
--- a/infra/data-impl/src/test/resources/test-diff.yang
+++ b/infra/data-impl/src/test/resources/test-diff.yang
@@ -7,6 +7,10 @@ module test-diff {
description "Initial revision";
}
+ container presence {
+ presence "testing presence";
+ }
+
container top-container {
leaf string {
type string;