From 16a40ff6953d77e80b46a03f1cf283db96461ff6 Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Thu, 3 Aug 2017 13:20:10 +0900 Subject: [PATCH] trigger: implement API functions using the internal job scheduler API Change-Id: Idf903ba2903c469117c0698f79919e2e8b88d5e4 Signed-off-by: Mu-Woong Lee --- src/trigger/context_trigger.cpp | 633 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 601 insertions(+), 32 deletions(-) diff --git a/src/trigger/context_trigger.cpp b/src/trigger/context_trigger.cpp index 512510a..46d5298 100644 --- a/src/trigger/context_trigger.cpp +++ b/src/trigger/context_trigger.cpp @@ -88,6 +88,7 @@ typedef struct _context_trigger_rule_entry_s { int type; std::string uri; ctx_sched_job_context_h jobContext; + std::set conjunctionKeys; std::set disjunctionKeys; _context_trigger_rule_entry_s(int c, int t, const char* u) : @@ -194,158 +195,726 @@ static Scheduler __scheduler; EXPORT_API int context_trigger_add_rule(context_trigger_rule_h rule, int* rule_id) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(rule && rule_id); + + int err = ctx_sched_add_job(SCHED, rule->job, rule_id); + + if (err == E_PARAM) + return E_INV_RULE; + + return err; } EXPORT_API int context_trigger_remove_rule(int rule_id) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + if (rule_id <= 0) + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + + int err = ctx_sched_remove_job(SCHED, rule_id); + + if (err == E_RULE_ON) + return CONTEXT_TRIGGER_ERROR_RULE_ENABLED; + else if (err == E_PARAM) + return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; + + return err; } EXPORT_API int context_trigger_enable_rule(int rule_id) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + if (rule_id <= 0) + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + + int err = ctx_sched_start_job(SCHED, rule_id); + + if (err == E_PARAM) + return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; + + return err; } EXPORT_API int context_trigger_disable_rule(int rule_id) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + if (rule_id <= 0) + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + + int err = ctx_sched_stop_job(SCHED, rule_id); + + if (err == E_PARAM) + return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; + + return err; +} + +static bool __foreach_job_cb(ctx_sched_h scheduler, ctx_sched_job_h job, void *user_data) +{ + auto jobs = static_cast*>(user_data); + jobs->push_back(job); + return true; } EXPORT_API int context_trigger_get_own_rule_ids(int** enabled_rule_ids, int* enabled_rule_count, int** disabled_rule_ids, int* disabled_rule_count) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(enabled_rule_ids && enabled_rule_count && disabled_rule_ids && disabled_rule_count); + + std::vector jobs; + + int err = ctx_sched_foreach_job(SCHED, __foreach_job_cb, &jobs); + + if (err == E_NO_DATA) { + *enabled_rule_ids = NULL; + *enabled_rule_count = 0; + *disabled_rule_ids = NULL; + *disabled_rule_count = 0; + return E_NONE; + } + + IF_FAIL_RETURN(IS_SUCCESS(err), err); + + std::vector startedJobIds; + std::vector stoppedJobIds; + + for (auto& job : jobs) { + bool started = false; + int jobId = 0; + + ctx_sched_job_is_started(job, &started); + ctx_sched_job_get_id(job, &jobId); + ctx_sched_job_destroy(job); + + if (started) + startedJobIds.push_back(jobId); + else + stoppedJobIds.push_back(jobId); + } + + *enabled_rule_count = startedJobIds.size(); + + if (*enabled_rule_count > 0) + *enabled_rule_ids = static_cast(g_memdup(startedJobIds.data(), startedJobIds.size() * sizeof(int))); + else + *enabled_rule_ids = NULL; + + *disabled_rule_count = stoppedJobIds.size(); + + if (*disabled_rule_count > 0) + *disabled_rule_ids = static_cast(g_memdup(stoppedJobIds.data(), stoppedJobIds.size() * sizeof(int))); + else + *disabled_rule_ids = NULL; + + return E_NONE; } EXPORT_API int context_trigger_get_rule_by_id(int rule_id, context_trigger_rule_h* rule) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(rule); + if (rule_id <= 0) + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + + ctx_sched_job_h job = NULL; + + int err = ctx_sched_get_job(SCHED, rule_id, &job); + + if (err == E_PARAM) + return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; + else if (err != E_NONE) + return err; + + *rule = new(std::nothrow) _context_trigger_rule_h(job); + if (*rule == NULL) { + _E_ALLOC; + ctx_sched_job_destroy(job); + return E_NO_MEM; + } + + return E_NONE; } EXPORT_API int context_trigger_rule_create(context_trigger_logical_type_e logical_type, context_trigger_rule_h* rule) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + ASSERT_NOT_NULL(rule); + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); + + *rule = new(std::nothrow) _context_trigger_rule_h(); + ASSERT_ALLOC(*rule); + if ((*rule)->job == NULL) { + _E_ALLOC; + delete *rule; + return E_NO_MEM; + } + + ctx_sched_job_set_disjunction((*rule)->job, logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION); + + return E_NONE; } EXPORT_API int context_trigger_rule_destroy(context_trigger_rule_h rule) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(rule); + + delete rule; + + return E_NONE; +} + +static int __set_event(context_trigger_rule_h rule, context_trigger_rule_entry_h event) +{ + IF_FAIL_RETURN(event->jobContext, E_PARAM); + IF_FAIL_RETURN_TAG(!rule->hasEvent, E_INV_RULE, _E, "The rule already has the event"); + + EventItem contextItem(event->type); + IF_FAIL_RETURN_TAG(contextItem.isValid(event->jobContext), E_INV_RULE, _E, "Incomplete event"); + + ctx_sched_job_context_h dup = ctx_sched_job_context_duplicate(event->jobContext); + ASSERT_ALLOC(dup); + + int err = ctx_sched_job_add_trigger(rule->job, dup); + if (IS_FAILED(err)) { + ctx_sched_job_context_destroy(dup); + return err; + } + + rule->hasEvent = true; + + return E_NONE; +} + +static int __add_condition(context_trigger_rule_h rule, context_trigger_rule_entry_h condition) +{ + IF_FAIL_RETURN(condition->jobContext, E_PARAM); + + bool exist = (rule->conditions.find(condition->uri) != rule->conditions.end()); + IF_FAIL_RETURN_TAG(!exist, E_INV_RULE, _E, "The same condition exists"); + + ConditionItem contextItem(condition->type); + IF_FAIL_RETURN_TAG(contextItem.isValid(condition->jobContext), E_INV_RULE, _E, "Incomplete condition"); + + ctx_sched_job_context_h dup = ctx_sched_job_context_duplicate(condition->jobContext); + ASSERT_ALLOC(dup); + + int err = ctx_sched_job_add_requirement(rule->job, dup); + if (IS_FAILED(err)) { + ctx_sched_job_context_destroy(dup); + return err; + } + + return E_NONE; } EXPORT_API int context_trigger_rule_add_entry(context_trigger_rule_h rule, context_trigger_rule_entry_h entry) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + ASSERT_NOT_NULL(rule && entry); + IF_FAIL_RETURN_TAG(!rule->readOnly, E_PARAM, + _E, "A rule acquired by context_trigger_get_rule_by_id() is not allowed to be modified."); + + if (entry->category == CATEGORY_EVENT) + return __set_event(rule, entry); + else + return __add_condition(rule, entry); +} + +static bool __is_call_operation(app_control_h ctrl) +{ + char *op = NULL; + int err = app_control_get_operation(ctrl, &op); + IF_FAIL_RETURN_TAG(err == APP_CONTROL_ERROR_NONE, false, _E, "Getting operation of app control failed"); + + bool ret = STR_EQ(op, APP_CONTROL_OPERATION_CALL); + g_free(op); + + return ret; +} + +static bool __is_ui_app(app_control_h ctrl) +{ + char* appId = NULL; + int err = app_control_get_app_id(ctrl, &appId); + + IF_FAIL_RETURN_TAG(err == E_NONE, false, _E, "Failed to get the app id"); + + pkgmgrinfo_appinfo_h appInfo; + err = pkgmgrinfo_appinfo_get_usr_appinfo(appId, getuid(), &appInfo); + g_free(appId); + + IF_FAIL_RETURN_TAG(err == PMINFO_R_OK, false, _E, "No such app"); + + char *appType = NULL; + pkgmgrinfo_appinfo_get_component_type(appInfo, &appType); + + bool ret = STR_EQ(appType, "uiapp"); + + pkgmgrinfo_appinfo_destroy_appinfo(appInfo); + + return ret; } EXPORT_API int context_trigger_rule_set_action_app_control(context_trigger_rule_h rule, app_control_h app_control) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(rule && app_control); + + if (!PrivilegeChecker::hasPrivilege("http://tizen.org/privilege/appmanager.launch")) { + _E("Privilege denied"); + return E_ACCESS; + } + + if (__is_call_operation(app_control) && + !PrivilegeChecker::hasPrivilege("http://tizen.org/privilege/call")) { + _E("Privilege denied"); + return E_ACCESS; + } + + IF_FAIL_RETURN_TAG(!rule->hasAction, E_INV_RULE, _E, "The rule has an action"); + IF_FAIL_RETURN_TAG(__is_ui_app(app_control), E_INV_RULE, _E, "Invalid app-control"); + + bundle* bn = NULL; + app_control_export_as_bundle(app_control, &bn); + IF_FAIL_RETURN_TAG(bn, E_PARAM, _E, "Converting failed"); + + int ret = ctx_sched_job_set_app_control(rule->job, bn); + + if (ret == E_NONE) + rule->hasAction = true; + + return ret; } -EXPORT_API int context_trigger_rule_set_action_notification(context_trigger_rule_h rule, const char* title, const char* content, const char* icon_path, app_control_h app_control) +static bool __is_valid_app_control(app_control_h ctrl) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + if (!ctrl) return true; + + char* appId = NULL; + int err = app_control_get_app_id(ctrl, &appId); + IF_FAIL_RETURN_TAG(err == E_NONE, false, _E, "Failed to get the app id"); + + pkgmgrinfo_appinfo_h appInfo; + err = pkgmgrinfo_appinfo_get_usr_appinfo(appId, getuid(), &appInfo); + g_free(appId); + IF_FAIL_RETURN_TAG(err == PMINFO_R_OK, false, _E, "No such app"); + + pkgmgrinfo_appinfo_destroy_appinfo(appInfo); + + return true; +} + +EXPORT_API int context_trigger_rule_set_action_notification(context_trigger_rule_h rule, + const char* title, const char* content, const char* icon_path, app_control_h app_control) +{ + INIT_SCHED; + ASSERT_NOT_NULL(rule && title && content); + + if (!PrivilegeChecker::hasPrivilege("http://tizen.org/privilege/notification")) { + _E("Privilege denied"); + return E_ACCESS; + } + + IF_FAIL_RETURN_TAG(!rule->hasAction, E_INV_RULE, _E, "The rule has an action"); + IF_FAIL_RETURN_TAG(__is_valid_app_control(app_control), E_INV_RULE, _E, "Invalid app-control"); + + bundle* bn = NULL; + if (app_control) { + app_control_export_as_bundle(app_control, &bn); + IF_FAIL_RETURN_TAG(bn, E_PARAM, _E, "Converting failed"); + } + + int ret = ctx_sched_job_set_notification(rule->job, title, content, icon_path, bn); + + if (ret == E_NONE) + rule->hasAction = true; + + return ret; } //LCOV_EXCL_START EXPORT_API int context_trigger_rule_set_action_dbus_call(context_trigger_rule_h rule, const char *bus_name, const char *object_path, const char *interface_name, const char *method_name, GVariant *param) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + ASSERT_NOT_NULL(rule && bus_name && object_path && interface_name && method_name); + IF_FAIL_RETURN_TAG(!rule->hasAction, E_INV_RULE, _E, "The rule has an action"); + + int ret = ctx_sched_job_set_dbus(rule->job, bus_name, object_path, interface_name, method_name, param); + + if (ret == E_NONE) + rule->hasAction = true; + + return ret; } //LCOV_EXCL_STOP EXPORT_API int context_trigger_rule_set_description(context_trigger_rule_h rule, const char* description) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + ASSERT_NOT_NULL(rule && description); + IF_FAIL_RETURN(strlen(description) > 0, E_PARAM); + + return ctx_sched_job_set_user_data(rule->job, description, strlen(description) + 1); } EXPORT_API int context_trigger_rule_get_description(context_trigger_rule_h rule, char** description) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + ASSERT_NOT_NULL(rule && description); + + char* val = NULL; + size_t len = 0; + int err = ctx_sched_job_get_user_data(rule->job, &val, &len); + IF_FAIL_RETURN(IS_SUCCESS(err), err); + IF_FAIL_RETURN(val, E_NONE); + + *description = val; + + return E_NONE; } EXPORT_API int context_trigger_rule_event_create(context_trigger_event_e event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(entry); + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); + + EventItem contextItem(event_item); + IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Event: %d", event_item); + + if (contextItem.deprecated()) + _DEPRECATED_EVENT(event_item); + + IF_FAIL_RETURN_TAG(contextItem.allowed(), E_ACCESS, _E, "Privilege denied"); + + bool supported = false; + ctx_sched_job_trigger_is_supported(SCHED, contextItem.getUri(), &supported); + IF_FAIL_RETURN_TAG(supported, E_SUPPORT, _E, "Event-%d is not supported", event_item); + + *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_EVENT, event_item, contextItem.getUri()); + ASSERT_ALLOC(*entry); + + ctx_sched_job_context_set_disjunction((*entry)->jobContext, (logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION)); + + return E_NONE; +} + +static bool __is_valid_pkg_id(const char* pkgId) +{ + IF_FAIL_RETURN(pkgId, false); + + pkgmgrinfo_pkginfo_h pkgInfo; + int err = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId, getuid(), &pkgInfo); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkgInfo); + + return (PMINFO_R_OK == err); } EXPORT_API int context_trigger_rule_custom_event_create(const char* event_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(event_item && provider && entry); + IF_FAIL_RETURN_TAG(__is_valid_pkg_id(provider), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); + + std::string uri = __get_custom_uri(event_item, provider); + + bool registered = false; + ctx_sched_custom_is_registered(SCHED, uri.c_str(), provider, ®istered); + IF_FAIL_RETURN_TAG(registered, E_SUPPORT, _W, "%s is not registered yet", event_item); + + *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_EVENT, 0, uri.c_str()); + ASSERT_ALLOC(*entry); + + return E_NONE; } EXPORT_API int context_trigger_rule_event_is_supported(context_trigger_event_e event_item, bool* supported) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(supported); + + EventItem contextItem(event_item); + IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Event: %d", event_item); + + return ctx_sched_job_trigger_is_supported(SCHED, contextItem.getUri(), supported); } EXPORT_API int context_trigger_rule_condition_create(context_trigger_condition_e condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(entry); + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); + + ConditionItem contextItem(condition_item); + IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Condition: %d", condition_item); + + if (contextItem.deprecated()) + _DEPRECATED_COND(condition_item); + + IF_FAIL_RETURN_TAG(contextItem.allowed(), E_ACCESS, _E, "Privilege denied"); + + bool supported = false; + ctx_sched_job_requirement_is_supported(SCHED, contextItem.getUri(), &supported); + IF_FAIL_RETURN_TAG(supported, E_SUPPORT, _E, "Condition-%d is not supported", condition_item); + + *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_CONDITION, condition_item, contextItem.getUri()); + ASSERT_ALLOC(*entry); + + ctx_sched_job_context_set_disjunction((*entry)->jobContext, (logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION)); + + return E_NONE; } EXPORT_API int context_trigger_rule_custom_condition_create(const char* condition_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(condition_item && provider && entry); + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); + IF_FAIL_RETURN_TAG(__is_valid_pkg_id(provider), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); + + std::string uri = __get_custom_uri(condition_item, provider); + + bool registered = false; + ctx_sched_custom_is_registered(SCHED, uri.c_str(), provider, ®istered); + IF_FAIL_RETURN_TAG(registered, E_SUPPORT, _W, "%s is not registered yet", condition_item); + + *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_CONDITION, 0, uri.c_str()); + ASSERT_ALLOC(*entry); + + return E_NONE; } EXPORT_API int context_trigger_rule_condition_is_supported(context_trigger_condition_e condition_item, bool* supported) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(supported); + + ConditionItem contextItem(condition_item); + IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Condition: %d", condition_item); + + return ctx_sched_job_requirement_is_supported(SCHED, contextItem.getUri(), supported); } EXPORT_API int context_trigger_rule_entry_destroy(context_trigger_rule_entry_h entry) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(entry); + + delete entry; + + return E_NONE; } EXPORT_API int context_trigger_rule_entry_add_option_int(context_trigger_rule_entry_h entry, const char* option_key, int value) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + ASSERT_NOT_NULL(entry && option_key); + + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); + + bool valid = contextItem->isValid(option_key, value); + delete contextItem; + IF_FAIL_RETURN(valid, E_INV_RULE); + + ctx_sched_job_context_prepare_attribute_int(entry->jobContext, option_key); + return ctx_sched_job_context_attribute_add_eq_int(entry->jobContext, option_key, value); } EXPORT_API int context_trigger_rule_entry_add_option_string(context_trigger_rule_entry_h entry, const char* option_key, const char* value) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + _DEPRECATED_FUNC; + ASSERT_NOT_NULL(entry && option_key && value); + + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); + + bool valid = contextItem->isValid(option_key, value); + delete contextItem; + IF_FAIL_RETURN(valid, E_INV_RULE); + + ctx_sched_job_context_prepare_attribute_str(entry->jobContext, option_key); + return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, option_key, value); } EXPORT_API int context_trigger_rule_entry_add_option(context_trigger_rule_entry_h entry, const char* option_key, const char* event_data_key) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + _DEPRECATED_FUNC; + ASSERT_NOT_NULL(entry && option_key && event_data_key); + IF_FAIL_RETURN(entry->category == CATEGORY_CONDITION, E_INV_RULE); + + ConditionItem contextItem(entry->type); + IF_FAIL_RETURN(contextItem.isValid(option_key), E_INV_RULE); + + ctx_sched_job_context_prepare_attribute_str(entry->jobContext, option_key); + return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, option_key, event_data_key); +} + +static bool __is_member_key(context_trigger_rule_entry_h entry, const char* key) +{ + if (entry->conjunctionKeys.find(key) != entry->conjunctionKeys.end() || + entry->disjunctionKeys.find(key) != entry->disjunctionKeys.end()) { + _D("'%s' found", key); + return true; + } + + _D("'%s' not found", key); + return false; } EXPORT_API int context_trigger_rule_entry_add_key(context_trigger_rule_entry_h entry, context_trigger_logical_type_e logical_type, const char* key) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + ASSERT_NOT_NULL(entry && key); + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); + + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); + + bool valid = contextItem->isValid(key); + delete contextItem; + IF_FAIL_RETURN_TAG(valid, E_INV_RULE, _E, "Invalid parameter"); + IF_FAIL_RETURN(!__is_member_key(entry, key), E_INV_RULE); + + if (logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION) + entry->conjunctionKeys.insert(key); + else + entry->disjunctionKeys.insert(key); + + return E_NONE; } EXPORT_API int context_trigger_rule_entry_add_comparison(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* event_data_key) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + _DEPRECATED_FUNC; + ASSERT_NOT_NULL(entry && key && op && event_data_key); + IF_FAIL_RETURN(entry->category == CATEGORY_CONDITION, E_INV_RULE); + + ConditionItem contextItem(entry->type); + IF_FAIL_RETURN(contextItem.isValid(key), E_INV_RULE); + IF_FAIL_RETURN(__is_member_key(entry, key), E_NO_DATA); + + ctx_sched_job_context_prepare_attribute_str(entry->jobContext, key); + + if (__getOpType(op) == OpType::EQ) + return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, key, event_data_key); + + if (__getOpType(op) == OpType::NE) + return ctx_sched_job_context_attribute_add_ne_str(entry->jobContext, key, event_data_key); + + _E("Invalid operator"); + return E_INV_RULE; } EXPORT_API int context_trigger_rule_entry_add_comparison_int(context_trigger_rule_entry_h entry, const char* key, const char* op, int value) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + ASSERT_NOT_NULL(entry && key && op); + + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); + + bool valid = contextItem->isValid(key, value); + delete contextItem; + IF_FAIL_RETURN_TAG(valid, E_INV_RULE, _E, "Invalid parameter"); + IF_FAIL_RETURN(__is_member_key(entry, key), E_NO_DATA); + + ctx_sched_job_context_prepare_attribute_int(entry->jobContext, key); + + if (__getOpType(op) == OpType::EQ) + return ctx_sched_job_context_attribute_add_eq_int(entry->jobContext, key, value); + + if (__getOpType(op) == OpType::NE) + return ctx_sched_job_context_attribute_add_ne_int(entry->jobContext, key, value); + + //TODO: Consider logical disjunction + if (__getOpType(op) == OpType::GT) + return ctx_sched_job_context_attribute_set_gt_int(entry->jobContext, key, value); + + if (__getOpType(op) == OpType::GE) + return ctx_sched_job_context_attribute_set_ge_int(entry->jobContext, key, value); + + if (__getOpType(op) == OpType::LT) + return ctx_sched_job_context_attribute_set_lt_int(entry->jobContext, key, value); + + if (__getOpType(op) == OpType::LE) + return ctx_sched_job_context_attribute_set_le_int(entry->jobContext, key, value); + + _E("Invalid operator"); + return E_INV_RULE; } EXPORT_API int context_trigger_rule_entry_add_comparison_string(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* value) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + ASSERT_NOT_NULL(entry && key && op && value); + + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); + + bool valid = contextItem->isValid(key, value); + delete contextItem; + IF_FAIL_RETURN_TAG(valid, E_INV_RULE, _E, "Invalid parameter"); + IF_FAIL_RETURN(__is_member_key(entry, key), E_NO_DATA); + + ctx_sched_job_context_prepare_attribute_str(entry->jobContext, key); + + if (__getOpType(op) == OpType::EQ) + return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, key, value); + + if (__getOpType(op) == OpType::NE) + return ctx_sched_job_context_attribute_add_ne_str(entry->jobContext, key, value); + + _E("Invalid operator"); + return E_INV_RULE; } EXPORT_API int context_trigger_custom_register(const char* name, const char* attr_template) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(name && attr_template); + + //TODO: Is it allowed to overwrite a template? + CustomTemplate::remove(name); + + bool success = CustomTemplate::add(name, attr_template); + IF_FAIL_RETURN_TAG(success, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid template"); + + const char* pkgId = __get_pkg_id(); + IF_FAIL_RETURN_TAG(pkgId, E_SUPPORT, _E, "PkgId is required"); + + std::string uri = __get_custom_uri(name, pkgId); + + int err = ctx_sched_custom_register(SCHED, uri.c_str()); + IF_FAIL_RETURN(err == E_NONE, E_FAILED); + + return E_NONE; } EXPORT_API int context_trigger_custom_unregister(const char* name) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(name); + + CustomTemplate::remove(name); + + const char* pkgId = __get_pkg_id(); + IF_FAIL_RETURN_TAG(pkgId, E_SUPPORT, _E, "PkgId is required"); + + std::string uri = __get_custom_uri(name, pkgId); + + ctx_sched_custom_unregister(SCHED, uri.c_str()); + + return E_NONE; } EXPORT_API int context_trigger_custom_publish(const char* name, const char* fact) { - return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED; + INIT_SCHED; + ASSERT_NOT_NULL(name && fact); + + CustomTemplate* customTemplate = CustomTemplate::get(name); + IF_FAIL_RETURN_TAG(customTemplate, E_PARAM, _E, "Unknown custom name"); + IF_FAIL_RETURN(customTemplate->match(fact), CONTEXT_TRIGGER_ERROR_INVALID_DATA); + + const char* pkgId = __get_pkg_id(); + IF_FAIL_RETURN_TAG(pkgId, E_SUPPORT, _E, "PkgId is required"); + + std::string uri = __get_custom_uri(name, pkgId); + + return ctx_sched_publish_context_json(SCHED, uri.c_str(), fact); } -- 2.7.4