/*
* 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 java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import mobisocial.musubi.model.MPendingIdentity;
import mobisocial.musubi.util.Util;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
/**
*
* @see MPendingIdentity
*
*/
public class PendingIdentityManager extends ManagerBase {
private SQLiteStatement sqlUpdateIdentity;
private SQLiteStatement sqlInsertIdentity;
private static final int _id = 0;
private static final int identityId = 1;
private static final int key = 2;
private static final int notified = 3;
private static final int requestId = 4;
private static final int timestamp = 5;
private static final String[] STANDARD_FIELDS = new String[] {
MPendingIdentity.COL_ID,
MPendingIdentity.COL_IDENTITY_ID,
MPendingIdentity.COL_KEY,
MPendingIdentity.COL_NOTIFIED,
MPendingIdentity.COL_REQUEST_ID,
MPendingIdentity.COL_TIMESTAMP
};
private static final int KEY_SIZE = 32;
public PendingIdentityManager(SQLiteOpenHelper databaseSource) {
super(databaseSource);
}
public PendingIdentityManager(SQLiteDatabase db) {
super(db);
}
public void insertIdentity(MPendingIdentity identity) {
SQLiteDatabase db = initializeDatabase();
if (sqlInsertIdentity == null) {
synchronized(this) {
StringBuilder sql = new StringBuilder(200)
.append(" INSERT INTO ").append(MPendingIdentity.TABLE).append("(")
.append(MPendingIdentity.COL_IDENTITY_ID).append(",")
.append(MPendingIdentity.COL_KEY).append(",")
.append(MPendingIdentity.COL_NOTIFIED).append(",")
.append(MPendingIdentity.COL_REQUEST_ID).append(",")
.append(MPendingIdentity.COL_TIMESTAMP)
.append(") VALUES (?,?,?,?,?)");
sqlInsertIdentity = db.compileStatement(sql.toString());
}
}
synchronized(sqlInsertIdentity) {
bindField(sqlInsertIdentity, identityId, identity.identityId_);
bindField(sqlInsertIdentity, key, identity.key_);
bindField(sqlInsertIdentity, notified, identity.notified_ ? 1 : 0);
bindField(sqlInsertIdentity, requestId, identity.requestId_);
bindField(sqlInsertIdentity, timestamp, identity.timestamp_);
identity.id_ = sqlInsertIdentity.executeInsert();
}
}
public void updateIdentity(MPendingIdentity identity) {
SQLiteDatabase db = initializeDatabase();
if (sqlUpdateIdentity == null) {
synchronized(this) {
StringBuilder sql = new StringBuilder("UPDATE ")
.append(MPendingIdentity.TABLE)
.append(" SET ")
.append(MPendingIdentity.COL_IDENTITY_ID).append("=?,")
.append(MPendingIdentity.COL_KEY).append("=?,")
.append(MPendingIdentity.COL_NOTIFIED).append("=?,")
.append(MPendingIdentity.COL_REQUEST_ID).append("=?,")
.append(MPendingIdentity.COL_TIMESTAMP).append("=?")
.append(" WHERE ").append(MPendingIdentity.COL_ID).append("=?");
sqlUpdateIdentity = db.compileStatement(sql.toString());
}
}
synchronized(sqlUpdateIdentity) {
bindField(sqlUpdateIdentity, identityId, identity.identityId_);
bindField(sqlUpdateIdentity, key, identity.key_);
bindField(sqlUpdateIdentity, notified, identity.notified_ ? 1 : 0);
bindField(sqlUpdateIdentity, requestId, identity.requestId_);
bindField(sqlUpdateIdentity, timestamp, identity.timestamp_);
bindField(sqlUpdateIdentity, 6, identity.id_);
sqlUpdateIdentity.execute();
}
}
public Set<MPendingIdentity> lookupIdentities(Long identityId) {
SQLiteDatabase db = initializeDatabase();
String table = MPendingIdentity.TABLE;
String selection = MPendingIdentity.COL_IDENTITY_ID + "=?";
String[] selectionArgs = new String[] { identityId.toString() };
String groupBy = null, having = null, orderBy = null;
Cursor c = db.query(table, STANDARD_FIELDS, selection, selectionArgs,
groupBy, having, orderBy);
try {
HashSet<MPendingIdentity> ids = new HashSet<MPendingIdentity>();
while (c.moveToNext()) {
ids.add(fillInStandardFields(c));
}
return ids;
} finally {
c.close();
}
}
public MPendingIdentity lookupIdentity(Long identityId, Long timestamp) {
SQLiteDatabase db = initializeDatabase();
String table = MPendingIdentity.TABLE;
String selection = MPendingIdentity.COL_IDENTITY_ID +
"=? AND " + MPendingIdentity.COL_TIMESTAMP + "=?";
String[] selectionArgs = new String[] { identityId.toString(), timestamp.toString() };
String groupBy = null, having = null, orderBy = null;
Cursor c = db.query(table, STANDARD_FIELDS, selection, selectionArgs,
groupBy, having, orderBy);
try {
if (c.moveToFirst()) {
return fillInStandardFields(c);
}
else {
return null;
}
} finally {
c.close();
}
}
public MPendingIdentity lookupIdentity(Long identityId, Long timestamp, Integer requestId) {
SQLiteDatabase db = initializeDatabase();
String table = MPendingIdentity.TABLE;
String selection = MPendingIdentity.COL_IDENTITY_ID +
"=? AND " + MPendingIdentity.COL_TIMESTAMP +
"=? AND " + MPendingIdentity.COL_REQUEST_ID + "=?";
String[] selectionArgs = new String[] { identityId.toString(),
timestamp.toString(), requestId.toString() };
String groupBy = null, having = null, orderBy = null;
Cursor c = db.query(table, STANDARD_FIELDS, selection, selectionArgs,
groupBy, having, orderBy);
try {
if (c.moveToFirst()) {
return fillInStandardFields(c);
}
else {
return null;
}
} finally {
c.close();
}
}
public List<MPendingIdentity> getUnnotifiedIdentities() {
SQLiteDatabase db = initializeDatabase();
Cursor c = db.query(
MPendingIdentity.TABLE, STANDARD_FIELDS,
MPendingIdentity.COL_NOTIFIED + "=0",
null, null, null, null);
try {
LinkedList<MPendingIdentity> ids = new LinkedList<MPendingIdentity>();
while (c.moveToNext()) {
ids.add(fillInStandardFields(c));
}
return ids;
} finally {
c.close();
}
}
public List<MPendingIdentity> getUnnotifiedIdentities(Long identityId) {
SQLiteDatabase db = initializeDatabase();
Cursor c = db.query(
MPendingIdentity.TABLE, STANDARD_FIELDS,
MPendingIdentity.COL_NOTIFIED + "=0 AND " + MPendingIdentity.COL_IDENTITY_ID + "=?",
new String[] { identityId.toString() },
null, null, null);
try {
LinkedList<MPendingIdentity> ids = new LinkedList<MPendingIdentity>();
while (c.moveToNext()) {
ids.add(fillInStandardFields(c));
}
return ids;
} finally {
c.close();
}
}
public boolean deleteIdentity(long id) {
SQLiteDatabase db = initializeDatabase();
String table = MPendingIdentity.TABLE;
String whereClause = MPendingIdentity.COL_ID + "=?";
String[] whereArgs = new String[] { Long.toString(id) };
return db.delete(table, whereClause, whereArgs) > 0;
}
public boolean deleteIdentity(long identityId, long timestamp) {
SQLiteDatabase db = initializeDatabase();
String table = MPendingIdentity.TABLE;
String whereClause = MPendingIdentity.COL_IDENTITY_ID +
"=? AND " + MPendingIdentity.COL_TIMESTAMP + "=?";
String[] whereArgs = new String[]
{ Long.toString(identityId), Long.toString(timestamp) };
return db.delete(table, whereClause, whereArgs) > 0;
}
public MPendingIdentity fillPendingIdentity(long identityId, long timestamp) {
MPendingIdentity id = new MPendingIdentity();
id.identityId_ = identityId;
id.timestamp_ = timestamp;
id.notified_ = false;
// Random bytes for encryption and a random request ID
byte[] keyInBytes = new byte[KEY_SIZE];
Random random = new Random();
random.nextBytes(keyInBytes);
id.key_ = Util.convertToHex(keyInBytes);
id.requestId_ = random.nextInt();
return id;
}
private MPendingIdentity fillInStandardFields(Cursor c) {
MPendingIdentity id = new MPendingIdentity();
id.id_ = c.getLong(_id);
id.identityId_ = c.getLong(identityId);
id.key_ = c.getString(key);
id.notified_ = c.getLong(notified) != 0;
id.requestId_ = c.getInt(requestId);
id.timestamp_ = c.getLong(timestamp);
return id;
}
@Override
public void close() {
if (sqlUpdateIdentity != null) {
sqlUpdateIdentity.close();
sqlUpdateIdentity = null;
}
if (sqlInsertIdentity != null) {
sqlInsertIdentity.close();
sqlInsertIdentity = null;
}
}
}