/**
* Copyright 2012 Neurowork Consulting S.L.
*
* This file is part of eMobc.
*
* DataEngine.java
* eMobc Android Framework
*
* eMobc is free software: you can redistribute it and/or modify
* it under the terms of the Affero GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* eMobc 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 Affero GNU General Public License
* along with eMobc. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.emobc.android.data.engine;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.emobc.android.data.metadata.Entity;
import com.emobc.android.data.metadata.Field;
import com.emobc.android.data.metadata.Model;
import com.emobc.android.data.metadata.Table;
import com.emobc.android.data.sql.SQLiteSqlCreator;
/**
* Simple SQLite Database Engine Wrapper.
* This class uses the metadata objects such as {@link Table} and {@link Field}
* to create a CRUD Facade.
* @author Jorge E. Villaverde
* @since 0.1
* @version 0.1
*/
public class DataEngine extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private final Model model;
private SQLiteSqlCreator sqlCreator = new SQLiteSqlCreator();
public DataEngine(Context context, Model model){
super(context, model.getName(), null, DATABASE_VERSION);
this.model = model;
}
@Override
public void onCreate(SQLiteDatabase db) {
final String createSql = sqlCreator.createModelSql(model);
db.execSQL(createSql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
final String dropSql = sqlCreator.dropModelSql(model);
db.execSQL(dropSql);
onCreate(db);
}
/**
* @return Database Model Metadata.
*/
public Model getModel() {
return model;
}
/**
* Creates a {@link Cursor} for {@link Table}.
* If the table does not exist in the model, an {@link IllegalArgumentException} is thrown.
* @param table
* @return
*/
public Cursor readTable(Table table){
if(table == null)
throw new IllegalArgumentException("Table is null");
Table modelTable = model.getTable(table.getName());
if(modelTable == null)
throw new IllegalArgumentException("Model has no table: " + table.getName());
Cursor ret = getReadableDatabase().query(table.getName(),
table.getColumns(),
null, null, null, null, null);
return ret;
}
/**
* Read all {@link Entity} from the database.
* @param table
* @return List of entities read form database.
*/
public List<Entity> readAllEntities(Table table) {
Cursor cursor = readTable(table);
if(cursor == null)
return null;
List<Entity> entities = new ArrayList<Entity>();
if (cursor.moveToFirst()) {
do {
Entity entity = readEntityFromCursor(cursor, table);
entities.add(entity);
}while(cursor.moveToNext());
}
cursor.close();
return entities;
}
public Entity findEntityById(Table table, String id){
checkTable(table);
Cursor cursor = getReadableDatabase().query(table.getName(),
table.getColumns(),
Table.DEFAULT_WHERE,
new String[]{id},
null,
null,
null);
Entity ret = null;
if (cursor.moveToFirst()) {
do {
ret = readEntityFromCursor(cursor, table);
if(ret != null){
break;
}
}while(cursor.moveToNext());
}
cursor.close();
return ret ;
}
public boolean createEntity(Entity entity) {
return createEntity(entity.getTable(), entity.getData());
}
public boolean createEntity(Table table, Object[] data){
if(table == null)
throw new IllegalArgumentException("Table is null");
Table modelTable = model.getTable(table.getName());
if(modelTable == null)
throw new IllegalArgumentException("Model has no table: " + table.getName());
ContentValues values = new ContentValues();
List<Field> fields = table.getFields();
for(int i = 0; i < fields.size(); i++){
Field field = fields.get(i);
if(!Table.DEFAULT_ID_FIELD_NAME.equals(field.getName())){
values.put(field.getName(), data[i].toString());
}
}
Long id = getWritableDatabase().insert(table.getName(), null, values);
return (id != -1);
}
public boolean updateEntity(Entity entity){
checkEntity(entity);
Table table = entity.getTable();
Object[] data = entity.getData();
String id = null;
ContentValues values = new ContentValues();
List<Field> fields = table.getFields();
for(int i = 0; i < fields.size(); i++){
Field field = fields.get(i);
if(Table.DEFAULT_ID_FIELD_NAME.equals(field.getName())){
id = data[i].toString();
}else{
values.put(field.getName(), data[i].toString());
}
}
int ret = getWritableDatabase().update(
table.getName(),
values, Table.DEFAULT_WHERE,
new String[]{id});
return (ret != -1);
}
public boolean deleteEntity(Entity entity){
checkEntity(entity);
Table table = entity.getTable();
String id = entity.getId();
int rowsAffected = getWritableDatabase().delete(
table.getName(),
Table.DEFAULT_WHERE,
new String[]{id});
return (rowsAffected > 0);
}
private void checkEntity(Entity entity) {
if(entity == null)
throw new IllegalArgumentException("Entity is null");
if(entity.getTable() == null)
throw new IllegalArgumentException("Table is null");
if(model.getTable(entity.getTable().getName()) == null)
throw new IllegalArgumentException("Model has no table: " + entity.getTable().getName());
if(entity.getData() == null)
throw new IllegalArgumentException("Entity Data is null");
}
private void checkTable(Table table){
if(model.getTable(table.getName()) == null)
throw new IllegalArgumentException("Model has no table: " + table.getName());
}
private static Entity readEntityFromCursor(Cursor cursor, Table table){
List<Field> fields = table.getFields();
List<Object> data = new ArrayList<Object>(fields.size());
for(int i=0;i < fields.size(); i++){
Field field = fields.get(i);
switch (field.getType()) {
case TEXT:
data.add(cursor.getString(i));
break;
case NUMBER:
data.add(cursor.getInt(i));
break;
case DATE:
data.add(cursor.getString(i));
break;
default:
break;
}
}
Entity entity = new Entity(table, data.toArray());
return entity;
}
}