/*
* Kodkod -- Copyright (c) 2005-present, Emina Torlak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package kodkod.util.ints;
import java.util.Collection;
import java.util.Iterator;
/**
* <p>Represents a sparse sequence -- a sequence whose indices are not
* necessarily contiguous. For example, a sparse sequence can have
* elements at indices 10, 2121, and 3000, without having any elements
* in between. This specification of sparse sequences also supports
* negative indeces. Formally, the following methods specify a partial
* function from integers to values of type V.</p>
*
* <p>Sequence implementations are not required to support mutation.
* All mutating operations are optional and may
* throw an UnsupportedOperationException.</p>
*
* @specfield entries: int -> lone V
*
* @author Emina Torlak
*/
public interface SparseSequence<V> extends Iterable<IndexedEntry<V>> {
/**
* Returns the number of entries in this sequence.
* @return #this.entries
*/
public abstract int size();
/**
* Returns true if this sequence is empty; otherwise returns false.
* @return no this.entries
*/
public abstract boolean isEmpty();
/**
* Removes all entries from this sequences.
* @ensures no this.entries'
*/
public abstract void clear();
/**
* Puts the given value at the specified index. If the
* sequence already mapped the index to a value, the
* previous value is replaced with the new one and returned.
*
* @ensures this.entries' = this.entries + index->value
* @return this.entries[index]
* @throws IndexOutOfBoundsException the given index
* is not valid for this sequence.
* @throws IllegalArgumentException the given value cannot
* be stored in this sequence.
*/
public abstract V put(int index, V value);
/**
* Copies all of the entries from the specified sparse sequence to
* this sequence. The effect of this call is equivalent to that of
* calling put(e.index, e.value) on this sequence once for each entry
* e in the specified sequence.
* @ensures this.entries' = this.entries ++ s.entries
* @throws IndexOutOfBoundsException s contains indeces that are
* not valid for this sequence.
* @throws IllegalArgumentException s contains a value that cannot
* be stored in this sequence.
*/
public abstract void putAll(SparseSequence<? extends V> s);
/**
* Returns the value to which this sequence maps the given
* index. If the index is not mapped, null is returned.
* @return this.entries[index]
*/
public abstract V get(int index);
/**
* Removes the entry with the given index, if it exists, and
* returns the value previously stored at the index. If the
* sequence had no previous mapping for the index, null is returned.
* @ensures this.entries' = this.entries - index->E
* @return this.entries[index]
*/
public abstract V remove(int index);
/**
* Returns true if this sparse sequence has an entry for the
* given index; otherwise returns false.
* @return some this.entries[index]
*/
public abstract boolean containsIndex(int index);
/**
* Returns the set of all indices mapped by this sparse sequence.
* The returned set supports removal iff this is not an unmodifiable
* sparse sequence. The returned set may be uncloneable.
* @return {s: IntSet | s.ints = this.entries.V}
*/
public abstract IntSet indices();
/**
* Returns true if this sequence has an entry with the given value;
* otherwise returns false.
* @return some this.entries.value
*/
public abstract boolean contains(Object value);
/**
* Returns a Collection view of the values stored in this sequence.
* The returned collection supports removal iff this is not an
* unmodifiable sparse sequence.
* @return {c: Collection | c.size()=this.size() &&
* all v: V | c.contains(v) <=> this.contains(v) }
*/
public abstract Collection<V> values();
/**
* Returns an iterator over the entries in this sequence
* in the ascending order of indeces, starting at this.first().
* @return an iterator over this.entries starting at the entry
* with the smallest index
*/
public abstract Iterator<IndexedEntry<V>> iterator();
/**
* Returns an iterator over the entries in this sequence,
* whose indeces are between from and to. If from < to,
* the entries are returned in the ascending order of
* indeces. Otherwise, they are returned in the descending
* order of indeces.
* @return an iterator over the entries in this sequence
* whose indeces are between from and to. Formally, if
* from < to, then the first and last entries returned
* by the iterator are this.ceil(from) and this.floor(to).
* Otherwise, they are this.floor(from) and this.ceil(to).
*/
public abstract Iterator<IndexedEntry<V>> iterator(int from, int to);
/**
* Returns the entry with the smallest index. If the sequence
* is empty, returns null.
* @return {e: IndexedEntry | e.index = min(this.entries.E) &&
* e.value = this.entries[e.index] }
*/
public abstract IndexedEntry<V> first();
/**
* Returns the entry with the largest index. If the sequence
* is empty, returns null.
* @return {e: IndexedEntry | e.index = max(this.entries.E) &&
* e.value = this.entries[e.index] }
*/
public abstract IndexedEntry<V> last();
/**
* If an entry for the given index exists, it is returned. Otherwise,
* successor(index) is returned.
* @return this.containsIndex(index) =>
* {e: IndexedEntry | e.index = index && e.value = this.entries[index] },
* successor(index)
*/
public abstract IndexedEntry<V> ceil(int index);
/**
* If an entry for the given index exists, it is returned. Otherwise,
* predecessor(index) is returned.
* @return this.containsIndex(index) =>
* {e: IndexedEntry | e.index = index && e.value = this.entries[index] },
* predecessor(index)
*/
public abstract IndexedEntry<V> floor(int index);
/**
* Compares the specified object with this sequence for equality.
* Returns true if the given object is also a sparse sequence and the two
* sequences have the same entries. More formally, two sequences t1 and t2 have the
* the same entries if they represent the same function from integers to values: i.e.
* t1.entries = t2.entries. This ensures that the equals method works properly across
* different implementations of the SparseSequence interface.
* @return o in SparseSequence && o.entries = this.entries
*/
public abstract boolean equals(Object o);
/**
* Returns the hash code value for this sparse sequence.
* A hash function for a sparse sequence must ensure that t1.equals(t2)
* implies that t1.hashCode()==t2.hashCode() for any two sequences t1 and t2,
* as required by the general contract of Object.hashCode.
* @return hash code for this sparse sequence
*/
public abstract int hashCode();
/**
* Returns a copy of this sparse sequence. The copy is independent of this
* sequence unless this is a singleton or immutable, in which case
* clone() may return this. An implementing class that does not support
* cloning may throw a CloneNotSupportedException.
* @return a copy of this sparse sequence.
* @throws CloneNotSupportedException this is not cloneable
*/
public abstract SparseSequence<V> clone() throws CloneNotSupportedException;
}