2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.data.api.schema.tree;
10 import com.google.common.annotations.Beta;
11 import com.google.common.base.Preconditions;
12 import java.util.Collection;
13 import java.util.Iterator;
14 import javax.annotation.Nonnull;
15 import javax.annotation.Nullable;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
18 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
21 public final class DataTreeCandidateNodes {
22 private DataTreeCandidateNodes() {
23 throw new UnsupportedOperationException();
27 * Return an empty {@link DataTreeCandidateNode} identified by specified {@link PathArgument}.
28 * @param identifier Node identifier
29 * @return An empty DataTreeCandidateNode
31 public static DataTreeCandidateNode empty(final PathArgument identifier) {
32 return new EmptyDataTreeCandidateNode(identifier);
35 public static DataTreeCandidateNode fromNormalizedNode(final NormalizedNode<?, ?> node) {
36 return new NormalizedNodeDataTreeCandidateNode(node);
40 * Applies the {@code node} to the {@code cursor}, note that if the top node of (@code node} is RootNode
41 * you need to use {@link #applyRootedNodeToCursor(DataTreeModificationCursor, YangInstanceIdentifier,
42 * DataTreeCandidateNode) applyRootedNodeToCursor} method that works with rooted node candidates.
44 * @param cursor cursor from the modification we want to apply the {@code node} to
45 * @param node candidate tree to apply
47 public static void applyToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidateNode node) {
48 switch (node.getModificationType()) {
50 cursor.delete(node.getIdentifier());
52 case SUBTREE_MODIFIED:
53 cursor.enter(node.getIdentifier());
54 AbstractNodeIterator iterator = new ExitingNodeIterator(null, node.getChildNodes().iterator());
56 iterator = iterator.next(cursor);
57 } while (iterator != null);
63 cursor.write(node.getIdentifier(), node.getDataAfter().get());
66 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
71 * Applies the {@code node} that is rooted(doesn't have an identifier) in tree A to tree B's {@code cursor}
72 * at location specified by {@code rootPath}.
74 * @param cursor cursor from the modification we want to apply the {@code node} to
75 * @param rootPath path in the {@code cursor}'s tree we want to apply to candidate to
76 * @param node candidate tree to apply
78 public static void applyRootedNodeToCursor(final DataTreeModificationCursor cursor,
79 final YangInstanceIdentifier rootPath, final DataTreeCandidateNode node) {
80 switch (node.getModificationType()) {
82 cursor.delete(rootPath.getLastPathArgument());
84 case SUBTREE_MODIFIED:
85 cursor.enter(rootPath.getLastPathArgument());
86 AbstractNodeIterator iterator = new ExitingNodeIterator(null, node.getChildNodes().iterator());
88 iterator = iterator.next(cursor);
89 } while (iterator != null);
95 cursor.write(rootPath.getLastPathArgument(), node.getDataAfter().get());
98 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
102 public static void applyRootToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidateNode node) {
103 switch (node.getModificationType()) {
105 throw new IllegalArgumentException("Can not delete root.");
107 case SUBTREE_MODIFIED:
108 AbstractNodeIterator iterator = new RootNonExitingIterator(node.getChildNodes().iterator());
110 iterator = iterator.next(cursor);
111 } while (iterator != null);
117 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
121 private abstract static class AbstractNodeIterator {
122 private final Iterator<DataTreeCandidateNode> iterator;
124 AbstractNodeIterator(final Iterator<DataTreeCandidateNode> iterator) {
125 this.iterator = Preconditions.checkNotNull(iterator);
128 AbstractNodeIterator next(final DataTreeModificationCursor cursor) {
129 while (iterator.hasNext()) {
130 final DataTreeCandidateNode node = iterator.next();
131 switch (node.getModificationType()) {
133 cursor.delete(node.getIdentifier());
137 case SUBTREE_MODIFIED:
138 final Collection<DataTreeCandidateNode> children = node.getChildNodes();
139 if (!children.isEmpty()) {
140 cursor.enter(node.getIdentifier());
141 return new ExitingNodeIterator(this, children.iterator());
148 cursor.write(node.getIdentifier(), node.getDataAfter().get());
151 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
158 protected abstract @Nullable AbstractNodeIterator getParent();
160 protected abstract void exitNode(DataTreeModificationCursor cursor);
163 private static final class RootNonExitingIterator extends AbstractNodeIterator {
165 protected RootNonExitingIterator(@Nonnull final Iterator<DataTreeCandidateNode> iterator) {
170 protected void exitNode(final DataTreeModificationCursor cursor) {
175 protected AbstractNodeIterator getParent() {
180 private static final class ExitingNodeIterator extends AbstractNodeIterator {
182 private final AbstractNodeIterator parent;
184 public ExitingNodeIterator(@Nullable final AbstractNodeIterator parent,
185 @Nonnull final Iterator<DataTreeCandidateNode> iterator) {
187 this.parent = parent;
191 protected AbstractNodeIterator getParent() {
196 protected void exitNode(final DataTreeModificationCursor cursor) {