From a10f89d551d5592577b8b573d571a9b0cf3f3ae2 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Thu, 19 Mar 2015 12:23:57 +0100 Subject: [PATCH] BUG-2383: deprecate ModificationType.MERGE The entire ModificationType enum is an accidental leak from the implementation. The most pressing deficiency is that we do not want to leak the merge operation, but report it either as a subtree modification or a write. Introduce a new type, LogicalOperation, which contains all the current and use it internally. The new name also implies slight changes in how the states are called: ModificationType.UNMODIFIED maps to LogicalOperation.NONE ModificationType.SUBTREE_MODIFIED maps to LogicalOperation.TOUCH Change-Id: I446e4391583de060b2ab722deb5c004f60c8e6e7 Signed-off-by: Robert Varga --- .../api/schema/tree/ModificationType.java | 5 ++ .../impl/schema/tree/InMemoryDataTree.java | 3 +- .../tree/InMemoryDataTreeCandidate.java | 38 +++++++++++- .../tree/InMemoryDataTreeModification.java | 5 +- .../impl/schema/tree/LogicalOperation.java | 49 +++++++++++++++ .../data/impl/schema/tree/ModifiedNode.java | 61 ++++++++----------- .../impl/schema/tree/NodeModification.java | 6 +- .../schema/tree/NoopDataTreeCandidate.java | 2 +- .../tree/SchemaAwareApplyOperation.java | 17 +++--- 9 files changed, 131 insertions(+), 55 deletions(-) create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/LogicalOperation.java diff --git a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/ModificationType.java b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/ModificationType.java index 047d71e481..3c2c299fff 100644 --- a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/ModificationType.java +++ b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/ModificationType.java @@ -40,6 +40,11 @@ public enum ModificationType { * contents, it has been merged. This means that any incoming nodes which * were present in the tree have been replaced, but their child nodes have * been retained. + * + * @deprecated This value is never reported. Whenever it would be reported, based + * on the actual effects, either {@link #WRITE} or {@link #SUBTREE_MODIFIED} + * is reported. */ + @Deprecated MERGE, } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTree.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTree.java index 215de62490..0f680fddad 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTree.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTree.java @@ -19,7 +19,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; -import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.slf4j.Logger; @@ -85,7 +84,7 @@ final class InMemoryDataTree implements DataTree { final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification; final ModifiedNode root = m.getRootModification(); - if (root.getType() == ModificationType.UNMODIFIED) { + if (root.getOperation() == LogicalOperation.NONE) { return new NoopDataTreeCandidate(PUBLIC_ROOT_PATH, root); } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeCandidate.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeCandidate.java index f6c5081bb6..f6bb6ba2aa 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeCandidate.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeCandidate.java @@ -15,6 +15,10 @@ import java.util.Collection; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; 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.NormalizedNodeContainer; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; +import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode; import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode; @@ -69,7 +73,39 @@ final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate { @Override public ModificationType getModificationType() { - return mod.getType(); + switch (mod.getOperation()) { + case DELETE: + return ModificationType.DELETE; + case MERGE: + // Merge into non-existing data is a write + if (oldMeta == null) { + return ModificationType.WRITE; + } + + // Data-based checks to narrow down types + final NormalizedNode data = newMeta.getData(); + + // leaf or anyxml are always written + if (!(data instanceof NormalizedNodeContainer)) { + return ModificationType.WRITE; + } + + // Unkeyed collections are always written + if (data instanceof UnkeyedListNode || data instanceof OrderedMapNode || data instanceof OrderedLeafSetNode) { + return ModificationType.WRITE; + } + + // Everything else is subtree modified + return ModificationType.SUBTREE_MODIFIED; + case TOUCH: + return ModificationType.SUBTREE_MODIFIED; + case NONE: + return ModificationType.UNMODIFIED; + case WRITE: + return ModificationType.WRITE; + } + + throw new IllegalStateException("Unhandled internal operation " + mod.getOperation()); } private Optional> optionalData(final TreeNode meta) { diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java index 0b0c8516d8..eb6b9726be 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java @@ -16,7 +16,6 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; -import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; import org.opendaylight.yangtools.yang.data.api.schema.tree.StoreTreeNodes; import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode; import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version; @@ -118,7 +117,7 @@ final class InMemoryDataTreeModification implements DataTreeModification { private ModificationApplyOperation resolveModificationStrategy(final YangInstanceIdentifier path) { LOG.trace("Resolving modification apply strategy for {}", path); - if (rootNode.getType() == ModificationType.UNMODIFIED) { + if (rootNode.getOperation() == LogicalOperation.NONE) { strategyTree.upgradeIfPossible(); } @@ -164,7 +163,7 @@ final class InMemoryDataTreeModification implements DataTreeModification { public DataTreeModification newModification() { Preconditions.checkState(sealed == 1, "Attempted to chain on an unsealed modification"); - if (rootNode.getType() == ModificationType.UNMODIFIED) { + if (rootNode.getOperation() == LogicalOperation.NONE) { // Simple fast case: just use the underlying modification return snapshot.newModification(); } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/LogicalOperation.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/LogicalOperation.java new file mode 100644 index 0000000000..bdaa954a49 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/LogicalOperation.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 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.data.impl.schema.tree; + +import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; + +/** + * Enumeration of all possible node modification states. These are used in + * data tree modification context to quickly assess what sort of modification + * the node is undergoing. This is a superset of {@link ModificationType}: + * where this type represents a logical operation, {@link ModificationType} + * represents a physical operation. + */ +enum LogicalOperation { + /** + * Node is currently unmodified. + */ + NONE, + + /** + * A child node, either direct or indirect, has been modified. This means + * that the data representation of this node has potentially changed. + */ + TOUCH, + + /** + * This node has been placed into the tree, potentially completely replacing + * pre-existing contents. + */ + WRITE, + + /** + * This node has been deleted along with any of its child nodes. + */ + DELETE, + + /** + * Node has been written into the tree, but instead of replacing pre-existing + * contents, it has been merged. This means that any incoming nodes which + * were present in the tree have been replaced, but their child nodes have + * been retained. + */ + MERGE, +} 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 448828bd9a..053e21ff26 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 @@ -38,24 +38,24 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode children; private final Optional original; private final PathArgument identifier; - private ModificationType modificationType = ModificationType.UNMODIFIED; + private LogicalOperation operation = LogicalOperation.NONE; private Optional snapshotCache; private NormalizedNode value; @@ -84,24 +84,15 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode getOriginal() { return original; } - /** - * Returns modification type - * - * @return modification type - */ + @Override - ModificationType getType() { - return modificationType; + LogicalOperation getOperation() { + return operation; } /** @@ -131,8 +122,8 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode value) { clearSnapshot(); - updateModificationType(ModificationType.WRITE); + updateModificationType(LogicalOperation.WRITE); children.clear(); this.value = value; } void merge(final NormalizedNode value) { clearSnapshot(); - updateModificationType(ModificationType.MERGE); + updateModificationType(LogicalOperation.MERGE); /* * Blind overwrite of any previous data is okay, no matter whether the node @@ -245,14 +236,14 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode { /** * Get the type of modification. * - * @return Modification type. + * @return Operation type. */ - abstract ModificationType getType(); + abstract LogicalOperation getOperation(); /** * Get the original tree node to which the modification is to be applied. diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/NoopDataTreeCandidate.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/NoopDataTreeCandidate.java index 7a91e232d8..979e79c1c7 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/NoopDataTreeCandidate.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/NoopDataTreeCandidate.java @@ -57,7 +57,7 @@ final class NoopDataTreeCandidate extends AbstractDataTreeCandidate { protected NoopDataTreeCandidate(final YangInstanceIdentifier rootPath, final ModifiedNode modificationRoot) { super(rootPath); - Preconditions.checkArgument(modificationRoot.getType() == ModificationType.UNMODIFIED); + Preconditions.checkArgument(modificationRoot.getOperation() == LogicalOperation.NONE); } @Override 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 39c164faf1..aaee9c30d8 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 @@ -18,7 +18,6 @@ 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.DataValidationFailedException; import org.opendaylight.yangtools.yang.data.api.schema.tree.IncorrectDataStructureException; -import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode; import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; @@ -113,17 +112,17 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { @Override public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException { - if (modification.getType() == ModificationType.WRITE) { + if (modification.getOperation() == LogicalOperation.WRITE) { verifyWrittenStructure(modification.getWrittenValue()); } } @Override public final void checkApplicable(final YangInstanceIdentifier path,final NodeModification modification, final Optional current) throws DataValidationFailedException { - switch (modification.getType()) { + switch (modification.getOperation()) { case DELETE: checkDeleteApplicable(modification, current); - case SUBTREE_MODIFIED: + case TOUCH: checkSubtreeModificationApplicable(path, modification, current); return; case WRITE: @@ -132,10 +131,10 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { case MERGE: checkMergeApplicable(path, modification, current); return; - case UNMODIFIED: + case NONE: return; default: - throw new UnsupportedOperationException("Suplied modification type "+ modification.getType()+ "is not supported."); + throw new UnsupportedOperationException("Suplied modification type "+ modification.getOperation()+ "is not supported."); } } @@ -192,10 +191,10 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { public final Optional apply(final ModifiedNode modification, final Optional currentMeta, final Version version) { - switch (modification.getType()) { + switch (modification.getOperation()) { case DELETE: return modification.setSnapshot(Optional. absent()); - case SUBTREE_MODIFIED: + case TOUCH: Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification", modification); return modification.setSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(), @@ -213,7 +212,7 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { return modification.setSnapshot(Optional.of(result)); case WRITE: return modification.setSnapshot(Optional.of(applyWrite(modification, currentMeta, version))); - case UNMODIFIED: + case NONE: return currentMeta; default: throw new IllegalArgumentException("Provided modification type is not supported."); -- 2.36.6