package it.unimi.dsi.mg4j.search;
/*
* MG4J: Managing Gigabytes for Java
*
* Copyright (C) 2003-2010 Paolo Boldi and Sebastiano Vigna
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
import it.unimi.dsi.mg4j.index.IndexIterator;
import it.unimi.dsi.util.Interval;
import it.unimi.dsi.util.Intervals;
import java.util.Collections;
import java.util.NoSuchElementException;
/** A class providing static methods and objects that do useful things with interval iterators.
*
*/
public class IntervalIterators {
private IntervalIterators() {}
/** An iterator that throws an exception on all advancing method calls, except for {@link #hasNext()},
* which has a settable value. The extent is 0.
*
* <P>The only purpose of this class is to instantiate singleton iterators
* such as {@link #TRUE} and {@link #FALSE}.
*/
protected static class FakeIterator extends AbstractObjectIterator<Interval> implements IntervalIterator {
final boolean hasNext;
private FakeIterator( final boolean hasNext ) { this.hasNext = hasNext; }
public boolean hasNext() { return hasNext; }
public void reset() {}
public Interval next() { throw hasNext ? new UnsupportedOperationException() : new NoSuchElementException(); }
public Interval nextInterval() { if ( ! hasNext ) new UnsupportedOperationException(); return null; }
public int extent() { return 0; } // TODO: this is not correct for FALSE (but it is unlikely to be a problem)
public String toString() { return this.getClass().getName() + "." + ( hasNext ? "TRUE" : "FALSE" ); }
public void intervalTerms( IntSet terms ) {}
}
/** A singleton iterator representing maximum truth.
*
* <p>This iterator is a placeholder for an iterator returning just {@link Intervals#EMPTY_INTERVAL}.
* The antichain formed by the empty interval is the top element of the lattice of antichains, and
* thus represents the highest truth. Since, however, <code>EMPTY_INTERVAL</code>
* is a singleton that slightly violates the {@link Interval} invariants, an iterator actually
* returning <code>EMPTY_INTERVAL</code> would cause severe problems in all algorithms manipulating
* intervals. Rather, {@link #TRUE} is treated separately and is never actually used in
* an algorithm on interval antichains (also because, albeit it claims to have elements,
* it will return <code>null</code> on {@link IntervalIterator#nextInterval()}).
*
* <P>A most natural appearance of {@link #TRUE} is due to negation: all documents satisfying
* a negative query return {@link #TRUE} as interval iterator.
*
* <P>Finally, an {@link IndexIterator} by convention returns {@link #TRUE}
* when {@link DocumentIterator#intervalIterator(it.unimi.dsi.mg4j.index.Index)}
* is called with an argument that is not the {@linkplain IndexIterator#index() key index}.
* The idea is that there is no witness to be returned, but the query is nonetheless true.
*/
public final static IntervalIterator TRUE = new FakeIterator( true );
/** A singleton empty interval iterator.
*
* <P>The main usefulness of this iterator is as a singleton: in some circumstances you have
* to return an empty iterator, and since it is by definition stateless, it is a pity
* to create a new object (the same considerations led to {@link Collections#emptySet()}).
*/
public final static IntervalIterator FALSE = new FakeIterator( false );
}