4ded53408fd8b3558695ada4522095ac8a069e58
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / AbstractReadyIterator.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.impl.schema.tree;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import java.util.Collection;
13 import java.util.Iterator;
14 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
15
16 abstract class AbstractReadyIterator {
17     final Iterator<ModifiedNode> children;
18     final ModifiedNode node;
19     final ModificationApplyOperation op;
20
21     private AbstractReadyIterator(final ModifiedNode node, final Iterator<ModifiedNode> children,
22             final ModificationApplyOperation operation) {
23         this.children = Preconditions.checkNotNull(children);
24         this.node = Preconditions.checkNotNull(node);
25         this.op = Preconditions.checkNotNull(operation);
26     }
27
28     static AbstractReadyIterator create(final ModifiedNode root, final ModificationApplyOperation operation) {
29         return new RootReadyIterator(root, root.getChildren().iterator(), operation);
30     }
31
32     final AbstractReadyIterator process(final Version version) {
33         // Walk all child nodes and remove any children which have not
34         // been modified. If a child has children, we need to iterate
35         // through it via re-entering this method on the child iterator.
36         while (children.hasNext()) {
37             final ModifiedNode child = children.next();
38             final Optional<ModificationApplyOperation> childOperation = op.getChild(child.getIdentifier());
39             Preconditions.checkState(childOperation.isPresent(), "Schema for child %s is not present.",
40                     child.getIdentifier());
41             final Collection<ModifiedNode> grandChildren = child.getChildren();
42             final ModificationApplyOperation childOp = childOperation.get();
43
44             if (grandChildren.isEmpty()) {
45                 // The child is empty, seal it
46                 child.seal(childOp, version);
47                 if (child.getOperation() == LogicalOperation.NONE) {
48                     children.remove();
49                 }
50             } else {
51                 return new NestedReadyIterator(this, child, grandChildren.iterator(), childOp);
52             }
53         }
54
55         // We are done with this node, seal it.
56         node.seal(op, version);
57
58         // Remove from parent if we have one and this is a no-op
59         if (node.getOperation() == LogicalOperation.NONE) {
60             removeFromParent();
61         }
62
63         // Sub-iteration complete, return back to parent
64         return getParent();
65     }
66
67     abstract AbstractReadyIterator getParent();
68
69     abstract void removeFromParent();
70
71     private static final class NestedReadyIterator extends AbstractReadyIterator {
72         private final AbstractReadyIterator parent;
73
74         private NestedReadyIterator(final AbstractReadyIterator parent, final ModifiedNode node,
75                 final Iterator<ModifiedNode> children, final ModificationApplyOperation operation) {
76             super(node, children, operation);
77             this.parent = Preconditions.checkNotNull(parent);
78         }
79
80         @Override
81         AbstractReadyIterator getParent() {
82             return parent;
83         }
84
85         @Override
86         void removeFromParent() {
87             parent.children.remove();
88         }
89     }
90
91     private static final class RootReadyIterator extends AbstractReadyIterator {
92         private RootReadyIterator(final ModifiedNode node, final Iterator<ModifiedNode> children,
93                 final ModificationApplyOperation operation) {
94             super(node, children, operation);
95         }
96
97         @Override
98         AbstractReadyIterator getParent() {
99             return null;
100         }
101
102         @Override
103         void removeFromParent() {
104             // No-op, since root node cannot be removed
105         }
106     }
107 }