package by.istin.android.xcore.model;
import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.CharArrayBuffer;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import by.istin.android.xcore.utils.CursorUtils;
/**
* Created by Uladzimir_Klyshevich on 8/30/13.
*/
public class CursorModel implements Cursor, List<Cursor> {
public static interface CursorModelCreator {
CursorModel create(Cursor cursor);
public static CursorModelCreator DEFAULT = new CursorModelCreator() {
@Override
public CursorModel create(Cursor cursor) {
return new CursorModel(cursor);
}
};
}
public void doInBackground(Context context) {
}
private Cursor mCursor;
private final Set<ContentObserver> mContentObservers = Collections.synchronizedSet(new HashSet<ContentObserver>());
private final Set<Cursor> mCursors = Collections.synchronizedSet(new HashSet<Cursor>());
private final Set<DataSetObserver> mDataSetObservers = Collections.synchronizedSet(new HashSet<DataSetObserver>());
private final Object mLock = new Object();
public CursorModel(Cursor cursor) {
this(cursor, true);
}
public CursorModel(Cursor cursor, boolean isMoveToFirst) {
this.mCursor = cursor;
if (isMoveToFirst) {
this.mCursor.moveToFirst();
}
}
@Override
public int getCount() {
return mCursor.getCount();
}
@Override
public int getPosition() {
return mCursor.getPosition();
}
@Override
public boolean move(int i) {
return mCursor.move(i);
}
@Override
public boolean moveToPosition(int i) {
return mCursor.moveToPosition(i);
}
@Override
public boolean moveToFirst() {
return mCursor.moveToFirst();
}
@Override
public boolean moveToLast() {
return mCursor.moveToLast();
}
@Override
public boolean moveToNext() {
return mCursor.moveToNext();
}
@Override
public boolean moveToPrevious() {
return mCursor.moveToPrevious();
}
@Override
public boolean isFirst() {
return mCursor.isFirst();
}
@Override
public boolean isLast() {
return mCursor.isLast();
}
@Override
public boolean isBeforeFirst() {
return mCursor.isBeforeFirst();
}
@Override
public boolean isAfterLast() {
return mCursor.isAfterLast();
}
@Override
public int getColumnIndex(String s) {
return mCursor.getColumnIndex(s);
}
@Override
public int getColumnIndexOrThrow(String s) throws IllegalArgumentException {
return mCursor.getColumnIndexOrThrow(s);
}
@Override
public String getColumnName(int i) {
return mCursor.getColumnName(i);
}
@Override
public String[] getColumnNames() {
return mCursor.getColumnNames();
}
@Override
public int getColumnCount() {
return mCursor.getColumnCount();
}
@Override
public byte[] getBlob(int i) {
return mCursor.getBlob(i);
}
@Override
public String getString(int i) {
return mCursor.getString(i);
}
@Override
public void copyStringToBuffer(int i, CharArrayBuffer charArrayBuffer) {
mCursor.copyStringToBuffer(i, charArrayBuffer);
}
protected void setCursor(Cursor cursor) {
synchronized (mLock) {
if (mCursor != cursor) {
Cursor oldCursor = mCursor;
mCursor = cursor;
if (!mContentObservers.isEmpty()) {
for (ContentObserver contentObserver : mContentObservers) {
registerContentObserver(contentObserver);
}
}
if (!mDataSetObservers.isEmpty()) {
for (DataSetObserver dataSetObserver : mDataSetObservers) {
registerDataSetObserver(dataSetObserver);
}
}
mCursors.add(oldCursor);
}
}
}
@Override
public short getShort(int i) {
return mCursor.getShort(i);
}
@Override
public int getInt(int i) {
return mCursor.getInt(i);
}
@Override
public long getLong(int i) {
return mCursor.getLong(i);
}
@Override
public float getFloat(int i) {
return mCursor.getFloat(i);
}
@Override
public double getDouble(int i) {
return mCursor.getDouble(i);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public int getType(int i) {
return mCursor.getType(i);
}
@Override
public boolean isNull(int i) {
return mCursor.isNull(i);
}
@Override
public void deactivate() {
mCursor.deactivate();
}
@Override
public boolean requery() {
return mCursor.requery();
}
@Override
public void close() {
synchronized (mLock) {
mCursor.close();
if (!mCursors.isEmpty()) {
for (Cursor cursor : mCursors) {
CursorUtils.close(cursor);
}
mCursors.clear();
}
}
}
@Override
public boolean isClosed() {
return mCursor.isClosed();
}
@Override
public void registerContentObserver(ContentObserver contentObserver) {
synchronized (mLock) {
this.mContentObservers.add(contentObserver);
mCursor.registerContentObserver(contentObserver);
}
}
@Override
public void unregisterContentObserver(ContentObserver contentObserver) {
synchronized (mLock) {
this.mContentObservers.remove(contentObserver);
mCursor.unregisterContentObserver(contentObserver);
}
}
@Override
public void registerDataSetObserver(DataSetObserver dataSetObserver) {
synchronized (mLock) {
this.mDataSetObservers.add(dataSetObserver);
mCursor.registerDataSetObserver(dataSetObserver);
}
}
@Override
public void unregisterDataSetObserver(DataSetObserver dataSetObserver) {
synchronized (mLock) {
this.mDataSetObservers.remove(dataSetObserver);
mCursor.unregisterDataSetObserver(dataSetObserver);
}
}
@Override
public void setNotificationUri(ContentResolver contentResolver, Uri uri) {
mCursor.setNotificationUri(contentResolver, uri);
}
@Override
public boolean getWantsAllOnMoveCalls() {
return mCursor.getWantsAllOnMoveCalls();
}
@Override
public Bundle getExtras() {
return mCursor.getExtras();
}
@Override
public Bundle respond(Bundle bundle) {
return mCursor.respond(bundle);
}
public Long getLong(String key) {
return CursorUtils.getLong(key, mCursor);
}
public byte[] getBlob(String key) {
return CursorUtils.getBlob(key, mCursor);
}
public Integer getInt(String key) {
return CursorUtils.getInt(key, mCursor);
}
public Byte getByte(String key) {
return CursorUtils.getByte(key, mCursor);
}
public Double getDouble(String key) {
return CursorUtils.getDouble(key, mCursor);
}
public Float getFloat(String key) {
return CursorUtils.getFloat(key, mCursor);
}
public Short getShort(String key) {
return CursorUtils.getShort(key, mCursor);
}
public String getString(String key) {
return CursorUtils.getString(key, mCursor);
}
@Override
public boolean add(Cursor object) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection<? extends Cursor> collection) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean contains(Object object) {
throw new UnsupportedOperationException();
}
@Override
public boolean containsAll(Collection<?> collection) {
throw new UnsupportedOperationException();
}
@Override
public boolean isEmpty() {
return CursorUtils.isEmpty(mCursor);
}
@Override
public Iterator<Cursor> iterator() {
return new Iterator<Cursor>() {
@Override
public boolean hasNext() {
return !CursorUtils.isEmpty(mCursor) && !mCursor.isLast();
}
@Override
public Cursor next() {
mCursor.moveToNext();
return mCursor;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public boolean remove(Object object) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection<?> collection) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection<?> collection) {
throw new UnsupportedOperationException();
}
@Override
public int size() {
return CursorUtils.getSize(mCursor);
}
@Override
public ContentValues[] toArray() {
List<ContentValues> list = new ArrayList<ContentValues>();
CursorUtils.convertToContentValues(mCursor, list, CursorUtils.Converter.get());
return list.toArray(new ContentValues[list.size()]);
}
@Override
public <T> T[] toArray(T[] array) {
throw new UnsupportedOperationException("use toArray method instead of");
}
@Override
public void add(int location, Cursor object) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(int location, Collection<? extends Cursor> collection) {
throw new UnsupportedOperationException();
}
@Override
public CursorModel get(int location) {
mCursor.moveToPosition(location);
return this;
}
@Override
public int indexOf(Object object) {
throw new UnsupportedOperationException();
}
@Override
public int lastIndexOf(Object object) {
throw new UnsupportedOperationException();
}
private class CursorListIterator implements ListIterator<Cursor> {
private int currentPostion = 0;
private CursorListIterator(int intialPostion) {
this.currentPostion = intialPostion;
mCursor.moveToPosition(currentPostion);
}
@Override
public void add(Cursor object) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasNext() {
return currentPostion < CursorUtils.getSize(mCursor);
}
@Override
public boolean hasPrevious() {
return currentPostion != 0;
}
@Override
public Cursor next() {
currentPostion = nextIndex();
mCursor.moveToPosition(currentPostion);
return mCursor;
}
@Override
public int nextIndex() {
return currentPostion+1;
}
@Override
public Cursor previous() {
currentPostion = previousIndex();
mCursor.moveToPosition(currentPostion);
return mCursor;
}
@Override
public int previousIndex() {
return currentPostion -1;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void set(Cursor object) {
throw new UnsupportedOperationException();
}
}
@Override
public ListIterator<Cursor> listIterator() {
return new CursorListIterator(0);
}
@Override
public ListIterator<Cursor> listIterator(int location) {
return new CursorListIterator(location);
}
@Override
public Cursor remove(int location) {
throw new UnsupportedOperationException();
}
@Override
public Cursor set(int location, Cursor object) {
throw new UnsupportedOperationException();
}
@Override
public List<Cursor> subList(int start, int end) {
throw new UnsupportedOperationException();
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public Uri getNotificationUri() {
return mCursor.getNotificationUri();
}
}