/**
*
*/
package photoSpreadUtilities;
import java.io.File;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
import photoSpread.PhotoSpreadException;
import photoSpread.PhotoSpreadException.IllegalArgumentException;
import photoSpreadObjects.ObjectIndexerFinder;
import photoSpreadParser.photoSpreadExpression.PhotoSpreadComputable;
import photoSpreadTable.PhotoSpreadTable;
/**
* @author paepcke
*
* Extends TreeSetRandomSubsetIterable to provide two iterator facilities.
* First, an iterator that starts at the nth position
* inclusive in the TreeSetRandomSubsetIterable and continues from there.
*
* Second, an iterator that starts a the nth position,
* inclusive, but only provides elements to the mth
* position, exclusive.
*
* @param <E>: The type object the tree will hold.
*
*/
public class TreeSetRandomSubsetIterable <E>
extends TreeSet<E> implements Iterable<E> {
private static final long serialVersionUID = 1L;
private ObjectIndexerFinder<E> _indexer = null;
/****************************************************
* Constructors
* @param addIndex TODO
*****************************************************/
public TreeSetRandomSubsetIterable() {
super();
}
public TreeSetRandomSubsetIterable(E singleInitialElement) {
super();
add(singleInitialElement);
}
public TreeSetRandomSubsetIterable(E[] initialElements) {
super();
for (E item : initialElements)
add(item);
}
public TreeSetRandomSubsetIterable(Comparator<E> comp) {
super(comp);
}
/****************************************************
* Methods
*****************************************************/
public RandomSubsetIterator iterator (int startPosIncl) throws IllegalArgumentException {
return new RandomSubsetIterator(startPosIncl, this);
}
public RandomSubsetIterator iterator (int startPosIncl, int endPosExcl) throws IllegalArgumentException {
return new RandomSubsetIterator(startPosIncl, endPosExcl, this);
}
public void setIndexer(ObjectIndexerFinder<E> indexer) {
this._indexer = indexer;
}
public ObjectIndexerFinder<?> getIndexer() {
return _indexer;
}
public boolean hasIndexer () {
return (_indexer != null);
}
@Override
public boolean add(E obj) {
if (_indexer != null) {
try {
_indexer.add((PhotoSpreadComputable)obj);
} catch (IllegalArgumentException e) {
Misc.showErrorMsgAndStackTrace(e, "");
//e.printStackTrace();
}
}
return super.add((E) obj);
}
/**
* Add the given object 'obj' to this collection.
* BUT: if the uniqueObjs contain an object that
* wraps the same item (e.g. string, double), then
* add that original object to this collection instead.
* @param obj
* @param uniqueObjs
* @return
*/
public E add(E obj, TreeSetRandomSubsetIterable<E> uniqueObjs) {
E referenceObj = uniqueObjs.containsObject(obj);
if (referenceObj == null) {
add(obj);
return obj;
}
else {
add(referenceObj);
return referenceObj;
}
}
/* NOTE: We dont' need to override addAll(), because the superclass
* simply calls add() anyway. Indexing is done there! We don't
* want to do it twice.
@Override
public boolean addAll(Collection objs) {
if (_indexer != null) {
try {
_indexer.addAll((Collection<PhotoSpreadComputable>)objs);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (ClassCastException e) {
e.printStackTrace();
}
}
return super.addAll(objs);
}
*/
public void addAll(Collection<E> objs, TreeSetRandomSubsetIterable<E> uniqueObjs) {
for (E obj : objs) {
add(obj, uniqueObjs);
}
}
@Override
public boolean remove (Object obj) {
if (_indexer != null) {
try {
_indexer.remove((PhotoSpreadComputable)obj);
} catch (IllegalArgumentException e) {
Misc.showErrorMsgAndStackTrace(e, "");
//e.printStackTrace();
}
}
return super.remove(obj);
}
@Override
public void clear () {
if (_indexer != null)
_indexer.clear();
super.clear();
}
/**
* Given a string, find the object in this
* collection that wraps that string.
* @param <T> is the type of the wrapping object that will be returned.
* @param str
* @return The object that wraps the given string.
*/
public <T> T find (String str) {
if (_indexer != null)
return (T) _indexer.find(str);
else
return null;
}
/**
* Given a Java.IO.File object, find the object in this
* collection that wraps a file of the same pathname.
* @param <T> is the type of the wrapping object that will be returned.
* @param fileObj is the file object for which we want to find the wrapper.
* @return The <T> object that wraps an object with the same file path
* as the given File object.
*/
public <T> T find (File fileObj) {
if (_indexer != null)
return (T) _indexer.find(fileObj);
else
return null;
}
/**
* Given a Double, find the object in this
* collection that wraps that Double number.
* @param <T> is the type of the wrapping object that will be returned.
* @param num is the number whose wrapping object we want to find.
* @return The object that wraps the given Double.
*/
public <T> T find (Double num) {
if (_indexer != null)
return (T) _indexer.find(num);
else
return null;
}
/**
* Given a Table object, find the object in this
* collection that wraps that Table object.
* @param <T> is the type of the wrapping object that will be returned.
* @param tableObj is the table whose wrapping object we want to find.
* @return The object that wraps the given table.
*/
public <T> T find (PhotoSpreadTable tableObj) {
if (_indexer != null)
return (T) _indexer.find(tableObj);
else
return null;
}
public E containsObject (E objToCheckFor) {
if (_indexer != null)
return _indexer.containsValue(objToCheckFor);
return null;
}
/****************************************************
* Inner) Classes
*****************************************************/
class RandomSubsetIterator implements Iterator<E> {
TreeSetRandomSubsetIterable<E> _TreeSetRandomSubsetIterableInstance;
java.util.Iterator<E> _supersIterator;
int _startPosIncl = -1;
int _endPosExcl = -1;
int _currIndex = 0;
/**
* Given a start position <i>n</i>, return an iterator
* whose first element is the TreeMap's <i>nth</i> element.
*
* We use the same iterator that TreeSetRandomSubsetIterable provides. No
* copying of element.
*
* @param startPos
* @return the Iterator
* @throws IllegalArgumentException
*/
public RandomSubsetIterator (
int startPosIncl,
TreeSetRandomSubsetIterable<E> TreeSetRandomSubsetIterableInstance)
throws IllegalArgumentException {
if ((startPosIncl < 0) ||
(startPosIncl >= TreeSetRandomSubsetIterableInstance.size()))
throw new PhotoSpreadException.IllegalArgumentException(
"Random access iterator requires positive start positions that " +
"are less than the size of the collection (which is " +
TreeSetRandomSubsetIterableInstance.size() +
"). But " +
startPosIncl + " (start position) was passed in.");
_startPosIncl = startPosIncl;
_TreeSetRandomSubsetIterableInstance = TreeSetRandomSubsetIterableInstance;
_supersIterator = (java.util.Iterator<E>) _TreeSetRandomSubsetIterableInstance.iterator();
for (int i=0; i<_startPosIncl; i++) {
if (_supersIterator.hasNext())
_supersIterator.next();
}
}
public RandomSubsetIterator (
int startPosIncl,
int endPosExcl,
TreeSetRandomSubsetIterable<E> TreeSetRandomSubsetIterableInstance)
throws IllegalArgumentException {
if ((startPosIncl < 0) ||
(endPosExcl < 0) ||
(startPosIncl >= TreeSetRandomSubsetIterableInstance.size()))
throw new PhotoSpreadException.IllegalArgumentException(
"Random access iterator requires positive start/end positions \n" +
"that are less than the collection size (which is " +
TreeSetRandomSubsetIterableInstance.size() +
"). \nBut '" +
startPosIncl + "' (start position) and '" +
endPosExcl +
"' (end position) were passed in.");
_startPosIncl = startPosIncl;
_endPosExcl = endPosExcl;
_TreeSetRandomSubsetIterableInstance = TreeSetRandomSubsetIterableInstance;
_supersIterator = (java.util.Iterator<E>) _TreeSetRandomSubsetIterableInstance.iterator();
for (int i=0; i<_startPosIncl; i++) {
_supersIterator.next();
}
_currIndex = _startPosIncl;
}
/*
* Version of hasNext() that honors the endPosExcl setting.
*
* @see java.util.Iterator#hasNext()
*/
public boolean hasNext() {
if (_endPosExcl == -1)
// No end position. Iterator is to run to end
// of the TreeSetRandomSubsetIterable's elements:
return _supersIterator.hasNext();
if (_currIndex >= _endPosExcl)
return false;
else
return true;
}
/**
* Next() method that stops as instructed in the constructor.
* @return
* @see java.util.Iterator#next()
*/
@Override
public E next() {
if (hasNext()) {
_currIndex++;
return _supersIterator.next();
}
else
throw new java.util.NoSuchElementException(
"Called next() on iterator with ceiling " +
_endPosExcl +
" (exclusive) and collection size of " +
_TreeSetRandomSubsetIterableInstance.size() +
".");
}
/* (non-Javadoc)
* @see java.util.Iterator#remove()
*/
@Override
public void remove() {
throw new UnsupportedOperationException("Remove is not implemented for this iterator.");
}
}
}