/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.yang.data.impl.schema.tree; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import java.util.Collection; import java.util.Iterator; import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version; abstract class AbstractReadyIterator { final Iterator<ModifiedNode> children; final ModifiedNode node; final ModificationApplyOperation op; private AbstractReadyIterator(final ModifiedNode node, final Iterator<ModifiedNode> children, final ModificationApplyOperation operation) { this.children = Preconditions.checkNotNull(children); this.node = Preconditions.checkNotNull(node); this.op = Preconditions.checkNotNull(operation); } static AbstractReadyIterator create(final ModifiedNode root, final ModificationApplyOperation operation) { return new RootReadyIterator(root, root.getChildren().iterator(), operation); } final AbstractReadyIterator process(final Version version) { // Walk all child nodes and remove any children which have not // been modified. If a child has children, we need to iterate // through it via re-entering this method on the child iterator. while (children.hasNext()) { final ModifiedNode child = children.next(); final Optional<ModificationApplyOperation> childOperation = op.getChild(child.getIdentifier()); Preconditions.checkState(childOperation.isPresent(), "Schema for child %s is not present.", child.getIdentifier()); final Collection<ModifiedNode> grandChildren = child.getChildren(); final ModificationApplyOperation childOp = childOperation.get(); if (grandChildren.isEmpty()) { // The child is empty, seal it child.seal(childOp, version); if (child.getOperation() == LogicalOperation.NONE) { children.remove(); } } else { return new NestedReadyIterator(this, child, grandChildren.iterator(), childOp); } } // We are done with this node, seal it. node.seal(op, version); // Remove from parent if we have one and this is a no-op if (node.getOperation() == LogicalOperation.NONE) { removeFromParent(); } // Sub-iteration complete, return back to parent return getParent(); } abstract AbstractReadyIterator getParent(); abstract void removeFromParent(); private static final class NestedReadyIterator extends AbstractReadyIterator { private final AbstractReadyIterator parent; private NestedReadyIterator(final AbstractReadyIterator parent, final ModifiedNode node, final Iterator<ModifiedNode> children, final ModificationApplyOperation operation) { super(node, children, operation); this.parent = Preconditions.checkNotNull(parent); } @Override AbstractReadyIterator getParent() { return parent; } @Override void removeFromParent() { parent.children.remove(); } } private static final class RootReadyIterator extends AbstractReadyIterator { private RootReadyIterator(final ModifiedNode node, final Iterator<ModifiedNode> children, final ModificationApplyOperation operation) { super(node, children, operation); } @Override AbstractReadyIterator getParent() { return null; } @Override void removeFromParent() { // No-op, since root node cannot be removed } } }