From 28ca0fdf953115638b9e569d37a54b18d2dd49bf Mon Sep 17 00:00:00 2001 From: Maciek Blim Date: Sun, 21 Dec 2014 10:05:10 +0100 Subject: [PATCH] [Messaging] moved MessageConversation class Change-Id: I0134a4ae62e3ab4df54f65499f87ba945b9f1352 Signed-off-by: Maciek Blim --- src/messaging/message_conversation.cc | 500 ++++++++++++++++++++++++++ src/messaging/message_conversation.h | 97 +++++ src/messaging/messaging.gyp | 4 +- src/messaging/messaging_util.cc | 14 + src/messaging/messaging_util.h | 15 + 5 files changed, 629 insertions(+), 1 deletion(-) create mode 100644 src/messaging/message_conversation.cc create mode 100644 src/messaging/message_conversation.h diff --git a/src/messaging/message_conversation.cc b/src/messaging/message_conversation.cc new file mode 100644 index 00000000..a3fd9de7 --- /dev/null +++ b/src/messaging/message_conversation.cc @@ -0,0 +1,500 @@ +// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "common/logger.h" +#include "common/platform_exception.h" + +#include "messaging_util.h" +#include "message.h" +#include "message_conversation.h" + +#define MAX_THREAD_DATA_LEN 128 + +namespace extension { +namespace messaging { + +using namespace tizen; + +// *** constructor +MessageConversation::MessageConversation(): + m_conversation_id(-1), + m_conversation_type(UNDEFINED), + m_count(0), + m_unread_messages(0), + m_is_read(false) +{ + LoggerD("Message Conversation constructor."); +} + +MessageConversation::~MessageConversation() +{ + LoggerD("Message Conversation destructor."); +} +// *** attributes getters +int MessageConversation::getConversationId() const +{ + return m_conversation_id; +} + +MessageType MessageConversation::getType() const +{ + return m_conversation_type; +} + +time_t MessageConversation::getTimestamp() const +{ + return m_timestamp; +} + +unsigned long MessageConversation::getMessageCount() const +{ + return m_count; +} + +unsigned long MessageConversation::getUnreadMessages() const +{ + return m_unread_messages; +} + +std::string MessageConversation::getPreview() const +{ + return m_preview; +} + +std::string MessageConversation::getSubject() const +{ + return m_conversation_subject; +} + +bool MessageConversation::getIsRead() const +{ + return m_is_read; +} + +std::string MessageConversation::getFrom() const +{ + return m_from; +} + +std::vector MessageConversation::getTo() const +{ + return m_to; +} + +std::vector MessageConversation::getCC() const +{ + return m_cc; +} + +std::vector MessageConversation::getBCC() const +{ + return m_bcc; +} + +int MessageConversation::getLastMessageId() const +{ + return m_last_message_id; +} + +std::shared_ptr MessageConversation::convertMsgConversationToObject( + unsigned int threadId, msg_handle_t handle) +{ + std::shared_ptr conversation (new MessageConversation()); + + msg_struct_t msgInfo = NULL; + msg_struct_t sendOpt = NULL; + + msg_struct_t msg_thread = NULL; + + msg_struct_list_s convViewList; + msg_list_handle_t addr_list = NULL; + msg_struct_t addr_info = NULL; + + msg_error_t err = MSG_SUCCESS; + + int tempInt; + bool tempBool; + int nToCnt; + unsigned int lastMsgIndex = 0; + char msgData[MAX_THREAD_DATA_LEN] = {0,}; + + try { + msgInfo = msg_create_struct(MSG_STRUCT_MESSAGE_INFO); + sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT); + + conversation->m_conversation_id = threadId; + + msg_thread = msg_create_struct(MSG_STRUCT_THREAD_INFO); + err = msg_get_thread(handle, conversation->m_conversation_id, msg_thread); + if (err != MSG_SUCCESS) + { + LoggerE("Failed to retrieve thread."); + throw common::UnknownException("Failed to retrieve thread."); + } + msg_get_int_value(msg_thread, MSG_THREAD_MSG_TYPE_INT, &tempInt); + switch(tempInt) + { + case MSG_TYPE_SMS: + case MSG_TYPE_SMS_CB: + case MSG_TYPE_SMS_JAVACB: + case MSG_TYPE_SMS_WAPPUSH: + case MSG_TYPE_SMS_MWI: + case MSG_TYPE_SMS_SYNCML: + case MSG_TYPE_SMS_REJECT: + conversation->m_conversation_type = SMS; + break; + case MSG_TYPE_MMS: + case MSG_TYPE_MMS_JAVA: + case MSG_TYPE_MMS_NOTI: + conversation->m_conversation_type = MMS; + break; + } + + msg_get_int_value(msg_thread, MSG_THREAD_MSG_TIME_INT, &tempInt); + conversation->m_timestamp = tempInt; + + msg_get_int_value(msg_thread, MSG_THREAD_UNREAD_COUNT_INT, &tempInt); + conversation->m_unread_messages = tempInt; + + msg_get_str_value(msg_thread, MSG_THREAD_MSG_DATA_STR, msgData, MAX_THREAD_DATA_LEN); + + conversation->m_preview = msgData; + + err = msg_get_conversation_view_list(handle, conversation->m_conversation_id, + &convViewList); + if (err != MSG_SUCCESS) + { + LoggerE("Get conversation(msg) view list fail."); + throw common::UnknownException("Get conversation(msg) view list fail."); + } + + lastMsgIndex = convViewList.nCount - 1; + conversation->m_count = convViewList.nCount; + + msg_get_bool_value(convViewList.msg_struct_info[lastMsgIndex], MSG_CONV_MSG_READ_BOOL, &tempBool); + conversation->m_is_read = tempBool; + + msg_get_int_value(convViewList.msg_struct_info[lastMsgIndex], MSG_CONV_MSG_ID_INT, &tempInt); + conversation->m_last_message_id = tempInt; + + if (msg_get_message(handle, conversation->m_last_message_id, msgInfo, + sendOpt) != MSG_SUCCESS) + { + LoggerE("Get message fail."); + throw common::UnknownException("get message fail."); + } + + msg_get_int_value(convViewList.msg_struct_info[lastMsgIndex], MSG_CONV_MSG_DIRECTION_INT, &tempInt); + + msg_get_list_handle(msgInfo, MSG_MESSAGE_ADDR_LIST_HND, (void **)&addr_list); + nToCnt = msg_list_length(addr_list); + + if (MSG_DIRECTION_TYPE_MT == tempInt) + { + if (nToCnt > 0 && nToCnt < MAX_TO_ADDRESS_CNT ) + { + char strNumber[MAX_ADDRESS_VAL_LEN] = {0,}; + addr_info = (msg_struct_t)msg_list_nth_data(addr_list, nToCnt-1); + msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR, strNumber, MAX_ADDRESS_VAL_LEN); + + if (strNumber[0] != '\0') + { + conversation->m_from = strNumber; + } + else + { + LoggerD("address is null "); + } + } + else + { + LoggerD("address count index fail"); + } + } + else + { + if (nToCnt > 0 && nToCnt < MAX_TO_ADDRESS_CNT ) + { + for (int index = 0; index < nToCnt; index++) + { + addr_info = (msg_struct_t)msg_list_nth_data(addr_list, index); + char strNumber[MAX_ADDRESS_VAL_LEN] = {0,}; + msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR, strNumber, MAX_ADDRESS_VAL_LEN); + + conversation->m_to.push_back(strNumber); + } + } + else + { + LoggerD("address fetch fail"); + } + } + + char strTemp[MAX_SUBJECT_LEN] = {0}; + msg_get_str_value(msgInfo, MSG_MESSAGE_SUBJECT_STR, strTemp, MAX_SUBJECT_LEN); + + conversation->m_conversation_subject = strTemp; + msg_release_list_struct(&convViewList); + msg_release_struct(&msgInfo); + msg_release_struct(&sendOpt); + msg_release_struct(&msg_thread); + } catch (const common::PlatformException& ex) { + msg_release_list_struct(&convViewList); + msg_release_struct(&msgInfo); + msg_release_struct(&sendOpt); + msg_release_struct(&msg_thread); + LoggerE("%s (%s)", (ex.name()).c_str(), (ex.message()).c_str()); + throw common::UnknownException("Unable to convert short message conversation."); + } catch (...) { + msg_release_list_struct(&convViewList); + msg_release_struct(&msgInfo); + msg_release_struct(&sendOpt); + msg_release_struct(&msg_thread); + throw common::UnknownException("Unable to convert short message conversation."); + } + + return conversation; +} + +std::shared_ptr MessageConversation::convertEmailConversationToObject( + unsigned int threadId) +{ + std::shared_ptr conversation (new MessageConversation()); + + email_mail_list_item_t *resultMail = NULL; + + if(email_get_thread_information_ex(threadId, &resultMail) != EMAIL_ERROR_NONE) + { + LoggerE("Couldn't get conversation"); + throw common::UnknownException("Couldn't get conversation."); + } else { + if (!resultMail) + { + LoggerE("Data is null"); + throw common::UnknownException("Get email data fail."); + } + + email_mail_data_t* mailData = NULL; + + if (email_get_mail_data(resultMail->mail_id, + &mailData) != EMAIL_ERROR_NONE) + { + free(resultMail); + throw common::UnknownException("Get email data fail."); + } + + if (!mailData) { + free(resultMail); + throw common::UnknownException("Get email data fail."); + } + + int index = 0; + int count = 0; + conversation->m_unread_messages = 0; + email_mail_list_item_t *mailList = NULL; + + if (email_get_mail_list(mailData->account_id, 0, threadId, 0, + resultMail->thread_item_count, EMAIL_SORT_DATETIME_HIGH, &mailList, + &count) != EMAIL_ERROR_NONE) + { + email_free_mail_data(&mailData , 1); + free(resultMail); + throw common::UnknownException("Get email data list fail."); + } + + for (index = 0; index < count; index++) + { + if (mailList[index].flags_seen_field) + { + conversation->m_unread_messages++; + } + } + conversation->m_count = resultMail->thread_item_count; + + conversation->m_conversation_id = threadId; + + conversation->m_conversation_type = EMAIL; + + conversation->m_timestamp = resultMail->date_time; + + if (resultMail->preview_text[0] != '\0') + { + conversation->m_preview = resultMail->preview_text; + } + + if (resultMail->subject[0] != '\0') + { + conversation->m_conversation_subject = resultMail->subject; + } + + conversation->m_is_read = (bool)resultMail->flags_seen_field; + + if (resultMail->full_address_from[0] != '\0') + { + conversation->m_from = MessagingUtil::extractSingleEmailAddress( + resultMail->full_address_from); + } + + if (mailData->full_address_to != NULL) + { + conversation->m_to = Message::getEmailRecipientsFromStruct( + mailData->full_address_to); + } + + if (mailData->full_address_cc != NULL) + { + conversation->m_cc = Message::getEmailRecipientsFromStruct( + mailData->full_address_cc); + } + + if (mailData->full_address_bcc != NULL) + { + conversation->m_bcc = Message::getEmailRecipientsFromStruct( + mailData->full_address_bcc); + } + + conversation->m_last_message_id = resultMail->mail_id; + + if (mailData != NULL) + { + email_free_mail_data(&mailData , 1); + } + } + + if (resultMail != NULL) + { + free(resultMail); + } + + return conversation; +} + +std::shared_ptr MessageConversation::convertConversationStructToObject( + unsigned int threadId, MessageType msgType, msg_handle_t handle) +{ + std::shared_ptr conversation (new MessageConversation()); + + if (EMAIL == msgType) { + conversation = convertEmailConversationToObject(threadId); + } else { + if(handle != NULL) { + conversation = convertMsgConversationToObject(threadId, handle); + } else { + LoggerE("Handle has not been sent."); + throw common::UnknownException("Handle has not been sent."); + } + } + + return conversation; +} + +void MessageConversation::setConversationId(int id) +{ + m_conversation_id = id; +} +void MessageConversation::setMessageCount(int count) +{ + m_count = count; +} + +void MessageConversation::setUnreadMessages(int count) +{ + m_unread_messages = count; +} + +/** + * + * Attribute | Attribute filter| Attribute range filter + * | supported | supported + * ----------------+-----------------+------------------------ + * id | Yes | No + * type | Yes | No + * timestamp | No | Yes + * messageCount | Yes | No + * unreadMessages | Yes | No + * preview | Yes | No + * subject | No | No + * isRead | No | No + * from | Yes | No + * to | Yes | No + * cc | No | No + * bcc | No | No + * lastMessageId | No | No + */ + +namespace CONVERSATION_FILTER_ATTRIBUTE { +const std::string ID = MESSAGE_CONVERSATION_ATTRIBUTE_ID; +const std::string TYPE = MESSAGE_CONVERSATION_ATTRIBUTE_TYPE; +const std::string TIMESTAMP = MESSAGE_CONVERSATION_ATTRIBUTE_TIMESTAMP; +const std::string MESSAGE_COUNT = MESSAGE_CONVERSATION_ATTRIBUTE_MESSAGE_COUNT; +const std::string UNREAD_MESSAGES = MESSAGE_CONVERSATION_ATTRIBUTE_UNREAD_MESSAGES; +const std::string PREVIEW = MESSAGE_CONVERSATION_ATTRIBUTE_PREVIEW; +const std::string FROM = MESSAGE_CONVERSATION_ATTRIBUTE_FROM; +const std::string TO = MESSAGE_CONVERSATION_ATTRIBUTE_TO; +} //namespace CONVERSATION_FILTER_ATTRIBUTE + +bool MessageConversation::isMatchingAttribute(const std::string& attribute_name, + const FilterMatchFlag match_flag, + AnyPtr match_value) const +{ + LoggerD("Entered"); + auto key = match_value->toString(); + LoggerD("attribute_name: %s match_flag:%d match_value:%s", attribute_name.c_str(), + match_flag, key.c_str()); + + using namespace CONVERSATION_FILTER_ATTRIBUTE; + + if(ID == attribute_name) { + return FilterUtils::isStringMatching(key, std::to_string(getConversationId()), + match_flag); + } + else if(TYPE == attribute_name) { + const MessageType msg_type = getType(); + const std::string msg_type_str = MessagingUtil::messageTypeToString(msg_type); + return FilterUtils::isStringMatching(key, msg_type_str, match_flag); + } + else if(MESSAGE_COUNT == attribute_name) { + return FilterUtils::isStringMatching(key, std::to_string(getMessageCount()), + match_flag); + } + else if(UNREAD_MESSAGES == attribute_name) { + return FilterUtils::isStringMatching(key, std::to_string(getUnreadMessages()), + match_flag); + } + else if(PREVIEW == attribute_name) { + return FilterUtils::isStringMatching(key, getPreview(), match_flag); + } + else if(FROM == attribute_name) { + return FilterUtils::isStringMatching(key, getFrom(), match_flag); + } + else if(TO == attribute_name) { + return FilterUtils::isAnyStringMatching(key, getTo(), match_flag); + } + else { + LoggerD("attribute:%s is NOT SUPPORTED", attribute_name.c_str()); + } + + return false; +} + +bool MessageConversation::isMatchingAttributeRange(const std::string& attribute_name, + AnyPtr initial_value, + AnyPtr end_value) const +{ + LoggerD("Entered attribute_name: %s", attribute_name.c_str()); + + using namespace CONVERSATION_FILTER_ATTRIBUTE; + + if(TIMESTAMP == attribute_name) { + return FilterUtils::isTimeStampInRange(getTimestamp(), initial_value, end_value); + } + else { + LoggerD("attribute:%s is NOT SUPPORTED", attribute_name.c_str()); + } + return false; +} + +} //messaging +} //extension + diff --git a/src/messaging/message_conversation.h b/src/messaging/message_conversation.h new file mode 100644 index 00000000..f1aa50a4 --- /dev/null +++ b/src/messaging/message_conversation.h @@ -0,0 +1,97 @@ +// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#ifndef __TIZEN_MESSAGE_CONVERSATION_H__ +#define __TIZEN_MESSAGE_CONVERSATION_H__ + +#include +#include +#include +#include +#include +#include +#include +#include "messaging_util.h" +#include "MsgCommon/AbstractFilter.h" + +namespace extension { +namespace messaging { + +class MessageConversation; + +struct MessageConversationHolder { + std::shared_ptrptr; +}; + +typedef std::shared_ptr ConversationPtr; + +typedef std::vector ConversationPtrVector; + +class MessageConversation : public tizen::FilterableObject { +public: + MessageConversation(); + ~MessageConversation(); + + // attributes getters + int getConversationId() const; + MessageType getType() const; + time_t getTimestamp() const; + unsigned long getMessageCount() const; + unsigned long getUnreadMessages() const; + std::string getPreview() const; + std::string getSubject() const; + bool getIsRead() const; + std::string getFrom() const; + std::vector getTo() const; + std::vector getCC() const; + std::vector getBCC() const; + int getLastMessageId() const; + + static std::shared_ptr convertConversationStructToObject( + unsigned int threadId, MessageType msgType, msg_handle_t handle = NULL); + static std::shared_ptr convertEmailConversationToObject( + unsigned int threadId); + /** + * + * @param threadId Id of Message (not Conversation) + * @param handle + * @return + */ + static std::shared_ptr convertMsgConversationToObject( + unsigned int threadId, msg_handle_t handle); + + virtual void setConversationId(int id); + virtual void setMessageCount(int count); + virtual void setUnreadMessages(int count); + + // tizen::FilterableObject + virtual bool isMatchingAttribute(const std::string& attribute_name, + const tizen::FilterMatchFlag match_flag, + tizen::AnyPtr match_value) const; + + virtual bool isMatchingAttributeRange(const std::string& attribute_name, + tizen::AnyPtr initial_value, + tizen::AnyPtr end_value) const; + +private: + int m_conversation_id; + MessageType m_conversation_type; + time_t m_timestamp; + unsigned long m_count; + unsigned long m_unread_messages; + std::string m_preview; + std::string m_conversation_subject; + bool m_is_read; + std::string m_from; + std::vector m_to; + std::vector m_cc; + std::vector m_bcc; + int m_last_message_id; +}; + +} //messaging +} //extension + +#endif // __TIZEN_MESSAGE_CONVERSATION_H__ diff --git a/src/messaging/messaging.gyp b/src/messaging/messaging.gyp index 2309cfe4..4f485063 100644 --- a/src/messaging/messaging.gyp +++ b/src/messaging/messaging.gyp @@ -93,7 +93,9 @@ 'messages_change_callback.cc', 'messages_change_callback.h', 'message_folder.cc', - 'message_folder.h' + 'message_folder.h', + 'message_conversation.cc', + 'message_conversation.h' ], 'includes': [ '../common/pkg-config.gypi', diff --git a/src/messaging/messaging_util.cc b/src/messaging/messaging_util.cc index 62b8f99f..5dc530aa 100644 --- a/src/messaging/messaging_util.cc +++ b/src/messaging/messaging_util.cc @@ -63,6 +63,20 @@ const char* MESSAGE_ATTACHMENT_ATTRIBUTE_FILE_PATH = "filePath"; const char* MESSAGE_FOLDER_ATTRIBUTE_SERVICE_ID = "serviceId"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_ID = "id"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_TYPE = "type"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_TIMESTAMP = "timestamp"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_MESSAGE_COUNT = "messageCount"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_UNREAD_MESSAGES = "unreadMessages"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_PREVIEW = "preview"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_SUBJECT = "subject"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_IS_READ = "isRead"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_FROM = "from"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_TO = "to"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_CC = "cc"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_BCC = "bcc"; +const char* MESSAGE_CONVERSATION_ATTRIBUTE_LAST_MESSAGE_ID = "lastMessageId"; + namespace { const std::string TYPE_SMS = "messaging.sms"; const std::string TYPE_MMS = "messaging.mms"; diff --git a/src/messaging/messaging_util.h b/src/messaging/messaging_util.h index 11f31c59..68bd101f 100644 --- a/src/messaging/messaging_util.h +++ b/src/messaging/messaging_util.h @@ -51,6 +51,7 @@ extern const char* MESSAGE_BODY_ATTRIBUTE_LOADED; extern const char* MESSAGE_BODY_ATTRIBUTE_PLAIN_BODY; extern const char* MESSAGE_BODY_ATTRIBUTE_HTML_BODY; +extern const char* MESSAGE_ATTRIBUTE_MESSAGE_ATTACHMENT; extern const char* MESSAGE_ATTACHMENT_ATTRIBUTE_ID; extern const char* MESSAGE_ATTACHMENT_ATTRIBUTE_MESSAGE_ID; extern const char* MESSAGE_ATTACHMENT_ATTRIBUTE_MIME_TYPE; @@ -58,6 +59,20 @@ extern const char* MESSAGE_ATTACHMENT_ATTRIBUTE_FILE_PATH; extern const char* MESSAGE_FOLDER_ATTRIBUTE_SERVICE_ID; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_ID; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_TYPE; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_TIMESTAMP; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_MESSAGE_COUNT; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_UNREAD_MESSAGES; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_PREVIEW; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_SUBJECT; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_IS_READ; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_FROM; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_TO; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_CC; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_BCC; +extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_LAST_MESSAGE_ID; + enum MessageType { UNDEFINED = 0, SMS, -- 2.34.1