X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-data-api%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fdata%2Fapi%2Fschema%2Ftree%2FDataTreeCandidateNodes.java;h=2b133a8765d36de32c30fbd645ce24b5734e044c;hb=8f2876d895936b36aba1fc3ec65b18900e559184;hp=e1636ae77e8707baccc837e5f721ad78cbc30a55;hpb=7fedd460044be8d15547f65b713ecbeec0f74296;p=yangtools.git diff --git a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/DataTreeCandidateNodes.java b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/DataTreeCandidateNodes.java index e1636ae77e..2b133a8765 100644 --- a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/DataTreeCandidateNodes.java +++ b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/DataTreeCandidateNodes.java @@ -7,10 +7,15 @@ */ package org.opendaylight.yangtools.yang.data.api.schema.tree; +import static java.util.Objects.requireNonNull; + import com.google.common.annotations.Beta; -import com.google.common.base.Preconditions; import java.util.Collection; import java.util.Iterator; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +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; @Beta @@ -19,69 +24,178 @@ public final class DataTreeCandidateNodes { throw new UnsupportedOperationException(); } + /** + * Return an empty {@link DataTreeCandidateNode} identified by specified {@link PathArgument}. + * @param identifier Node identifier + * @return An empty DataTreeCandidateNode + */ + public static DataTreeCandidateNode empty(final PathArgument identifier) { + return new EmptyDataTreeCandidateNode(identifier); + } + public static DataTreeCandidateNode fromNormalizedNode(final NormalizedNode node) { return new NormalizedNodeDataTreeCandidateNode(node); } + /** + * Applies the {@code node} to the {@code cursor}, note that if the top node of (@code node} is RootNode + * you need to use {@link #applyRootedNodeToCursor(DataTreeModificationCursor, YangInstanceIdentifier, + * DataTreeCandidateNode) applyRootedNodeToCursor} method that works with rooted node candidates. + * + * @param cursor cursor from the modification we want to apply the {@code node} to + * @param node candidate tree to apply + */ public static void applyToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidateNode node) { switch (node.getModificationType()) { - case DELETE: - cursor.delete(node.getIdentifier()); - break; - case SUBTREE_MODIFIED: - cursor.enter(node.getIdentifier()); - NodeIterator iterator = new NodeIterator(null, node.getChildNodes().iterator()); - do { - iterator = iterator.next(cursor); - } while (iterator != null); - break; - case UNMODIFIED: - // No-op - break; - case WRITE: - cursor.write(node.getIdentifier(), node.getDataAfter().get()); - break; - default: - throw new IllegalArgumentException("Unsupported modification " + node.getModificationType()); + case DELETE: + cursor.delete(node.getIdentifier()); + break; + case SUBTREE_MODIFIED: + cursor.enter(node.getIdentifier()); + AbstractNodeIterator iterator = new ExitingNodeIterator(null, node.getChildNodes().iterator()); + do { + iterator = iterator.next(cursor); + } while (iterator != null); + break; + case UNMODIFIED: + // No-op + break; + case WRITE: + cursor.write(node.getIdentifier(), node.getDataAfter().get()); + break; + default: + throw new IllegalArgumentException("Unsupported modification " + node.getModificationType()); + } + } + + /** + * Applies the {@code node} that is rooted(doesn't have an identifier) in tree A to tree B's {@code cursor} + * at location specified by {@code rootPath}. + * + * @param cursor cursor from the modification we want to apply the {@code node} to + * @param rootPath path in the {@code cursor}'s tree we want to apply to candidate to + * @param node candidate tree to apply + */ + public static void applyRootedNodeToCursor(final DataTreeModificationCursor cursor, + final YangInstanceIdentifier rootPath, final DataTreeCandidateNode node) { + switch (node.getModificationType()) { + case DELETE: + cursor.delete(rootPath.getLastPathArgument()); + break; + case SUBTREE_MODIFIED: + cursor.enter(rootPath.getLastPathArgument()); + AbstractNodeIterator iterator = new ExitingNodeIterator(null, node.getChildNodes().iterator()); + do { + iterator = iterator.next(cursor); + } while (iterator != null); + break; + case UNMODIFIED: + // No-op + break; + case WRITE: + cursor.write(rootPath.getLastPathArgument(), node.getDataAfter().get()); + break; + default: + throw new IllegalArgumentException("Unsupported modification " + node.getModificationType()); + } + } + + public static void applyRootToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidateNode node) { + switch (node.getModificationType()) { + case DELETE: + throw new IllegalArgumentException("Can not delete root."); + case WRITE: + case SUBTREE_MODIFIED: + AbstractNodeIterator iterator = new RootNonExitingIterator(node.getChildNodes().iterator()); + do { + iterator = iterator.next(cursor); + } while (iterator != null); + break; + case UNMODIFIED: + // No-op + break; + default: + throw new IllegalArgumentException("Unsupported modification " + node.getModificationType()); } } - private static final class NodeIterator { + private abstract static class AbstractNodeIterator { private final Iterator iterator; - private final NodeIterator parent; - NodeIterator(final NodeIterator parent, final Iterator iterator) { - this.parent = Preconditions.checkNotNull(parent); - this.iterator = Preconditions.checkNotNull(iterator); + AbstractNodeIterator(final Iterator iterator) { + this.iterator = requireNonNull(iterator); } - NodeIterator next(final DataTreeModificationCursor cursor) { + AbstractNodeIterator next(final DataTreeModificationCursor cursor) { while (iterator.hasNext()) { final DataTreeCandidateNode node = iterator.next(); switch (node.getModificationType()) { - case DELETE: - cursor.delete(node.getIdentifier()); - break; - case SUBTREE_MODIFIED: - final Collection children = node.getChildNodes(); - if (!children.isEmpty()) { - cursor.enter(node.getIdentifier()); - return new NodeIterator(this, children.iterator()); - } - break; - case UNMODIFIED: - // No-op - break; - case WRITE: - cursor.write(node.getIdentifier(), node.getDataAfter().get()); - break; - default: - throw new IllegalArgumentException("Unsupported modification " + node.getModificationType()); + case DELETE: + cursor.delete(node.getIdentifier()); + break; + case APPEARED: + case DISAPPEARED: + case SUBTREE_MODIFIED: + final Collection children = node.getChildNodes(); + if (!children.isEmpty()) { + cursor.enter(node.getIdentifier()); + return new ExitingNodeIterator(this, children.iterator()); + } + break; + case UNMODIFIED: + // No-op + break; + case WRITE: + cursor.write(node.getIdentifier(), node.getDataAfter().get()); + break; + default: + throw new IllegalArgumentException("Unsupported modification " + node.getModificationType()); } } + exitNode(cursor); + return getParent(); + } - cursor.exit(); + protected abstract @Nullable AbstractNodeIterator getParent(); + + protected abstract void exitNode(DataTreeModificationCursor cursor); + } + + private static final class RootNonExitingIterator extends AbstractNodeIterator { + + protected RootNonExitingIterator(@Nonnull final Iterator iterator) { + super(iterator); + } + + @Override + protected void exitNode(final DataTreeModificationCursor cursor) { + // Intentional noop. + } + + @Override + protected AbstractNodeIterator getParent() { + return null; + } + } + + private static final class ExitingNodeIterator extends AbstractNodeIterator { + + private final AbstractNodeIterator parent; + + ExitingNodeIterator(@Nullable final AbstractNodeIterator parent, + @Nonnull final Iterator iterator) { + super(iterator); + this.parent = parent; + } + + @Override + protected AbstractNodeIterator getParent() { return parent; } + + @Override + protected void exitNode(final DataTreeModificationCursor cursor) { + cursor.exit(); + } } }