8145bfe711884fbe1a72fba28ee7c19eb8ef1469
[yangtools.git] / yang / yang-data-api / src / main / java / org / opendaylight / yangtools / yang / data / api / schema / tree / DataTreeCandidateNodes.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.data.api.schema.tree;
9
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.schema.NormalizedNode;
17
18 @Beta
19 public final class DataTreeCandidateNodes {
20     private DataTreeCandidateNodes() {
21         throw new UnsupportedOperationException();
22     }
23
24     public static DataTreeCandidateNode fromNormalizedNode(final NormalizedNode<?, ?> node) {
25         return new NormalizedNodeDataTreeCandidateNode(node);
26     }
27
28     public static void applyToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidateNode node) {
29         switch (node.getModificationType()) {
30         case DELETE:
31             cursor.delete(node.getIdentifier());
32             break;
33         case SUBTREE_MODIFIED:
34                 cursor.enter(node.getIdentifier());
35                 AbstractNodeIterator iterator = new ExitingNodeIterator(null, node.getChildNodes().iterator());
36             do {
37                 iterator = iterator.next(cursor);
38             } while (iterator != null);
39             break;
40         case UNMODIFIED:
41             // No-op
42             break;
43         case WRITE:
44             cursor.write(node.getIdentifier(), node.getDataAfter().get());
45             break;
46         default:
47             throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
48         }
49     }
50
51     public static void applyRootToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidateNode node) {
52         switch (node.getModificationType()) {
53             case DELETE:
54                 throw new IllegalArgumentException("Can not delete root.");
55             case WRITE:
56             case SUBTREE_MODIFIED:
57                 AbstractNodeIterator iterator = new RootNonExitingIterator(node.getChildNodes().iterator());
58                 do {
59                     iterator = iterator.next(cursor);
60                 } while (iterator != null);
61                 break;
62             case UNMODIFIED:
63                 // No-op
64                 break;
65             default:
66                 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
67         }
68     }
69
70     private abstract static class AbstractNodeIterator {
71         private final Iterator<DataTreeCandidateNode> iterator;
72
73         AbstractNodeIterator(final Iterator<DataTreeCandidateNode> iterator) {
74             this.iterator = Preconditions.checkNotNull(iterator);
75         }
76
77         AbstractNodeIterator next(final DataTreeModificationCursor cursor) {
78             while (iterator.hasNext()) {
79                 final DataTreeCandidateNode node = iterator.next();
80                 switch (node.getModificationType()) {
81                 case DELETE:
82                     cursor.delete(node.getIdentifier());
83                     break;
84                 case SUBTREE_MODIFIED:
85                     final Collection<DataTreeCandidateNode> children = node.getChildNodes();
86                     if (!children.isEmpty()) {
87                         cursor.enter(node.getIdentifier());
88                             return new ExitingNodeIterator(this, children.iterator());
89                     }
90                     break;
91                 case UNMODIFIED:
92                     // No-op
93                     break;
94                 case WRITE:
95                     cursor.write(node.getIdentifier(), node.getDataAfter().get());
96                     break;
97                 default:
98                     throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
99                 }
100             }
101             exitNode(cursor);
102             return getParent();
103         }
104
105         protected abstract @Nullable AbstractNodeIterator getParent();
106
107         protected abstract void exitNode(DataTreeModificationCursor cursor);
108     }
109
110     private static final class RootNonExitingIterator extends AbstractNodeIterator {
111
112         protected RootNonExitingIterator(@Nonnull final Iterator<DataTreeCandidateNode> iterator) {
113             super(iterator);
114         }
115
116         @Override
117         protected void exitNode(final DataTreeModificationCursor cursor) {
118             // Intentional noop.
119         }
120
121         @Override
122         protected AbstractNodeIterator getParent() {
123             return null;
124         }
125     }
126
127     private static final class ExitingNodeIterator extends AbstractNodeIterator {
128
129         private final AbstractNodeIterator parent;
130
131         public ExitingNodeIterator(@Nullable final AbstractNodeIterator parent,
132                 @Nonnull final Iterator<DataTreeCandidateNode> iterator) {
133             super(iterator);
134             this.parent = parent;
135         }
136
137         @Override
138         protected AbstractNodeIterator getParent() {
139             return parent;
140         }
141
142         @Override
143         protected void exitNode(final DataTreeModificationCursor cursor) {
144             cursor.exit();
145         }
146     }
147 }