/*
* Copyright 2012 The Stanford MobiSocial Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mobisocial.musubi.model.helpers;
import gnu.trove.list.linked.TLongLinkedList;
import java.util.LinkedList;
import java.util.List;
import mobisocial.musubi.model.MApp;
import mobisocial.musubi.model.MAppAction;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDoneException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
public class AppManager extends ManagerBase {
SQLiteStatement mSqlGetId;
SQLiteStatement mSqlGetAppId;
SQLiteStatement mSqlInsertApp;
SQLiteStatement mSqlUpdateApp;
SQLiteStatement mSqlInsertAppAction;
String mSqlLookupAppByAppId;
static final String[] STANDARD_FIELDS = new String[] {
MApp.COL_ID, MApp.COL_APP_ID, MApp.COL_NAME, MApp.COL_ANDROID_PACKAGE, MApp.COL_WEB_APP_URL, MApp.COL_DELETED
};
final static int id = 0;
final static int appId = 1;
final static int name = 2;
final static int androidPackage = 3;
final static int webAppUrl = 4;
final static int deleted = 5;
public AppManager(SQLiteDatabase db) {
super(db);
}
public AppManager(SQLiteOpenHelper databaseSource) {
super(databaseSource);
}
public String getAppIdentifier(long id) {
SQLiteDatabase db = initializeDatabase();
if(mSqlGetAppId == null) {
synchronized(this) {
if(mSqlGetAppId == null) {
mSqlGetAppId = db.compileStatement(
"SELECT " + MApp.COL_APP_ID +
" FROM " + MApp.TABLE +
" WHERE " + MApp.COL_ID + "=?"
);
}
}
}
synchronized (mSqlGetAppId) {
try {
mSqlGetAppId.bindLong(1, id);
return mSqlGetAppId.simpleQueryForString();
} catch(SQLiteDoneException e) {
return null;
}
}
}
/**
* Ensures that an app record exists for the given app identifier,
* creating one if necessary.
*/
public MApp ensureApp(String appIdentifier) {
SQLiteDatabase db = initializeDatabase();
if(mSqlGetId == null) {
synchronized(this) {
if(mSqlGetId == null) {
mSqlGetId = db.compileStatement(
"SELECT " + MApp.COL_ID +
" FROM " + MApp.TABLE +
" WHERE " + MApp.COL_APP_ID + "=?"
);
}
}
}
synchronized (mSqlGetId) {
try {
mSqlGetId.bindString(1, appIdentifier);
long id = mSqlGetId.simpleQueryForLong();
MApp app = new MApp();
app.id_ = id;
app.appId_ = appIdentifier;
return app;
} catch(SQLiteDoneException e) {
//must insert
}
}
ContentValues values = new ContentValues();
values.put(MApp.COL_APP_ID, appIdentifier);
long rowId = db.insert(MApp.TABLE, null, values);
MApp app = new MApp();
app.id_ = rowId;
app.appId_ = appIdentifier;
return app;
}
public void insertApp(MApp app) {
SQLiteDatabase db = initializeDatabase();
if (mSqlInsertApp == null) {
synchronized (this) {
StringBuilder sql = new StringBuilder(100)
.append(" INSERT INTO ").append(MApp.TABLE).append("(")
.append(MApp.COL_APP_ID).append(",")
.append(MApp.COL_NAME).append(",")
.append(MApp.COL_ANDROID_PACKAGE).append(",")
.append(MApp.COL_WEB_APP_URL).append(",")
.append(MApp.COL_DELETED)
.append(") VALUES (?,?,?,?,?)");
mSqlInsertApp = db.compileStatement(sql.toString());
}
}
synchronized (mSqlInsertApp) {
bindField(mSqlInsertApp, appId, app.appId_);
bindField(mSqlInsertApp, name, app.name_);
bindField(mSqlInsertApp, androidPackage, app.androidPackage_);
bindField(mSqlInsertApp, webAppUrl, app.webAppUrl_);
bindField(mSqlInsertApp, deleted, app.deleted_ ? 1 : 0);
app.id_ = mSqlInsertApp.executeInsert();
}
}
public void updateApp(MApp app) {
SQLiteDatabase db = initializeDatabase();
if (mSqlUpdateApp == null) {
synchronized (this) {
if (mSqlUpdateApp == null) {
StringBuilder sql = new StringBuilder("UPDATE ").append(MApp.TABLE)
.append(" SET ")
.append(MApp.COL_APP_ID).append("=?,")
.append(MApp.COL_NAME).append("=?,")
.append(MApp.COL_ANDROID_PACKAGE).append("=?,")
.append(MApp.COL_WEB_APP_URL).append("=?,")
.append(MApp.COL_DELETED).append("=?")
.append(" WHERE ").append(MApp.COL_ID).append("=?");
mSqlUpdateApp = db.compileStatement(sql.toString());
}
}
}
synchronized (mSqlUpdateApp) {
bindField(mSqlUpdateApp, appId, app.appId_);
bindField(mSqlUpdateApp, name, app.name_);
bindField(mSqlUpdateApp, androidPackage, app.androidPackage_);
bindField(mSqlUpdateApp, webAppUrl, app.webAppUrl_);
bindField(mSqlUpdateApp, deleted, app.deleted_ ? 1 : 0);
bindField(mSqlUpdateApp, 6, app.id_);
mSqlUpdateApp.execute();
}
}
/**
* Returns a fully-populated MApp object for the given id, or
* null if no such app.
*/
public MApp lookupApp(long appId) {
SQLiteDatabase db = initializeDatabase();
String table = MApp.TABLE;
String selection = MApp.COL_ID + "=?";
String[] selectionArgs = new String[] { Long.toString(appId) };
String groupBy = null, having = null, orderBy = null;
Cursor c = db.query(table, STANDARD_FIELDS, selection, selectionArgs, groupBy, having, orderBy);
try {
if (c.moveToFirst()) {
// Existing app
MApp app = new MApp();
app.id_ = appId;
if (!c.isNull(AppManager.appId)) {
app.appId_ = c.getString(AppManager.appId);
}
if (!c.isNull(name)) {
app.name_ = c.getString(name);
}
if (!c.isNull(androidPackage)) {
app.androidPackage_ = c.getString(androidPackage);
}
if (!c.isNull(webAppUrl)) {
app.webAppUrl_ = c.getString(webAppUrl);
}
app.deleted_ = c.getInt(deleted) != 0;
return app;
} else {
return null;
}
} finally {
c.close();
}
}
public MApp lookupAppByAppId(String appId) {
SQLiteDatabase db = initializeDatabase();
if (mSqlLookupAppByAppId == null) {
StringBuilder sql = new StringBuilder(80).append("SELECT ");
for (String f : STANDARD_FIELDS) {
sql.append(f).append(",");
}
sql.setLength(sql.length()-1);
sql.append(" FROM ").append(MApp.TABLE)
.append(" WHERE ").append(MApp.COL_APP_ID).append("=?");
mSqlLookupAppByAppId = sql.toString();
}
String[] selectionArgs = new String[] { appId };
Cursor c = db.rawQuery(mSqlLookupAppByAppId, selectionArgs);
try {
if (c.moveToFirst()) {
MApp app = new MApp();
app.id_ = c.getLong(AppManager.id);
if (!c.isNull(AppManager.appId)) {
app.appId_ = c.getString(AppManager.appId);
}
if (!c.isNull(name)) {
app.name_ = c.getString(name);
}
if (!c.isNull(androidPackage)) {
app.androidPackage_ = c.getString(androidPackage);
}
if (!c.isNull(webAppUrl)) {
app.webAppUrl_ = c.getString(webAppUrl);
}
app.deleted_ = c.getInt(deleted) != 0;
return app;
} else {
return null;
}
} finally {
c.close();
}
}
/**
* Returns the appId and id fields of an MApp if found in the database.
*/
public MApp getAppBasics(long id) {
String appId = getAppIdentifier(id);
if(appId == null)
return null;
MApp app = new MApp();
app.id_ = id;
app.appId_ = appId;
return app;
}
/**
* Returns true if a row was deleted.
*/
public boolean deleteAppWithId(String appId) {
SQLiteDatabase db = initializeDatabase();
String whereClause = MApp.COL_APP_ID + "=?";
String[] whereArgs = new String[] { appId };
ContentValues cv = new ContentValues();
cv.put(MApp.COL_DELETED, true);
return db.update(MApp.TABLE, cv, whereClause, whereArgs) > 0;
}
//super simple interface for now, no updates. in a transaaction delete
//all the existing registered actions. then add all of the newly discovered ones
public MAppAction insertAppAction(MApp app, String type, String action) {
SQLiteDatabase db = initializeDatabase();
if (mSqlInsertAppAction == null) {
synchronized (this) {
StringBuilder sql = new StringBuilder(100)
.append(" INSERT INTO ").append(MAppAction.TABLE).append("(")
.append(MAppAction.COL_APP_ID).append(",")
.append(MAppAction.COL_OBJ_TYPE).append(",")
.append(MAppAction.COL_ACTION)
.append(") VALUES (?,?,?)");
mSqlInsertAppAction = db.compileStatement(sql.toString());
}
}
MAppAction app_action = new MAppAction();
app_action.appId_ = app.id_;
app_action.objType_ = type;
app_action.action_ = action;
synchronized (mSqlInsertAppAction) {
bindField(mSqlInsertAppAction, 1, app_action.appId_);
bindField(mSqlInsertAppAction, 2, app_action.objType_);
bindField(mSqlInsertAppAction, 3, app_action.action_);
app_action.id_ = mSqlInsertAppAction.executeInsert();
}
return app_action;
}
/**
* Returns true if a row was deleted.
*/
public boolean deleteAppActionWithForApp(MApp app) {
SQLiteDatabase db = initializeDatabase();
String whereClause = MAppAction.COL_APP_ID + "=?";
String[] whereArgs = new String[] { String.valueOf(app.id_) };
return db.delete(MAppAction.TABLE, whereClause, whereArgs) > 0;
}
public List<MAppAction> lookupActions(String objType) {
SQLiteDatabase db = initializeDatabase();
String[] columns = new String[] {
MAppAction.COL_ID,
MAppAction.COL_APP_ID,
MAppAction.COL_OBJ_TYPE,
MAppAction.COL_ACTION,
};
String whereClause = MAppAction.COL_OBJ_TYPE + "=? AND " + MApp.TABLE + "." + MApp.COL_DELETED +"=0";
String[] whereArgs = new String[] { objType };
Cursor c = db.query(MAppAction.TABLE, columns, whereClause, whereArgs, null, null, null);
try {
LinkedList<MAppAction> actions = new LinkedList<MAppAction>();
while(c.moveToNext()) {
MAppAction app_action = new MAppAction();
app_action.id_ = c.getLong(0);
app_action.appId_ = c.getLong(1);
app_action.objType_ = c.getString(2);
app_action.action_ = c.getString(3);
actions.add(app_action);
}
return actions;
} finally {
c.close();
}
}
public List<MApp> lookupAppForAction(String objType, String action) {
SQLiteDatabase db = initializeDatabase();
String[] columns = new String[] {
MApp.TABLE + "." + MApp.COL_ID,
};
String whereClause = MAppAction.TABLE + "." + MAppAction.COL_OBJ_TYPE + "=? AND " + MAppAction.TABLE + "." + MAppAction.COL_ACTION + "=? AND " + MApp.TABLE + "." + MApp.COL_DELETED +"=0";
String[] whereArgs = new String[] { objType, action };
String orderBy = MApp.TABLE + "." + MApp.COL_NAME;
String join = " JOIN " + MApp.TABLE + " ON " + MAppAction.TABLE + "." + MAppAction.COL_APP_ID + "=" + MApp.TABLE + "." + MApp.COL_ID;
Cursor c = db.query(MAppAction.TABLE + join, columns, whereClause, whereArgs, null, null, orderBy);
LinkedList<MApp> apps = new LinkedList<MApp>();
try {
while(c.moveToNext()) {
long app_id = c.getLong(0);
apps.add(lookupApp(app_id));
}
return apps;
} finally {
c.close();
}
}
public long[] listApps() {
SQLiteDatabase db = initializeDatabase();
Cursor c = db.query(MApp.TABLE, new String[] {MApp.COL_ID}, MApp.COL_DELETED +"=0", null, null, null, null);
try {
TLongLinkedList apps = new TLongLinkedList();
while (c.moveToNext()) {
apps.add(c.getLong(0));
}
return apps.toArray();
} finally {
c.close();
}
}
@Override
public synchronized void close() {
if (mSqlGetId != null) {
mSqlGetId.close();
mSqlGetId = null;
}
if (mSqlGetAppId != null) {
mSqlGetAppId.close();
mSqlGetAppId = null;
}
if (mSqlInsertApp != null) {
mSqlInsertApp.close();
mSqlInsertApp = null;
}
if (mSqlUpdateApp != null) {
mSqlUpdateApp.close();
mSqlUpdateApp = null;
}
if (mSqlInsertAppAction != null) {
mSqlInsertAppAction.close();
mSqlInsertAppAction = null;
}
}
}