/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at
* src/com/vodafone360/people/VODAFONE.LICENSE.txt or
* http://github.com/360/360-Engine-for-Android
* See the License for the specific language governing permissions and
* limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each file and
* include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the fields
* enclosed by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2010 Vodafone Sales & Services Ltd. All rights reserved.
* Use is subject to license terms.
*/
package com.vodafone360.people.database.tables;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import com.vodafone360.people.database.DatabaseHelper;
import com.vodafone360.people.datatypes.ChatMessage;
import com.vodafone360.people.engine.presence.NetworkPresence.SocialNetwork;
import com.vodafone360.people.utils.CloseUtils;
public abstract class ConversationsTable {
/***
* The name of the table as it appears in the database. TODO: methods
* signatures might change
*/
public static final String TABLE_NAME = "Conversations"; // it is used in
// the tests
private static final String DEFAULT_ERROR_MESSAGE = "ConversationsTable: the passed in database is null!";
private static final long THIRTY_MINUTES = 30 * 60 * 1000;
private static final String COLUMNS = "::";
/**
* An enumeration of all the field names in the database, containing ID,
* LOCAL_CONTACT_ID, USER_ID, NETWORK_ID, NETWORK_STATUS.
*/
private static enum Field {
/**
* The primary key.
*/
ID("id"), // INT
/**
* the conversation unique id
*/
CONVERSATION_ID("conversationId"), // STRING
/**
* the other party of the conversation unique id, localContactId
*/
LOCALCONTACT_ID("fromLocalContactId"), // LONG
/**
* the other party of the conversation web id: IM address, 360 userId
*/
USER_ID("toUserId"), // STRING
/**
* @see SocialNetwork
*/
NETWORK_ID("networkId"),
/**
* the last time a message on this conversation was sent/received
*/
LATEST_MESSAGE("timeStamp"); // LONG the chat
// message id
/**
* The name of the field as it appears in the database.
*/
private String mField;
/**
* Constructor.
*
* @param field - Field name
*/
private Field(String field) {
mField = field;
}
/*
* This implementation returns the field name. (non-Javadoc)
* @see java.lang.Enum#toString()
*/
public String toString() {
return mField;
}
}
// private static final int ID = 0;
private static final int CONVERSATION_ID = 1;
// private static final int LOCAL_CONTACT_ID = 2;
private static final int USER_ID = 3;
// private static final int NETWORK_ID = 4;
private static final int LATEST_MESSAGE = 5;
/**
* This method creates the PresenceTable.
*
* @param writableDb - the writable database
* @throws SQLException is thrown when request to create a table fails with
* an SQLException
* @throws NullPointerException if the passed in database instance is null
*/
public static void create(SQLiteDatabase writableDb) throws SQLException, NullPointerException {
DatabaseHelper.trace(true, "Conversations.create()");
if (writableDb == null) {
throw new NullPointerException(DEFAULT_ERROR_MESSAGE);
}
String createSql = "CREATE TABLE " + TABLE_NAME + " (" + Field.ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + Field.CONVERSATION_ID + " STRING, "
+ Field.LOCALCONTACT_ID + " LONG, " + Field.USER_ID + " STRING, "
+ Field.NETWORK_ID + " INTEGER, " + Field.LATEST_MESSAGE + " LONG);";
writableDb.execSQL(createSql);
}
public static void addNewConversationId(ChatMessage msg, SQLiteDatabase writableDb)
throws SQLException, NullPointerException {
DatabaseHelper.trace(true, "PresenceTable.create()");
if (writableDb == null) {
throw new NullPointerException(DEFAULT_ERROR_MESSAGE);
}
if (!conversationIdExists(msg.getConversationId(), writableDb)) {
// remove old conversation for this user if it existed
removeOldConversationByLocalContactIdAndNetworkId(msg.getLocalContactId(), msg
.getNetworkId(), writableDb);
ContentValues values = new ContentValues();
values.put(Field.CONVERSATION_ID.toString(), msg.getConversationId());
values.put(Field.LOCALCONTACT_ID.toString(), msg.getLocalContactId());
values.put(Field.USER_ID.toString(), msg.getUserId());
values.put(Field.NETWORK_ID.toString(), msg.getNetworkId());
values.put(Field.LATEST_MESSAGE.toString(), System.currentTimeMillis());
writableDb.insertOrThrow(TABLE_NAME, null, values);
values.clear();
}
}
/**
* TODO: this method might need redesign for performance: don't SELECT !!*
*
* @param timeLineId
* @param readableDb
* @return
* @throws SQLException
* @throws NullPointerException
*/
public static void fillMessageInByLocalContactIdAndNetworkId(ChatMessage msg,
SQLiteDatabase readableDb, SQLiteDatabase writableDb) throws SQLException,
NullPointerException {
DatabaseHelper.trace(true, "PresenceTable.create()");
if (readableDb == null || (writableDb == null)) {
throw new NullPointerException(DEFAULT_ERROR_MESSAGE);
}
Cursor c = null;
try {
c = readableDb.rawQuery("SELECT * FROM " + TABLE_NAME + " WHERE "
+ Field.LOCALCONTACT_ID + "=" + msg.getLocalContactId() + " AND "
+ Field.NETWORK_ID + "=" + msg.getNetworkId(), null);
List<String> tos = null;
// should be just one
while (c.moveToNext()) {
if (System.currentTimeMillis() - c.getLong(LATEST_MESSAGE) < THIRTY_MINUTES) {
msg.setUserId(c.getString(USER_ID));
msg.setConversationId(c.getString(CONVERSATION_ID));
tos = new ArrayList<String>();
tos.add(SocialNetwork.getSocialNetworkValue(msg.getNetworkId()) + COLUMNS
+ msg.getUserId());
} else {
removeOldConversationByLocalContactIdAndNetworkId(msg.getLocalContactId(), msg
.getNetworkId(), writableDb);
}
break;
}
msg.setTos(tos);
// this finally part should always run, while the exception is still
// thrown
} finally {
CloseUtils.close(c);
c = null;
}
}
/**
* @param localContactId
* @param networkId
* @param writableDb
* @return
* @throws SQLException
* @throws NullPointerException
*/
private static int removeOldConversationByLocalContactIdAndNetworkId(long localContactId,
int networkId, SQLiteDatabase writableDb) throws SQLException, NullPointerException {
DatabaseHelper.trace(true, "PresenceTable.create()");
if (writableDb == null) {
throw new NullPointerException(DEFAULT_ERROR_MESSAGE);
}
return writableDb.delete(TABLE_NAME, Field.LOCALCONTACT_ID + "=" + localContactId + " AND "
+ Field.NETWORK_ID + "=" + networkId, null);
}
/**
* @param conversationId
* @param readableDb
* @return
* @throws SQLException
* @throws NullPointerException
*/
private static boolean conversationIdExists(String conversationId, SQLiteDatabase readableDb)
throws SQLException, NullPointerException {
DatabaseHelper.trace(true, "PresenceTable.create()");
if (readableDb == null) {
throw new NullPointerException(DEFAULT_ERROR_MESSAGE);
}
boolean exists = false;
Cursor c = null;
try {
c = readableDb.rawQuery("SELECT * FROM " + TABLE_NAME + " WHERE "
+ Field.CONVERSATION_ID + "=\"" + conversationId + "\"", null);
if (c == null)
return false;
exists = c.getCount() > 0;
} finally {
CloseUtils.close(c);
c = null;
}
return exists;
}
/**
* This method removes the conversation with this id
*
* @param conversationId String - the conversation id to be removed
* @param writableDb DatabaseHelper - database
* @return the number of affected rows
* @throws SQLException
* @throws NullPointerException
*/
public static int removeConversation(String conversationId, SQLiteDatabase writableDb)
throws SQLException, NullPointerException {
DatabaseHelper.trace(true, "ConversationsTable.removeOldConversation():" + conversationId);
if (writableDb == null) {
throw new NullPointerException(DEFAULT_ERROR_MESSAGE);
}
return writableDb.delete(TABLE_NAME, Field.CONVERSATION_ID + "=\"" + conversationId + "\"",
null);
}
/**
* This method removes the conversation with this contact on this network
*
* @param localContactId long - the contacts mLocalContactId
* @param networkId int - the network id, @see SocialNetwork
* @param writableDb DatabaseHelper - the database
* @return the number of affected rows
* @throws SQLException
* @throws NullPointerException
*/
public static int removeConversation(long localContactId, int network, SQLiteDatabase writableDb)
throws SQLException, NullPointerException {
DatabaseHelper.trace(true, "ConversationsTable.removeConversation():" + localContactId
+ " with network " + network);
if (writableDb == null) {
throw new NullPointerException(DEFAULT_ERROR_MESSAGE);
}
return writableDb.delete(TABLE_NAME, Field.LOCALCONTACT_ID + "=\"" + localContactId
+ "\" AND " + Field.NETWORK_ID + "=" + network, null);
}
}