package com.openvehicles.OVMS.ui.utils;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.openvehicles.OVMS.R;
import com.openvehicles.OVMS.entities.ChargePoint;
import com.openvehicles.OVMS.utils.NotificationData;
import com.openvehicles.OVMS.utils.OVMSNotifications;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
public class Database extends SQLiteOpenHelper {
private static final String TAG = "Database";
private static final int SCHEMA_VERSION = 5;
Context context;
SQLiteDatabase db;
public SimpleDateFormat isoDateTime;
public Database(Context context) {
super(context, "sampledatabase", null, SCHEMA_VERSION);
this.context = context;
this.isoDateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
}
public void open() {
db = this.getWritableDatabase();
}
public void beginWrite() {
open();
db.beginTransaction();
}
public void endWrite(boolean commit) {
if (commit)
db.setTransactionSuccessful();
db.endTransaction();
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, "Database creation");
db.execSQL("CREATE TABLE mapdetails(cpid INTEGER PRIMARY KEY," +
"Latitude TEXT, Longitude TEXT, Title TEXT," +
"OperatorInfo TEXT, StatusType TEXT, UsageType TEXT," +
"AddressLine1 TEXT, RelatedURL TEXT, UsageCost TEXT," +
"AccessComments TEXT, GeneralComments TEXT," +
"NumberOfPoints TEXT)");
db.execSQL("CREATE TABLE if not exists company(id INTEGER PRIMARY KEY AUTOINCREMENT,userid TEXT,instance TEXT,companyname TEXT)");
db.execSQL("CREATE TABLE IF NOT EXISTS latlngdetail(id INTEGER PRIMARY KEY AUTOINCREMENT," +
"lat INTEGER, lng INTEGER, last_update INTEGER)");
db.execSQL("CREATE TABLE if not exists ConnectionTypes(Id INTEGER PRIMARY KEY AUTOINCREMENT,tId TEXT,title TEXT,chec TEXT,CompanyName TEXT)");
db.execSQL("CREATE TABLE if not exists ConnectionTypes_Main(Id TEXT,tId TEXT,title TEXT)");
db.execSQL("CREATE TABLE if not exists companydetail(companyname TEXT,buffer TEXT)");
db.execSQL("CREATE TABLE if not exists companydetails(companyname TEXT,buffer TEXT,bufferserver TEXT)");
db.execSQL("CREATE TABLE if not exists interviewuser(companyname TEXT,username TEXT)");
db.execSQL("CREATE TABLE if not exists interviewuserdetails(companyname TEXT,username TEXT,buffer TEXT,bufferserver TEXT)");
// Version 3:
// multiple connections per chargepoint:
db.execSQL("CREATE TABLE IF NOT EXISTS Connection(" +
"conCpId INTEGER, conTypeId INTEGER," +
"conTypeTitle TEXT, conLevelTitle TEXT)");
db.execSQL("CREATE INDEX conCp ON Connection (conCpId)");
db.execSQL("CREATE INDEX conType ON Connection (conTypeId)");
// create Notifications table:
db.execSQL("CREATE TABLE IF NOT EXISTS Notification(" +
"nID INTEGER PRIMARY KEY AUTOINCREMENT," +
"nType TEXT, nTimestamp TEXT, nTitle TEXT, nMessage TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "Database upgrade from version " + oldVersion + " to version " + newVersion);
if (oldVersion < 2) {
// Version 2:
// update OCM POI details:
db.execSQL("DROP TABLE mapdetails");
db.execSQL("CREATE TABLE mapdetails(cpid INTEGER PRIMARY KEY," +
"lat text,lng text,title text,optr text,status text,usage text," +
"AddressLine1 text,level1 text,level2 text,connction_id text,connction1 text," +
"numberofpoint TEXT)");
// update OCM POI cache:
db.execSQL("DROP TABLE latlngdetail");
db.execSQL("CREATE TABLE latlngdetail(id INTEGER PRIMARY KEY AUTOINCREMENT," +
"lat INTEGER, lng INTEGER, last_update INTEGER)");
}
if (oldVersion < 3) {
// Version 3:
// multiple connections per chargepoint:
db.execSQL("CREATE TABLE IF NOT EXISTS Connection(" +
"conCpId INTEGER, conTypeId INTEGER," +
"conTypeTitle TEXT, conLevelTitle TEXT)");
db.execSQL("CREATE INDEX conCp ON Connection (conCpId)");
db.execSQL("CREATE INDEX conType ON Connection (conTypeId)");
// this obsoletes mapdetails fields:
// level1 text,level2 text,connction_id text,connction1 text
// but SQLite doesn't support DROP COLUMN
// Todo:
// could conTypeTitle be fetched from ConnectionTypes_Main?
// conLevelTitle: no Level core reference data available?
}
if (oldVersion < 4) {
// Version 4:
// mapdetails:
// remove level1, level2, connction_id, connction1
// add UsageCost, AccessComments, RelatedURL, GeneralComments
db.execSQL("DROP TABLE mapdetails");
db.execSQL("CREATE TABLE mapdetails(cpid INTEGER PRIMARY KEY," +
"Latitude TEXT, Longitude TEXT, Title TEXT," +
"OperatorInfo TEXT, StatusType TEXT, UsageType TEXT," +
"AddressLine1 TEXT, RelatedURL TEXT, UsageCost TEXT," +
"AccessComments TEXT, GeneralComments TEXT," +
"NumberOfPoints TEXT)");
// clear cache:
db.execSQL("DELETE FROM Connection");
db.execSQL("DELETE FROM latlngdetail");
}
if (oldVersion < 5) {
// Version 5:
// create Notifications table:
db.execSQL("CREATE TABLE IF NOT EXISTS Notification(" +
"nID INTEGER PRIMARY KEY AUTOINCREMENT," +
"nType TEXT, nTimestamp TEXT, nTitle TEXT, nMessage TEXT)");
// migrate Notifications from file storage to table:
ArrayList<NotificationData> notifications;
try {
String filename = "OVMSSavedNotifications.obj";
Log.d(TAG, "Migrating saved notifications list from internal storage file: " + filename);
// read file:
FileInputStream fis = context.openFileInput(filename);
ObjectInputStream is = new ObjectInputStream(fis);
notifications = (ArrayList<NotificationData>) is.readObject();
is.close();
Log.d(TAG, String.format("Loaded %d saved notifications.", notifications.size()));
// copy to db:
for (int i=0; i < notifications.size(); i++) {
addNotificationInt(notifications.get(i), db);
}
Log.d(TAG, String.format("Added %d notifications to table.", notifications.size()));
// done, remove file:
context.deleteFile(filename);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// NOP = allow (to be able to redo upgrades for development)
}
public void insert_mapdetails(ChargePoint cp) {
try {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("cpid", cp.ID); // primary key
if (cp.AddressInfo != null) {
contentValues.put("Latitude", cp.AddressInfo.Latitude);
contentValues.put("Longitude", cp.AddressInfo.Longitude);
contentValues.put("Title", ifNull(cp.AddressInfo.Title, "untitled"));
contentValues.put("AddressLine1", ifNull(cp.AddressInfo.AddressLine1, ""));
contentValues.put("AccessComments", ifNull(cp.AddressInfo.AccessComments, ""));
contentValues.put("RelatedURL", ifNull(cp.AddressInfo.RelatedURL, ""));
}
if (cp.OperatorInfo != null) {
contentValues.put("OperatorInfo", ifNull(cp.OperatorInfo.Title, "unknown"));
}
if (cp.StatusType != null) {
contentValues.put("StatusType", ifNull(cp.StatusType.Title, "unknown"));
}
if (cp.UsageType != null) {
contentValues.put("UsageType", ifNull(cp.UsageType.Title, "unknown"));
}
contentValues.put("UsageCost", ifNull(cp.UsageCost, "unknown"));
contentValues.put("GeneralComments", ifNull(cp.GeneralComments, ""));
contentValues.put("NumberOfPoints", ifNull(cp.NumberOfPoints, "1"));
if (cp.Connections != null) {
ContentValues addCon = new ContentValues();
ChargePoint.Connection con;
// rebuild associated connections:
db.delete("Connection", "conCpId=" + cp.ID, null);
for (int i=0; i < cp.Connections.length; i++) {
con = cp.Connections[i];
addCon.clear();
addCon.put("conCpId", cp.ID);
if (con.ConnectionType != null) {
addCon.put("conTypeId", ifNull(con.ConnectionType.ID, "0"));
addCon.put("conTypeTitle", ifNull(con.ConnectionType.Title, "unknown"));
}
if (con.Level != null) {
addCon.put("conLevelTitle", ifNull(con.Level.Title, "unknown"));
}
db.insert("Connection", null, addCon);
}
}
db.insertWithOnConflict("mapdetails", null, contentValues, SQLiteDatabase.CONFLICT_REPLACE);
} catch(Exception e) {
e.printStackTrace();
}
}
public void addCompany(String userid, String companyname, String instance) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("userid", userid);
contentValues.put("companyname", companyname);
contentValues.put("instance", instance);
db.insert("company", null, contentValues);
}
// update/add OCM latlng cache tile:
public void addlatlngdetail(int lat, int lng) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("lat", lat);
contentValues.put("lng", lng);
contentValues.put("last_update", System.currentTimeMillis() / 1000);
if (db.update("latlngdetail", contentValues, "lat=" + lat + " AND lng=" + lng, null) == 0) {
db.insert("latlngdetail", null, contentValues);
}
}
// query OCM latlng cache tile:
public Cursor getlatlngdetail(int lat, int lng) {
open();
Cursor cursor = db.rawQuery("select * from latlngdetail where lat="
+ lat + " and lng=" + lng, null);
return cursor;
}
// clear OCM latlng cache:
public void clear_latlngdetail() {
open();
db.delete("latlngdetail", null, null);
}
public void addConnectionTypes_Main(String Id, String tId, String Title) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("Id", Id);
contentValues.put("tId", tId);
contentValues.put("Title", Title);
db.insert("ConnectionTypes_Main", null, contentValues);
}
public void addConnectionTypesDetail(String tId, String Title,
String check, String CompanyName) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("tId", tId);
contentValues.put("Title", Title);
contentValues.put("chec", check);
contentValues.put("CompanyName", CompanyName);
db.insert("ConnectionTypes", null, contentValues);
}
public void updateConnectionTypesDetail(String Id, String check,
String CompanyName) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("Id", Id);
contentValues.put("chec", check);
String whereClause = "Id=" + Id;
contentValues.put("CompanyName", CompanyName);
db.update("ConnectionTypes", contentValues, whereClause, null);
}
public void resetConnectionTypesDetail(String CompanyName) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("chec", "false");
String whereClause = "CompanyName=?";
String whereArgs[] = { CompanyName };
db.update("ConnectionTypes", contentValues, whereClause, whereArgs);
}
public void addcompanydetail(String companyname, String buffer) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("buffer", buffer);
contentValues.put("companyname", companyname);
db.insert("companydetail", null, contentValues);
}
public void addcompanydetail1(String companyname, String buffer,
String bufferserver) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("buffer", buffer);
contentValues.put("bufferserver", bufferserver);
contentValues.put("companyname", companyname);
db.insert("companydetails", null, contentValues);
}
public void updatecompanydetail(String companyname, String buffer,
String bufferserver) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("buffer", buffer);
contentValues.put("bufferserver", bufferserver);
contentValues.put("companyname", companyname);
db.update("companydetails", contentValues, "companyname='"
+ companyname + "'", null);
}
public void addinterviewuser(String companyname, String user) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("username", user);
contentValues.put("companyname", companyname);
db.insert("interviewuser", null, contentValues);
}
public void addinterviewuserdetails(String companyname, String user,
String bufferserver) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("username", user);
contentValues.put("buffer", bufferserver);
contentValues.put("bufferserver", bufferserver);
contentValues.put("companyname", companyname);
db.insert("interviewuserdetails", null, contentValues);
}
public void updateinterviewuser(String companyname, String user) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("username", user);
contentValues.put("companyname", companyname);
db.update("interviewuser", contentValues, "companyname='" + companyname
+ "'", null);
}
public void updateinterviewuserdetails(String companyname, String user,
String bufferserver) {
open();
ContentValues contentValues = new ContentValues();
contentValues.put("username", user);
contentValues.put("buffer", bufferserver);
contentValues.put("bufferserver", bufferserver);
contentValues.put("companyname", companyname);
db.update("interviewuserdetails", contentValues, "companyname='"
+ companyname + "'", null);
}
public Cursor get_mapdetails() {
open();
Cursor cursor = db.rawQuery("select * from mapdetails", null);
return cursor;
}
public Cursor get_mapdetails(String filterConTypeIds) {
open();
Cursor cursor = db.rawQuery(
"SELECT DISTINCT mapdetails.*" +
"FROM mapdetails JOIN Connection ON ( conCpId = cpid )" +
"WHERE conTypeId IN (" + filterConTypeIds + ")", null);
return cursor;
}
public Cursor getChargePoint(String cpId) {
open();
Cursor cursor = db.rawQuery(
"SELECT * FROM mapdetails WHERE cpid=" + cpId, null);
return cursor;
}
public Cursor getChargePointConnections(String cpId) {
open();
Cursor cursor = db.rawQuery(
"SELECT * FROM Connection WHERE conCpId=" + cpId, null);
return cursor;
}
// public Cursor get_ConnectionTypesdetails() {
// SQLiteDatabase db = this.getWritableDatabase();
// Cursor cursor = db.rawQuery(
// "select * from ConnectionTypes ORDER BY title", null);
// return cursor;
// }
public Cursor get_ConnectionTypes_Main() {
open();
Cursor cursor = db.rawQuery(
"select * from ConnectionTypes_Main ORDER BY title", null);
return cursor;
}
public Cursor get_ConnectionTypesdetails(String cmpname) {
open();
Cursor cursor = db.rawQuery(
"select * from ConnectionTypes where CompanyName='" + cmpname
+ "' ORDER BY title", null);
return cursor;
}
public String getConnectionFilter(String vehicleLabel) {
open();
Cursor cursor = get_ConnectionTypesdetails(vehicleLabel);
StringBuffer idList = new StringBuffer(1000);
while (cursor.moveToNext()) {
if (cursor.getString(cursor.getColumnIndex("chec")).equals("true"))
idList.append("," + cursor.getString(cursor.getColumnIndex("tId")));
}
cursor.close();
return (idList.length() > 1) ? idList.substring(1) : "";
}
public Cursor getCompanydetails() {
open();
Cursor cursor = db.rawQuery("select * from company", null);
return cursor;
}
public Cursor getinterviewuserdetails() {
open();
Cursor cursor = db.rawQuery("select * from interviewuser", null);
return cursor;
}
public Cursor getinterviewuserdetailsdetails() {
open();
Cursor cursor = db.rawQuery("select * from interviewuserdetails", null);
return cursor;
}
public Cursor getCdetails() {
open();
Cursor cursor = db.rawQuery("select * from companydetail", null);
return cursor;
}
public Cursor getCdetails1() {
open();
Cursor cursor = db.rawQuery("select * from companydetails", null);
return cursor;
}
public Cursor getCompanydetails(String instance) {
open();
Cursor cursor = db.rawQuery("select * from company where instance='"
+ instance + "'", null);
return cursor;
}
public Cursor getsearchvalues(String name) {
open();
Cursor cursor = db.rawQuery(
"SELECT * FROM producttable WHERE productidno LIKE '%" + name
+ "%'", null);
return cursor;
}
public Cursor del(String name, String company) {
open();
Cursor cursor = db.rawQuery(
"delete FROM interviewuserdetails WHERE username='" + name
+ "'&companyname='" + company + "'", null);
return cursor;
}
public void deleteTable() {
open();
String deleteSQL = "delete from producttable";
db.execSQL(deleteSQL);
}
public void addNotification(NotificationData notificationData) {
open();
addNotificationInt(notificationData, db);
}
private void addNotificationInt(NotificationData notificationData, SQLiteDatabase db) {
ContentValues contentValues = new ContentValues();
contentValues.put("nType", notificationData.Type);
contentValues.put("nTimestamp", isoDateTime.format(notificationData.Timestamp));
contentValues.put("nTitle", notificationData.Title);
contentValues.put("nMessage", notificationData.Message);
db.insert("Notification", null, contentValues);
}
public void removeNotification(NotificationData notificationData) {
open();
db.delete("Notification", "nID=" + notificationData.ID, null);
}
public int removeOldNotifications(int keepSize) {
int deletedRows = 0;
open();
Cursor maxIdCursor = db.rawQuery("SELECT MAX(nID) AS maxID FROM Notifications", null);
if (maxIdCursor.moveToFirst()) {
long maxId = maxIdCursor.getLong(maxIdCursor.getColumnIndex("maxID"));
deletedRows = db.delete("Notification", "nID <= " + (maxId - keepSize), null);
}
return deletedRows;
}
public Cursor getNotifications() {
open();
Cursor cursor = db.rawQuery("SELECT * FROM Notification ORDER BY nID", null);
return cursor;
}
public NotificationData getNextNotification(Cursor cursor) {
if (cursor == null || !cursor.moveToNext())
return null;
Date timestamp;
try {
timestamp = isoDateTime.parse(cursor.getString(cursor.getColumnIndex("nTimestamp")));
} catch (Exception e) {
timestamp = new Date();
}
NotificationData data = new NotificationData(
cursor.getLong(cursor.getColumnIndex("nID")),
cursor.getInt(cursor.getColumnIndex("nType")),
timestamp,
cursor.getString(cursor.getColumnIndex("nTitle")),
cursor.getString(cursor.getColumnIndex("nMessage")));
return data;
}
public static <T> T ifNull(T toCheck, T ifNull){
if(toCheck == null){
return ifNull;
}
return toCheck;
}
}