/**
*
*/
package org.commcare.android.database;
import java.util.Iterator;
import org.javarosa.core.services.storage.IStorageIterator;
import org.javarosa.core.services.storage.Persistable;
import org.javarosa.core.services.storage.StorageModifiedException;
import android.database.Cursor;
/**
* @author ctsims
*
*/
public class SqlStorageIterator<T extends Persistable> implements IStorageIterator, Iterator<T> {
Cursor c;
SqlStorage<T> storage;
boolean isClosedByProgress = false;
int count;
String primaryId;
public SqlStorageIterator(Cursor c, SqlStorage<T> storage) {
this(c, storage, null);
}
/**
* Creates an iterator into either a full or partial sql storage.
*
* @param c The uninitialized cursor for a query.
* @param storage The storage being queried
* @param primaryId An optional key index for a primary id that is part
* of the returned iterator
*/
public SqlStorageIterator(Cursor c, SqlStorage<T> storage, String primaryId) {
this.c = c;
this.storage = storage;
this.primaryId = primaryId;
count = c.getCount();
if(count == 0) {
c.close();
isClosedByProgress = true;
} else {
c.moveToFirst();
}
}
/* (non-Javadoc)
* @see org.javarosa.core.services.storage.IStorageIterator#hasMore()
*/
public boolean hasMore() {
if(!c.isClosed()) {
return !c.isAfterLast();
} else {
if(isClosedByProgress) {
return false;
} else {
//If we didn't close the cursor as part of the iterator, it means that it
//was forcibly invalidated externally, fail accordingly.
throw new StorageModifiedException("Storage Iterator [" + storage.table + "]" + " was invalidated");
}
}
}
/* (non-Javadoc)
* @see org.javarosa.core.services.storage.IStorageIterator#nextID()
*/
public int nextID() {
int id = c.getInt(c.getColumnIndexOrThrow(DbUtil.ID_COL));
c.moveToNext();
if(c.isAfterLast()) {
c.close();
isClosedByProgress = true;
}
return id;
}
/* (non-Javadoc)
* @see org.javarosa.core.services.storage.IStorageIterator#nextRecord()
*/
public T nextRecord() {
byte[] data = c.getBlob(c.getColumnIndexOrThrow(DbUtil.DATA_COL));
//we don't really use this
nextID();
return storage.newObject(data);
}
/* (non-Javadoc)
* @see org.javarosa.core.services.storage.IStorageIterator#numRecords()
*/
public int numRecords() {
return count;
}
public boolean hasNext() {
return hasMore();
}
public T next() {
return nextRecord();
}
public void remove() {
//Unsupported for now
}
public int peekID() {
int id = c.getInt(c.getColumnIndexOrThrow(DbUtil.ID_COL));
return id;
}
//TESTING ONLY
/* (non-Javadoc)
* @see org.javarosa.core.services.storage.IStorageIterator#nextRecord()
*/
private byte[] getBlob() {
byte[] data = c.getBlob(c.getColumnIndexOrThrow(DbUtil.DATA_COL));
return data;
}
private Cursor getRawCursor() {
return c;
}
public String getPrimaryId() {
return c.getString(c.getColumnIndexOrThrow(primaryId));
}
}