From: Somin Kim Date: Mon, 4 Jul 2016 07:14:00 +0000 (+0900) Subject: Modified template format based on JSON schema X-Git-Tag: submit/tizen/20160705.023110~1^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7c7d5dd1f79e4f56337ea8b90e0083cf00db75ec;p=platform%2Fcore%2Fapi%2Fcontext.git Modified template format based on JSON schema Change-Id: Ic7817690f94cd809ce2a3ea28326cd2a8148c5e2 Signed-off-by: Somin Kim --- diff --git a/include/context_trigger_types_internal.h b/include/context_trigger_types_internal.h index 1e03b46..ca01dcc 100644 --- a/include/context_trigger_types_internal.h +++ b/include/context_trigger_types_internal.h @@ -108,9 +108,9 @@ #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_ENUM "enum" +#define CT_CUSTOM_MIN "minimum" +#define CT_CUSTOM_MAX "maximum" #define CT_CUSTOM_SUBJECT "subject" #define TYPE_EVENT 1 @@ -118,6 +118,7 @@ #define TYPE_INT_STR "integer" #define TYPE_STRING_STR "string" +#define TYPE_ENUM_STR "enum" #define TYPE_DOUBLE_STR "double" #define TYPE_OPTION_STR "options" diff --git a/src/context_trigger.cpp b/src/context_trigger.cpp index 8aa246d..5b3ca48 100644 --- a/src/context_trigger.cpp +++ b/src/context_trigger.cpp @@ -876,7 +876,7 @@ SO_EXPORT int context_trigger_rule_entry_add_comparison(context_trigger_rule_ent IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); // Err: Invalid operator - std::string type = ctx::rule_validator::get_data_type(TYPE_ATTR_STR, name, key); + std::string type = ctx::rule_validator::get_data_type_from_template(TYPE_ATTR_STR, name, key); ret = ctx::rule_validator::is_valid_operator(type, op); IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); diff --git a/src/rule_validator.cpp b/src/rule_validator.cpp index f85cc18..e6b5859 100644 --- a/src/rule_validator.cpp +++ b/src/rule_validator.cpp @@ -23,15 +23,7 @@ #include "DBusClient.h" #include "rule_validator.h" -#define KEY_TEMPLATE "templates" -#define KEY_NAME "name" -#define KEY_OPTION TYPE_OPTION_STR -#define KEY_ATTR TYPE_ATTR_STR #define KEY_KEY "key" -#define KEY_TYPE "type" -#define KEY_MIN "min" -#define KEY_MAX "max" -#define KEY_VALUES "values" #define KEY_REF "ref" typedef std::map template_map_t; @@ -40,7 +32,13 @@ template_map_t template_map; // static int string_to_int(std::string str); static bool check_value_int(ctx::Json& tmpl, std::string key, int value); static bool check_value_string(ctx::Json& tmpl, std::string key, std::string value); +static bool check_value_enum(ctx::Json& tmpl, std::string key, std::string value); static ctx::Json get_template(std::string name); +static bool check_template_int(ctx::Json& elem); +static bool check_template_string(ctx::Json& elem); +static bool check_template_enum(ctx::Json& elem); +static std::string get_data_type(ctx::Json& elem, std::string& key); +static bool is_equal_type(std::string& type1, std::string& type2); int string_to_int(std::string str) { @@ -102,7 +100,7 @@ bool ctx::rule_validator::check_option(ctx::Json& item) // No option needed ctx::Json opt_tmpl; - tmpl.get(NULL, KEY_OPTION, &opt_tmpl); + tmpl.get(NULL, TYPE_OPTION_STR, &opt_tmpl); std::list opt_keys; IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); @@ -134,7 +132,7 @@ bool ctx::rule_validator::check_option_int(std::string name, std::string key, in IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); ctx::Json opt_tmpl; - tmpl.get(NULL, KEY_OPTION, &opt_tmpl); + tmpl.get(NULL, TYPE_OPTION_STR, &opt_tmpl); // Err: Item with no option std::list opt_keys; @@ -142,13 +140,12 @@ bool ctx::rule_validator::check_option_int(std::string name, std::string key, in IF_FAIL_RETURN(opt_keys.size() > 0, false); // Err: Invalid option key or Invalid value type - std::string t_type; - bool ret = opt_tmpl.get(key.c_str(), KEY_TYPE, &t_type); - IF_FAIL_RETURN(ret && t_type == TYPE_INT_STR, false); + std::string t_type = get_data_type(opt_tmpl, key); + IF_FAIL_RETURN(t_type == TYPE_INT_STR, false); // Err: Inappropriate value // a. normal case - ret = check_value_int(opt_tmpl, key, value); + bool ret = check_value_int(opt_tmpl, key, value); IF_FAIL_RETURN(ret, false); return true; @@ -161,7 +158,7 @@ bool ctx::rule_validator::check_option_string(std::string name, std::string key, IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); ctx::Json opt_tmpl; - tmpl.get(NULL, KEY_OPTION, &opt_tmpl); + tmpl.get(NULL, TYPE_OPTION_STR, &opt_tmpl); // Err: ';' for SQL injection IF_FAIL_RETURN(value.find(';') == std::string::npos, false); @@ -172,13 +169,12 @@ bool ctx::rule_validator::check_option_string(std::string name, std::string key, IF_FAIL_RETURN(opt_keys.size() > 0, false); // Err: Invalid option key or Invalid value type - std::string t_type; - bool ret = opt_tmpl.get(key.c_str(), KEY_TYPE, &t_type); - IF_FAIL_RETURN(ret && t_type == TYPE_STRING_STR, false); + std::string t_type = get_data_type(opt_tmpl, key); + IF_FAIL_RETURN(t_type == TYPE_STRING_STR || t_type == TYPE_ENUM_STR, false); // Err: Inappropriate value // a. spacial case - if ((name == CT_CONDITION_APP_USE_FREQUENCY || name == CT_CONDITION_COMMUNICATION_FREQUENCY + if (t_type == TYPE_STRING_STR && (name == CT_CONDITION_APP_USE_FREQUENCY || name == CT_CONDITION_COMMUNICATION_FREQUENCY || name == CT_CONDITION_MUSIC_PLAYBACK_FREQUENCY || name == CT_CONDITION_VIDEO_PLAYBACK_FREQUENCY) && key == CONTEXT_TRIGGER_TIME_OF_DAY) { std::size_t found = value.find("-"); @@ -201,10 +197,14 @@ bool ctx::rule_validator::check_option_string(std::string name, std::string key, } // b. normal case - ret = check_value_string(opt_tmpl, key, value); - IF_FAIL_RETURN(ret, false); + bool ret; + if (t_type == TYPE_STRING_STR) { + ret = check_value_string(opt_tmpl, key, value); + } else if (t_type == TYPE_ENUM_STR) { + ret = check_value_enum(opt_tmpl, key, value); + } - return true; + return ret; } // called by context_trigger_rule_entry_add_comparison_int() @@ -214,16 +214,15 @@ bool ctx::rule_validator::check_comparison_int(std::string name, std::string key IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); ctx::Json attr_tmpl; - tmpl.get(NULL, KEY_ATTR, &attr_tmpl); + tmpl.get(NULL, TYPE_ATTR_STR, &attr_tmpl); // Err: Invalid attribute key or Invalid value type - std::string t_type; - bool ret = attr_tmpl.get(key.c_str(), KEY_TYPE, &t_type); - IF_FAIL_RETURN(ret && t_type == TYPE_INT_STR, false); + std::string t_type = get_data_type(attr_tmpl, key); + IF_FAIL_RETURN(t_type == TYPE_INT_STR, false); // Err: Invalid operator for the value // a. normal case - ret = is_valid_operator(TYPE_INT_STR, op); + bool ret = is_valid_operator(TYPE_INT_STR, op); IF_FAIL_RETURN(ret, false); // b. special case if (name == CT_EVENT_TIME && key == CONTEXT_TRIGGER_TIME_OF_DAY) { @@ -245,24 +244,28 @@ bool ctx::rule_validator::check_comparison_string(std::string name, std::string IF_FAIL_RETURN(tmpl != ctx::Json(EMPTY_JSON_OBJECT), false); ctx::Json attr_tmpl; - tmpl.get(NULL, KEY_ATTR, &attr_tmpl); + tmpl.get(NULL, TYPE_ATTR_STR, &attr_tmpl); // Err: ';' for SQL injection IF_FAIL_RETURN(value.find(';') == std::string::npos, false); - // Err: Invalid attribute key or Invalid value type - std::string t_type; - bool ret = attr_tmpl.get(key.c_str(), KEY_TYPE, &t_type); - IF_FAIL_RETURN(ret && t_type == TYPE_STRING_STR, false); + // Err: Invalid option key or Invalid value type + std::string t_type = get_data_type(attr_tmpl, key); + IF_FAIL_RETURN(t_type == TYPE_STRING_STR || t_type == TYPE_ENUM_STR, false); // Err: Invalid operator for the value - ret = is_valid_operator(TYPE_STRING_STR, op); + bool ret = is_valid_operator(t_type, op); IF_FAIL_RETURN(ret, false); // Err: Inappropriate value // a. normal case - ret = check_value_string(attr_tmpl, key, value); - IF_FAIL_RETURN(ret, false); + if (t_type == TYPE_STRING_STR) { + ret = check_value_string(attr_tmpl, key, value); + IF_FAIL_RETURN(ret, false); + } else if (t_type == TYPE_ENUM_STR) { + ret = check_value_enum(attr_tmpl, key, value); + IF_FAIL_RETURN(ret, false); + } return true; } @@ -284,11 +287,11 @@ bool check_value_int(ctx::Json& tmpl, std::string key, int value) { int min, max; - if (tmpl.get(key.c_str(), KEY_MIN, &min)) { + if (tmpl.get(key.c_str(), CT_CUSTOM_MIN, &min)) { IF_FAIL_RETURN(value >= min, false); } - if (tmpl.get(key.c_str(), KEY_MAX, &max)) { + if (tmpl.get(key.c_str(), CT_CUSTOM_MAX, &max)) { IF_FAIL_RETURN(value <= max, false); } @@ -297,13 +300,13 @@ bool check_value_int(ctx::Json& tmpl, std::string key, int value) bool check_value_string(ctx::Json& tmpl, std::string key, std::string value) { - // case1: any value is accepted - if (tmpl.getSize(key.c_str(), KEY_VALUES) <= 0) - return true; + return true; +} - // case2: check acceptable value +bool check_value_enum(ctx::Json& tmpl, std::string key, std::string value) +{ std::string t_val; - for (int i = 0; tmpl.getAt(key.c_str(), KEY_VALUES, i, &t_val); i++) { + for (int i = 0; tmpl.getAt(key.c_str(), CT_CUSTOM_ENUM, i, &t_val); i++) { if (t_val == value) return true; } @@ -321,20 +324,19 @@ bool ctx::rule_validator::set_ref_info(std::string type, ctx::Json* jref, std::s ctx::Json detailed_tmpl; tmpl.get(NULL, type.c_str(), &detailed_tmpl); - std::string dt; - bool ret = detailed_tmpl.get(key.c_str(), KEY_TYPE, &dt); - IF_FAIL_RETURN(ret, false); + std::string dt = get_data_type(detailed_tmpl, key); + IF_FAIL_RETURN(dt == TYPE_INT_STR || dt == TYPE_STRING_STR || dt == TYPE_ENUM_STR, false); ctx::Json temp; - temp.set(NULL, KEY_NAME, name); + temp.set(NULL, CT_CUSTOM_NAME, name); temp.set(NULL, KEY_KEY, key); - temp.set(NULL, KEY_TYPE, dt); + temp.set(NULL, CT_CUSTOM_TYPE, dt); temp.set(NULL, KEY_REF, ref_data); if (type == TYPE_OPTION_STR) { - jref->append(NULL, KEY_OPTION, temp); + jref->append(NULL, TYPE_OPTION_STR, temp); } else if (type == TYPE_ATTR_STR) { - jref->append(NULL, KEY_ATTR, temp); + jref->append(NULL, TYPE_ATTR_STR, temp); } else { return false; } @@ -342,8 +344,22 @@ bool ctx::rule_validator::set_ref_info(std::string type, ctx::Json* jref, std::s return true;; } +std::string get_data_type(ctx::Json& elem, std::string& key) +{ + std::string data_type; + bool ret = elem.get(key.c_str(), CT_CUSTOM_TYPE, &data_type); + if (!ret) { + int size = elem.getSize(key.c_str(), CT_CUSTOM_ENUM); + IF_FAIL_RETURN(size > 0, ""); + data_type = TYPE_ENUM_STR; + } + IF_FAIL_RETURN(data_type == TYPE_INT_STR || data_type == TYPE_STRING_STR || data_type == TYPE_ENUM_STR, ""); + + return data_type; +} + // called by context_trigger_rule_entry_add_comparison() -std::string ctx::rule_validator::get_data_type(std::string type, std::string name, std::string key) +std::string ctx::rule_validator::get_data_type_from_template(std::string type, std::string name, std::string key) { ctx::Json tmpl = get_template(name); IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, ""); @@ -351,11 +367,7 @@ std::string ctx::rule_validator::get_data_type(std::string type, std::string nam ctx::Json detailed_tmpl; tmpl.get(NULL, type.c_str(), &detailed_tmpl); - std::string dt; - bool ret = detailed_tmpl.get(key.c_str(), KEY_TYPE, &dt); - IF_FAIL_RETURN(ret, ""); - - return dt; + return get_data_type(detailed_tmpl, key); } // called by context_trigger_rule_add_entry() @@ -364,39 +376,51 @@ bool ctx::rule_validator::check_referential_data(std::string name, ctx::Json& re std::map type_map; ctx::Json ref_data; - for (int i = 0; ref_info.getAt(NULL, KEY_OPTION, i, &ref_data); i++) { + for (int i = 0; ref_info.getAt(NULL, TYPE_OPTION_STR, i, &ref_data); i++) { std::string ref_key; ref_data.get(NULL, KEY_REF, &ref_key); std::string cond_type; - ref_data.get(NULL, KEY_TYPE, &cond_type); + ref_data.get(NULL, CT_CUSTOM_TYPE, &cond_type); if (type_map.count(ref_key) == 0) { - type_map[ref_key] = get_data_type(TYPE_ATTR_STR, name, ref_key); // "", if invalid key + type_map[ref_key] = get_data_type_from_template(TYPE_ATTR_STR, name, ref_key); // "", if invalid key } // Err: Invalid key or Value type not matched - if (cond_type != type_map[ref_key]) - return false; + IF_FAIL_RETURN(is_equal_type(cond_type, type_map[ref_key]), false); } - for (int i = 0; ref_info.getAt(NULL, KEY_ATTR, i, &ref_data); i++) { + for (int i = 0; ref_info.getAt(NULL, TYPE_ATTR_STR, i, &ref_data); i++) { std::string ref_key; ref_data.get(NULL, KEY_REF, &ref_key); std::string cond_type; - ref_data.get(NULL, KEY_TYPE, &cond_type); + ref_data.get(NULL, CT_CUSTOM_TYPE, &cond_type); if (type_map.count(ref_key) == 0) { - type_map[ref_key] = get_data_type(TYPE_ATTR_STR, name, ref_key); // "", if invalid key + type_map[ref_key] = get_data_type_from_template(TYPE_ATTR_STR, name, ref_key); // "", if invalid key } // Err: Invalid key or Value type not matched - if (cond_type != type_map[ref_key]) - return false; + IF_FAIL_RETURN(is_equal_type(cond_type, type_map[ref_key]), false); } return true; } +bool is_equal_type(std::string& type1, std::string& type2) +{ + // This function regards TYPE_ENUM_STR as TYPE_STRING_STR for referential data + if (type1 == type2) { + return true; + } + + if ((type1 == TYPE_STRING_STR || type1 == TYPE_ENUM_STR) && (type2 == TYPE_STRING_STR || type2 == TYPE_ENUM_STR)) { + return true; + } + + return false; +} + bool ctx::rule_validator::is_valid_operator(std::string type, std::string op) { if (op == CONTEXT_TRIGGER_EQUAL_TO || op == CONTEXT_TRIGGER_NOT_EQUAL_TO) { @@ -425,38 +449,90 @@ bool ctx::rule_validator::is_valid_template(ctx::Json& attr_template) 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"); + std::string type = get_data_type(attr_template, key); + IF_FAIL_RETURN_TAG(type == CT_CUSTOM_INT || type == CT_CUSTOM_STRING || type == CT_CUSTOM_ENUM, + false, _E, "Custom template: invalid data type"); ctx::Json elem; attr_template.get(NULL, key.c_str(), &elem); - std::list elem_keys; - elem.getKeys(&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.getSize(key.c_str(), CT_CUSTOM_VALUES); - if (size > 0) { - std::string val_str; - for (int i = 0; i < size; i++) { - ret = attr_template.getAt(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"); + if (type == CT_CUSTOM_INT) { + ret = check_template_int(elem); + IF_FAIL_RETURN(ret, false); + } else if (type == CT_CUSTOM_STRING) { + ret = check_template_string(elem); + IF_FAIL_RETURN(ret, false); + } else if (type == CT_CUSTOM_ENUM) { + ret = check_template_enum(elem); + IF_FAIL_RETURN(ret, false); + } + } + + return true; +} + +bool check_template_int(ctx::Json& elem) +{ + std::list elem_keys; + elem.getKeys(&elem_keys); + + bool min; + bool max; + int min_val; + int max_val; + + for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { + std::string elem_key = *it2; + if (elem_key == CT_CUSTOM_MIN) { + min = elem.get(NULL, elem_key.c_str(), &min_val); + IF_FAIL_RETURN_TAG(min, false, _E, "Custom template: failed to get integer type value"); + } else if (elem_key == CT_CUSTOM_MAX) { + max = elem.get(NULL, elem_key.c_str(), &max_val); + IF_FAIL_RETURN_TAG(max, false, _E, "Custom template: failed to get integer type value"); + } else { + IF_FAIL_RETURN_TAG(elem_key == CT_CUSTOM_TYPE, false, _E, "Custom template: invalid key"); + } + } + + if (min && max) { + IF_FAIL_RETURN_TAG(min_val <= max_val, false, _E, "Custom template: invalid min, max value"); + } + + return true; +} + +bool check_template_string(ctx::Json& elem) +{ + std::list elem_keys; + elem.getKeys(&elem_keys); + + for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { + std::string elem_key = *it2; + _D("SOM TEST >>> elem key (%s)", elem_key.c_str()); + IF_FAIL_RETURN_TAG(elem_key == CT_CUSTOM_TYPE, false, _E, "Custom template: invalid key"); + } + + return true; +} + +bool check_template_enum(ctx::Json& elem) +{ + std::list elem_keys; + elem.getKeys(&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_ENUM) { + int size = elem.getSize(NULL, CT_CUSTOM_ENUM); + IF_FAIL_RETURN_TAG(size > 0, false, _E, "Custom template: invalid enum"); + + std::string val_str; + for (int i = 0; i < size; i++) { + bool ret = elem.getAt(NULL, CT_CUSTOM_ENUM, 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"); } } diff --git a/src/rule_validator.h b/src/rule_validator.h index c7e727d..15cf340 100644 --- a/src/rule_validator.h +++ b/src/rule_validator.h @@ -33,7 +33,7 @@ namespace ctx { bool check_valid_key(std::string type, std::string name, std::string key); bool set_ref_info(std::string type, ctx::Json *jref, std::string name, std::string key, std::string ref_key); - std::string get_data_type(std::string type, std::string name, std::string key); + std::string get_data_type_from_template(std::string type, std::string name, std::string key); bool check_referential_data(std::string name, ctx::Json &ref_info); bool is_valid_operator(std::string type, std::string op);