/* * Copyright (c) 2011 LinkedIn, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ /** * */ package com.flaptor.indextank.util; import java.util.List; import com.flaptor.util.CollectionsUtil.PeekingIterator; import com.google.common.base.Function; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; public abstract class Intersection<K,V extends Comparable<V>> extends AbstractSkippableIterable<V> { private Iterable<SkippableIterable<K>> cursors; public Intersection(Iterable<SkippableIterable<K>> cursors) { this.cursors = cursors; } protected abstract V transform(K k); protected boolean shouldUse(V v, List<K> ks) { return true; } @Override public SkippableIterator<V> iterator() { return new AbstractSkippableIterator<V>() { private List<PeekingSkippableIterator<K>> iterators = Lists.newArrayList(Iterables.transform(cursors, Intersection.<K>peekingIteratorFunction())); @Override protected V computeNext() { V current = null; while (true) { boolean found = true; for (PeekingSkippableIterator<K> it : iterators) { while (it.hasNext() && current != null && transform(it.peek()).compareTo(current) < 0) { advanceTo(it, current); it.next(); } if (!it.hasNext()) { return endOfData(); } if (current != null && transform(it.peek()).equals(current)) { continue; } else { found = false; current = transform(it.peek()); } } if (found) { V r = null; if (shouldUse(current, peekedItems())) { r = current; } for (PeekingIterator<K> it : iterators) { it.next(); } if (r != null) return r; } } } private List<K> peekedItems() { return Lists.transform(iterators, Intersection.<K>peekFunction()); } @Override public void skipTo(int i) { for (PeekingSkippableIterator<K> it : iterators) { it.skipTo(i); } } }; } public static <T> Function<PeekingIterator<T>, T> peekFunction() { return new Function<PeekingIterator<T>, T>() { @Override public T apply(PeekingIterator<T> it) { return it.peek(); } }; } public static <T> Function<SkippableIterable<T>, PeekingSkippableIterator<T>> peekingIteratorFunction() { return new Function<SkippableIterable<T>, PeekingSkippableIterator<T>>() { @Override public PeekingSkippableIterator<T> apply(SkippableIterable<T> ts) { return new PeekingSkippableIterator<T>(ts.iterator()); } }; } protected void advanceTo(PeekingSkippableIterator<K> it, V current) { } }