From: Somin Kim Date: Thu, 21 Jan 2016 05:22:15 +0000 (+0900) Subject: Added API for custom items X-Git-Tag: submit/tizen/20160314.020719~1^2~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4005f36ebd4ad6b51104d79cf0cef0f53075ed3b;p=platform%2Fcore%2Fapi%2Fcontext.git Added API for custom items - add_custom_item(), remove_custom_item(), publish_custom_data() - context_trigger_enable_rule() will return NOT_SUPPORTED Change-Id: I88d232f2ef4af59a5fcbb510f0192bd84ad4e0f4 Signed-off-by: Somin Kim --- diff --git a/include/context_trigger.h b/include/context_trigger.h index e259786..ebc9166 100644 --- a/include/context_trigger.h +++ b/include/context_trigger.h @@ -523,6 +523,8 @@ typedef enum { CONTEXT_TRIGGER_ERROR_RULE_NOT_ENABLED = (TIZEN_ERROR_CONTEXT | 0X06), /**< Rule is not enabled */ CONTEXT_TRIGGER_ERROR_INVALID_RULE = (TIZEN_ERROR_CONTEXT | 0X07), /**< Invalid rule */ CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST = (TIZEN_ERROR_CONTEXT | 0X08), /**< Rule does not exist */ + CONTEXT_TRIGGER_ERROR_INVALID_DATA = CONTEXT_TRIGGER_ERROR_INVALID_RULE, /**< Invalid data */ + CONTEXT_TRIGGER_ERROR_DATA_EXIST = (TIZEN_ERROR_CONTEXT | 0X09), /**< Data exist */ } context_trigger_error_e; /** @@ -654,6 +656,7 @@ int context_trigger_remove_rule(int rule_id); * @return 0 on success, otherwise a negative error value * @retval #CONTEXT_TRIGGER_ERROR_NONE Successful * @retval #CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED Unsupported event/condition contained * @retval #CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY Out of memory * @retval #CONTEXT_TRIGGER_ERROR_OPERATION_FAILED Operation failed * @retval #CONTEXT_TRIGGER_ERROR_RULE_ENABLED Rule is enabled already diff --git a/include/context_trigger_internal.h b/include/context_trigger_internal.h index 23b5146..d5c2fde 100644 --- a/include/context_trigger_internal.h +++ b/include/context_trigger_internal.h @@ -20,6 +20,103 @@ #include #include +/** + * @brief Add custom event/condition item with its template. + * @since_tizen 3.0 + * + * @param[in] name The name of custom item to register + * @param[in] attr_template The attribute template in json style + * + * @return 0 on success, otherwise a negative error value + * @retval #CONTEXT_TRIGGER_ERROR_NONE Successful + * @retval #CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #CONTEXT_TRIGGER_ERROR_INVALID_DATA Invalid data + * @retval #CONTEXT_TRIGGER_ERROR_DATA_EXIST Data exist + * + * @see context_trigger_remove_custom_item() + */ +int context_trigger_add_custom_item(const char* name, const char* attr_template); + +/** + * @brief Remove custom event/condition item. + * @since_tizen 3.0 + * + * @param[in] name The name of custom item to be removed + * + * @return 0 on success, otherwise a negative error value + * @retval #CONTEXT_TRIGGER_ERROR_NONE Successful + * @retval #CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED Unsupported event/condition item + * + * @see context_trigger_add_custom_item() + */ +int context_trigger_remove_custom_item(const char* name); + +/** + * @brief Publish custom event/condition data. + * @since_tizen 3.0 + * + * @param[in] name The name of custom item to provide data + * @param[in] fact The fact data in json style to publish + * + * @return 0 on success, otherwise a negative error value + * @retval #CONTEXT_TRIGGER_ERROR_NONE Successful + * @retval #CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED Unsupported event/condition contained + * @retval #CONTEXT_TRIGGER_ERROR_INVALID_DATA Invalid data + */ +int context_trigger_publish_custom_item(const char* name, const char* fact); + +/** + * @brief Creates an event entry which uses custom event. + * @details An event of a contextual event item, which will be provided by an application/system, is created. + * @since_tizen 3.0 + * + * @remarks The @c entry must be released using context_trigger_rule_entry_destroy(). + * + * @param[in] event_item The contextual event item + * @param[in] provider The id of the package which provide the event item + * @param[in] logical_type The logical operator + * @param[out] entry The event entry to be initialized + * + * @return 0 on success, otherwise a negative error value + * @retval #CONTEXT_TRIGGER_ERROR_NONE Successful + * @retval #CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY Memory allocation failed + * @retval #CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED Unsupported event contained + * + * @see context_trigger_rule_entry_destroy() + */ +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); + +/** + * @brief Creates a condition entry which uses custom condition. + * @details A condition of a contextual condition item is created. + * @since_tizen 3.0 + * + * @remarks The @c entry must be released using context_trigger_rule_entry_destroy(). + * + * @param[in] condition_item The contextual condition item + * @param[in] provider The id of the package which provide the condition item + * @param[in] logical_type The logical operator + * @param[out] entry The condition entry to be initialized + * + * @return 0 on success, otherwise a negative error value + * @retval #CONTEXT_TRIGGER_ERROR_NONE Successful + * @retval #CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY Memory allocation failed + * @retval #CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED Unsupported condition contained + * + + * @see context_trigger_rule_entry_destroy() + */ +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); + /** * @brief Sets a D-Bus method call as the action of a rule. * @since_tizen 2.4 diff --git a/include/context_trigger_types_internal.h b/include/context_trigger_types_internal.h index 13fb60b..3c591d3 100644 --- a/include/context_trigger_types_internal.h +++ b/include/context_trigger_types_internal.h @@ -24,6 +24,9 @@ #define CONTEXT_TRIGGER_SUBJECT_GET "trigger/get" #define CONTEXT_TRIGGER_SUBJECT_GET_RULE_IDS "trigger/get_rule_ids" #define CONTEXT_TRIGGER_SUBJECT_GET_TEMPLATE "trigger/tepmlate/get" +#define CONTEXT_TRIGGER_SUBJECT_CUSTOM_ADD "custom/add" +#define CONTEXT_TRIGGER_SUBJECT_CUSTOM_REMOVE "custom/remove" +#define CONTEXT_TRIGGER_SUBJECT_CUSTOM_PUBLISH "custom/publish" #define CT_RULE_ARRAY_ENABLED "ARRAY_ENABLED" #define CT_RULE_ARRAY_DISABLED "ARRAY_DISABLED" @@ -94,6 +97,18 @@ #define CT_CONDITION_MUSIC_PLAYBACK_FREQUENCY "stats/music/frequency" #define CT_CONDITION_VIDEO_PLAYBACK_FREQUENCY "stats/video/frequency" +#define CT_CUSTOM_NAME "name" +#define CT_CUSTOM_ATTRIBUTES "attributes" +#define CT_CUSTOM_FACT "fact" +#define CT_CUSTOM_TYPE "type" +#define CT_CUSTOM_INT "integer" +#define CT_CUSTOM_STRING "string" +#define CT_CUSTOM_MIN "min" +#define CT_CUSTOM_MAX "max" +#define CT_CUSTOM_VALUES "values" +#define CT_CUSTOM_SUBJECT "subject" +#define CT_CUSTOM_DELIMITER std::string("::") + #define TYPE_EVENT 1 #define TYPE_CONDITION 2 diff --git a/src/context_trigger.cpp b/src/context_trigger.cpp index b185ef4..fe03b69 100644 --- a/src/context_trigger.cpp +++ b/src/context_trigger.cpp @@ -35,6 +35,8 @@ #define EVENT_DATA_KEY_PREFIX_STR std::string("?") //#define DOUBLE_PRECISION 2 +static int context_trigger_rule_event_create_internal(const char* event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom = false); +static int context_trigger_rule_condition_create_internal(const char* condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom = false); static std::string convert_event_to_string(context_trigger_event_e item); static std::string convert_condition_to_string(context_trigger_condition_e item); static std::string convert_logical_type_to_string(context_trigger_logical_type_e logical_type); @@ -527,16 +529,43 @@ EXTAPI int context_trigger_rule_event_create(context_trigger_event_e event_item, return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; } + int error = context_trigger_rule_event_create_internal(eitem_str.c_str(), logical_type, entry); + return error; +} + +EXTAPI 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) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(event_item && provider && entry); + + // Err: Invalid provider + pkgmgrinfo_pkginfo_h pkg_info; + int error = pkgmgrinfo_pkginfo_get_usr_pkginfo(provider, getuid(), &pkg_info); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_info); + IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); + + std::string subject = provider + CT_CUSTOM_DELIMITER + event_item; + error = context_trigger_rule_event_create_internal(subject.c_str(), logical_type, entry, true); + + return error; +} + +int context_trigger_rule_event_create_internal(const char* event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(event_item); + + // Err: Invalid logical operator std::string logical_str = convert_logical_type_to_string(logical_type); if (logical_str.empty()) { return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; } - int error = ctx::rule_validator::request_template(eitem_str); + int error = ctx::rule_validator::request_template(event_item, is_custom); IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to request template: %#x", error); *entry = new(std::nothrow) _context_trigger_rule_entry_h(TYPE_EVENT); - (*entry)->jentry.set(NULL, CT_RULE_EVENT_ITEM, eitem_str); + (*entry)->jentry.set(NULL, CT_RULE_EVENT_ITEM, event_item); (*entry)->jentry.set(NULL, CT_RULE_EVENT_OPERATOR, logical_str); return CONTEXT_TRIGGER_ERROR_NONE; @@ -577,16 +606,41 @@ EXTAPI int context_trigger_rule_condition_create(context_trigger_condition_e con return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; } + int error = context_trigger_rule_condition_create_internal(citem_str.c_str(), logical_type, entry); + return error; +} + +EXTAPI 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) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(condition_item && provider && entry); + + // Err: Invalid provider + pkgmgrinfo_pkginfo_h pkg_info; + int error = pkgmgrinfo_pkginfo_get_usr_pkginfo(provider, getuid(), &pkg_info); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_info); + IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); + + std::string subject = provider + CT_CUSTOM_DELIMITER + condition_item; + error = context_trigger_rule_condition_create_internal(subject.c_str(), logical_type, entry, true); + return error; +} + +int context_trigger_rule_condition_create_internal(const char* condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(condition_item); + std::string logical_str = convert_logical_type_to_string(logical_type); if (logical_str.empty()) { return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; } - int error = ctx::rule_validator::request_template(citem_str); + int error = ctx::rule_validator::request_template(condition_item, is_custom); IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to request template: %#x", error); *entry = new(std::nothrow) _context_trigger_rule_entry_h(TYPE_CONDITION); - (*entry)->jentry.set(NULL, CT_RULE_CONDITION_ITEM, citem_str); + (*entry)->jentry.set(NULL, CT_RULE_CONDITION_ITEM, condition_item); (*entry)->jentry.set(NULL, CT_RULE_CONDITION_OPERATOR, logical_str); return CONTEXT_TRIGGER_ERROR_NONE; @@ -860,6 +914,67 @@ EXTAPI int context_trigger_rule_entry_add_comparison_string(context_trigger_rule return error; } +EXTAPI int context_trigger_add_custom_item(const char* name, const char* attr_template) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(name && attr_template); + + // Err: Invalid json + ctx::json jattr_template = attr_template; + IF_FAIL_RETURN_TAG(jattr_template.valid(), CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Failed to parse template"); + + // Err: Invalid template + bool ret = ctx::rule_validator::is_valid_template(jattr_template); + IF_FAIL_RETURN_TAG(ret, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid template"); + + ctx::json data; + data.set(NULL, CT_CUSTOM_NAME, name); + data.set(NULL, CT_CUSTOM_ATTRIBUTES, jattr_template); + + int error = ctx::request_handler::write_with_reply(CONTEXT_TRIGGER_SUBJECT_CUSTOM_ADD, &data, NULL); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to add custom item: %#x", error); + + return error; +} + +EXTAPI int context_trigger_remove_custom_item(const char* name) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(name); + + ctx::json data; + data.set(NULL, CT_CUSTOM_NAME, name); + + ctx::json subj; + int error = ctx::request_handler::write_with_reply(CONTEXT_TRIGGER_SUBJECT_CUSTOM_REMOVE, &data, &subj); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to remove custom item: %#x", error); + + std::string subject; + subj.get(NULL, CT_CUSTOM_SUBJECT, &subject); + ctx::rule_validator::remove_template(subject); + + return error; +} + +EXTAPI int context_trigger_publish_custom_item(const char* name, const char* fact) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(name && fact); + + // Err: Invalid json + ctx::json jfact = fact; + IF_FAIL_RETURN_TAG(jfact.valid(), CONTEXT_TRIGGER_ERROR_INVALID_RULE, _E, "Cannot parse fact json" ); + + ctx::json data; + data.set(NULL, CT_CUSTOM_NAME, name); + data.set(NULL, CT_CUSTOM_FACT, jfact); + + int error = ctx::request_handler::write_with_reply(CONTEXT_TRIGGER_SUBJECT_CUSTOM_PUBLISH, &data, NULL); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to publish custom data"); + + return error; +} + std::string convert_event_to_string(context_trigger_event_e item) { std::string str; diff --git a/src/rule_validator.cpp b/src/rule_validator.cpp index fb1568b..f1a1f8a 100644 --- a/src/rule_validator.cpp +++ b/src/rule_validator.cpp @@ -59,10 +59,12 @@ ctx::json get_template(std::string name) return template_map[name]; } -int ctx::rule_validator::request_template(std::string name) +int ctx::rule_validator::request_template(std::string name, bool mandatory) { - template_map_t::iterator it = template_map.find(name); - IF_FAIL_RETURN(it == template_map.end(), ERR_NONE); + if (!mandatory) { + template_map_t::iterator it = template_map.find(name); + IF_FAIL_RETURN(it == template_map.end(), ERR_NONE); + } // Request template ctx::json request; @@ -71,6 +73,11 @@ int ctx::rule_validator::request_template(std::string name) int req_id; ctx::json tmpl; int error = ctx::request_handler::read_sync(CONTEXT_TRIGGER_SUBJECT_GET_TEMPLATE, &request, &req_id, &tmpl); + if (error == ERR_NOT_SUPPORTED) { + template_map.erase(name); + _E("Failed to get request: not supported"); + return ERR_NOT_SUPPORTED; + } IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get request"); template_map[name] = tmpl; @@ -78,6 +85,11 @@ int ctx::rule_validator::request_template(std::string name) return ERR_NONE; } +void ctx::rule_validator::remove_template(std::string name) +{ + template_map.erase(name); +} + // called by context_trigger_rule_add_entry() bool ctx::rule_validator::check_option(ctx::json& item) { @@ -399,3 +411,53 @@ bool ctx::rule_validator::is_valid_operator(std::string type, std::string op) return false; } + +// For custom item template +bool ctx::rule_validator::is_valid_template(ctx::json& attr_template) +{ + IF_FAIL_RETURN_TAG(attr_template != EMPTY_JSON_OBJECT, false, _E, "Custom template: empty json"); + + bool ret; + std::list keys; + attr_template.get_keys(&keys); + + for (std::list::iterator it = keys.begin(); it != keys.end(); it++) { + std::string key = *it; + + std::string type; + ret = attr_template.get(key.c_str(), CT_CUSTOM_TYPE, &type); + IF_FAIL_RETURN_TAG(ret, false, _E, "Custom template: type missing"); + IF_FAIL_RETURN_TAG(type == CT_CUSTOM_INT || type == CT_CUSTOM_STRING, false, _E, "Custom template: invalid data type"); + + ctx::json elem; + attr_template.get(NULL, key.c_str(), &elem); + std::list elem_keys; + elem.get_keys(&elem_keys); + + for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { + std::string elem_key = *it2; + if (elem_key == CT_CUSTOM_MIN || elem_key == CT_CUSTOM_MAX) { + IF_FAIL_RETURN_TAG(type == CT_CUSTOM_INT, false, _E, "Custom template: integer type support min, max"); + + int val; + ret = attr_template.get(key.c_str(), elem_key.c_str(), &val); + IF_FAIL_RETURN_TAG(ret, false, _E, "Custom template: failed to get integer type value"); + } else if (elem_key == CT_CUSTOM_VALUES) { + IF_FAIL_RETURN_TAG(type == CT_CUSTOM_STRING, false, _E, "Custom template: string type support values"); + + int size = attr_template.array_get_size(key.c_str(), CT_CUSTOM_VALUES); + if (size > 0) { + std::string val_str; + for (int i = 0; i < size; i++) { + ret = attr_template.get_array_elem(key.c_str(), CT_CUSTOM_VALUES, i, &val_str); + IF_FAIL_RETURN_TAG(ret, false, _E, "Custom template: failed to get string type value"); + } + } + } else { + IF_FAIL_RETURN_TAG(elem_key == CT_CUSTOM_TYPE, false, _E, "Custom template: invalid key"); + } + } + } + + return true; +} diff --git a/src/rule_validator.h b/src/rule_validator.h index 72c8e6a..f6922a1 100644 --- a/src/rule_validator.h +++ b/src/rule_validator.h @@ -22,7 +22,8 @@ namespace ctx { namespace rule_validator { - int request_template(std::string name); + int request_template(std::string name, bool mandatory = false); + void remove_template(std::string name); bool check_option(ctx::json &item); bool check_option_int(std::string name, std::string key, int value); bool check_option_string(std::string name, std::string key, std::string value); @@ -36,6 +37,7 @@ namespace ctx { bool check_referential_data(std::string name, ctx::json &ref_info); bool is_valid_operator(std::string type, std::string op); + bool is_valid_template(ctx::json& attr_template); } } /* namespace ctx */