Add method to retrieve size of a conversation history and a part of it

parent 6ed82cb7
......@@ -1347,9 +1347,24 @@ LINPHONE_PUBLIC MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int
LINPHONE_PUBLIC void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr);
LINPHONE_PUBLIC void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
LINPHONE_PUBLIC void linphone_chat_room_delete_history(LinphoneChatRoom *cr);
/**
* Gets the number of messages in a chat room.
* @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which size has to be computed
* @return the number of messages.
*/
LINPHONE_PUBLIC int linphone_chat_room_get_history_size(LinphoneChatRoom *cr);
/**
* Gets the partial list of messages in the given range, sorted from most recent to oldest.
* @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which messages should be retrieved
* @param[in] begin The first message of the range to be retrieved. History most recent message has index 0.
* @param[in] end The last message of the range to be retrieved. History oldest message has index of history size - 1 (use #linphone_chat_room_get_history_size to retrieve history size)
* @return the list of messages in the given range, or NULL if nothing has been found.
*/
LINPHONE_PUBLIC MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end);
/**
* Notify the destination of the chat message being composed that the user is typing a new message.
* Notifies the destination of the chat message being composed that the user is typing a new message.
* @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which a new message is being typed.
*/
LINPHONE_PUBLIC void linphone_chat_room_compose(LinphoneChatRoom *cr);
......
......@@ -2425,12 +2425,11 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getFriendByAddress(JNIE
env->ReleaseStringUTFChars(jaddress, address);
return (jlong) lf;
}
//LinphoneChatRoom
extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNIEnv* env
extern "C" jlongArray _LinphoneChatRoomImpl_getHistory(JNIEnv* env
,jobject thiz
,jlong ptr
,jint limit) {
MSList* history = linphone_chat_room_get_history((LinphoneChatRoom*)ptr, limit);
,MSList* history) {
int historySize = ms_list_size(history);
jlongArray jHistory = env->NewLongArray(historySize);
jlong *jInternalArray = env->GetLongArrayElements(jHistory, NULL);
......@@ -2446,6 +2445,21 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNI
return jHistory;
}
extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistoryRange(JNIEnv* env
,jobject thiz
,jlong ptr
,jint start
,jint end) {
MSList* history = linphone_chat_room_get_history_range((LinphoneChatRoom*)ptr, start, end);
return _LinphoneChatRoomImpl_getHistory(env, thiz, ptr, history);
}
extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNIEnv* env
,jobject thiz
,jlong ptr
,jint limit) {
MSList* history = linphone_chat_room_get_history((LinphoneChatRoom*)ptr, limit);
return _LinphoneChatRoomImpl_getHistory(env, thiz, ptr, history);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_getPeerAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
......@@ -2484,6 +2498,11 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatM
return (jlong) chatMessage;
}
extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getHistorySize (JNIEnv* env
,jobject thiz
,jlong ptr) {
return (jint) linphone_chat_room_get_history_size((LinphoneChatRoom*)ptr);
}
extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getUnreadMessagesCount(JNIEnv* env
,jobject thiz
,jlong ptr) {
......
......@@ -217,14 +217,14 @@ void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *ms
sqlite3_free(buf);
}
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t unread_only){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
int numrows=0;
if (lc->db==NULL) return 0;
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
char *buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q AND read = 0;",peer);
char *buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?"AND read = 0":"");
sqlite3_stmt *selectStatement;
int returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL);
if (returnValue == SQLITE_OK){
......@@ -238,6 +238,14 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
return numrows;
}
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
return linphone_chat_room_get_messages_count(cr, TRUE);
}
int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){
return linphone_chat_room_get_messages_count(cr, FALSE);
}
void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
LinphoneCore *lc=cr->lc;
......@@ -260,31 +268,50 @@ void linphone_chat_room_delete_history(LinphoneChatRoom *cr){
ms_free(peer);
}
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
MSList *ret;
char *buf;
char *peer;
uint64_t begin,end;
int buf_max_size = 512;
if (lc->db==NULL) return NULL;
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
cr->messages_hist = NULL;
if (nb_message > 0)
buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC LIMIT %i ;",peer,nb_message);
else
buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC;",peer);
/*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/
buf=ms_malloc(buf_max_size);
buf=sqlite3_snprintf(buf_max_size-1,buf,"SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC",peer);
if (endm>0&&endm>=startm){
buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT %i ",buf,endm+1-startm);
}else if(startm>0){
ms_message("%s(): end is lower than start (%d < %d). No end assumed.",__FUNCTION__,endm,startm);
buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT -1",buf);
}
if (startm>0){
buf=sqlite3_snprintf(buf_max_size-1,buf,"%s OFFSET %i ",buf,startm);
}
begin=ortp_get_cur_time_ms();
linphone_sql_request_message(lc->db,buf,cr);
end=ortp_get_cur_time_ms();
ms_message("linphone_chat_room_get_history(): completed in %i ms",(int)(end-begin));
sqlite3_free(buf);
ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin));
ms_free(buf);
ret=cr->messages_hist;
cr->messages_hist=NULL;
ms_free(peer);
return ret;
}
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
return linphone_chat_room_get_history_range(cr, 0, nb_message);
}
void linphone_close_storage(sqlite3* db){
sqlite3_close(db);
}
......@@ -484,6 +511,10 @@ MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
return NULL;
}
LINPHONE_PUBLIC MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end){
return NULL;
}
void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
}
......@@ -506,4 +537,8 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
return 0;
}
int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){
return 0;
}
#endif
......@@ -21,8 +21,8 @@ package org.linphone.core;
import org.linphone.core.LinphoneChatMessage.State;
/**
*
* A chat room is the place where text messages are exchanged.
*
* A chat room is the place where text messages are exchanged.
Can be created by linphone_core_create_chat_room().
*
*/
......@@ -43,7 +43,7 @@ public interface LinphoneChatRoom {
* @param chat message
*/
void sendMessage(LinphoneChatMessage message, LinphoneChatMessage.StateListener listener);
/**
* Create a LinphoneChatMessage
* @param chatRoom chat room associated to the message
......@@ -51,31 +51,45 @@ public interface LinphoneChatRoom {
* @return LinphoneChatMessage object
*/
LinphoneChatMessage createLinphoneChatMessage(String message);
/**
* Returns the chat history associated with the peer address associated with this chat room
* @return an array of LinphoneChatMessage
*/
LinphoneChatMessage[] getHistory();
/**
* Returns the chat history associated with the peer address associated with this chat room
* @param limit the maximum number of messages to fetch
* @return an array of LinphoneChatMessage
*/
LinphoneChatMessage[] getHistory(int limit);
/**
* Returns the chat history associated with the peer address associated with this chat room for the given range
* @param begin the first (most recent) message to retrieve. Newest message has index 0. If negative, use value 0 instead.
* @param end the last (oldest) message to retrieve. Oldest message has value "history size" - 1 (equivalent to -1). If negative or lower than begin value, value is given, use -1.
* @return an array of LinphoneChatMessage, empty if nothing has been found
*/
LinphoneChatMessage[] getHistoryRange(int begin, int end);
/**
* Destroys a LinphoneChatRoom.
*/
void destroy();
/**
* Returns the amount of unread messages associated with the peer of this chatRoom.
* @return the amount of unread messages
*/
int getUnreadMessagesCount();
/**
* Returns the amount of messages associated with the peer of this chatRoom.
* @return the amount of messages in the conversation
*/
int getHistorySize();
/**
* Deletes all the messages associated with the peer of this chat room
*/
......@@ -91,24 +105,24 @@ public interface LinphoneChatRoom {
* @return true if the remote is currently composing a message, false otherwise.
*/
boolean isRemoteComposing();
/**
* Marks all the messages in this conversation as read
*/
void markAsRead();
/**
* Deletes a message
* @param message the message to delete
*/
void deleteMessage(LinphoneChatMessage message);
/**
* Update the value stored in the database for the external_body_url field
* @param message to update
*/
void updateUrl(LinphoneChatMessage message);
/**
* Create a LinphoneChatMessage
* @return LinphoneChatMessage object
......
......@@ -27,9 +27,11 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
private native long getPeerAddress(long ptr);
private native void sendMessage(long ptr, String message);
private native void sendMessage2(long ptr, Object msg, long messagePtr, StateListener listener);
private native long[] getHistoryRange(long ptr, int begin, int end);
private native long[] getHistory(long ptr, int limit);
private native void destroy(long ptr);
private native int getUnreadMessagesCount(long ptr);
private native int getHistorySize(long ptr);
private native void deleteHistory(long ptr);
private native void compose(long ptr);
private native boolean isRemoteComposing(long ptr);
......@@ -53,7 +55,7 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
sendMessage(nativePtr,message);
}
}
@Override
public void sendMessage(LinphoneChatMessage message, StateListener listener) {
synchronized(getCore()){
......@@ -67,37 +69,43 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
return new LinphoneChatMessageImpl(createLinphoneChatMessage(nativePtr, message));
}
}
public LinphoneChatMessage[] getHistory() {
synchronized(getCore()){
return getHistory(0);
}
}
public LinphoneChatMessage[] getHistoryRange(int begin, int end) {
synchronized(getCore()){
long[] typesPtr = getHistoryRange(nativePtr, begin, end);
return getHistoryPrivate(typesPtr);
}
}
public LinphoneChatMessage[] getHistory(int limit) {
synchronized(getCore()){
long[] typesPtr = getHistory(nativePtr, limit);
if (typesPtr == null) return null;
LinphoneChatMessage[] messages = new LinphoneChatMessage[typesPtr.length];
for (int i=0; i < messages.length; i++) {
messages[i] = new LinphoneChatMessageImpl(typesPtr[i]);
}
return messages;
return getHistoryPrivate(typesPtr);
}
}
public void destroy() {
destroy(nativePtr);
}
public int getUnreadMessagesCount() {
synchronized(getCore()){
return getUnreadMessagesCount(nativePtr);
}
}
public int getHistorySize() {
synchronized(getCore()){
return getHistorySize(nativePtr);
}
}
public void deleteHistory() {
synchronized(getCore()){
deleteHistory(nativePtr);
......@@ -115,27 +123,27 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
return isRemoteComposing(nativePtr);
}
}
public void markAsRead() {
synchronized(getCore()){
markAsRead(nativePtr);
}
}
public void deleteMessage(LinphoneChatMessage message) {
synchronized(getCore()){
if (message != null)
deleteMessage(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr());
}
}
public void updateUrl(LinphoneChatMessage message) {
synchronized(getCore()){
if (message != null)
updateUrl(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr());
}
}
@Override
public LinphoneChatMessage createLinphoneChatMessage(String message,
String url, State state, long timestamp, boolean isRead,
......@@ -150,4 +158,14 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
public synchronized LinphoneCore getCore() {
return (LinphoneCore)getCore(nativePtr);
}
private LinphoneChatMessage[] getHistoryPrivate(long[] typesPtr) {
if (typesPtr == null) return null;
LinphoneChatMessage[] messages = new LinphoneChatMessage[typesPtr.length];
for (int i=0; i < messages.length; i++) {
messages[i] = new LinphoneChatMessageImpl(typesPtr[i]);
}
return messages;
}
}
......@@ -754,12 +754,11 @@ static void is_composing_notification(void) {
/*
* Copy file "from" to file "to".
* Destination file is truncated if existing.
* Return 1 on success, 0 on error (printing an error).
* Return 0 on success, positive value on error.
*/
static int
message_tester_copy_file(const char *from, const char *to)
{
char message[256];
FILE *in, *out;
char buf[256];
size_t n;
......@@ -768,21 +767,17 @@ message_tester_copy_file(const char *from, const char *to)
in=fopen(from, "r");
if ( in == NULL )
{
snprintf(message, 255, "Can't open %s for reading: %s\n",
from, strerror(errno));
fprintf(stderr, "%s", message);
return 0;
ms_error("Can't open %s for reading: %s\n",from,strerror(errno));
return 1;
}
/* Open "to" file for writing (will truncate existing files) */
out=fopen(to, "w");
if ( out == NULL )
{
snprintf(message, 255, "Can't open %s for writing: %s\n",
to, strerror(errno));
fprintf(stderr, "%s", message);
ms_error("Can't open %s for writing: %s\n",to,strerror(errno));
fclose(in);
return 0;
return 2;
}
/* Copy data from "in" to "out" */
......@@ -790,16 +785,17 @@ message_tester_copy_file(const char *from, const char *to)
{
if ( ! fwrite(buf, 1, n, out) )
{
ms_error("Could not write in %s: %s\n",to,strerror(errno));
fclose(in);
fclose(out);
return 0;
return 3;
}
}
fclose(in);
fclose(out);
return 1;
return 0;
}
static int check_no_strange_time(void* data,int argc, char** argv,char** cNames) {
......@@ -814,7 +810,7 @@ static void message_storage_migration() {
snprintf(src_db,sizeof(src_db), "%s/messages.db", liblinphone_tester_file_prefix);
snprintf(tmp_db,sizeof(tmp_db), "%s/tmp.db", liblinphone_tester_writable_dir_prefix);
CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 1);
CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 0);
// enable to test the performances of the migration step
//linphone_core_message_storage_set_debug(marie->lc, TRUE);
......@@ -830,6 +826,45 @@ static void message_storage_migration() {
CU_ASSERT(sqlite3_exec(marie->lc->db, "SELECT * FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK );
}
static void history_messages_count() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneAddress *jehan_addr = linphone_address_new("<sip:Jehan@sip.linphone.org>");
LinphoneChatRoom *chatroom;
MSList *messages;
char src_db[256];
char tmp_db[256];
snprintf(src_db,sizeof(src_db), "%s/messages.db", liblinphone_tester_file_prefix);
snprintf(tmp_db,sizeof(tmp_db), "%s/tmp.db", liblinphone_tester_writable_dir_prefix);
CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 0);
linphone_core_set_chat_database_path(marie->lc, tmp_db);
chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr);
CU_ASSERT_PTR_NOT_NULL(chatroom);
if (chatroom){
MSList *history=linphone_chat_room_get_history(chatroom,0);
CU_ASSERT_EQUAL(linphone_chat_room_get_history_size(chatroom), 1270);
CU_ASSERT_EQUAL(ms_list_size(history), linphone_chat_room_get_history_size(chatroom));
/*check the second most recent message*/
CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)history->next->data), "Fore and aft follow each other.");
/*test offset+limit: retrieve the 42th latest message only and check its content*/
messages=linphone_chat_room_get_history_range(chatroom, 42, 42);
CU_ASSERT_EQUAL(ms_list_size(messages), 1);
CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)messages->data), "If you open yourself to the Tao is intangible and evasive, yet prefers to keep us at the mercy of the kingdom, then all of the streams of hundreds of valleys because of its limitless possibilities.");
/*test offset without limit*/
CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 1265, -1)), 1270-1265);
/*test limit without offset*/
CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 0, 5)), 6);
}
linphone_core_manager_destroy(marie);
linphone_address_destroy(jehan_addr);
}
#endif
test_t message_tests[] = {
......@@ -852,6 +887,7 @@ test_t message_tests[] = {
{ "IsComposing notification", is_composing_notification }
#ifdef MSG_STORAGE_ENABLED
,{ "Database migration", message_storage_migration }
,{ "History count", history_messages_count }
#endif
};
......
No preview for this file type
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment