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