| /******************************************************************************* |
| * Copyright (c) 2016 Obeo. |
| * 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 |
| * |
| * Contributors: |
| * Obeo - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.emf.compare.internal.conflict; |
| |
| import java.util.Iterator; |
| import java.util.NoSuchElementException; |
| import java.util.function.Predicate; |
| |
| import org.eclipse.emf.common.util.TreeIterator; |
| import org.eclipse.emf.compare.Diff; |
| import org.eclipse.emf.compare.Match; |
| import org.eclipse.emf.compare.internal.SubMatchIterator; |
| |
| /** |
| * A custom iterator that will walk a Match->submatch tree, and allow iteration over the Diffs of these |
| * Matches. |
| * <p> |
| * Since we're walking over Matches but returning Diffs, this is not a good candidate for guava's filters. |
| * We're providing the custom {@link DiffTreeIterator#setFilter(Predicate)} and |
| * {@link DiffTreeIterator#setPruningFilter(Predicate)} to allow for filtering or pruning the the iteration. |
| * </p> |
| * |
| * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a> |
| */ |
| public class DiffTreeIterator implements Iterator<Diff> { |
| /** |
| * The tree iterator that will walk over our Match tree. Some of the paths can be pruned through the use |
| * of a {@link #pruningFilter}. |
| */ |
| private final TreeIterator<Match> subMatchIterator; |
| |
| /** An iterator over the differences of the current Match. */ |
| private Iterator<Diff> diffIterator; |
| |
| /** Current match. */ |
| private Match current; |
| |
| /** The Diff that will be returned by the next call to {@link #next()}. */ |
| private Diff nextDiff; |
| |
| /** Only Diffs that meet this criterion will be returned by this iterator. */ |
| private Predicate<? super Diff> filter = x -> true; |
| |
| /** |
| * This particular filter can be used in order to prune a given Match and all of its differences and |
| * sub-differences. |
| */ |
| private Predicate<? super Match> pruningFilter = x -> false; |
| |
| /** |
| * Constructs our iterator given the root of the Match tree to iterate over. |
| * |
| * @param start |
| * Starting match of the tree we'll iterate over. |
| */ |
| public DiffTreeIterator(Match start) { |
| this.current = start; |
| this.subMatchIterator = new SubMatchIterator(start); |
| this.diffIterator = start.getDifferences().iterator(); |
| } |
| |
| /** |
| * Sets the criterion that Diffs must meet to be returned by this iterator. |
| * |
| * @param filter |
| * The filter differences must meet. |
| */ |
| public void setFilter(Predicate<? super Diff> filter) { |
| this.filter = filter; |
| } |
| |
| /** |
| * Sets the pruning filter for this iterator. Any Match that meets this criterion will be pruned along |
| * with all of its differences and sub-differences. |
| * |
| * @param pruningFilter |
| * The pruning filter for this iterator. |
| */ |
| public void setPruningFilter(Predicate<? super Match> pruningFilter) { |
| this.pruningFilter = pruningFilter; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see java.util.Iterator#hasNext() |
| */ |
| public boolean hasNext() { |
| if (nextDiff != null) { |
| return true; |
| } |
| if (!diffIterator.hasNext()) { |
| computeNextMatch(); |
| } |
| while (nextDiff == null && diffIterator.hasNext()) { |
| final Diff next = diffIterator.next(); |
| if (filter.test(next)) { |
| nextDiff = next; |
| } |
| } |
| return nextDiff != null; |
| } |
| |
| /** |
| * Computes the next match within the sub-match tree, pruning those that may meet {@link #pruningFilter}. |
| */ |
| private void computeNextMatch() { |
| final Match old = current; |
| while (current == old && subMatchIterator.hasNext()) { |
| final Match next = subMatchIterator.next(); |
| if (pruningFilter.test(next)) { |
| subMatchIterator.prune(); |
| } else { |
| current = next; |
| diffIterator = current.getDifferences().iterator(); |
| } |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see java.util.Iterator#next() |
| */ |
| public Diff next() { |
| if (!hasNext()) { |
| throw new NoSuchElementException(); |
| } |
| final Diff next = nextDiff; |
| nextDiff = null; |
| return next; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see java.util.Iterator#remove() |
| */ |
| public void remove() { |
| diffIterator.remove(); |
| } |
| } |