X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-dom-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fdom%2Fstore%2Fimpl%2Ftree%2FNodeModification.java;fp=opendaylight%2Fmd-sal%2Fsal-dom-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fdom%2Fstore%2Fimpl%2Ftree%2FNodeModification.java;h=764afcb3e185f3d48d09b192660c3cc882c36537;hp=0000000000000000000000000000000000000000;hb=f8d1b972aef029a829a60336c05b557b2bc4edc8;hpb=d5759c52d69ba8725d9bbdc18e81848f319861d1 diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/NodeModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/NodeModification.java new file mode 100644 index 0000000000..764afcb3e1 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/NodeModification.java @@ -0,0 +1,198 @@ +/* + * 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.controller.md.sal.dom.store.impl.tree; + +import static com.google.common.base.Preconditions.checkState; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.opendaylight.yangtools.concepts.Identifiable; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +import com.google.common.base.Optional; + +/** + * Node Modification Node and Tree + * + * Tree which structurally resembles data tree and captures client modifications + * 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()}. + * + */ +public class NodeModification implements StoreTreeNode, Identifiable { + + private final PathArgument identifier; + private ModificationType modificationType = ModificationType.UNMODIFIED; + + + private final Optional original; + + private NormalizedNode value; + + private StoreMetadataNode snapshotCache; + + private final Map childModification; + + private boolean sealed = false; + + protected NodeModification(final PathArgument identifier, final Optional original) { + this.identifier = identifier; + this.original = original; + childModification = new LinkedHashMap<>(); + } + + /** + * + * + * @return + */ + public NormalizedNode getWritenValue() { + return value; + } + + @Override + public PathArgument getIdentifier() { + return identifier; + } + + /** + * + * Returns original store metadata + * @return original store metadata + */ + public final Optional getOriginal() { + return original; + } + + /** + * Returns modification type + * + * @return modification type + */ + public final ModificationType getModificationType() { + return modificationType; + } + + /** + * + * Returns child modification if child was modified + * + * @return Child modification if direct child or it's subtree + * was modified. + * + */ + @Override + public Optional getChild(final PathArgument child) { + return Optional. fromNullable(childModification.get(child)); + } + + /** + * + * Returns child modification if child was modified, creates {@link NodeModification} + * for child otherwise. + * + * If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED} + * changes modification type to {@link ModificationType#SUBTREE_MODIFIED} + * + * @param child + * @return {@link NodeModification} for specified child, with {@link #getOriginal()} + * containing child metadata if child was present in original data. + */ + public synchronized NodeModification modifyChild(final PathArgument child) { + checkSealed(); + if(modificationType == ModificationType.UNMODIFIED) { + updateModificationType(ModificationType.SUBTREE_MODIFIED); + } + final NodeModification potential = childModification.get(child); + if (potential != null) { + return potential; + } + Optional currentMetadata = Optional.absent(); + if(original.isPresent()) { + currentMetadata = original.get().getChild(child); + } + NodeModification newlyCreated = new NodeModification(child,currentMetadata); + childModification.put(child, newlyCreated); + return newlyCreated; + } + + /** + * + * Returns all recorded direct child modification + * + * @return all recorded direct child modifications + */ + public Iterable getModifications() { + return childModification.values(); + } + + + /** + * + * Records a delete for associated node. + * + */ + public synchronized void delete() { + checkSealed(); + updateModificationType(ModificationType.DELETE); + childModification.clear(); + this.value = null; + } + + /** + * + * Records a write for associated node. + * + * @param value + */ + public synchronized void write(final NormalizedNode value) { + checkSealed(); + updateModificationType(ModificationType.WRITE); + childModification.clear(); + this.value = value; + } + + private void checkSealed() { + checkState(!sealed, "Node Modification is sealed. No further changes allowed."); + } + + public synchronized void seal() { + sealed = true; + for(NodeModification child : childModification.values()) { + child.seal(); + } + } + + private void clearSnapshot() { + snapshotCache = null; + } + + public boolean hasAdditionalModifications() { + return !childModification.isEmpty(); + } + + public void updateModificationType(final ModificationType type) { + modificationType = type; + clearSnapshot(); + } + + @Override + public String toString() { + return "NodeModification [identifier=" + identifier + ", modificationType=" + + modificationType + ", value=" + value + ", childModification=" + childModification + "]"; + } + + public static NodeModification createUnmodified(final StoreMetadataNode metadataTree) { + return new NodeModification(metadataTree.getIdentifier(), Optional.of(metadataTree)); + } + +}