/*
* 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 android.database.sqlite.SQLiteException;
import com.vodafone360.people.database.DatabaseHelper;
import com.vodafone360.people.datatypes.Contact;
import com.vodafone360.people.service.ServiceStatus;
import com.vodafone360.people.utils.CloseUtils;
import com.vodafone360.people.utils.LogUtils;
/**
* Contains all the functionality related to the contact groups database table.
* This table stores all contact/group associations (0-many to 0-many
* relationship). This class is never instantiated hence all methods must be
* static.
*
* @version %I%, %G%
*/
public abstract class ContactGroupsTable {
/**
* Name of the table as it appears in the database
*/
public static final String TABLE_NAME = "ContactGroupRelations";
/**
* Represents the data stored in a record
*/
private static class ContactGroup {
/**
* The local contact ID from Contacts table
*/
private Long mLocalContactId = null;
/**
* The server group ID
*/
private Long mZybGroupId = null;
}
/**
* An enumeration of all the field names in the database.
*/
public static enum Field {
LOCALRELATIONID("LocalRelationId"),
LOCALCONTACTID("LocalContactId"),
ZYBGROUPID("ZybGroupId");
/**
* The name of the field as it appears in the database
*/
private final String mField;
/**
* Constructor
*
* @param field - The name of the field (see list above)
*/
private Field(String field) {
mField = field;
}
/**
* @return the name of the field as it appears in the database.
*/
public String toString() {
return mField;
}
}
/**
* Create Contact Groups Table.
*
* @param writeableDb A writable SQLite database
* @throws SQLException If an SQL compilation error occurs
*/
public static void create(SQLiteDatabase writeableDb) throws SQLException {
DatabaseHelper.trace(true, "ContactGroupsTable.create()");
writeableDb.execSQL("CREATE TABLE " + TABLE_NAME + " (" + Field.LOCALRELATIONID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + Field.LOCALCONTACTID + " LONG, "
+ Field.ZYBGROUPID + " LONG);");
}
/**
* Returns a ContentValues object that can be used to insert or update a new
* contact/group association to the table.
*
* @param contactGroup A ContactGroup object with the local Contact ID and
* Group Id set appropriately.
* @return The ContactValues object
*/
private static ContentValues fillUpdateData(ContactGroup contactGroup) {
DatabaseHelper.trace(false, "ContactGroupsTable.fillUpdateData()");
ContentValues contactValues = new ContentValues();
contactValues.put(Field.LOCALCONTACTID.toString(), contactGroup.mLocalContactId);
contactValues.put(Field.ZYBGROUPID.toString(), contactGroup.mZybGroupId);
return contactValues;
}
/**
* Associates a contact and a group
*
* @param localContactId The local contact Id from the Contacts table
* @param zybGroupId The server group ID from groups table
* @param writeableDb A writable SQLite database
* @return true if successful, false otherwise
*/
public static boolean addContactToGroup(long localContactId, long zybGroupId,
SQLiteDatabase writableDb) {
DatabaseHelper.trace(true, "ContactGroupsTable.addContactToGroup()");
try {
final ContactGroup contactGroup = new ContactGroup();
contactGroup.mLocalContactId = localContactId;
contactGroup.mZybGroupId = zybGroupId;
final ContentValues values = fillUpdateData(contactGroup);
if (writableDb.insertOrThrow(TABLE_NAME, null, values) < 0) {
LogUtils.logE("ContactGroupsTable.addContactToGroup() "
+ "Unable to insert new contact group summary");
return false;
}
return true;
} catch (SQLException e) {
LogUtils.logE("ContactGroupsTable.addContactToGroup() SQLException - "
+ "Unable to insert new contact summary", e);
return false;
}
}
/**
* Remove the association between contact and group.
*
* @param localContactId The local contact Id from the Contacts table
* @param zybGroupId The server group ID from groups table
* @param writeableDb A writable SQLite database
* @return true if successful, false otherwise
*/
public static boolean deleteContactFromGroup(long localContactId, long zybGroupId,
SQLiteDatabase writableDb) {
DatabaseHelper.trace(true, "ContactGroupsTable.deleteContactFromGroup()");
try {
if (writableDb.delete(TABLE_NAME, Field.LOCALCONTACTID + "=" + localContactId + " AND "
+ Field.ZYBGROUPID + "=" + zybGroupId, null) <= 0) {
LogUtils.logE("ContactGroupsTable.deleteContactFromGroup() "
+ "Unable to delete contact from group");
return false;
}
return true;
} catch (SQLException e) {
LogUtils.logE("ContactGroupsTable.deleteContactFromGroup() SQLException - "
+ "Unable to delete contact from group", e);
return false;
}
}
/**
* Removes all references to a contact from the table (should be called when
* a contact is deleted).
*
* @param localContactId The local contact Id from the Contacts table
* @param writeableDb A writable SQLite database
* @return true if successful, false otherwise
*/
public static boolean deleteContact(long localContactId, SQLiteDatabase writableDb) {
DatabaseHelper.trace(true, "ContactGroupsTable.deleteContact()");
try {
if (writableDb.delete(TABLE_NAME, Field.LOCALCONTACTID + "=" + localContactId, null) < 0) {
LogUtils.logE("ContactGroupsTable.deleteContact() "
+ "Unable to delete contact from contact groups table");
return false;
}
return true;
} catch (SQLException e) {
LogUtils.logE("ContactGroupsTable.deleteContact() SQLException - "
+ "Unable to delete contact from contact groups table", e);
return false;
}
}
/**
* Fetches all the groups associated with a given contact.
*
* @param localContactId The local contact Id from the Contacts table
* @param groupIds A list that will be populated with the result.
* @param readableDb A readable SQLite database
* @return true if successful, false otherwise
*/
public static boolean fetchContactGroups(long localContactId, List<Long> groupIds,
SQLiteDatabase readableDb) {
DatabaseHelper.trace(false, "ContactGroupsTable.fetchContactGroups() localContactId["
+ localContactId + "]");
String[] args = {
String.format("%d", localContactId)
};
Cursor c1 = null;
groupIds.clear();
try {
c1 = readableDb.rawQuery("SELECT " + Field.ZYBGROUPID + " FROM " + TABLE_NAME
+ " WHERE " + Field.LOCALCONTACTID + " = ?", args);
while (c1.moveToNext()) {
if (!c1.isNull(0)) {
groupIds.add(c1.getLong(0));
}
}
c1.close();
} catch (SQLiteException e) {
LogUtils.logE("ContactGroupsTable.fetchContactGroups()"
+ " Exception - Unable to fetch contact groups", e);
return false;
} finally {
CloseUtils.close(c1);
c1 = null;
}
return true;
}
/**
* Merges the given contact group relation changes into the database.
*
* @param contact the updated contact with the new group relations. If any
* of the group IDs are -1 the associated will be ignored.
* @param writeableDb A writable SQLite database
* @return SUCCESS or a suitable error code
*/
public static ServiceStatus modifyContact(Contact contact, SQLiteDatabase db) {
DatabaseHelper.trace(false, "ContactGroupsTable.modifyContact()");
final List<Long> contactGroups = new ArrayList<Long>();
final List<Long> updatedContactGroups = contact.groupList;
// get the contact groups
fetchContactGroups(contact.localContactID, contactGroups, db);
// check deleted groups
for (int i = 0; i < contactGroups.size();) {
Long groupId = contactGroups.get(i);
if (groupId != -1) {
if (!updatedContactGroups.contains(groupId)) {
contactGroups.remove(i);
if (!deleteContactFromGroup(contact.localContactID, groupId, db)) {
return ServiceStatus.ERROR_DATABASE_CORRUPT;
}
} else {
i++;
}
} else {
i++;
}
}
// check added groups
for (Long groupId : updatedContactGroups) {
if (groupId != -1) {
if (!contactGroups.contains(groupId)) {
if (!addContactToGroup(contact.localContactID, groupId, db)) {
return ServiceStatus.ERROR_DATABASE_CORRUPT;
}
}
}
}
return ServiceStatus.SUCCESS;
}
}