Files
MuditaOS/module-db/Interface/CalllogRecord.cpp
T
Marcin Smoczyński c47923d70a [EGD-3107] Call number validation
Use specialized class to to pass phone number between apps and services
instead of ambigious std::string. Introduced class (utils::PhoneNumber)
wraps calls to libphonenumber providing more convienient interface.
However using libphonenumber directly may be resource hungry in terms
of stack, heap and cpu usage, so helper class has been introduced to
pass information about phone numbers (utils::PhoneNumber::View). It is
designed to maintain integrity thus can be created from an instance of
utils::PhoneNumber only or moved/copied to.

Add new field to the calllog db holding e164 formatted number. Both
entered and e164 numbers will be needed to be able to match with
contacts correctly.

Add constexpr information about country codes (utils::country).
2020-05-05 00:51:53 +02:00

198 lines
6.9 KiB
C++

/*
* @file CalllogRecord.cpp
* @author Aleksander Rudnik (aleksander.rudnik@mudita.com)
* @date 23.09.2019
* @brief Call Log DB Record
* @copyright Copyright (C) 2019 mudita.com
* @details
*/
#include "CalllogRecord.hpp"
#include <ContactRecord.hpp>
#include <log/log.hpp>
#include <Tables/CalllogTable.hpp>
#include <PhoneNumber.hpp>
#include <Utils.hpp>
#include <cassert>
#include <exception>
#include <sstream>
#include <vector>
#include <utility>
CalllogRecord::CalllogRecord(const CalllogTableRow &tableRow)
: Record{tableRow.ID}, presentation(tableRow.presentation), date(tableRow.date), duration(tableRow.duration),
type(tableRow.type), name(tableRow.name), contactId(tableRow.contactId),
phoneNumber(utils::PhoneNumber::validateNumber(tableRow.e164number, tableRow.number))
{}
uint32_t CalllogRecord::getContactId() const
{
try {
return static_cast<uint32_t>(std::stoi(contactId));
}
catch (const std::exception &e) {
LOG_ERROR("Invalid contactId %s", contactId.c_str());
return DB_ID_NONE;
}
}
std::ostream &operator<<(std::ostream &out, const CalllogRecord &rec)
{
out << " <id> " << rec.ID << " <number> " << rec.phoneNumber.getEntered() << " <e164number> "
<< rec.phoneNumber.getE164() << " <formatted> " << rec.phoneNumber.getFormatted() << " <presentation> "
<< static_cast<uint32_t>(rec.presentation) << " <date> " << rec.date << " <duration> " << rec.duration
<< " <type> " << static_cast<uint32_t>(rec.type) << " <name> " << rec.name << " <contactID> " << rec.contactId;
return out;
}
CalllogRecordInterface::CalllogRecordInterface(CalllogDB *calllogDb, ContactsDB *contactsDb)
: calllogDB(calllogDb), contactsDB(contactsDb)
{}
CalllogRecordInterface::~CalllogRecordInterface()
{}
bool CalllogRecordInterface::Add(const CalllogRecord &rec)
{
ContactRecordInterface contactInterface(contactsDB);
auto contactRec =
contactInterface.GetByNumber(rec.phoneNumber.getE164(), ContactRecordInterface::CreateTempContact::True);
if (contactRec->size() == 0) {
LOG_ERROR("Cannot get contact, for number %s", rec.phoneNumber.getE164().c_str());
return false;
}
auto localRec = rec;
auto contact = (*contactRec)[0];
localRec.contactId = std::to_string(contact.ID);
localRec.name = contact.getFormattedName();
LOG_DEBUG("Adding calllog record %s", utils::to_string(localRec).c_str());
return calllogDB->calls.Add(CalllogTableRow{.ID = localRec.ID, // this is only to remove warning
.number = localRec.phoneNumber.getEntered(),
.e164number = localRec.phoneNumber.getE164(),
.presentation = localRec.presentation,
.date = localRec.date,
.duration = localRec.duration,
.type = localRec.type,
.name = localRec.name,
.contactId = localRec.contactId});
;
}
uint32_t CalllogRecordInterface::GetLastID()
{
return calllogDB->GetLastInsertRowID();
}
std::unique_ptr<std::vector<CalllogRecord>> CalllogRecordInterface::GetLimitOffsetByField(uint32_t offset,
uint32_t limit,
CalllogRecordField field,
const char *str)
{
// TODO: alek: need proper implementation
return GetLimitOffset(offset, limit);
}
ContactRecord CalllogRecordInterface::GetContactRecordByID(const UTF8 &contactId)
{
assert(contactsDB != nullptr);
ContactRecordInterface contactInterface(contactsDB);
try {
return contactInterface.GetByID(std::atoi(contactId.c_str()));
}
catch (const std::exception &e) {
LOG_ERROR("Exception %s occured", e.what());
return ContactRecord();
}
}
std::unique_ptr<std::vector<CalllogRecord>> CalllogRecordInterface::GetLimitOffset(uint32_t offset, uint32_t limit)
{
auto calls = calllogDB->calls.GetLimitOffset(offset, limit);
auto records = std::make_unique<std::vector<CalllogRecord>>();
for (auto &c : calls) {
auto contactRec = GetContactRecordByID(c.contactId);
if (contactRec.ID == DB_ID_NONE) {
LOG_ERROR("Cannot find contact for ID %s", c.contactId.c_str());
continue;
}
c.name = contactRec.getFormattedName();
records->push_back(c);
}
return records;
}
bool CalllogRecordInterface::Update(const CalllogRecord &rec)
{
auto call = calllogDB->calls.GetByID(rec.ID);
if (call.ID == 0) {
return false;
}
return calllogDB->calls.Update(CalllogTableRow{.ID = rec.ID,
.number = rec.phoneNumber.getEntered(),
.e164number = rec.phoneNumber.getE164(),
.presentation = rec.presentation,
.date = rec.date,
.duration = rec.duration,
.type = rec.type,
.name = rec.name,
.contactId = rec.contactId});
}
bool CalllogRecordInterface::RemoveByID(uint32_t id)
{
auto call = calllogDB->calls.GetByID(id);
if (call.ID == 0) {
return false;
}
return calllogDB->calls.RemoveByID(id);
}
bool CalllogRecordInterface::RemoveByField(CalllogRecordField field, const char *str)
{
switch (field) {
case CalllogRecordField::DATE:
return calllogDB->calls.RemoveByField(CalllogTableFields::DATE, str);
case CalllogRecordField::TYPE:
return calllogDB->calls.RemoveByField(CalllogTableFields::TYPE, str);
default:
return false;
}
}
CalllogRecord CalllogRecordInterface::GetByID(uint32_t id)
{
auto call = calllogDB->calls.GetByID(id);
auto contactRec = GetContactRecordByID(call.contactId);
if (contactRec.ID == DB_ID_NONE) {
auto contactRec = GetContactRecordByID(call.contactId);
LOG_ERROR("Cannot find contact for ID %s", call.contactId.c_str());
return CalllogRecord();
}
call.name = contactRec.getFormattedName();
return CalllogRecord(call);
}
uint32_t CalllogRecordInterface::GetCount(EntryState state)
{
return calllogDB->calls.GetCount(state);
}
uint32_t CalllogRecordInterface::GetCount()
{
return GetCount(EntryState::ALL);
}