Modified template format based on JSON schema 67/78067/1
authorSomin Kim <somin926.kim@samsung.com>
Mon, 4 Jul 2016 07:14:00 +0000 (16:14 +0900)
committerSomin Kim <somin926.kim@samsung.com>
Mon, 4 Jul 2016 07:14:00 +0000 (16:14 +0900)
Change-Id: Ic7817690f94cd809ce2a3ea28326cd2a8148c5e2
Signed-off-by: Somin Kim <somin926.kim@samsung.com>
include/context_trigger_types_internal.h
src/context_trigger.cpp
src/rule_validator.cpp
src/rule_validator.h

index 1e03b46..ca01dcc 100644 (file)
 #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
 
 #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"
index 8aa246d..5b3ca48 100644 (file)
@@ -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);
 
index f85cc18..e6b5859 100644 (file)
 #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<std::string, ctx::Json> template_map_t;
@@ -40,7 +32,13 @@ template_map_t template_map; // <name, template>
 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<std::string> 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<std::string> 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<std::string, std::string> 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<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");
+               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<std::string> elem_keys;
-               elem.getKeys(&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.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<std::string> elem_keys;
+       elem.getKeys(&elem_keys);
+
+       bool min;
+       bool max;
+       int min_val;
+       int max_val;
+
+       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) {
+                       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<std::string> elem_keys;
+       elem.getKeys(&elem_keys);
+
+       for (std::list<std::string>::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<std::string> elem_keys;
+       elem.getKeys(&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_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");
                }
        }
 
index c7e727d..15cf340 100644 (file)
@@ -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);