/*
* Copyright (C) 2013 jonas.oreland@gmail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.runnerup.db.entities;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.CursorIndexOutOfBoundsException;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import org.runnerup.common.util.Constants;
import java.util.Arrays;
import java.util.List;
@TargetApi(Build.VERSION_CODES.FROYO)
public abstract class AbstractEntity implements DBEntity {
private final ContentValues mContentValues;
protected abstract List<String> getValidColumns();
protected abstract String getTableName();
protected abstract String getNullColumnHack();
public AbstractEntity() {
this.mContentValues = new ContentValues();
}
/**
* Returns the {@code ContentValues} wrapped by this object.
*/
protected final ContentValues values() {
return mContentValues;
}
public Long getId() {
if (mContentValues.containsKey(Constants.DB.PRIMARY_KEY)) {
return mContentValues.getAsLong(Constants.DB.PRIMARY_KEY);
}
return null;
}
public void setId(Long value) {
values().put(Constants.DB.PRIMARY_KEY, value);
}
public long insert(SQLiteDatabase db) {
this.setId(db.insert(getTableName(), getNullColumnHack(), values()));
return this.getId();
}
public void update(SQLiteDatabase db) {
if (getId() != null) {
db.update(getTableName(), values(), Constants.DB.PRIMARY_KEY + " = ?", new String[]{Long.toString(getId())});
} else {
throw new IllegalArgumentException("Entity has no primary key");
}
}
protected void toContentValues(Cursor c) {
if (c.isClosed() || c.isAfterLast() || c.isBeforeFirst()) {
throw new CursorIndexOutOfBoundsException("Cursor not readable");
}
if (getValidColumns().containsAll(Arrays.asList(c.getColumnNames()))) {
if (Build.VERSION.SDK_INT > 10) {
this.cursorRowToContentValues(c, values());
} else {
DatabaseUtils.cursorRowToContentValues(c, values());
}
} else {
throw new IllegalArgumentException("Cursor " + c.toString() + " is incompatible with the Entity " + this.getClass().getName());
}
for (String column : getValidColumns()) {
if (values().get(column) == null)
values().remove(column);
}
}
// This is a replacement for DatabaseUtils.cursorRowToContentValues
// see https://code.google.com/p/android/issues/detail?id=22219
@SuppressLint("NewApi")
private static void cursorRowToContentValues(Cursor cursor, ContentValues values) {
String[] columns = cursor.getColumnNames();
int length = columns.length;
for (int i = 0; i < length; i++) {
switch (cursor.getType(i)) {
case Cursor.FIELD_TYPE_NULL:
values.putNull(columns[i]);
break;
case Cursor.FIELD_TYPE_INTEGER:
values.put(columns[i], cursor.getLong(i));
break;
case Cursor.FIELD_TYPE_FLOAT:
values.put(columns[i], cursor.getDouble(i));
break;
case Cursor.FIELD_TYPE_STRING:
values.put(columns[i], cursor.getString(i));
break;
case Cursor.FIELD_TYPE_BLOB:
values.put(columns[i], cursor.getBlob(i));
break;
}
}
}
public void readByPrimaryKey(SQLiteDatabase DB, long primaryKey) {
String cols[] = new String[getValidColumns().size()];
getValidColumns().toArray(cols);
Cursor cursor = DB.query(getTableName(), cols, "_id = "
+ primaryKey, null, null, null, null);
try {
if (cursor.moveToFirst()) {
toContentValues(cursor);
}
} finally {
cursor.close();
}
}
}