X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-data-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fdata%2Fimpl%2Fschema%2Ftree%2FModifiedNode.java;h=dd06b890cb367569d8dcefaa10b9452c04fb9513;hb=f4be08675ce4837517c449ef5888383756fd4902;hp=cfece17b886c8616c222790bd7e996d270fc0486;hpb=774cfc9c95b20bad92b33a6398793c940f1339a2;p=yangtools.git 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 cfece17b88..dd06b890cb 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 @@ -10,13 +10,15 @@ package org.opendaylight.yangtools.yang.data.impl.schema.tree; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; +import com.google.common.base.Verify; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.concurrent.NotThreadSafe; -import org.opendaylight.yangtools.concepts.Identifiable; 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.ModificationType; @@ -30,51 +32,59 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode; * to the data store tree. * * This tree is lazily created and populated via {@link #modifyChild(PathArgument)} - * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}. + * and {@link TreeNode} which represents original state as tracked by {@link #getOriginal()}. */ @NotThreadSafe final class ModifiedNode extends NodeModification implements StoreTreeNode { - - public static final Predicate IS_TERMINAL_PREDICATE = new Predicate() { + static final Predicate IS_TERMINAL_PREDICATE = new Predicate() { @Override public boolean apply(final @Nonnull ModifiedNode input) { Preconditions.checkNotNull(input); - switch (input.getType()) { + switch (input.getOperation()) { case DELETE: case MERGE: case WRITE: return true; - case SUBTREE_MODIFIED: - case UNMODIFIED: + case TOUCH: + case NONE: return false; } - throw new IllegalArgumentException(String.format("Unhandled modification type %s", input.getType())); + throw new IllegalArgumentException(String.format("Unhandled modification type %s", input.getOperation())); } }; private final Map 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; + private ModificationType modType; - private ModifiedNode(final PathArgument identifier, final Optional original, final boolean isOrdered) { + private ModifiedNode(final PathArgument identifier, final Optional original, final ChildTrackingPolicy childPolicy) { this.identifier = identifier; this.original = original; - if (isOrdered) { + switch (childPolicy) { + case NONE: + children = Collections.emptyMap(); + break; + case ORDERED: children = new LinkedHashMap<>(); - } else { + break; + case UNORDERED: children = new HashMap<>(); + break; + default: + throw new IllegalArgumentException("Unsupported child tracking policy " + childPolicy); } } /** + * Return the value which was written to this node. * - * - * @return + * @return Currently-written value */ public NormalizedNode getWrittenValue() { return value; @@ -85,24 +95,14 @@ 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; } /** @@ -120,20 +120,21 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode getChildren() { + Collection getChildren() { return children.values(); } /** - * * Records a delete for associated node. - * */ - public void delete() { - final ModificationType newType; + void delete() { + final LogicalOperation newType; - switch (modificationType) { + switch (operation) { case DELETE: - case UNMODIFIED: + case NONE: // We need to record this delete. - newType = ModificationType.DELETE; + newType = LogicalOperation.DELETE; break; case MERGE: - case SUBTREE_MODIFIED: + case TOUCH: case WRITE: /* * We are canceling a previous modification. This is a bit tricky, @@ -189,36 +187,50 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode value) { + void write(final NormalizedNode value) { clearSnapshot(); - updateModificationType(ModificationType.WRITE); + updateOperationType(LogicalOperation.WRITE); children.clear(); this.value = value; } - public void merge(final NormalizedNode data) { + void merge(final NormalizedNode value) { clearSnapshot(); - updateModificationType(ModificationType.MERGE); - // FIXME: Probably merge with previous value. - this.value = data; + updateOperationType(LogicalOperation.MERGE); + + /* + * Blind overwrite of any previous data is okay, no matter whether the node + * is simple or complex type. + * + * If this is a simple or complex type with unkeyed children, this merge will + * be turned into a write operation, overwriting whatever was there before. + * + * If this is a container with keyed children, there are two possibilities: + * - if it existed before, this value will never be consulted and the children + * will get explicitly merged onto the original data. + * - if it did not exist before, this value will be used as a seed write and + * children will be merged into it. + * In either case we rely on OperationWithModification to manipulate the children + * before calling this method, so unlike a write we do not want to clear them. + */ + this.value = value; } /** @@ -235,14 +247,14 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode storeSnapshot(final Optional snapshot) { - snapshotCache = snapshot; - return snapshot; + Optional getSnapshot() { + return snapshotCache; } - public Optional> getSnapshotCache() { - return Optional.fromNullable(snapshotCache); + Optional setSnapshot(final Optional snapshot) { + snapshotCache = Preconditions.checkNotNull(snapshot); + return snapshot; } - private void updateModificationType(final ModificationType type) { - modificationType = type; + private void updateOperationType(final LogicalOperation type) { + operation = type; + modType = null; clearSnapshot(); } @Override public String toString() { return "NodeModification [identifier=" + identifier + ", modificationType=" - + modificationType + ", childModification=" + children + "]"; + + operation + ", childModification=" + children + "]"; + } + + void resolveModificationType(@Nonnull final ModificationType type) { + modType = type; + } + + @Nonnull ModificationType modificationType() { + return Verify.verifyNotNull(modType, "Node %s does not have resolved modification type", this); } /** @@ -278,12 +299,23 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode value) { - final ModifiedNode ret = new ModifiedNode(getIdentifier(), Optional.absent(), false); + /* + * We are instantiating an "equivalent" of this node. Currently the only callsite does not care + * about the actual iteration order, so we do not have to specify the same tracking policy as + * we were instantiated with. Since this is the only time we need to know that policy (it affects + * only things in constructor), we do not want to retain it (saves some memory on per-instance + * basis). + * + * We could reconstruct it using two instanceof checks (to undo what the constructor has done), + * which would give perfect results. The memory saving would be at most 32 bytes of a short-lived + * object, so let's not bother with that. + */ + final ModifiedNode ret = new ModifiedNode(getIdentifier(), Optional.absent(), ChildTrackingPolicy.UNORDERED); ret.write(value); return ret; } - public static ModifiedNode createUnmodified(final TreeNode metadataTree, final boolean isOrdered) { - return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree), isOrdered); + public static ModifiedNode createUnmodified(final TreeNode metadataTree, final ChildTrackingPolicy childPolicy) { + return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree), childPolicy); } }