Added API for custom items 69/57569/8
authorSomin Kim <somin926.kim@samsung.com>
Thu, 21 Jan 2016 05:22:15 +0000 (14:22 +0900)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Wed, 17 Feb 2016 02:27:13 +0000 (18:27 -0800)
- 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 <somin926.kim@samsung.com>
include/context_trigger.h
include/context_trigger_internal.h
include/context_trigger_types_internal.h
src/context_trigger.cpp
src/rule_validator.cpp
src/rule_validator.h

index e259786..ebc9166 100644 (file)
@@ -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
index 23b5146..d5c2fde 100644 (file)
 #include <context_trigger.h>
 
 /**
+ * @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
  *
index 13fb60b..3c591d3 100644 (file)
@@ -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"
 #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
 
index b185ef4..fe03b69 100644 (file)
@@ -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;
index fb1568b..f1a1f8a 100644 (file)
@@ -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<std::string> keys;
+       attr_template.get_keys(&keys);
+
+       for (std::list<std::string>::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<std::string> elem_keys;
+               elem.get_keys(&elem_keys);
+
+               for (std::list<std::string>::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;
+}
index 72c8e6a..f6922a1 100644 (file)
@@ -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 */