#include "common/logger.h"
#include "common/converter.h"
#include "common/task-queue.h"
+#include "common/filter-utils.h"
#include "calendar/calendar_manager.h"
#include "calendar/calendar_privilege.h"
#include "calendar/calendar_item.h"
namespace extension {
namespace calendar {
+typedef std::unique_ptr<std::remove_pointer<calendar_filter_h>::type,
+ void (*)(calendar_filter_h)> CalendarFilterPtr;
+
+void CalendarFilterDeleter(calendar_filter_h calendar_filter) {
+ if (CALENDAR_ERROR_NONE != calendar_filter_destroy(calendar_filter)) {
+ LoggerE("failed to destroy contacts_filter_h");
+ }
+}
+
using namespace common;
int Calendar::current_db_version_ = 0;
void Calendar::Get(const picojson::object& args, picojson::object& out) {
LoggerD("enter");
-// NativePlugin::CheckAccess(Privilege::kCalendarRead);
-
if (!CalendarManager::GetInstance().IsConnected()) {
throw UnknownException("DB Connection failed.");
}
CalendarRecord::GetById(id, CalendarRecord::TypeToUri(type));
picojson::value record_obj = picojson::value(picojson::object());
CalendarItem::ToJson(type, record_ptr.get(), &out);
-
}
void Calendar::Add(const picojson::object& args, picojson::object& out) {
LoggerD("enter");
-
if (!CalendarManager::GetInstance().IsConnected()) {
throw UnknownException("DB Connection failed.");
}
CalendarRecordPtr item_ptr = CalendarItem::Create(type);
CalendarItem::FromJson(type, item_ptr.get(), item);
int record_id = CalendarRecord::Insert(item_ptr.get());
-
out.insert(std::make_pair("uid", std::to_string(record_id)));
if (type == CALENDAR_BOOK_TYPE_EVENT) {
out["rid"] = picojson::value();
}
}
-
}
-void Calendar::AddBatch(const picojson::object& args,
- picojson::array& array) {
+void Calendar::AddBatch(const picojson::object& args, picojson::array& array) {
LoggerD("enter");
if (!CalendarManager::GetInstance().IsConnected()) {
LoggerE("Could not create list for batch operation");
throw UnknownException("Could not create list for batch operation");
}
- CalendarListPtr list_ptr =
- CalendarListPtr(list, CalendarRecord::ListDeleter);
+ CalendarListPtr list_ptr = CalendarListPtr(list, CalendarRecord::ListDeleter);
int ret;
calendar_record_h record;
throw UnknownException("Can't create platform record");
}
CalendarItem::FromJson(type, record, item.get<picojson::object>());
-
if (CALENDAR_ERROR_NONE != calendar_list_add(list_ptr.get(), record)) {
LoggerE("Could not add record to list events");
throw InvalidValuesException("Could not add record to list");
free(ids);
}
-void Calendar::Update(const picojson::object& args,
- picojson::object& /*out*/) {
+void Calendar::Update(const picojson::object& args, picojson::object& /*out*/) {
LoggerD("enter");
if (!CalendarManager::GetInstance().IsConnected()) {
}
} else {
// first update the parent event
- std::string exdate = CalendarItem::ExceptionsFromJson(
- common::FromJson<picojson::array>(item, "recurrenceRule", "exceptions"));
- if (!common::IsNull(common::FromJson<picojson::object>(item, "id"), "rid")) {
+ std::string exdate =
+ CalendarItem::ExceptionsFromJson(common::FromJson<picojson::array>(
+ item, "recurrenceRule", "exceptions"));
+ if (!common::IsNull(common::FromJson<picojson::object>(item, "id"),
+ "rid")) {
exdate.append(common::FromJson<std::string>(item, "id", "rid"));
}
CalendarRecord::SetString(record_ptr.get(), _calendar_event.exdate, exdate);
LoggerE("Could not create list for batch operation");
throw UnknownException("Could not create list for batch operation");
}
- CalendarListPtr list_ptr =
- CalendarListPtr(list, CalendarRecord::ListDeleter);
+ CalendarListPtr list_ptr = CalendarListPtr(list, CalendarRecord::ListDeleter);
int ret, id;
calendar_record_h record;
}
}
-void Calendar::Remove(const picojson::object& args,
- picojson::object& out) {
+void Calendar::Remove(const picojson::object& args, picojson::object& out) {
LoggerD("enter");
if (!CalendarManager::GetInstance().IsConnected()) {
if (!CalendarManager::GetInstance().IsConnected()) {
throw UnknownException("DB Connection failed.");
}
-
- // TODO implement calendar filter and sorting in native code.
int calendar_id = common::stol(FromJson<std::string>(args, "calendarId"));
int error_code = 0;
CalendarRecordPtr calendar_ptr =
CalendarRecord::GetInt(calendar_ptr.get(), _calendar_book.store_type);
calendar_query_h calendar_query = nullptr;
if (type == CALENDAR_BOOK_TYPE_EVENT) {
- error_code =
- calendar_query_create(_calendar_event._uri, &calendar_query);
+ error_code = calendar_query_create(_calendar_event._uri, &calendar_query);
+ ErrorChecker(error_code);
} else {
- error_code =
- calendar_query_create(_calendar_todo._uri, &calendar_query);
+ error_code = calendar_query_create(_calendar_todo._uri, &calendar_query);
+ ErrorChecker(error_code);
}
if (CALENDAR_ERROR_NONE != error_code) {
throw UnknownException("calendar_query_create failed");
}
+ std::vector<std::vector<CalendarFilterPtr>> intermediate_filters(1);
+ if (!IsNull(args, "filter")) {
+ FilterVisitor visitor;
+ visitor.SetOnAttributeFilter([&](const std::string& name,
+ AttributeMatchFlag match_flag,
+ const picojson::value& match_value) {
+ int value = 0;
+ calendar_filter_h calendar_filter = nullptr;
+ if (type == CALENDAR_BOOK_TYPE_EVENT) {
+ error_code =
+ calendar_filter_create(_calendar_event._uri, &calendar_filter);
+ ErrorChecker(error_code);
+ } else {
+ error_code =
+ calendar_filter_create(_calendar_todo._uri, &calendar_filter);
+ ErrorChecker(error_code);
+ }
+ CalendarFilterPtr calendar_filter_ptr(calendar_filter,
+ CalendarFilterDeleter);
+ unsigned int propertyId = 0;
+ if (name == "startDate" || name == "endDate" || name == "dueDate")
+ propertyId = CalendarItem::GetPlatformProperty(type, name + "_time");
+ else
+ propertyId = CalendarItem::GetPlatformProperty(type, name);
+ if (name == "id" || name == "id.uid") {
+ if (type == CALENDAR_BOOK_TYPE_EVENT && name == "id") {
+ value = common::stol(
+ FromJson<std::string>(JsonCast<JsonObject>(match_value), "uid"));
+ } else {
+ value = common::stol(JsonCast<std::string>(match_value));
+ }
+ if (value < 0) {
+ throw InvalidValuesException("Match value cannot be less than 0");
+ }
+ calendar_match_int_flag_e flag;
+ if (AttributeMatchFlag::kExists == match_flag) {
+ flag = CALENDAR_MATCH_GREATER_THAN_OR_EQUAL;
+ value = 0;
+ } else if (AttributeMatchFlag::kStartsWith == match_flag ||
+ AttributeMatchFlag::kContains == match_flag) {
+ flag = CALENDAR_MATCH_GREATER_THAN_OR_EQUAL;
+ } else if (AttributeMatchFlag::kEndsWith == match_flag) {
+ flag = CALENDAR_MATCH_LESS_THAN_OR_EQUAL;
+ } else {
+ flag = CALENDAR_MATCH_EQUAL;
+ }
+ error_code =
+ calendar_filter_add_int(calendar_filter, propertyId, flag, value);
+ ErrorChecker(error_code);
+ } else if (name == "startDate" || name == "endDate" ||
+ name == "dueDate") {
+ calendar_match_int_flag_e flag;
+ Date dateTofilter =
+ CalendarItem::DateFromJson(JsonCast<picojson::object>(match_value));
+ if (AttributeMatchFlag::kExists == match_flag) {
+ flag = CALENDAR_MATCH_GREATER_THAN_OR_EQUAL;
+ value = 0;
+ } else if (AttributeMatchFlag::kStartsWith == match_flag ||
+ AttributeMatchFlag::kContains == match_flag) {
+ flag = CALENDAR_MATCH_GREATER_THAN_OR_EQUAL;
+ } else if (AttributeMatchFlag::kEndsWith == match_flag) {
+ flag = CALENDAR_MATCH_LESS_THAN_OR_EQUAL;
+ } else {
+ flag = CALENDAR_MATCH_EQUAL;
+ }
+
+ error_code = calendar_filter_add_caltime(
+ calendar_filter, propertyId, flag,
+ CalendarItem::DateToPlatform(dateTofilter, false));
+ ErrorChecker(error_code);
+ } else {
+ std::string value = JsonCast<std::string>(match_value);
+ calendar_match_str_flag_e flag = CALENDAR_MATCH_EXISTS;
+ if (AttributeMatchFlag::kExactly == match_flag) {
+ flag = CALENDAR_MATCH_EXACTLY;
+ } else if (AttributeMatchFlag::kFullString == match_flag) {
+ flag = CALENDAR_MATCH_FULLSTRING;
+ } else if (AttributeMatchFlag::kContains == match_flag) {
+ flag = CALENDAR_MATCH_CONTAINS;
+ } else if (AttributeMatchFlag::kStartsWith == match_flag) {
+ flag = CALENDAR_MATCH_STARTSWITH;
+ } else if (AttributeMatchFlag::kEndsWith == match_flag) {
+ flag = CALENDAR_MATCH_ENDSWITH;
+ } else if (AttributeMatchFlag::kExists == match_flag) {
+ flag = CALENDAR_MATCH_EXISTS;
+ value = "";
+ }
+ calendar_filter_add_str(calendar_filter, propertyId, flag,
+ value.c_str());
+ }
+ intermediate_filters[intermediate_filters.size() - 1].push_back(
+ std::move(calendar_filter_ptr));
+ });
+ visitor.SetOnCompositeFilterBegin([&](CompositeFilterType type) {
+ intermediate_filters.push_back(std::vector<CalendarFilterPtr>());
+ });
+
+ visitor.SetOnCompositeFilterEnd([&](CompositeFilterType calType) {
+ if (intermediate_filters.size() == 0) {
+ throw UnknownException("Reached stack size equal to 0!");
+ }
+ calendar_filter_h merged_filter = nullptr;
+
+ if (type == CALENDAR_BOOK_TYPE_EVENT) {
+ error_code =
+ calendar_filter_create(_calendar_event._uri, &merged_filter);
+ ErrorChecker(error_code);
+ } else {
+ error_code =
+ calendar_filter_create(_calendar_todo._uri, &merged_filter);
+ ErrorChecker(error_code);
+ }
+ CalendarFilterPtr merged_filter_ptr(merged_filter, CalendarFilterDeleter);
+ for (std::size_t i = 0; i < intermediate_filters.back().size(); ++i) {
+ error_code = calendar_filter_add_filter(
+ merged_filter, intermediate_filters.back().at(i).get());
+ ErrorChecker(error_code);
+ if (CompositeFilterType::kIntersection == calType) {
+ error_code = calendar_filter_add_operator(
+ merged_filter, CALENDAR_FILTER_OPERATOR_AND);
+ ErrorChecker(error_code);
+ } else if (CompositeFilterType::kUnion == calType) {
+ error_code = calendar_filter_add_operator(
+ merged_filter, CALENDAR_FILTER_OPERATOR_OR);
+ ErrorChecker(error_code);
+ } else {
+ throw InvalidValuesException("Invalid union type!");
+ }
+ }
+ intermediate_filters.pop_back();
+ intermediate_filters.back().push_back(std::move(merged_filter_ptr));
+ });
+
+ visitor.SetOnAttributeRangeFilter([&](const std::string& name,
+ const JsonValue& initial_value,
+ const JsonValue& end_value) {
+ unsigned int propertyId = 0;
+ if (name == "startDate" || name == "endDate" || name == "dueDate") {
+ propertyId = CalendarItem::GetPlatformProperty(type, name + "_time");
+
+ } else {
+ propertyId = CalendarItem::GetPlatformProperty(type, name);
+ }
+ calendar_filter_h calendar_filter = nullptr;
+ int error_code = 0;
+ if (type == CALENDAR_BOOK_TYPE_EVENT) {
+ error_code =
+ calendar_filter_create(_calendar_event._uri, &calendar_filter);
+ ErrorChecker(error_code);
+ } else {
+ error_code =
+ calendar_filter_create(_calendar_todo._uri, &calendar_filter);
+ ErrorChecker(error_code);
+ }
+ CalendarFilterPtr calendar_filter_ptr(calendar_filter,
+ CalendarFilterDeleter);
+
+ bool initial_value_exists = (!IsNull(initial_value));
+ bool end_value_exists = (!IsNull(end_value));
+ if (name == "id") {
+ int initial_value_date = 0;
+ int end_value_date = 0;
+
+ if (initial_value_exists)
+ initial_value_date =
+ common::stol(JsonCast<std::string>(initial_value));
+ if (end_value_exists)
+ end_value_date = common::stol(JsonCast<std::string>(end_value));
+
+ if (initial_value_exists && end_value_exists) {
+ calendar_filter_h sub_filter = NULL;
+
+ if (type == CALENDAR_BOOK_TYPE_EVENT) {
+ error_code =
+ calendar_filter_create(_calendar_event._uri, &sub_filter);
+ ErrorChecker(error_code);
+ } else {
+ error_code =
+ calendar_filter_create(_calendar_todo._uri, &sub_filter);
+ ErrorChecker(error_code);
+ }
+ CalendarFilterPtr sub_filter_ptr(sub_filter, CalendarFilterDeleter);
+
+ error_code = calendar_filter_add_int(
+ sub_filter, propertyId, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+ initial_value_date);
+
+ error_code = calendar_filter_add_operator(
+ sub_filter, CALENDAR_FILTER_OPERATOR_AND);
+
+ error_code = calendar_filter_add_int(
+ sub_filter, propertyId, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+ end_value_date);
+
+ error_code = calendar_filter_add_filter(calendar_filter, sub_filter);
+ ErrorChecker(error_code);
+ } else if (initial_value_exists) {
+ error_code = calendar_filter_add_int(
+ calendar_filter, propertyId, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+ initial_value_date);
+ ErrorChecker(error_code);
+ } else if (end_value_exists) {
+ error_code = calendar_filter_add_int(
+ calendar_filter, propertyId, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+ end_value_date);
+ ErrorChecker(error_code);
+ }
+ } else if (name == "startDate" || name == "dueDate" ||
+ name == "endDate") {
+ Date initial_value_date;
+ Date end_value_date;
+
+ if (initial_value_exists)
+ initial_value_date = CalendarItem::DateFromJson(
+ JsonCast<picojson::object>(initial_value));
+ if (end_value_exists)
+ end_value_date =
+ CalendarItem::DateFromJson(JsonCast<picojson::object>(end_value));
+
+ if (initial_value_exists && end_value_exists) {
+ calendar_filter_h sub_filter = NULL;
+
+ if (type == CALENDAR_BOOK_TYPE_EVENT) {
+ error_code =
+ calendar_filter_create(_calendar_event._uri, &sub_filter);
+ ErrorChecker(error_code);
+ } else {
+ error_code =
+ calendar_filter_create(_calendar_todo._uri, &sub_filter);
+ ErrorChecker(error_code);
+ }
+ CalendarFilterPtr sub_filter_ptr(sub_filter, CalendarFilterDeleter);
+
+ error_code = calendar_filter_add_caltime(
+ sub_filter, propertyId, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+ CalendarItem::DateToPlatform(initial_value_date, false));
+ ErrorChecker(error_code);
+
+ error_code = calendar_filter_add_operator(
+ sub_filter, CALENDAR_FILTER_OPERATOR_AND);
+ ErrorChecker(error_code);
+
+ error_code = calendar_filter_add_caltime(
+ sub_filter, propertyId, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+ CalendarItem::DateToPlatform(end_value_date, false));
+ ErrorChecker(error_code);
+
+ error_code = calendar_filter_add_filter(calendar_filter, sub_filter);
+ ErrorChecker(error_code);
+ } else if (initial_value_exists) {
+ error_code = calendar_filter_add_caltime(
+ calendar_filter, propertyId, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+ CalendarItem::DateToPlatform(initial_value_date, false));
+ ErrorChecker(error_code);
+ } else if (end_value_exists) {
+ error_code = calendar_filter_add_caltime(
+ calendar_filter, propertyId, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+ CalendarItem::DateToPlatform(end_value_date, false));
+ ErrorChecker(error_code);
+ }
+ } else {
+ std::string initial_value_str;
+ std::string end_value_str;
+
+ if (initial_value_exists) {
+ initial_value_str = JsonCast<std::string>(initial_value);
+ }
+
+ if (end_value_exists) {
+ end_value_str = JsonCast<std::string>(end_value);
+ }
+
+ if (initial_value_exists && end_value_exists) {
+ calendar_filter_h sub_filter = NULL;
+
+ if (type == CALENDAR_BOOK_TYPE_EVENT) {
+ error_code =
+ calendar_filter_create(_calendar_event._uri, &sub_filter);
+ ErrorChecker(error_code);
+ } else {
+ error_code =
+ calendar_filter_create(_calendar_todo._uri, &sub_filter);
+ ErrorChecker(error_code);
+ }
+ CalendarFilterPtr sub_filter_ptr(sub_filter, CalendarFilterDeleter);
+
+ error_code = calendar_filter_add_str(sub_filter, propertyId,
+ CALENDAR_MATCH_STARTSWITH,
+ initial_value_str.c_str());
+ ErrorChecker(error_code);
+ error_code = calendar_filter_add_operator(
+ sub_filter, CALENDAR_FILTER_OPERATOR_AND);
+ ErrorChecker(error_code);
+ error_code = calendar_filter_add_str(sub_filter, propertyId,
+ CALENDAR_MATCH_ENDSWITH,
+ end_value_str.c_str());
+ ErrorChecker(error_code);
+ error_code = calendar_filter_add_filter(calendar_filter, sub_filter);
+ ErrorChecker(error_code);
+ } else if (initial_value_exists) {
+ error_code = calendar_filter_add_str(calendar_filter, propertyId,
+ CALENDAR_MATCH_STARTSWITH,
+ initial_value_str.c_str());
+ ErrorChecker(error_code);
+ } else if (end_value_exists) {
+ error_code = calendar_filter_add_str(calendar_filter, propertyId,
+ CALENDAR_MATCH_ENDSWITH,
+ end_value_str.c_str());
+ ErrorChecker(error_code);
+ }
+ }
+ intermediate_filters[intermediate_filters.size() - 1].push_back(
+ std::move(calendar_filter_ptr));
+ });
+ visitor.Visit(FromJson<JsonObject>(args, "filter"));
+ if ((intermediate_filters.size() != 1) ||
+ (intermediate_filters[0].size() != 1)) {
+ LoggerE("Bad filter evaluation!");
+ throw UnknownException("Bad filter evaluation!");
+ }
+ error_code = calendar_query_set_filter(calendar_query,
+ intermediate_filters[0][0].get());
+ ErrorChecker(error_code);
+ }
+
+ if (!IsNull(args, "sortMode")) {
+ picojson::object sortModeObject =
+ FromJson<picojson::object>(args, "sortMode");
+ unsigned int propertyId = 0;
+ std::string attributeName =
+ FromJson<std::string>(sortModeObject, "attributeName");
+ std::string order = FromJson<std::string>(sortModeObject, "order");
+ if (attributeName == "startDate" || attributeName == "dueDate" ||
+ attributeName == "endDate")
+ propertyId =
+ CalendarItem::GetPlatformProperty(type, attributeName + "_time");
+ else
+ propertyId = CalendarItem::GetPlatformProperty(type, attributeName);
+ if (order.empty() || order == "ASC") {
+ error_code = calendar_query_set_sort(calendar_query, propertyId, true);
+ ErrorChecker(error_code);
+ } else if (order == "DESC") {
+ error_code = calendar_query_set_sort(calendar_query, propertyId, false);
+ ErrorChecker(error_code);
+ }
+ }
CalendarQueryPtr calendar_query_ptr(calendar_query,
CalendarRecord::QueryDeleter);
calendar_list_h record_list = nullptr;
- error_code = calendar_db_get_records_with_query(calendar_query, 0, 0,
- &record_list);
+ error_code =
+ calendar_db_get_records_with_query(calendar_query, 0, 0, &record_list);
if (CALENDAR_ERROR_NONE != error_code) {
throw UnknownException("calendar_db_get_records_with_query failed");
}
}
}
-void Calendar::AddChangeListener(const picojson::object& args, picojson::object& out) {
+void Calendar::AddChangeListener(const picojson::object& args,
+ picojson::object& out) {
LoggerD("enter");
if (!CalendarManager::GetInstance().IsConnected()) {
}
listeners_registered_.erase(type);
}
-
}
void Calendar::ChangeCallback(const char* view_uri, void*) {
picojson::value response = picojson::value(picojson::object());
picojson::object& response_obj = response.get<picojson::object>();
if (listeners_registered_.find("EVENT") != listeners_registered_.end())
- response_obj.insert(std::make_pair("listenerId", listeners_registered_["EVENT"]));
+ response_obj.insert(
+ std::make_pair("listenerId", listeners_registered_["EVENT"]));
else
- response_obj.insert(std::make_pair("listenerId", listeners_registered_["TASK"]));
+ response_obj.insert(
+ std::make_pair("listenerId", listeners_registered_["TASK"]));
picojson::array& added =
response_obj.insert(std::make_pair("added", picojson::array()))
picojson::value removed_row = picojson::value(picojson::object());
picojson::object& removed_obj = removed_row.get<picojson::object>();
- removed_obj.insert(std::make_pair("id", picojson::value(std::to_string(id))));
+ removed_obj.insert(
+ std::make_pair("id", picojson::value(std::to_string(id))));
removed_obj.insert(std::make_pair(
"calendarId", picojson::value(std::to_string(calendar_id))));
} else {
updated.push_back(record_obj);
}
- }
- catch(PlatformException& ex) {
- LoggerE("error occured");
+ } catch (PlatformException& ex) {
+ LoggerE("error occured");
}
calendar_list_next(list);
CalendarInstance::GetInstance().PostMessage(response.serialize().c_str());
}
+void Calendar::ErrorChecker(int errorCode) {
+ if (errorCode != CALENDAR_ERROR_NONE)
+ throw UnknownException("exception occured");
+}
+
} // namespace calendar
} // namespace webapi