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 static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.Beta;
13 import java.util.Collection;
14 import java.util.Iterator;
15 import javax.annotation.Nonnull;
16 import javax.annotation.Nullable;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
19 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
22 public final class DataTreeCandidateNodes {
23 private DataTreeCandidateNodes() {
24 throw new UnsupportedOperationException();
28 * Return an empty {@link DataTreeCandidateNode} identified by specified {@link PathArgument}.
29 * @param identifier Node identifier
30 * @return An empty DataTreeCandidateNode
32 public static DataTreeCandidateNode empty(final PathArgument identifier) {
33 return new EmptyDataTreeCandidateNode(identifier);
36 public static DataTreeCandidateNode fromNormalizedNode(final NormalizedNode<?, ?> node) {
37 return new NormalizedNodeDataTreeCandidateNode(node);
41 * Applies the {@code node} to the {@code cursor}, note that if the top node of (@code node} is RootNode
42 * you need to use {@link #applyRootedNodeToCursor(DataTreeModificationCursor, YangInstanceIdentifier,
43 * DataTreeCandidateNode) applyRootedNodeToCursor} method that works with rooted node candidates.
45 * @param cursor cursor from the modification we want to apply the {@code node} to
46 * @param node candidate tree to apply
48 public static void applyToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidateNode node) {
49 switch (node.getModificationType()) {
51 cursor.delete(node.getIdentifier());
53 case SUBTREE_MODIFIED:
54 cursor.enter(node.getIdentifier());
55 AbstractNodeIterator iterator = new ExitingNodeIterator(null, node.getChildNodes().iterator());
57 iterator = iterator.next(cursor);
58 } while (iterator != null);
64 cursor.write(node.getIdentifier(), node.getDataAfter().get());
67 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
72 * Applies the {@code node} that is rooted(doesn't have an identifier) in tree A to tree B's {@code cursor}
73 * at location specified by {@code rootPath}.
75 * @param cursor cursor from the modification we want to apply the {@code node} to
76 * @param rootPath path in the {@code cursor}'s tree we want to apply to candidate to
77 * @param node candidate tree to apply
79 public static void applyRootedNodeToCursor(final DataTreeModificationCursor cursor,
80 final YangInstanceIdentifier rootPath, final DataTreeCandidateNode node) {
81 switch (node.getModificationType()) {
83 cursor.delete(rootPath.getLastPathArgument());
85 case SUBTREE_MODIFIED:
86 cursor.enter(rootPath.getLastPathArgument());
87 AbstractNodeIterator iterator = new ExitingNodeIterator(null, node.getChildNodes().iterator());
89 iterator = iterator.next(cursor);
90 } while (iterator != null);
96 cursor.write(rootPath.getLastPathArgument(), node.getDataAfter().get());
99 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
103 public static void applyRootToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidateNode node) {
104 switch (node.getModificationType()) {
106 throw new IllegalArgumentException("Can not delete root.");
108 case SUBTREE_MODIFIED:
109 AbstractNodeIterator iterator = new RootNonExitingIterator(node.getChildNodes().iterator());
111 iterator = iterator.next(cursor);
112 } while (iterator != null);
118 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
122 private abstract static class AbstractNodeIterator {
123 private final Iterator<DataTreeCandidateNode> iterator;
125 AbstractNodeIterator(final Iterator<DataTreeCandidateNode> iterator) {
126 this.iterator = requireNonNull(iterator);
129 AbstractNodeIterator next(final DataTreeModificationCursor cursor) {
130 while (iterator.hasNext()) {
131 final DataTreeCandidateNode node = iterator.next();
132 switch (node.getModificationType()) {
134 cursor.delete(node.getIdentifier());
138 case SUBTREE_MODIFIED:
139 final Collection<DataTreeCandidateNode> children = node.getChildNodes();
140 if (!children.isEmpty()) {
141 cursor.enter(node.getIdentifier());
142 return new ExitingNodeIterator(this, children.iterator());
149 cursor.write(node.getIdentifier(), node.getDataAfter().get());
152 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
159 protected abstract @Nullable AbstractNodeIterator getParent();
161 protected abstract void exitNode(DataTreeModificationCursor cursor);
164 private static final class RootNonExitingIterator extends AbstractNodeIterator {
166 protected RootNonExitingIterator(@Nonnull final Iterator<DataTreeCandidateNode> iterator) {
171 protected void exitNode(final DataTreeModificationCursor cursor) {
176 protected AbstractNodeIterator getParent() {
181 private static final class ExitingNodeIterator extends AbstractNodeIterator {
183 private final AbstractNodeIterator parent;
185 ExitingNodeIterator(@Nullable final AbstractNodeIterator parent,
186 @Nonnull final Iterator<DataTreeCandidateNode> iterator) {
188 this.parent = parent;
192 protected AbstractNodeIterator getParent() {
197 protected void exitNode(final DataTreeModificationCursor cursor) {