Bug 4295: Fixed incorrectly introduced nodes when MERGE was followed by DELETE
[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
35         while (children.hasNext()) {
36             final ModifiedNode child = children.next();
37             final Optional<ModificationApplyOperation> childOperation = op.getChild(child.getIdentifier());
38             Preconditions.checkState(childOperation.isPresent(), "Schema for child %s is not present.",
39                     child.getIdentifier());
40             final Collection<ModifiedNode> grandChildren = child.getChildren();
41             final ModificationApplyOperation childOp = childOperation.get();
42
43             if (grandChildren.isEmpty()) {
44
45                 child.seal(childOp, version);
46                 if (child.getOperation() == LogicalOperation.NONE) {
47                     children.remove();
48                 }
49             } else {
50                 return new NestedReadyIterator(this, child, grandChildren.iterator(), childOp);
51             }
52         }
53
54         node.seal(op, version);
55
56         // Remove from parent if we have one and this is a no-op
57         if (node.getOperation() == LogicalOperation.NONE) {
58             removeFromParent();
59         }
60         return getParent();
61     }
62
63     abstract AbstractReadyIterator getParent();
64     abstract void removeFromParent();
65
66     private static final class NestedReadyIterator extends AbstractReadyIterator {
67         private final AbstractReadyIterator parent;
68
69         private NestedReadyIterator(final AbstractReadyIterator parent, final ModifiedNode node,
70                 final Iterator<ModifiedNode> children, final ModificationApplyOperation operation) {
71             super(node, children, operation);
72             this.parent = Preconditions.checkNotNull(parent);
73         }
74
75         @Override
76         AbstractReadyIterator getParent() {
77             return parent;
78         }
79
80         @Override
81         void removeFromParent() {
82             parent.children.remove();
83         }
84     }
85
86     private static final class RootReadyIterator extends AbstractReadyIterator {
87         private RootReadyIterator(final ModifiedNode node, final Iterator<ModifiedNode> children,
88                 final ModificationApplyOperation operation) {
89             super(node, children, operation);
90         }
91
92         @Override
93         AbstractReadyIterator getParent() {
94             return null;
95         }
96
97         @Override
98         void removeFromParent() {
99             // No-op, since root node cannot be removed
100         }
101     }
102
103 }