package com.mehmetakiftutuncu.eshotroid.database;
import java.util.ArrayList;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.mehmetakiftutuncu.eshotroid.model.Bus;
import com.mehmetakiftutuncu.eshotroid.model.BusTime;
/**
* A database class using singleton design pattern
*
* @author Mehmet Akif Tütüncü
*/
public class MyDatabase implements IDatabaseOperations<Bus>
{
/** Key for the number of a bus */
public static final String KEY_BUSSES_NUMBER = "busNumber";
/** Key for the source of a bus */
public static final String KEY_BUSSES_SOURCE = "busSource";
/** Key for the destination of a bus */
public static final String KEY_BUSSES_DESTINATION = "busDestination";
/** Key for the route of a bus */
public static final String KEY_BUSSES_ROUTE = "busRoute";
/** Key for the favorited flag of a bus */
public static final String KEY_BUSSES_ISFAVORITED = "busIsFavorited";
/** Key for the weekday times of a bus */
public static final String KEY_BUSSES_TIMESH = "busTimesH";
/** Key for the saturday times of a bus */
public static final String KEY_BUSSES_TIMESC = "busTimesC";
/** Key for the sunday times of a bus */
public static final String KEY_BUSSES_TIMESP = "busTimesP";
/** Name of the database */
private static final String DATABASE_NAME = "eshotroid_database";
/** Version of the database */
private static final int DATABASE_VERSION = 1;
/** Name of the busses table */
private static final String TABLE_NAME_BUSSES = "busses";
/** SQL string for creating busses table */
private static final String CREATE_SQL = "CREATE TABLE " + TABLE_NAME_BUSSES + " ("
+ KEY_BUSSES_NUMBER + " INTEGER PRIMARY KEY NOT NULL, "
+ KEY_BUSSES_SOURCE + " TEXT NOT NULL, "
+ KEY_BUSSES_DESTINATION + " TEXT NOT NULL, "
+ KEY_BUSSES_ROUTE + " TEXT, "
+ KEY_BUSSES_ISFAVORITED + " INTEGER NOT NULL, "
+ KEY_BUSSES_TIMESH + " TEXT, "
+ KEY_BUSSES_TIMESC + " TEXT, "
+ KEY_BUSSES_TIMESP + " TEXT);";
/** SQLiteDatabase object which is the actual database object to do database operations */
private SQLiteDatabase myDatabase;
/** Flag if the database is opened */
protected boolean isOpened = false;
/** MyDatabaseHelper instance for creating/opening the database */
private MyDatabaseHelper myHelper;
/**
* Tag for debugging
*/
public static final String LOG_TAG = "Eshotroid_Database";
private static class MyDatabaseHelper extends SQLiteOpenHelper
{
public MyDatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(CREATE_SQL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME_BUSSES);
onCreate(db);
}
}
/**
* Constructor setting the context
*
* @param context The context to be set
*/
public MyDatabase(Context context)
{
myHelper = new MyDatabaseHelper(context);
}
/**
* Creates and/or opens a writable database
*
* @return An instance of this class
*
* @throws SQLException <li>If database cannot be opened
*/
public MyDatabase openDB() throws SQLException
{
isOpened = true;
myDatabase = myHelper.getWritableDatabase();
return this;
}
/**
* Closes the opened database
*/
public void closeDB()
{
isOpened = false;
myHelper.close();
}
/**
* Gets the database of this instance
*
* @return The database of this instance
*/
protected SQLiteDatabase getDatabase()
{
return myDatabase;
}
@Override
public boolean addOrUpdate(Bus entry)
{
/* Result flag */
boolean result = true;
/* Set the row */
ContentValues values = new ContentValues();
values.put(KEY_BUSSES_NUMBER, entry.getNumber());
values.put(KEY_BUSSES_SOURCE, entry.getSource());
values.put(KEY_BUSSES_DESTINATION, entry.getDestination());
values.put(KEY_BUSSES_ROUTE, (entry.getRoute() != null ? entry.getRoute() : ""));
values.put(KEY_BUSSES_ISFAVORITED, (entry.isFavorited() ? 1 : 0));
values.put(KEY_BUSSES_TIMESH, (entry.getTimesH() != null ? new Gson().toJson(entry.getTimesH()) : ""));
values.put(KEY_BUSSES_TIMESC, (entry.getTimesC() != null ? new Gson().toJson(entry.getTimesC()) : ""));
values.put(KEY_BUSSES_TIMESP, (entry.getTimesP() != null ? new Gson().toJson(entry.getTimesP()) : ""));
try
{
/* Check if the entry is already in the database */
if(get(entry.getNumber()) != null)
{
/* Updating */
getDatabase().update(TABLE_NAME_BUSSES, values, KEY_BUSSES_NUMBER + "=" + entry.getNumber(), null);
}
else
{
/* Adding */
getDatabase().insert(TABLE_NAME_BUSSES, null, values);
}
}
catch(Exception e)
{
Log.e(LOG_TAG, "Error occurred while adding to/updating database!", e);
result = false;
}
/* Return the result */
return result;
}
@Override
public ArrayList<Bus> get()
{
/* Resulting list */
ArrayList<Bus> list = new ArrayList<Bus>();
/* Columns to select which are all except for route and times because they are not needed in the bus list */
String[] columns = new String[]
{
KEY_BUSSES_NUMBER,
KEY_BUSSES_SOURCE,
KEY_BUSSES_DESTINATION,
KEY_BUSSES_ISFAVORITED
};
/* Cursor to query the database */
Cursor cursor = getDatabase().query(TABLE_NAME_BUSSES, columns, null, null, null, null, null);
/* For every item that the cursor finds until the end */
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
{
/* Fields of the item */
int number;
String source;
String destination;
boolean isFavorited;
/* Get values for all fields */
number = cursor.getInt(cursor.getColumnIndex(KEY_BUSSES_NUMBER));
source = cursor.getString(cursor.getColumnIndex(KEY_BUSSES_SOURCE));
destination = cursor.getString(cursor.getColumnIndex(KEY_BUSSES_DESTINATION));
isFavorited = (cursor.getInt(cursor.getColumnIndex(KEY_BUSSES_ISFAVORITED)) == 1);
/* Add the item to the resulting list */
list.add(new Bus(number, source, destination, null, isFavorited, null, null, null));
}
/* Return the result */
return list;
}
@Override
public Bus get(int number)
{
/* Resulting item */
Bus item = null;
/* Columns to select which are all except for number because we know number */
String[] columns = new String[]
{
KEY_BUSSES_SOURCE,
KEY_BUSSES_DESTINATION,
KEY_BUSSES_ROUTE,
KEY_BUSSES_ISFAVORITED,
KEY_BUSSES_TIMESH,
KEY_BUSSES_TIMESC,
KEY_BUSSES_TIMESP
};
/* Cursor to query the database */
Cursor cursor = getDatabase().query(TABLE_NAME_BUSSES, columns, KEY_BUSSES_NUMBER + "=" + number, null, null, null, null);
/* If successfully queried */
if(cursor != null)
{
/* If any match is found */
if(cursor.getCount() > 0)
{
/* Go to the first match */
cursor.moveToFirst();
/* Fields of the item */
String source;
String destination;
String route;
boolean isFavorited;
ArrayList<BusTime> timesH;
ArrayList<BusTime> timesC;
ArrayList<BusTime> timesP;
/* Get values for all fields */
source = cursor.getString(cursor.getColumnIndex(KEY_BUSSES_SOURCE));
destination = cursor.getString(cursor.getColumnIndex(KEY_BUSSES_DESTINATION));
route = cursor.getString(cursor.getColumnIndex(KEY_BUSSES_ROUTE));
isFavorited = (cursor.getInt(cursor.getColumnIndex(KEY_BUSSES_ISFAVORITED)) == 1);
timesH = new Gson().fromJson(cursor.getString(cursor.getColumnIndex(KEY_BUSSES_TIMESH)), new TypeToken<ArrayList<BusTime>>(){}.getType());
timesC = new Gson().fromJson(cursor.getString(cursor.getColumnIndex(KEY_BUSSES_TIMESC)), new TypeToken<ArrayList<BusTime>>(){}.getType());
timesP = new Gson().fromJson(cursor.getString(cursor.getColumnIndex(KEY_BUSSES_TIMESP)), new TypeToken<ArrayList<BusTime>>(){}.getType());
/* Generate the resulting item */
item = new Bus(number, source, destination, route, isFavorited, timesH, timesC, timesP);
}
}
/* Return the result */
return item;
}
@Override
public boolean delete(int number)
{
/* Result flag */
boolean result = true;
/* Delete */
int affectedRows = getDatabase().delete(TABLE_NAME_BUSSES, KEY_BUSSES_NUMBER + "=" + number, null);
if(affectedRows == 0)
{
result = false;
}
/* Return the result */
return result;
}
}