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;
/**
* @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
#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
*
#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
#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);
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;
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;
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;
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;
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;
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)
{
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;
+}
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);
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 */