Commit 9fbf6a09 authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

[#1214] Add serialized/unserialized functions to pass data on DBUS

parent a40d6c00
......@@ -20,12 +20,55 @@
#include <historyitem.h>
#include <sstream>
#include "stdlib.h"
HistoryItem::HistoryItem (int timestamp, CallType call_type, std::string to, std::string from, std::string caller_id, std::string account_id)
#define ITEM_SEPARATOR "|"
HistoryItem::HistoryItem (std::string timestamp, CallType call_type, std::string to, std::string from, std::string caller_id, std::string account_id)
: _timestamp (timestamp), _call_type (call_type), _to (to), _from (from), _caller_id (caller_id), _account_id (account_id)
{
}
HistoryItem::HistoryItem (std::string timestamp, std::string serialized_form)
: _timestamp (timestamp)
{
size_t pos;
std::string tmp, id, to, from, callerid;
int indice=0;
while (serialized_form.find(ITEM_SEPARATOR, 0) != std::string::npos)
{
pos = serialized_form.find (ITEM_SEPARATOR, 0);
tmp = serialized_form.substr (0, pos);
serialized_form.erase (0, pos + 1);
switch (indice)
{
case 0: // The call type
id = tmp;
break;
case 1: // The to field
to = tmp;
break;
case 2: // The from field
from = tmp;
break;
case 3: // The calller id information
callerid = tmp;
break;
default: // error
std::cout <<"[ERROR] unserialized form not recognized."<<std::endl;
break;
}
indice ++;
}
_call_type = (CallType)atoi (id.c_str());
_to = to;
_from = from;
_caller_id = serialized_form;
}
HistoryItem::~HistoryItem ()
{
// TODO
......@@ -33,24 +76,32 @@ HistoryItem::~HistoryItem ()
bool HistoryItem::save (Conf::ConfigTree **history){
std::stringstream section, call_type, timestamp;
std::string section, timestamp;
std::stringstream call_type;
bool res;
// The section is : "[" + timestamp = "]"
section << _timestamp ;
section = get_timestamp ();
timestamp = get_timestamp ();
call_type << _call_type;
timestamp << _timestamp;
res = ( (*history)->setConfigTreeItem(section.str(), "type", call_type.str())
&& (*history)->setConfigTreeItem(section.str(), "timestamp", timestamp.str())
&& (*history)->setConfigTreeItem(section.str(), "to", _to)
&& (*history)->setConfigTreeItem(section.str(), "from", _from)
&& (*history)->setConfigTreeItem(section.str(), "id", _caller_id) );
res = ( (*history)->setConfigTreeItem(section, "type", call_type.str())
&& (*history)->setConfigTreeItem(section, "timestamp", timestamp)
&& (*history)->setConfigTreeItem(section, "to", _to)
&& (*history)->setConfigTreeItem(section, "from", _from)
&& (*history)->setConfigTreeItem(section, "id", _caller_id) );
return res;
}
std::string HistoryItem::serialize (void)
{
std::stringstream res;
std::string separator = ITEM_SEPARATOR;
res << _call_type << separator << _to << separator << _from << separator << _caller_id;
return res.str();
}
......
......@@ -23,6 +23,7 @@
#include <string>
#include <config/config.h>
#include <iostream>
typedef enum CallType {
CALL_MISSED,
......@@ -37,25 +38,32 @@ class HistoryItem {
/*
* Constructor
*/
HistoryItem (int, CallType, std::string, std::string, std::string, std::string="");
HistoryItem (std::string, CallType, std::string, std::string, std::string, std::string="");
/*
* Constructor from a serialized form
*/
HistoryItem (std::string, std::string="");
/*
* Destructor
*/
~HistoryItem ();
inline int get_timestamp () {
inline std::string get_timestamp () {
return _timestamp;
}
bool save (Conf::ConfigTree **history);
std::string serialize (void);
private:
/*
* Timestamp representing the date of the call
*/
int _timestamp;
std::string _timestamp;
/*
* Represents the type of call
......
......@@ -32,13 +32,21 @@ HistoryManager::~HistoryManager () {
_history_items.clear ();
}
bool HistoryManager::init (void)
int HistoryManager::load_history (std::string path)
{
Conf::ConfigTree history_list;
create_history_path ();
create_history_path (path);
load_history_from_file (&history_list);
load_history_items_map (&history_list);
return load_history_items_map (&history_list);
}
bool HistoryManager::save_history (void)
{
Conf::ConfigTree history_list;
save_history_items_map (&history_list);
return save_history_to_file (&history_list);
}
bool HistoryManager::load_history_from_file (Conf::ConfigTree *history_list)
......@@ -58,8 +66,7 @@ int HistoryManager::load_history_items_map (Conf::ConfigTree *history_list)
Conf::TokenList sections;
HistoryItem *item;
Conf::TokenList::iterator iter;
std::string to, from, caller_id, accountID;
int timestamp;
std::string to, from, caller_id, accountID, timestamp;
CallType type;
sections = history_list->getSections();
......@@ -68,7 +75,7 @@ int HistoryManager::load_history_items_map (Conf::ConfigTree *history_list)
while(iter != sections.end()) {
type = (CallType) getConfigInt (*iter, "type", history_list);
timestamp = getConfigInt (*iter, "timestamp", history_list);
timestamp = getConfigString (*iter, "timestamp", history_list);
to = getConfigString (*iter, "to", history_list);
from = getConfigString (*iter, "from", history_list);
caller_id = getConfigString (*iter, "id", history_list);
......@@ -86,7 +93,7 @@ int HistoryManager::load_history_items_map (Conf::ConfigTree *history_list)
bool HistoryManager::save_history_to_file (Conf::ConfigTree *history_list)
{
return history_list->saveConfigTree(_history_path.data());
return history_list->saveConfigTree (_history_path.data());
}
......@@ -119,22 +126,29 @@ void HistoryManager::add_new_history_entry (HistoryItem *new_item)
_history_items [new_item->get_timestamp ()] = new_item;
}
int HistoryManager::create_history_path (void) {
int HistoryManager::create_history_path (std::string path) {
std::string path;
std::string filename;
path = std::string(HOMEDIR) + DIR_SEPARATOR_STR + "." + PROGDIR;
if (mkdir (path.data(), 0755) != 0) {
// If directory creation failed
if (errno != EEXIST) {
_debug("Cannot create directory: %s\n", strerror(errno));
return -1;
if (path == "")
{
filename = std::string(HOMEDIR) + DIR_SEPARATOR_STR + "." + PROGDIR;
if (mkdir (filename.data(), 0755) != 0) {
// If directory creation failed
if (errno != EEXIST) {
_debug("Cannot create directory: %s\n", strerror(errno));
return -1;
}
}
// Load user's history
_history_path = filename + DIR_SEPARATOR_STR + "history";
}
else
set_history_path (path);
// Load user's history
_history_path = path + DIR_SEPARATOR_STR + "history";
return 0;
}
......@@ -161,3 +175,49 @@ HistoryManager::getConfigString(const std::string& section, const std::string& n
return "";
}
std::map <std::string, std::string> HistoryManager::get_history_serialized (void)
{
std::map <std::string, std::string> serialized;
HistoryItemMap::iterator iter;
HistoryItem *current;
std::string res, key;
iter = _history_items.begin ();
while (iter != _history_items.end())
{
current = iter->second;
if (current)
{
key = current->get_timestamp ();
res = current->serialize ();
serialized [key] = res;
}
iter ++;
}
return serialized;
}
int HistoryManager::set_serialized_history (std::map <std::string, std::string> history)
{
std::map <std::string, std::string>::iterator iter;
HistoryItem *new_item;
int items_added;
// Clear the existing history
_history_items.clear ();
iter = history.begin ();
while (iter != history.end ())
{
new_item = new HistoryItem (iter->first, iter->second);
add_new_history_entry (new_item);
items_added ++;
iter ++;
}
return items_added;
}
......@@ -25,7 +25,7 @@
#include <global.h>
#include <user_cfg.h>
typedef std::map <int, HistoryItem*> HistoryItemMap;
typedef std::map <std::string, HistoryItem*> HistoryItemMap;
class HistoryManager {
......@@ -40,7 +40,17 @@ class HistoryManager {
*/
~HistoryManager ();
bool init (void);
/**
*@param path A specific file to use; if empty, use the global one
*
*@return int The number of history items succesfully loaded
*/
int load_history (std::string path="");
/**
*@return bool True if the history has been successfully saved in the file
*/
bool save_history (void);
/*
* Load the history from a file to the dedicated data structure
......@@ -80,6 +90,10 @@ class HistoryManager {
return _history_items.size ();
}
std::map <std::string, std::string> get_history_serialized (void);
int set_serialized_history (std::map <std::string, std::string> history);
private:
......@@ -88,8 +102,10 @@ class HistoryManager {
/*
* Set the path to the history file
*
* @param path A specific file to use; if empty, use the global one
*/
int create_history_path (void);
int create_history_path (std::string path="");
/*
* Add a new history item in the data structure
*/
......
......@@ -83,12 +83,14 @@ ManagerImpl::ManagerImpl (void)
, _callConfigMap()
, _accountMap()
, _cleaner (NULL)
, _history (NULL)
{
// initialize random generator for call id
srand (time(NULL));
_cleaner = new NumberCleaner ();
_history = new HistoryManager ();
#ifdef TEST
testAccountMap();
......@@ -142,6 +144,10 @@ ManagerImpl::init()
if (audiolayer == 0)
audiolayer->stopStream();
// Load the history
_history->load_history ();
}
void ManagerImpl::terminate()
......@@ -2851,3 +2857,19 @@ std::map< std::string, std::string > ManagerImpl::getCallDetails(const CallID& c
return call_details;
}
std::map<std::string, std::string> ManagerImpl::send_history_to_client (void)
{
return _history->get_history_serialized ();
}
void ManagerImpl::receive_history_from_client (std::map<std::string, std::string> history)
{
_history->set_serialized_history (history);
_history->save_history ();
}
......@@ -37,6 +37,7 @@
#include "account.h"
#include "call.h"
#include "numbercleaner.h"
#include <history/historymanager.h>
#include "audio/tonelist.h" // for Tone::TONEID declaration
#include "audio/audiofile.h"
......@@ -1090,6 +1091,9 @@ class ManagerImpl {
*/
bool accountExists(const AccountID& accountID);
std::map<std::string, std::string> send_history_to_client (void);
void receive_history_from_client (std::map<std::string, std::string> history);
public:
/**
......@@ -1136,6 +1140,11 @@ private:
NumberCleaner *_cleaner;
/**
* To handle the persistent history
*/
HistoryManager *_history;
/**
* Check if the call is a classic call or a direct IP-to-IP call
*/
......
......@@ -14,7 +14,7 @@ type=2
[775354456]
from=5143848557
id=Chez wam
id=Chez wam
timestamp=775354456
to=
type=1
......
......@@ -89,6 +89,8 @@ void HistoryTest::test_save_history_to_file ()
{
std::string path;
Conf::ConfigTree history_list, history_list2;
std::map <std::string, std::string> res;
std::map <std::string, std::string>::iterator iter;
history->set_history_path (HISTORY_SAMPLE);
history->load_history_from_file (&history_list);
......@@ -97,6 +99,64 @@ void HistoryTest::test_save_history_to_file ()
CPPUNIT_ASSERT (history->save_history_to_file (&history_list2));
}
void HistoryTest::test_get_history_serialized ()
{
std::map <std::string, std::string> res;
std::map <std::string, std::string>::iterator iter;
std::string tmp;
CPPUNIT_ASSERT (history->load_history (HISTORY_SAMPLE) == HISTORY_SAMPLE_SIZE);
res = history->get_history_serialized ();
CPPUNIT_ASSERT (res.size()==HISTORY_SAMPLE_SIZE);
// Warning - If you change the history-sample file, you must change the following lines also so that the tests could work
// The reference here is the file history-sample in this test directory
// The serialized form is: calltype%to%from%callid
// Check the first
tmp = "0||514-276-5468|Savoir-faire Linux";
CPPUNIT_ASSERT (tmp == res ["144562436"]);
tmp = "2|136||Emmanuel Milou";
CPPUNIT_ASSERT (tmp == res ["747638685"]);
tmp = "1||5143848557|Chez wam";
CPPUNIT_ASSERT (tmp == res ["775354456"]);
}
void HistoryTest::test_set_serialized_history ()
{
// We build a map to have an efficient test
std::map <std::string, std::string> map_test;
std::string tmp;
Conf::ConfigTree history_list;
map_test["144562436"] = "0||514-276-5468|Savoir-faire Linux";
map_test["747638685"] = "2|136||Emmanuel Milou";
map_test["775354456"] = "1||5143848557|Chez wam";
CPPUNIT_ASSERT (history->load_history (HISTORY_SAMPLE) == HISTORY_SAMPLE_SIZE);
CPPUNIT_ASSERT (history->set_serialized_history (map_test) == 3);
CPPUNIT_ASSERT (history->get_history_size () == 3);
map_test.clear ();
map_test = history->get_history_serialized ();
CPPUNIT_ASSERT (map_test.size()==HISTORY_SAMPLE_SIZE);
// Check the first
tmp = "0||514-276-5468|Savoir-faire Linux";
CPPUNIT_ASSERT (tmp == map_test ["144562436"]);
tmp = "2|136||Emmanuel Milou";
CPPUNIT_ASSERT (tmp == map_test ["747638685"]);
tmp = "1||5143848557|Chez wam";
CPPUNIT_ASSERT (tmp == map_test ["775354456"]);
history->save_history_items_map (&history_list);
CPPUNIT_ASSERT (history->save_history_to_file (&history_list));
}
void HistoryTest::tearDown(){
// Delete the history object
delete history; history=0;
......
......@@ -47,6 +47,8 @@ class HistoryTest : public CppUnit::TestCase {
CPPUNIT_TEST (test_load_history_items_map);
CPPUNIT_TEST (test_save_history_items_map);
CPPUNIT_TEST (test_save_history_to_file);
CPPUNIT_TEST (test_get_history_serialized);
CPPUNIT_TEST (test_set_serialized_history);
CPPUNIT_TEST_SUITE_END ();
public:
......@@ -67,7 +69,11 @@ class HistoryTest : public CppUnit::TestCase {
void test_save_history_items_map ();
void test_save_history_to_file ();
void test_get_history_serialized ();
void test_set_serialized_history ();
/*
* Code factoring - Common resources can be released here.
* This method is called by unitcpp after each test
......
Supports Markdown
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