Bug 4657: Added handling of APPEARED, DISAPPEARED.
[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 APPEARED:
85                 case DISAPPEARED:
86                 case SUBTREE_MODIFIED:
87                     final Collection<DataTreeCandidateNode> children = node.getChildNodes();
88                     if (!children.isEmpty()) {
89                         cursor.enter(node.getIdentifier());
90                             return new ExitingNodeIterator(this, children.iterator());
91                     }
92                     break;
93                 case UNMODIFIED:
94                     // No-op
95                     break;
96                 case WRITE:
97                     cursor.write(node.getIdentifier(), node.getDataAfter().get());
98                     break;
99                 default:
100                     throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
101                 }
102             }
103             exitNode(cursor);
104             return getParent();
105         }
106
107         protected abstract @Nullable AbstractNodeIterator getParent();
108
109         protected abstract void exitNode(DataTreeModificationCursor cursor);
110     }
111
112     private static final class RootNonExitingIterator extends AbstractNodeIterator {
113
114         protected RootNonExitingIterator(@Nonnull final Iterator<DataTreeCandidateNode> iterator) {
115             super(iterator);
116         }
117
118         @Override
119         protected void exitNode(final DataTreeModificationCursor cursor) {
120             // Intentional noop.
121         }
122
123         @Override
124         protected AbstractNodeIterator getParent() {
125             return null;
126         }
127     }
128
129     private static final class ExitingNodeIterator extends AbstractNodeIterator {
130
131         private final AbstractNodeIterator parent;
132
133         public ExitingNodeIterator(@Nullable final AbstractNodeIterator parent,
134                 @Nonnull final Iterator<DataTreeCandidateNode> iterator) {
135             super(iterator);
136             this.parent = parent;
137         }
138
139         @Override
140         protected AbstractNodeIterator getParent() {
141             return parent;
142         }
143
144         @Override
145         protected void exitNode(final DataTreeModificationCursor cursor) {
146             cursor.exit();
147         }
148     }
149 }