/* * 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.api.schema.tree; import com.google.common.annotations.Beta; import com.google.common.base.Preconditions; import java.util.Iterator; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utility class holding methods useful when dealing with {@link DataTreeCandidate} instances. */ @Beta public final class DataTreeCandidates { private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidates.class); private DataTreeCandidates() { throw new UnsupportedOperationException(); } public static DataTreeCandidate newDataTreeCandidate(final YangInstanceIdentifier rootPath, final DataTreeCandidateNode rootNode) { return new DefaultDataTreeCandidate(rootPath, rootNode); } public static DataTreeCandidate fromNormalizedNode(final YangInstanceIdentifier rootPath, final NormalizedNode<?, ?> node) { return new DefaultDataTreeCandidate(rootPath, new NormalizedNodeDataTreeCandidateNode(node)); } public static void applyToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidate candidate) { DataTreeCandidateNodes.applyToCursor(cursor, candidate.getRootNode()); } public static void applyToModification(final DataTreeModification modification, final DataTreeCandidate candidate) { if (modification instanceof CursorAwareDataTreeModification) { applyToCursorAwareModification((CursorAwareDataTreeModification) modification, candidate); return; } final DataTreeCandidateNode node = candidate.getRootNode(); final YangInstanceIdentifier path = candidate.getRootPath(); switch (node.getModificationType()) { case DELETE: modification.delete(path); LOG.debug("Modification {} deleted path {}", modification, path); break; case SUBTREE_MODIFIED: LOG.debug("Modification {} modified path {}", modification, path); NodeIterator iterator = new NodeIterator(null, path, node.getChildNodes().iterator()); do { iterator = iterator.next(modification); } while (iterator != null); break; case UNMODIFIED: LOG.debug("Modification {} unmodified path {}", modification, path); // No-op break; case WRITE: modification.write(path, node.getDataAfter().get()); LOG.debug("Modification {} written path {}", modification, path); break; default: throw new IllegalArgumentException("Unsupported modification " + node.getModificationType()); } } private static void applyToCursorAwareModification(final CursorAwareDataTreeModification modification, final DataTreeCandidate candidate) { final YangInstanceIdentifier candidatePath = candidate.getRootPath(); if (candidatePath.isEmpty()) { try (DataTreeModificationCursor cursor = modification.createCursor(candidatePath)) { DataTreeCandidateNodes.applyRootToCursor(cursor, candidate.getRootNode()); } } else { try (DataTreeModificationCursor cursor = modification.createCursor(candidatePath.getParent())) { DataTreeCandidateNodes.applyRootedNodeToCursor(cursor, candidatePath, candidate.getRootNode()); } } } private static final class NodeIterator { private final Iterator<DataTreeCandidateNode> iterator; private final YangInstanceIdentifier path; private final NodeIterator parent; public NodeIterator(@Nullable final NodeIterator parent, @Nonnull final YangInstanceIdentifier path, @Nonnull final Iterator<DataTreeCandidateNode> iterator) { this.iterator = Preconditions.checkNotNull(iterator); this.path = Preconditions.checkNotNull(path); this.parent = parent; } NodeIterator next(final DataTreeModification modification) { while (iterator.hasNext()) { final DataTreeCandidateNode node = iterator.next(); final YangInstanceIdentifier child = path.node(node.getIdentifier()); switch (node.getModificationType()) { case DELETE: modification.delete(child); LOG.debug("Modification {} deleted path {}", modification, child); break; case APPEARED: case DISAPPEARED: case SUBTREE_MODIFIED: LOG.debug("Modification {} modified path {}", modification, child); return new NodeIterator(this, child, node.getChildNodes().iterator()); case UNMODIFIED: LOG.debug("Modification {} unmodified path {}", modification, child); // No-op break; case WRITE: modification.write(child, node.getDataAfter().get()); LOG.debug("Modification {} written path {}", modification, child); break; default: throw new IllegalArgumentException("Unsupported modification " + node.getModificationType()); } } return parent; } } }