/* * 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.engine.presence; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import android.database.sqlite.SQLiteDatabase; import com.vodafone360.people.database.DatabaseHelper; import com.vodafone360.people.database.tables.ActivitiesTable; import com.vodafone360.people.database.tables.ContactDetailsTable; import com.vodafone360.people.database.tables.ContactSummaryTable; import com.vodafone360.people.database.tables.ConversationsTable; import com.vodafone360.people.database.tables.ActivitiesTable.TimelineNativeTypes; import com.vodafone360.people.database.tables.ActivitiesTable.TimelineSummaryItem; import com.vodafone360.people.datatypes.ActivityItem; import com.vodafone360.people.datatypes.ChatMessage; import com.vodafone360.people.datatypes.ContactDetail; import com.vodafone360.people.datatypes.ContactSummary; import com.vodafone360.people.datatypes.VCardHelper; import com.vodafone360.people.datatypes.ContactDetail.DetailKeys; import com.vodafone360.people.engine.presence.NetworkPresence.SocialNetwork; import com.vodafone360.people.service.ServiceStatus; import com.vodafone360.people.utils.LogUtils; /*** * Utilities relating to Chat messages. */ public class ChatDbUtils { /** * User ID is formated <network>::<userId>, using this as the divider. */ protected static final String COLUMNS = "::"; /*** * Set the user ID, network ID and local contact ID values in the given * ChatMessage. * * The original msg.getUserId() is formatted <network>::<userId>, meaning * if "::" is present the values are split, otherwise the original value is * used. * * @param chatMessage ChatMessage to be altered. * @param databaseHelper DatabaseHelper with a readable database. */ public static void convertUserIds(final ChatMessage chatMessage, final DatabaseHelper databaseHelper) { /** * Use original User ID, in case of NumberFormatException (see * PAND-2356). */ final String originalUserId = chatMessage.getUserId(); int index = originalUserId.indexOf(COLUMNS); if (index > -1) { /** Parse a <networkId>::<userId> formatted user ID. **/ chatMessage.setUserId( originalUserId.substring(index + COLUMNS.length())); String network = originalUserId.substring(0, index); /** Parse the <networkId> component. **/ SocialNetwork sn = SocialNetwork.getValue(network); if (sn != null) { chatMessage.setNetworkId(sn.ordinal()); } else { chatMessage.setNetworkId(SocialNetwork.INVALID.ordinal()); LogUtils.logE("ChatUtils.convertUserIds() Invalid Network ID [" + network + "] in [" + originalUserId + "]"); } } chatMessage.setLocalContactId( ContactDetailsTable.findLocalContactIdByKey( SocialNetwork.getSocialNetworkValue( chatMessage.getNetworkId()).toString(), chatMessage.getUserId(), ContactDetail.DetailKeys.VCARD_IMADDRESS, databaseHelper.getReadableDatabase()) ); } /** * This method saves the supplied * * @param msg * @param type * @param databaseHelper */ protected static void saveChatMessageAsATimeline(ChatMessage message, TimelineSummaryItem.Type type, DatabaseHelper databaseHelper) { TimelineSummaryItem item = new TimelineSummaryItem(); fillInContactDetails(message, item, databaseHelper, type); SQLiteDatabase writableDatabase = databaseHelper.getWritableDatabase(); boolean isRead = true; if(type == TimelineSummaryItem.Type.INCOMING) { isRead = false; } if (ActivitiesTable.addChatTimelineEvent(item, isRead, writableDatabase) != -1) { ConversationsTable.addNewConversationId(message, writableDatabase); } else { LogUtils.logE("The msg was not saved to the ActivitiesTable"); } } /** * Remove hard code * * @param msg * @param item * @param databaseHelper * @param incoming */ private static void fillInContactDetails(ChatMessage msg, TimelineSummaryItem item, DatabaseHelper databaseHelper, TimelineSummaryItem.Type incoming) { item.mTimestamp = System.currentTimeMillis(); // here we set the time stamp back into the chat message // in order to be able to remove it from the chat history by time stamp in case its delivery fails msg.setTimeStamp(item.mTimestamp); item.mType = ActivityItem.Type.MESSAGE_IM_CONVERSATION; item.mDescription = msg.getBody(); item.mTitle = DateFormat.getDateInstance().format(new Date(item.mTimestamp)); // we store sender's localContactId for incoming msgs and recipient's // localContactId for outgoing msgs item.mLocalContactId = msg.getLocalContactId(); if (item.mLocalContactId != null && item.mLocalContactId != -1) { ContactDetail cd = ContactDetailsTable.fetchDetail(item.mLocalContactId, DetailKeys.VCARD_NAME, databaseHelper.getReadableDatabase()); if (cd == null || cd.getName() == null) { // if we don't get any details, we have to check the summary // table because gtalk contacts // without name will be otherwise show as unknown ContactSummary contactSummary = new ContactSummary(); ServiceStatus error = ContactSummaryTable.fetchSummaryItem(item.mLocalContactId, contactSummary, databaseHelper.getReadableDatabase()); if (error == ServiceStatus.SUCCESS) { item.mContactName = (contactSummary.formattedName != null) ? contactSummary.formattedName : ContactDetail.UNKNOWN_NAME; } else { item.mContactName = ContactDetail.UNKNOWN_NAME; } } else { /** Get name from contact details. **/ VCardHelper.Name name = cd.getName(); item.mContactName = (name != null) ? name.toString() : ContactDetail.UNKNOWN_NAME; } } item.mIncoming = incoming; item.mContactNetwork = SocialNetwork.getSocialNetworkValue(msg.getNetworkId()).toString(); item.mNativeItemType = TimelineNativeTypes.ChatLog.ordinal(); } /** * This method copies the conversation id and user id into the supplied * ChatMessage based on its mNetworkId and mLocalContactId * * @param chatMessage ChatMessage * @param databaseHelper Databasehelper */ protected static void fillMessageByLocalContactIdAndNetworkId(ChatMessage chatMessage, DatabaseHelper databaseHelper) { ConversationsTable.fillMessageInByLocalContactIdAndNetworkId(chatMessage, databaseHelper .getReadableDatabase(), databaseHelper.getWritableDatabase()); } /** * This method finds the user id (360 UserId or 3rd-party network id) and * sets it into the supplied chat message * * @param msg ChatMessage - the supplied chat message * @param databaseHelper DatabaseHelper - the database */ protected static void findUserIdForMessageByLocalContactIdAndNetworkId(ChatMessage msg, DatabaseHelper databaseHelper) { List<String> tos = new ArrayList<String>(); msg.setUserId(ContactDetailsTable.findChatIdByLocalContactIdAndNetwork(SocialNetwork .getSocialNetworkValue(msg.getNetworkId()).toString(), msg.getLocalContactId(), databaseHelper.getReadableDatabase())); String fullUserId = SocialNetwork.getSocialNetworkValue(msg.getNetworkId()).toString() + COLUMNS + msg.getUserId(); tos.add(fullUserId); msg.setUserId(fullUserId); msg.setTos(tos); } /** * This method deletes the conversation with the given id from the * ConversationsTable * * @param conversationId String - the conversation id * @param dbHelper DatabaseHelper - the database */ protected static void deleteConversationById(String conversationId, DatabaseHelper dbHelper) { ConversationsTable.removeConversation(conversationId, dbHelper.getWritableDatabase()); } /** * This method deletes conversations older than 1 week except for those with * current contact * * @param localContactId long- current contact mLocalContactId * @param dbHelper DatabaseHelper - the database */ protected static void cleanOldConversationsExceptForContact(long localContactId, DatabaseHelper dbHelper) { ActivitiesTable.removeChatTimelineExceptForContact(localContactId, dbHelper .getWritableDatabase()); } /** * This method returns the number of unread chat messages for this contact * * @param localContactId long - the contact's mLocalContactId * @param network String - the specified network, @see SocialNetwork * @param dbHelper Database - the database * @return int - the number of unread chat messages for the specified * contact */ public static int getNumberOfUnreadChatMessagesForContactAndNetwork(long localContactId, String network, DatabaseHelper dbHelper) { return ActivitiesTable.getNumberOfUnreadChatMessagesForContactAndNetwork(localContactId, network, dbHelper.getReadableDatabase()); } /** * This method deletes the last outgoing chat message in * ActivitiesTable, and removes the conversation id of this message from the * ConversationsTable. So that next time when user tries to send a message a * new conversation id will be requested. The message sending might fail * because the conversation id might have expired. * * Currently there's no reliable way to get the reason of message delivery failure, so * we assume that an expired conversation id might cause it as well, and remove it. * * In case the conversation id is valid the "get conversation" call will return the old id. * * @param dbHelper DatabaseHelper - database * @param message ChatMessage - the chat message which has not been sent and needs to be deleted from the history. */ protected static void deleteUnsentMessage(DatabaseHelper dbHelper, ChatMessage message) { ConversationsTable.removeConversation(message.getConversationId(), dbHelper.getWritableDatabase()); ActivitiesTable.deleteUnsentChatMessageForContact(message.getLocalContactId(), message.getTimeStamp(), dbHelper.getWritableDatabase()); } }