Sync with Tizen 2.4 79/46179/1
authorMu-Woong <muwoong.lee@samsung.com>
Mon, 17 Aug 2015 13:00:42 +0000 (22:00 +0900)
committerMu-Woong <muwoong.lee@samsung.com>
Mon, 17 Aug 2015 13:00:42 +0000 (22:00 +0900)
- Modified to use new template format
- Add SIGABRT to the signal handler
- Add basic working flow for adding trigger templates at runtime
- Cleanup trigger event/condition item names
- Clear uninstalled apps' rules(during initialization, after rule triggered)
- Modified to update description when adding identical rule(except description) is requested
- Fix error of rule action comparison

Change-Id: Ia3d46e3e1b21e07e29e21c1ce9c344df99cc3298
Signed-off-by: Somin Kim <somin926.kim@samsung.com>
Signed-off-by: Mu-Woong <muwoong.lee@samsung.com>
14 files changed:
data/trigger-template.json
src/context_mgr_impl.cpp
src/context_mgr_impl.h
src/context_trigger/fact_reader.cpp
src/context_trigger/fact_reader.h
src/context_trigger/rule_manager.cpp
src/context_trigger/rule_manager.h
src/context_trigger/script_generator.cpp
src/context_trigger/script_generator.h
src/context_trigger/timer.cpp
src/context_trigger/timer.h
src/context_trigger/timer_types.h
src/context_trigger/trigger.cpp
src/server.cpp

index 5a32ec96035bc7d79a92814ce3cffd960612cae0..e515ecb892f630294d7e58c009624925f960ef29 100644 (file)
 {
        "templates": [
                {
-                       "name": "timer/event",
+                       "name": "time/alarm",
                        "attributes": ["TimeOfDay", "DayOfWeek"]
                },
                {
-                       "name": "timer/state",
+                       "name": "time/now",
                        "attributes": ["TimeOfDay", "DayOfWeek", "DayOfMonth"]
                },
                {
-                       "name": "system/state/battery",
+                       "name": "system/battery",
                        "attributes": ["Level", "IsCharging"]
                },
                {
-                       "name": "system/state/charger",
+                       "name": "system/charger",
                        "attributes": ["IsConnected"]
                },
                {
-                       "name": "system/state/flight_mode",
-                       "attributes": ["IsEnabled"]
-               },
-               {
-                       "name": "system/state/gps",
+                       "name": "system/gps",
                        "attributes": ["State"]
                },
                {
-                       "name": "system/state/headphone",
+                       "name": "system/headphone",
                        "attributes": ["IsConnected", "Type"]
                },
                {
-                       "name": "system/state/ps_mode",
-                       "attributes": ["IsEnabled"]
-               },
-               {
-                       "name": "system/state/silent_mode",
-                       "attributes": ["IsEnabled"]
-               },
-               {
-                       "name": "system/state/vibration_mode",
+                       "name": "system/psmode",
                        "attributes": ["IsEnabled"]
                },
                {
-                       "name": "system/state/usb",
+                       "name": "system/usb",
                        "attributes": ["IsConnected"]
                },
                {
-                       "name": "system/state/wifi",
+                       "name": "system/wifi",
                        "attributes": ["State", "BSSID"]
                },
                {
-                       "name": "social/state/call",
+                       "name": "social/call",
                        "attributes": ["Medium", "State", "Address"]
                },
                {
-                       "name": "social/event/email",
+                       "name": "social/email",
                        "attributes": ["Event"]
                },
                {
-                       "name": "social/event/message",
+                       "name": "social/message",
                        "attributes": ["Event", "Type", "Address"]
                },
                {
-                       "name": "activity/event/stationary",
+                       "name": "activity/stationary",
                        "attributes": ["Event", "Accuracy"]
                },
                {
-                       "name": "activity/event/walking",
+                       "name": "activity/walking",
                        "attributes": ["Event", "Accuracy"]
                },
                {
-                       "name": "activity/event/running",
+                       "name": "activity/running",
                        "attributes": ["Event", "Accuracy"]
                },
                {
-                       "name": "activity/event/in_vehicle",
+                       "name": "activity/in_vehicle",
                        "attributes": ["Event", "Accuracy"]
                },
                {
-                       "name": "place/event/geofence",
+                       "name": "place/geofence",
                        "attributes": ["Event"],
                        "option": ["PlaceId"]
                },
                {
-                       "name": "app/history/use_freq",
+                       "name": "stats/app/frequency",
                        "attributes": ["Rank", "TotalCount"],
                        "option": ["AppId", "TimeOfDay", "DayOfWeek"]
                },
                {
-                       "name": "contact/history/comm_freq",
+                       "name": "stats/contact/frequency",
                        "attributes": ["Rank", "TotalCount"],
                        "option": ["Address", "TimeOfDay", "DayOfWeek"]
                },
                {
-                       "name": "music/history/play_freq",
+                       "name": "stats/music/frequency",
                        "attributes": ["TotalCount"],
                        "option": ["TimeOfDay", "DayOfWeek"]
                },
                {
-                       "name": "video/history/play_freq",
+                       "name": "stats/video/frequency",
                        "attributes": ["TotalCount"],
                        "option": ["TimeOfDay", "DayOfWeek"]
                }
index c58b4c78bc843b75cabf71aa2e7b12339b5980d6..a055da8caff4517a99ee655216babb10d3f2e74a 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <glib.h>
 #include <string>
+#include <list>
 
 #include <types_internal.h>
 #include <json.h>
 #include <internal/statistics_context_provider.h>
 #include <internal/place_context_provider.h>
 
+struct trigger_item_format_s {
+       std::string subject;
+       int operation;
+       ctx::json attributes;
+       ctx::json options;
+       trigger_item_format_s(std::string subj, int ops, ctx::json attr, ctx::json opt)
+               : subject(subj), operation(ops), attributes(attr), options(opt) {}
+};
+
+static std::list<trigger_item_format_s> __trigger_item_list;
+
 ctx::context_manager_impl::context_manager_impl()
 {
 }
@@ -85,6 +97,28 @@ bool ctx::context_manager_impl::register_provider(const char *subject, ctx::cont
        return true;
 }
 
+bool ctx::context_manager_impl::register_trigger_item(const char *subject, int operation, ctx::json attributes, ctx::json options)
+{
+       IF_FAIL_RETURN_TAG(subject, false, _E, "Invalid parameter");
+       __trigger_item_list.push_back(trigger_item_format_s(subject, operation, attributes, options));
+       return true;
+}
+
+bool ctx::context_manager_impl::pop_trigger_item(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options)
+{
+       IF_FAIL_RETURN(!__trigger_item_list.empty(), false);
+
+       trigger_item_format_s format = __trigger_item_list.front();
+       __trigger_item_list.pop_front();
+
+       subject = format.subject;
+       operation = format.operation;
+       attributes = format.attributes;
+       options = format.options;
+
+       return true;
+}
+
 void ctx::context_manager_impl::assign_request(ctx::request_info* request)
 {
        switch (request->get_type()) {
index 76bdae19a30feedd0945cb2866b2ae4288302607..64182240bad12b21dd1a31a968e8b60e3a67fdf1 100644 (file)
@@ -20,6 +20,7 @@
 #include <vector>
 #include <list>
 #include <map>
+#include <context_mgr.h>
 #include <context_mgr_iface.h>
 #include "request.h"
 
@@ -40,9 +41,11 @@ namespace ctx {
                void assign_request(ctx::request_info *request);
                bool is_supported(const char *subject);
                bool is_allowed(const char *client, const char *subject);
+               bool pop_trigger_item(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options);
 
                /* From the interface class */
                bool register_provider(const char *subject, context_provider_info &provider_info);
+               bool register_trigger_item(const char *subject, int operation, ctx::json attributes, ctx::json options);
                bool publish(const char *subject, ctx::json &option, int error, ctx::json &data_updated);
                bool reply_to_read(const char *subject, ctx::json &option, int error, ctx::json &data_read);
 
index 3c219d2a3ec059f90a3c8ce33c9b76452b98e78e..bdf6fe6ef58aa189f001af9fe9057dd0d263fa3f 100644 (file)
@@ -128,6 +128,11 @@ bool ctx::fact_reader::is_allowed(const char *client, const char *subject)
        return _context_mgr->is_allowed(client, subject);
 }
 
+bool ctx::fact_reader::get_fact_definition(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options)
+{
+       return _context_mgr->pop_trigger_item(subject, operation, attributes, options);
+}
+
 int ctx::fact_reader::subscribe(const char* subject, json* option, bool wait_response)
 {
        IF_FAIL_RETURN(subject, ERR_INVALID_PARAMETER);
index 4cbbbd784778754dfc65d004f0886e38b819fb45..182b836b5a08f9f2279a3ff64e9ffe1eaec9be13 100644 (file)
@@ -33,6 +33,7 @@ namespace ctx {
 
                bool is_supported(const char *subject);
                bool is_allowed(const char *client, const char *subject);
+               bool get_fact_definition(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options);
 
                int subscribe(const char *subject, json *option, bool wait_response = false);
                void unsubscribe(const char *subject, json *option);
index 2241daa67264997e1d91068dd7775d7ad56cb572..54b030759a8c7ac1782c5379dcb4e1c31eb1b98e 100644 (file)
@@ -30,6 +30,8 @@
 #include <context_trigger.h>
 #include <db_mgr.h>
 #include "../dbus_server_impl.h"
+#include <app_manager.h>
+#include "fact_reader.h"
 #include "rule_manager.h"
 #include "script_generator.h"
 #include "trigger.h"
 #define CONDITION_TABLE "context_trigger_condition"
 #define TEMPLATE_TABLE "context_trigger_template"
 
-#define RULE_TABLE_COLUMNS "enabled INTEGER DEFAULT 0 NOT NULL, creator TEXT DEFAULT '' NOT NULL, description TEXT DEFAULT '', details TEXT DEFAULT '' NOT NULL"
+#define RULE_TABLE_COLUMNS "enabled INTEGER DEFAULT 0 NOT NULL, creator TEXT DEFAULT '' NOT NULL, creator_app_id TEXT DEFAULT '' NOT NULL, description TEXT DEFAULT '', details TEXT DEFAULT '' NOT NULL"
 #define EVENT_TABLE_COLUMNS "rule_id INTEGER references context_trigger_rule(row_id) ON DELETE CASCADE NOT NULL, name TEXT DEFAULT '' NOT NULL, instance_name TEXT DEFAULT ''"
 #define CONDITION_TABLE_COLUMNS "rule_id INTEGER references context_trigger_rule(row_id) ON DELETE CASCADE NOT NULL, name TEXT DEFAULT '' NOT NULL, option TEXT DEFAULT '', instance_name TEXT DEFAULT ''"
-#define CREATE_TEMPLATE_TABLE "CREATE TABLE IF NOT EXISTS context_trigger_template (name TEXT DEFAULT '' NOT NULL PRIMARY KEY, j_template TEXT DEFAULT '' NOT NULL)"
-#define QUERY_TEMPLATE_TABLE "SELECT j_template FROM context_trigger_template"
+#define CREATE_TEMPLATE_TABLE "CREATE TABLE IF NOT EXISTS context_trigger_template (name TEXT DEFAULT '' NOT NULL PRIMARY KEY, operation INTEGER DEFAULT 3 NOT NULL, attributes TEXT DEFAULT '' NOT NULL, options TEXT DEFAULT '' NOT NULL)"
+#define QUERY_TEMPLATE_TABLE "SELECT name, operation, attributes, options FROM context_trigger_template"
 #define FOREIGN_KEYS_ON "PRAGMA foreign_keys = ON"
 #define DELETE_RULE_STATEMENT "DELETE FROM 'context_trigger_rule' where row_id = "
 #define UPDATE_RULE_ENABLED_STATEMENT "UPDATE context_trigger_rule SET enabled = 1 WHERE row_id = "
 #define UPDATE_RULE_DISABLED_STATEMENT "UPDATE context_trigger_rule SET enabled = 0 WHERE row_id = "
-#define QUERY_NAME_INSTANCE_NAME_AND_TEMPLATE_BY_RULE_ID_STATEMENT "SELECT context_trigger_condition.name, instance_name, j_template as templates FROM context_trigger_condition JOIN context_trigger_template ON (context_trigger_condition.name = context_trigger_template.name) WHERE rule_id = "
-#define QUERY_CONDITION_TEMPLATES_OF_INVOKED_EVENT_STATEMENT "SELECT DISTINCT context_trigger_condition.name, instance_name, option, j_template FROM context_trigger_condition JOIN context_trigger_template ON (context_trigger_condition.name = context_trigger_template.name) WHERE rule_id IN (SELECT row_id FROM context_trigger_rule WHERE enabled = 1 AND row_id IN (SELECT rule_id FROM context_trigger_event WHERE context_trigger_event.instance_name = '"
+#define QUERY_NAME_INSTANCE_NAME_AND_ATTRIBUTES_BY_RULE_ID_STATEMENT "SELECT context_trigger_condition.name, instance_name, attributes FROM context_trigger_condition JOIN context_trigger_template ON (context_trigger_condition.name = context_trigger_template.name) WHERE rule_id = "
+#define QUERY_CONDITION_TEMPLATES_OF_INVOKED_EVENT_STATEMENT "SELECT DISTINCT context_trigger_condition.name, instance_name, option, attributes, options FROM context_trigger_condition JOIN context_trigger_template ON (context_trigger_condition.name = context_trigger_template.name) WHERE rule_id IN (SELECT row_id FROM context_trigger_rule WHERE enabled = 1 AND row_id IN (SELECT rule_id FROM context_trigger_event WHERE context_trigger_event.instance_name = '"
 #define QUERY_RULE_BY_RULE_ID "SELECT details FROM context_trigger_rule WHERE row_id = "
-#define QUERY_EVENT_TEMPLATE_BY_RULE_ID "SELECT j_template FROM context_trigger_template WHERE name IN (SELECT name FROM context_trigger_event WHERE rule_id = "
+#define QUERY_EVENT_TEMPLATE_BY_RULE_ID "SELECT name, attributes, options FROM context_trigger_template WHERE name IN (SELECT name FROM context_trigger_event WHERE rule_id = "
 #define QUERY_CONDITION_BY_RULE_ID "SELECT name, option FROM context_trigger_condition WHERE rule_id = "
 
 #define INSTANCE_NAME_DELIMITER "/"
@@ -79,6 +81,20 @@ static std::string int_to_string(int i)
        return str;
 }
 
+static bool convert_str_to_json(ctx::json* val, const char* path, const char* key)
+{
+       // TODO:
+       IF_FAIL_RETURN(val, false);
+
+       std::string buf;
+       IF_FAIL_RETURN(val->get(path, key, &buf), false);
+
+       ctx::json temp = buf;
+       IF_FAIL_RETURN(val->set(path, key, temp), false);
+
+       return true;
+}
+
 ctx::rule_manager::rule_manager()
 {
 }
@@ -91,6 +107,7 @@ ctx::rule_manager::~rule_manager()
 bool ctx::rule_manager::init(ctx::context_trigger* tr, ctx::fact_reader* fr)
 {
        bool ret;
+       int error;
 
        clips_h = NULL;
        trigger = tr;
@@ -115,11 +132,204 @@ bool ctx::rule_manager::init(ctx::context_trigger* tr, ctx::fact_reader* fr)
        ret = db_manager::execute_sync(FOREIGN_KEYS_ON, &record);
        IF_FAIL_RETURN_TAG(ret, false, _E, "Foreign keys on failed");
 
+       apply_templates(fr);
+
+       if (get_uninstalled_app() > 0) {
+               error = clear_rule_of_uninstalled_app(true);
+               IF_FAIL_RETURN_TAG(error == ERR_NONE, false, _E, "Failed to remove uninstalled apps' rules while initialization");
+       }
        ret = reenable_rule();
 
        return ret;
 }
 
+void ctx::rule_manager::apply_templates(ctx::fact_reader *fr)
+{
+       std::string subject;
+       int operation;
+       ctx::json attributes;
+       ctx::json options;
+       std::string q_update;
+       std::string q_insert = "INSERT OR IGNORE INTO context_trigger_template (name, operation, attributes, options) VALUES";
+
+       while (fr->get_fact_definition(subject, operation, attributes, options)) {
+               _D("Subject: %s, Ops: %d", subject.c_str(), operation);
+               _J("Attr", attributes);
+               _J("Opt", options);
+
+               q_update += "UPDATE context_trigger_template SET operation=" + int_to_string(operation)
+                       + ", attributes='" + attributes.str() + "', options='" + options.str() + "' WHERE name='" + subject + "';";
+
+               q_insert += " ('" + subject + "', " + int_to_string(operation) + ", '" + attributes.str() + "', '" + options.str() + "'),";
+       }
+
+       q_insert.erase(q_insert.end() - 1, q_insert.end());
+       q_insert += ";";
+
+       bool ret = db_manager::execute(5, q_update.c_str(), NULL);
+       if (!ret)
+               _E("Update item definition failed");
+
+       ret = db_manager::execute(6, q_insert.c_str(), NULL);
+       IF_FAIL_VOID_TAG(ret, _E, "Insert item definition failed");
+}
+
+int ctx::rule_manager::get_uninstalled_app(void)
+{
+       // Return number of uninstalled apps
+       std::string q1 = "SELECT DISTINCT creator_app_id FROM context_trigger_rule";
+
+       std::vector<json> record;
+       bool ret = db_manager::execute_sync(q1.c_str(), &record);
+       IF_FAIL_RETURN_TAG(ret, -1, _E, "Query creators of registered rules failed");
+
+       std::vector<json>::iterator vec_end = record.end();
+       for (std::vector<json>::iterator vec_pos = record.begin(); vec_pos != vec_end; ++vec_pos) {
+               ctx::json elem = *vec_pos;
+               std::string app_id;
+               elem.get(NULL, "creator_app_id", &app_id);
+
+               if (is_uninstalled_package(app_id)) {
+                       uninstalled_apps.insert(app_id);
+               }
+       }
+
+       return uninstalled_apps.size();
+}
+
+bool ctx::rule_manager::is_uninstalled_package(std::string app_id)
+{
+       IF_FAIL_RETURN_TAG(!app_id.empty(), false, _D, "Empty app id");
+
+       app_info_h app_info;
+       int     error = app_manager_get_app_info(app_id.c_str(), &app_info);
+
+       if (error == APP_MANAGER_ERROR_NONE) {
+               app_info_destroy(app_info);
+       } else if (error == APP_MANAGER_ERROR_NO_SUCH_APP) {
+               // Uninstalled app found
+               _D("Uninstalled app found: %s", app_id.c_str());
+               return true;
+       } else {
+               _E("Get app info(%s) failed: %d", app_id.c_str(), error);
+       }
+
+       return false;
+}
+
+int ctx::rule_manager::clear_rule_of_uninstalled_app(bool is_init)
+{
+       if (uninstalled_apps.size() <= 0) {
+               return ERR_NONE;
+       }
+
+       int error;
+       bool ret;
+
+       _D("Clear uninstalled apps' rule started");
+       // creator list
+       std::string creator_list = "(";
+       std::set<std::string>::iterator it = uninstalled_apps.begin();
+       creator_list += "creator_app_id = '" + *it + "'";
+       it++;
+       for (; it != uninstalled_apps.end(); ++it) {
+               creator_list += " OR creator_app_id = '" + *it + "'";
+       }
+       creator_list += ")";
+
+       // After event received, disable all the enabled rules of uninstalled apps
+       if (!is_init) {
+               std::string q1 = "SELECT row_id, details FROM context_trigger_rule WHERE enabled = 1 and (";
+               q1 += creator_list;
+               q1 += ")";
+
+               std::vector<json> record;
+               ret = db_manager::execute_sync(q1.c_str(), &record);
+               IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Query enabled rules of uninstalled apps failed");
+
+               std::vector<json>::iterator vec_end = record.end();
+               for (std::vector<json>::iterator vec_pos = record.begin(); vec_pos != vec_end; ++vec_pos) {
+                       ctx::json elem = *vec_pos;
+                       error = disable_uninstalled_rule(elem);
+                       IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to disable rules" );
+               }
+               _D("Uninstalled apps' rules are disabled");
+       }
+
+       // Delete rules of uninstalled apps from DB
+       std::string q2 = "DELETE FROM context_trigger_rule WHERE " + creator_list;
+       std::vector<json> dummy;
+       ret = db_manager::execute_sync(q2.c_str(), &dummy);
+       IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Remove rule from db failed");
+       _D("Uninstalled apps's rule are deleted from db");
+
+       uninstalled_apps.clear();
+
+       return ERR_NONE;
+}
+
+int ctx::rule_manager::disable_uninstalled_rule(ctx::json& rule_info)
+{
+       int error;
+       bool ret;
+
+       int rule_id;
+       rule_info.get(NULL, "row_id", &rule_id);
+
+       // For event with options
+       std::string r1;
+       rule_info.get(NULL, "details", &r1);
+       ctx::json rule = r1;
+       ctx::json event;
+       rule.get(NULL, CT_RULE_EVENT, &event);
+       std::string ename;
+       event.get(NULL, CT_RULE_EVENT_ITEM, &ename);
+
+       // Unsubscribe event
+       error = c_monitor.unsubscribe(rule_id, ename, event);
+       IF_FAIL_RETURN_TAG(error == ERR_NONE, ERR_OPERATION_FAILED, _E, "Failed to unsubscribe %s of rule%d: %d", ename.c_str(), rule_id, error);
+
+       // Undef rule in clips
+       std::string id_str = int_to_string(rule_id);
+       std::string script = script_generator::generate_undefrule(id_str);
+       error = clips_h->route_string_command(script);
+       IF_FAIL_RETURN_TAG(error == ERR_NONE, ERR_OPERATION_FAILED, _E, "Failed to undefine rule%d: %d", rule_id, error);
+
+       // Remove condition instances
+       std::string q3 = "SELECT name, instance_name FROM context_trigger_condition WHERE rule_id = ";
+       q3 += id_str;
+       std::vector<json> name_record;
+       ret = db_manager::execute_sync(q3.c_str(), &name_record);
+       IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query condition table of rule%d failed: %d", rule_id, error);
+
+       std::vector<json>::iterator vec_end = name_record.end();
+       for (std::vector<json>::iterator vec_pos = name_record.begin(); vec_pos != vec_end; ++vec_pos) {
+               ctx::json elem = *vec_pos;
+
+               std::string cname;
+               std::string ciname;
+               elem.get(NULL, "name", &cname);
+               elem.get(NULL, "instance_name", &ciname);
+
+               if (cname.compare(ciname) != 0) {
+                       cond_cnt_map[ciname]--;
+
+                       if (cond_cnt_map[ciname] == 0) {
+                               error = clips_h->unmake_instance(ciname);
+                               IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to unmake instance %s of rule%d: %d", ciname.c_str(), rule_id, error);
+
+                               cond_cnt_map.erase(ciname);
+                       }
+               }
+       }
+
+       if (--enb_rule_cnt <= 0) {
+               enb_rule_cnt = 0;
+               destroy_clips();
+       }
+       return ERR_NONE;
+}
+
 bool ctx::rule_manager::initialize_clips(void)
 {
        if (clips_h) {
@@ -138,20 +348,19 @@ bool ctx::rule_manager::initialize_clips(void)
        // Make scripts for deftemplate, defclass, make-instance and load them to clips
        std::vector<json>::iterator vec_end = record.end();
        for (std::vector<json>::iterator vec_pos = record.begin(); vec_pos != vec_end; ++vec_pos) {
-               ctx::json elem = *vec_pos;
-               std::string tmpl_str;
-               elem.get(NULL, "j_template", &tmpl_str);
-               ctx::json tmpl = tmpl_str;
+               ctx::json tmpl = *vec_pos;
+               convert_str_to_json(&tmpl, NULL, "attributes");
+               convert_str_to_json(&tmpl, NULL, "options");
 
-               std::string deftemplate_str = script_generator::generate_deftemplate(&tmpl);
+               std::string deftemplate_str = script_generator::generate_deftemplate(tmpl);
                int error = clips_h->define_template(deftemplate_str);
                IF_FAIL_RETURN_TAG(error == ERR_NONE, false, _E, "Deftemplate failed");
 
-               std::string defclass_str = script_generator::generate_defclass(&tmpl);
+               std::string defclass_str = script_generator::generate_defclass(tmpl);
                error = clips_h->define_class(defclass_str);
                IF_FAIL_RETURN_TAG(error == ERR_NONE, false, _E, "Defclass failed");
 
-               std::string makeinstance_str = script_generator::generate_makeinstance(&tmpl);
+               std::string makeinstance_str = script_generator::generate_makeinstance(tmpl);
                error = clips_h->make_instance(makeinstance_str);
                IF_FAIL_RETURN_TAG(error == ERR_NONE, false, _E, "Makeinstance failed");
        }
@@ -337,30 +546,32 @@ bool ctx::rule_manager::rule_equals(ctx::json& lrule, ctx::json& rrule)
        }
 
        // Compare action
-       std::string laction, raction;
+       ctx::json laction, raction;
        lrule.get(NULL, CT_RULE_ACTION, &laction);
        rrule.get(NULL, CT_RULE_ACTION, &raction);
-       if (laction.compare(raction))
+       if (laction != raction)
                return false;
 
        return true;
 }
 
-int64_t ctx::rule_manager::get_duplicated_rule(std::string creator, ctx::json& rule)
+int64_t ctx::rule_manager::get_duplicated_rule_id(std::string creator, ctx::json& rule)
 {
-       std::string q = "SELECT row_id, details FROM context_trigger_rule WHERE creator = '";
+       std::string q = "SELECT row_id, description, details FROM context_trigger_rule WHERE creator = '";
        q += creator;
        q += "'";
 
-       std::vector<json> record;
-       bool ret = db_manager::execute_sync(q.c_str(), &record);
+       std::vector<json> d_record;
+       bool ret = db_manager::execute_sync(q.c_str(), &d_record);
        IF_FAIL_RETURN_TAG(ret, false, _E, "Query row_id, details by creator failed");
 
        ctx::json r_details;
        rule.get(NULL, CT_RULE_DETAILS, &r_details);
-       std::vector<json>::iterator vec_end = record.end();
+       std::string r_desc;
+       rule.get(NULL, CT_RULE_DESCRIPTION, &r_desc);
+       std::vector<json>::iterator vec_end = d_record.end();
 
-       for (std::vector<json>::iterator vec_pos = record.begin(); vec_pos != vec_end; ++vec_pos) {
+       for (std::vector<json>::iterator vec_pos = d_record.begin(); vec_pos != vec_end; ++vec_pos) {
                ctx::json elem = *vec_pos;
                std::string details;
                ctx::json d_details;
@@ -371,6 +582,23 @@ int64_t ctx::rule_manager::get_duplicated_rule(std::string creator, ctx::json& r
                if (rule_equals(r_details, d_details)) {
                        int64_t row_id;
                        elem.get(NULL, "row_id", &row_id);
+
+                       // Description comparison
+                       std::string d_desc;
+                       elem.get(NULL, "description", &d_desc);
+                       if (r_desc.compare(d_desc)) {
+                               // Only description is changed
+                               std::string q_update = "UPDATE context_trigger_rule SET description='" + r_desc + "' WHERE row_id = " + int_to_string(row_id);
+
+                               std::vector<json> record;
+                               ret = db_manager::execute_sync(q_update.c_str(), &record);
+                               if (ret) {
+                                       _D("Rule%lld description is updated", row_id);
+                               } else {
+                                       _W("Failed to update description of rule%lld", row_id);
+                               }
+                       }
+
                        return row_id;
                }
        }
@@ -378,7 +606,7 @@ int64_t ctx::rule_manager::get_duplicated_rule(std::string creator, ctx::json& r
        return -1;
 }
 
-int ctx::rule_manager::verify_rule(ctx::json& rule, const char* app_id)
+int ctx::rule_manager::verify_rule(ctx::json& rule, const char* creator)
 {
        ctx::json details;
        rule.get(NULL, CT_RULE_DETAILS, &details);
@@ -388,8 +616,8 @@ int ctx::rule_manager::verify_rule(ctx::json& rule, const char* app_id)
 
        IF_FAIL_RETURN_TAG(c_monitor.is_supported(e_name), ERR_NOT_SUPPORTED, _I, "Event(%s) is not supported", e_name.c_str());
 
-       if (app_id) {
-               if (!c_monitor.is_allowed(app_id, e_name.c_str())) {
+       if (creator) {
+               if (!c_monitor.is_allowed(creator, e_name.c_str())) {
                        _W("Permission denied for '%s'", e_name.c_str());
                        return ERR_PERMISSION_DENIED;
                }
@@ -402,7 +630,7 @@ int ctx::rule_manager::verify_rule(ctx::json& rule, const char* app_id)
 
                IF_FAIL_RETURN_TAG(c_monitor.is_supported(c_name), ERR_NOT_SUPPORTED, _I, "Condition(%s) is not supported", c_name.c_str());
 
-               if (!c_monitor.is_allowed(app_id, c_name.c_str())) {
+               if (!c_monitor.is_allowed(creator, c_name.c_str())) {
                        _W("Permission denied for '%s'", c_name.c_str());
                        return ERR_PERMISSION_DENIED;
                }
@@ -411,7 +639,7 @@ int ctx::rule_manager::verify_rule(ctx::json& rule, const char* app_id)
        return ERR_NONE;
 }
 
-int ctx::rule_manager::add_rule(std::string creator, ctx::json rule, ctx::json* rule_id)
+int ctx::rule_manager::add_rule(std::string creator, const char* app_id, ctx::json rule, ctx::json* rule_id)
 {
        // * Insert rule to DB
        bool ret;
@@ -422,9 +650,10 @@ int ctx::rule_manager::add_rule(std::string creator, ctx::json rule, ctx::json*
        IF_FAIL_RETURN(err==ERR_NONE, err);
 
        // Check if duplicated rule exits
-       if ((rid = get_duplicated_rule(creator, rule)) > 0) {
+       if ((rid = get_duplicated_rule_id(creator, rule)) > 0) {
                // Save rule id
                rule_id->set(NULL, CT_RULE_ID, rid);
+               _D("Duplicated rule found");
                return ERR_NONE;
        }
 
@@ -435,6 +664,9 @@ int ctx::rule_manager::add_rule(std::string creator, ctx::json rule, ctx::json*
        rule.get(NULL, CT_RULE_DESCRIPTION, &description);
        rule.get(NULL, CT_RULE_DETAILS, &details);
        r_record.set(NULL, "creator", creator);
+       if (app_id) {
+               r_record.set(NULL, "creator_app_id", app_id);
+       }
        r_record.set(NULL, "description", description);
        r_record.set(NULL, "details", details.str());
        ret = db_manager::insert_sync(RULE_TABLE, r_record, &rid);
@@ -504,11 +736,10 @@ int ctx::rule_manager::remove_rule(int rule_id)
        return ERR_NONE;
 }
 
-
 int ctx::rule_manager::enable_rule(int rule_id)
 {
        if (enb_rule_cnt == 0) {
-               initialize_clips();
+               IF_FAIL_RETURN_TAG(initialize_clips(), ERR_OPERATION_FAILED, _E, "Failed to init clips");
        }
 
        // Subscribe event
@@ -516,8 +747,7 @@ int ctx::rule_manager::enable_rule(int rule_id)
        std::string query;
        std::string ename;
        std::string script;
-       std::string r_details;
-       std::string etmpl_str;
+       std::string tmp;
 
        ctx::json jrule;
        ctx::json jetemplate;
@@ -525,7 +755,7 @@ int ctx::rule_manager::enable_rule(int rule_id)
        ctx::json inst_names;
 
        std::vector<json> rule_record;
-       std::vector<json> etemplate_record;
+       std::vector<json> etmpl_record;
        std::vector<json> cond_record;
        std::vector<json> record;
        std::vector<json>::iterator vec_end;
@@ -538,24 +768,26 @@ int ctx::rule_manager::enable_rule(int rule_id)
        error = (db_manager::execute_sync(query.c_str(), &rule_record))? ERR_NONE : ERR_OPERATION_FAILED;
        IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Query rule by rule id failed");
 
-       rule_record[0].get(NULL, "details", &r_details);
-       jrule = r_details;
+       rule_record[0].get(NULL, "details", &tmp);
+       jrule = tmp;
        jrule.get(NULL, CT_RULE_EVENT, &jevent);
 
        // Get event template by rule id
        query = QUERY_EVENT_TEMPLATE_BY_RULE_ID;
        query += int_to_string(rule_id);
        query += ")";
-       error = (db_manager::execute_sync(query.c_str(), &etemplate_record))? ERR_NONE : ERR_OPERATION_FAILED;
+       error = (db_manager::execute_sync(query.c_str(), &etmpl_record))? ERR_NONE : ERR_OPERATION_FAILED;
        IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Query event template by rule id failed");
-       etemplate_record[0].get(NULL, "j_template", &etmpl_str);
-       jetemplate = etmpl_str;
 
-       // Query name, instance name & template for conditions of the rule
-       query = QUERY_NAME_INSTANCE_NAME_AND_TEMPLATE_BY_RULE_ID_STATEMENT;
+       jetemplate = etmpl_record[0].str();
+       convert_str_to_json(&jetemplate, NULL, "attributes");
+       convert_str_to_json(&jetemplate, NULL, "options");
+
+       // Query name, instance name & attributes for conditions of the rule
+       query = QUERY_NAME_INSTANCE_NAME_AND_ATTRIBUTES_BY_RULE_ID_STATEMENT;
        query += id_str;
        error = (db_manager::execute_sync(query.c_str(), &cond_record))? ERR_NONE : ERR_OPERATION_FAILED;
-       IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Query condition's names, instance names, templates by rule id failed");
+       IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Query condition's names, instance names, attributes by rule id failed");
 
        vec_end = cond_record.end();
        for (std::vector<json>::iterator vec_pos = cond_record.begin(); vec_pos != vec_end; ++vec_pos) {
@@ -563,19 +795,16 @@ int ctx::rule_manager::enable_rule(int rule_id)
 
                std::string cname;
                std::string ciname;
-               std::string temp;
                elem.get(NULL, "name", &cname);
                elem.get(NULL, "instance_name", &ciname);
-               elem.get(NULL, "templates", &temp);
-               ctx::json ctemplate = temp;
-               ctemplate.set(NULL, "instance_name", ciname);
+               convert_str_to_json(&elem, NULL, "attributes");
 
                // For defrule script generation
                inst_names.set(NULL, cname.c_str(), ciname);
 
                if (cname.compare(ciname) != 0) {
                        if (!clips_h->find_instance(ciname)) {
-                               std::string makeinst_script = script_generator::generate_makeinstance(&ctemplate);
+                               std::string makeinst_script = script_generator::generate_makeinstance(elem);
                                error = (makeinst_script.length() > 0)? ERR_NONE : ERR_OPERATION_FAILED;
                                IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Make instance script generation failed");
                                error = clips_h->make_instance(makeinst_script);
@@ -594,7 +823,7 @@ int ctx::rule_manager::enable_rule(int rule_id)
        IF_FAIL_CATCH(error == ERR_NONE);
 
        // Generate defrule script and execute it
-       script = script_generator::generate_defrule(id_str, jetemplate, jrule, &inst_names);
+       script = script_generator::generate_defrule(id_str, jetemplate, jrule, inst_names);
        error = clips_h->define_rule(script);
        IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Defrule failed");
 
@@ -621,26 +850,30 @@ CATCH:
 std::string ctx::rule_manager::get_instance_name(std::string name, ctx::json& option)
 {
        std::string inst_name = name;
+       std::vector<json> record_tmpl;
+       ctx::json tmpl_c;
+       std::list<std::string> option_keys;
 
        // Get template for the option
-       std::string q = "SELECT j_template FROM context_trigger_template WHERE name = '";
+       std::string q = "SELECT options FROM context_trigger_template WHERE name = '";
        q += name;
        q += "'";
-       std::vector<json> template_record;
-       db_manager::execute_sync(q.c_str(), &template_record);
+       db_manager::execute_sync(q.c_str(), &record_tmpl);
+
+       convert_str_to_json(&record_tmpl[0], NULL, "options");
+       record_tmpl[0].get(NULL, "options", &tmpl_c);
 
-       std::string ct_str;
-       template_record[0].get(NULL, "j_template", &ct_str);
-       ctx::json j_template = ct_str;
+       tmpl_c.get_keys(&option_keys);
 
-       std::string option_key;
-       for (int i = 0; j_template.get_array_elem(NULL, "option", i, &option_key); i++) {
+       for (std::list<std::string>::iterator it = option_keys.begin(); it != option_keys.end(); ++it) {
+               std::string key = (*it);
                std::string val_str;
                int val;
-               if (option.get(NULL, option_key.c_str(), &val_str)) {
+
+               if (option.get(NULL, key.c_str(), &val_str)) {
                        inst_name += INSTANCE_NAME_DELIMITER;
                        inst_name += val_str;
-               } else if (option.get(NULL, option_key.c_str(), &val)) {
+               } else if (option.get(NULL, key.c_str(), &val)) {
                        inst_name += INSTANCE_NAME_DELIMITER;
                        inst_name += int_to_string(val);
                } else {
@@ -725,19 +958,23 @@ int ctx::rule_manager::disable_rule(int rule_id)
 
 void ctx::rule_manager::make_condition_option_based_on_event_data(ctx::json& ctemplate, ctx::json& edata, ctx::json* coption)
 {
-       std::string option_key;
-       for (int i = 0; ctemplate.get_array_elem(NULL, "option", i, &option_key); i++) {
+       std::list<std::string> option_keys;
+       ctemplate.get_keys(&option_keys);
+
+       for (std::list<std::string>::iterator it = option_keys.begin(); it != option_keys.end(); ++it) {
+               std::string key = (*it);
+
                std::string coption_valstr;
-               if (coption->get(NULL, option_key.c_str(), &coption_valstr)) {
+               if (coption->get(NULL, key.c_str(), &coption_valstr)) {
                        if (coption_valstr.find(EVENT_KEY_PREFIX) == 0) {
                                std::string event_key = coption_valstr.substr(1, coption_valstr.length() - 1);
 
                                std::string e_valstr;
                                int e_val;
                                if (edata.get(NULL, event_key.c_str(), &e_valstr)) {
-                                       coption->set(NULL, option_key.c_str(), e_valstr);
+                                       coption->set(NULL, key.c_str(), e_valstr);
                                } else if (edata.get(NULL, event_key.c_str(), &e_val)) {
-                                       coption->set(NULL, option_key.c_str(), e_val);
+                                       coption->set(NULL, key.c_str(), e_val);
                                }
                        }
                }
@@ -753,14 +990,15 @@ void ctx::rule_manager::on_event_received(std::string item, ctx::json option, ct
        bool ret;
 
        // Generate event fact script
-       std::string q1 = "SELECT j_template FROM context_trigger_template WHERE name = '";
+       std::string q1 = "SELECT attributes, options FROM context_trigger_template WHERE name = '";
        q1 += item;
        q1 += "'";
        std::vector<json> etemplate_record;
        db_manager::execute_sync(q1.c_str(), &etemplate_record);
-       std::string r1;
-       etemplate_record[0].get(NULL, "j_template", &r1);
-       ctx::json etemplate = r1;
+
+       ctx::json etemplate = etemplate_record[0];
+       convert_str_to_json(&etemplate, NULL, "attributes");
+       convert_str_to_json(&etemplate, NULL, "options");
 
        std::string eventfact_str = script_generator::generate_fact(item, etemplate, option, data);
 
@@ -775,9 +1013,8 @@ void ctx::rule_manager::on_event_received(std::string item, ctx::json option, ct
 
        int cond_num = conds.size();
        for (int i = 0; i < cond_num; i++) {
-               std::string temp;
-               conds[i].get(NULL, "j_template", &temp);
-               ctx::json ctemplate = temp;
+               convert_str_to_json(&conds[i], NULL, "options");
+               convert_str_to_json(&conds[i], NULL, "attributes");
 
                std::string cname;
                conds[i].get(NULL, "name", &cname);
@@ -795,7 +1032,7 @@ void ctx::rule_manager::on_event_received(std::string item, ctx::json option, ct
 
                // Check if the condition uses event data key as an option
                if (ciname.find(EVENT_KEY_PREFIX) != std::string::npos) {
-                       make_condition_option_based_on_event_data(ctemplate, data, &coption);
+                       make_condition_option_based_on_event_data(conds[i], data, &coption);    //TODO: conds[i] -> "options"
                }
 
                // TODO: Check permission of a condition(cname), if permission granted, read condition data. (or, condition data should be empty json)
@@ -807,8 +1044,8 @@ void ctx::rule_manager::on_event_received(std::string item, ctx::json option, ct
                        return;
                _D(YELLOW("Condition(%s(%s) - %s)."), cname.c_str(), coption.str().c_str(), condition_data.str().c_str());
 
-               // Generate ModifyInstance script
-               std::string modifyinst_script = script_generator::generate_modifyinstance(ciname, ctemplate, condition_data);
+               // Generate ModifyInstance script       // TODO: conds[i] => "attributes"
+               std::string modifyinst_script = script_generator::generate_modifyinstance(ciname, conds[i], condition_data);
 
                err = clips_h->route_string_command(modifyinst_script);
                IF_FAIL_VOID_TAG(err == ERR_NONE, _E, "Modify condition instance failed");
@@ -825,6 +1062,12 @@ void ctx::rule_manager::on_event_received(std::string item, ctx::json option, ct
        std::string retract_command = "(retract *)";
        err = clips_h->route_string_command(retract_command);
        IF_FAIL_VOID_TAG(err == ERR_NONE, _E, "Retract event fact failed");
+
+       // Clear uninstalled apps' rules if triggered
+       if (uninstalled_apps.size() > 0) {
+               err = clear_rule_of_uninstalled_app();
+               IF_FAIL_VOID_TAG(err == ERR_NONE, _E, "Failed to clear uninstalled apps' rules");
+       }
 }
 
 static void trigger_action_app_control(ctx::json& action)
@@ -857,7 +1100,7 @@ static void trigger_action_app_control(ctx::json& action)
        app_control_destroy(app);
 }
 
-static void trigger_action_notification(ctx::json& action, std::string creator)
+static void trigger_action_notification(ctx::json& action, std::string app_id)
 {
        int error;
        notification_h notification = notification_create(NOTIFICATION_TYPE_NOTI);
@@ -910,9 +1153,11 @@ static void trigger_action_notification(ctx::json& action, std::string creator)
                }
        }
 
-       error = notification_set_pkgname(notification, creator.c_str());
-       if (error != NOTIFICATION_ERROR_NONE) {
-               _E("Set pkgname(%s) failed(%d)", creator.c_str(), error);
+       if (!app_id.empty()) {
+               error = notification_set_pkgname(notification, app_id.c_str());
+               if (error != NOTIFICATION_ERROR_NONE) {
+                       _E("Set pkgname(%s) failed(%d)", app_id.c_str(), error);
+               }
        }
 
        error = notification_post(notification);
@@ -956,14 +1201,27 @@ static void trigger_action_dbus_call(ctx::json& action)
 
 void ctx::rule_manager::on_rule_triggered(int rule_id)
 {
-       _D(YELLOW("Rule%d is triggered"), rule_id);
-
-       std::string q = "SELECT details, creator FROM context_trigger_rule WHERE row_id =";
+       std::string q = "SELECT details, creator_app_id FROM context_trigger_rule WHERE row_id =";
        q += int_to_string(rule_id);
-
        std::vector<json> record;
        db_manager::execute_sync(q.c_str(), &record);
+       if (record.empty()) {
+               _E("Rule%d not exist", rule_id);
+               return;
+       }
+
+       // If rule's creator is uninstalled, skip action
+       std::string app_id;
+       record[0].get(NULL, "creator_app_id", &app_id);
+       if (is_uninstalled_package(app_id)) {
+               _D(YELLOW("Rule%d's creator(%s) is uninstalled. Skip action."), rule_id, app_id.c_str());
+               uninstalled_apps.insert(app_id);
+               return;
+       }
+
+       _D(YELLOW("Rule%d is triggered"), rule_id);
 
+       // Do action
        std::string details_str;
        record[0].get(NULL, "details", &details_str);
        ctx::json details = details_str;
@@ -975,9 +1233,7 @@ void ctx::rule_manager::on_rule_triggered(int rule_id)
                if (type.compare(CT_RULE_ACTION_TYPE_APP_CONTROL) == 0) {
                        trigger_action_app_control(action);
                } else if (type.compare(CT_RULE_ACTION_TYPE_NOTIFICATION) == 0) {
-                       std::string creator;
-                       record[0].get(NULL, "creator", &creator);
-                       trigger_action_notification(action, creator);
+                       trigger_action_notification(action, app_id);
                } else if (type.compare(CT_RULE_ACTION_TYPE_DBUS_CALL) == 0) {
                        trigger_action_dbus_call(action);
                }
index b64a6587352d8ddcd020ac1baa8f7132cfed6f3e..2585a5388e12dd87422a53fba6bb63c61f1c0da6 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef __RULE_MANAGER_H__
 #define __RULE_MANAGER_H__
 
+#include <set>
 #include "clips_handler.h"
 #include "context_monitor.h"
 
@@ -31,7 +32,7 @@ namespace ctx {
                        rule_manager();
                        ~rule_manager();
                        bool init(ctx::context_trigger* tr, ctx::fact_reader* fr);
-                       int add_rule(std::string creator, ctx::json rule, ctx::json* rule_id);
+                       int add_rule(std::string creator, const char* app_id, ctx::json rule, ctx::json* rule_id);
                        int remove_rule(int rule_id);
                        int enable_rule(int rule_id);
                        int disable_rule(int rule_id);
@@ -47,18 +48,24 @@ namespace ctx {
                        clips_handler* clips_h;
                        context_monitor c_monitor;
 
+                       void apply_templates(ctx::fact_reader *fr);
                        bool reenable_rule(void);
                        int verify_rule(ctx::json& rule, const char* app_id);
-                       int64_t get_duplicated_rule(std::string creator, ctx::json& rule);
+                       int64_t get_duplicated_rule_id(std::string creator, ctx::json& rule);
                        bool rule_data_arr_elem_equals(ctx::json& lelem, ctx::json& relem);
                        bool rule_item_equals(ctx::json& litem, ctx::json& ritem);
                        bool rule_equals(ctx::json& lrule, ctx::json& rrule);
                        std::string get_instance_name(std::string name, ctx::json& condition);
                        void make_condition_option_based_on_event_data(ctx::json& ctemplate, ctx::json& edata, ctx::json* coption);
+                       int get_uninstalled_app(void);
+                       bool is_uninstalled_package(std::string app_id);
+                       int clear_rule_of_uninstalled_app(bool is_init = false);
+                       int disable_uninstalled_rule(ctx::json& rule_info);
                        bool initialize_clips(void);
                        void destroy_clips(void);
 
                        std::map<std::string, int> cond_cnt_map; // <condition instance name, count>
+                       std::set<std::string> uninstalled_apps;
    };  /* class rule_manager */
 
 }      /* namespace ctx */
index 7480d188a23a9097b6fe9e5aea00059121928b1f..fd2ee722e14bc21feaa235ee4c7a3bf8aa947bc0 100644 (file)
@@ -29,9 +29,9 @@
 #define CONDITION_WEEKDAY "(or (eq (send [%s] get-DayOfWeek) \"Mon\") (eq (send [%s] get-DayOfWeek) \"Tue\") (eq (send [%s] get-DayOfWeek) \"Wed\") (eq (send [%s] get-DayOfWeek) \"Thu\") (eq (send [%s] get-DayOfWeek) \"Fri\"))"
 #define CONDITION_WEEKEND "(or (eq (send [%s] get-DayOfWeek) \"Sat\") (eq (send [%s] get-DayOfWeek) \"Sun\"))"
 
-static std::string generate_initial_fact(ctx::json event_template, ctx::json option);
-static std::string generate_event_data(ctx::json event);
-static std::string generate_condition_data(std::string rule_id, ctx::json conditions, std::string rule_op, ctx::json* inst_names);
+static std::string generate_initial_fact(ctx::json& event_tmpl, ctx::json& option);
+static std::string generate_event_data(ctx::json& event);
+static std::string generate_condition_data(std::string rule_id, ctx::json& conditions, std::string rule_op, ctx::json& inst_names);
 
 static std::string int_to_string(int i)
 {
@@ -54,23 +54,29 @@ static std::string convert_condition_weekday_weekend(std::string inst_name, std:
        return buf;
 }
 
-std::string ctx::script_generator::generate_deftemplate(ctx::json* item)
+std::string ctx::script_generator::generate_deftemplate(ctx::json& tmpl)
 {
        std::string script;
-
        std::string name;
-       item->get(NULL, "name", &name);
-
+       ctx::json attrs;
+       ctx::json options;
+       std::list<std::string> attr_keys;
+       std::list<std::string> option_keys;
        std::set<std::string> slot;
 
-       std::string opt_name;
-       for (int i = 0; item->get_array_elem(NULL, "option", i, &opt_name); i++) {
-               slot.insert(opt_name);
+       tmpl.get(NULL, "name", &name);
+       tmpl.get(NULL, "attributes", &attrs);
+       tmpl.get(NULL, "options", &options);
+
+       attrs.get_keys(&attr_keys);
+       options.get_keys(&option_keys);
+
+       for (std::list<std::string>::iterator it = attr_keys.begin(); it != attr_keys.end(); ++it) {
+               slot.insert(*it);
        }
 
-       std::string attr_name;
-       for (int i = 0; item->get_array_elem(NULL, "attributes", i, &attr_name); i++) {
-               slot.insert(attr_name);
+       for (std::list<std::string>::iterator it = option_keys.begin(); it != option_keys.end(); ++it) {
+               slot.insert(*it);
        }
 
        //template name is "itemname"
@@ -88,52 +94,54 @@ std::string ctx::script_generator::generate_deftemplate(ctx::json* item)
        return script;
 }
 
-std::string ctx::script_generator::generate_defclass(ctx::json* item)
+std::string ctx::script_generator::generate_defclass(ctx::json& tmpl)
 {
        std::string script;
-
        std::string name;
-       item->get(NULL, "name", &name);
+       ctx::json attrs;
+       std::list<std::string> attr_keys;
+
+       tmpl.get(NULL, "name", &name);
+       tmpl.get(NULL, "attributes", &attrs);
+
+       attrs.get_keys(&attr_keys);
 
        //class name is "C.itemname"
        script = "(defclass C.";
        script += name;
        script += " (is-a USER) (role concrete) ";
 
-       std::string attr_name;
-       for (int i = 0; item->get_array_elem(NULL, "attributes", i, &attr_name); i++) {
-               script += "(slot ";
-               script += attr_name;
-               script += " (default nil)(create-accessor read-write))";
+       for (std::list<std::string>::iterator it = attr_keys.begin(); it != attr_keys.end(); ++it) {
+               script += "(slot " + (*it) + " (default nil)(create-accessor read-write))";
        }
        script += ")\n";
 
        return script;
 }
 
-std::string ctx::script_generator::generate_makeinstance(ctx::json* item)
+std::string ctx::script_generator::generate_makeinstance(ctx::json& tmpl)
 {
        std::string script;
-
        std::string name;
-       item->get(NULL, "name", &name);
+       ctx::json attrs;
+       std::list<std::string> attr_keys;
+
+       tmpl.get(NULL, "name", &name);
+       tmpl.get(NULL, "attributes", &attrs);
+
+       attrs.get_keys(&attr_keys);
 
        std::string instance_name;
-       if (!item->get(NULL, "instance_name", &instance_name)) {
+       if (!tmpl.get(NULL, "instance_name", &instance_name)) {
+               // For default instance w/o option
                instance_name = name;
        }
 
        //instance name is "[itemname]"
-       script = "([";
-       script += instance_name;
-       script += "] of C.";
-       script += name;
+       script = "([" + instance_name + "] of C." + name;
 
-       std::string attr_name;
-       for (int i = 0; item->get_array_elem(NULL, "attributes", i, &attr_name); i++) {
-               script += " (";
-               script += attr_name;
-               script += " 0)";
+       for (std::list<std::string>::iterator it = attr_keys.begin(); it != attr_keys.end(); ++it) {
+               script += " (" + (*it) + " 0)";
        }
        script += ")\n";
 
@@ -150,14 +158,14 @@ std::string ctx::script_generator::generate_undefrule(std::string rule_id)
        return script;
 }
 
-std::string ctx::script_generator::generate_defrule(std::string rule_id, ctx::json event_template, ctx::json rule, ctx::json* inst_names)
+std::string ctx::script_generator::generate_defrule(std::string rule_id, ctx::json& event_tmpl, ctx::json& rule, ctx::json& inst_names)
 {
        std::string script;
        ctx::json option = NULL;
        rule.get(CT_RULE_EVENT, CT_RULE_EVENT_OPTION, &option);
 
        script = "(defrule rule" + rule_id + " ";
-       script += generate_initial_fact(event_template, option);
+       script += generate_initial_fact(event_tmpl, option);
        script += " => ";
 
        int eventdata_num = rule.array_get_size(CT_RULE_EVENT, CT_RULE_DATA_ARR);
@@ -203,21 +211,27 @@ std::string ctx::script_generator::generate_defrule(std::string rule_id, ctx::js
        return script;
 }
 
-std::string generate_initial_fact(ctx::json event_template, ctx::json option)
+std::string generate_initial_fact(ctx::json& event_tmpl, ctx::json& option)
 {
-       std::string script = "(";
+       std::string script;
        std::string e_name;
-       event_template.get(NULL, "name", &e_name);
+       ctx::json attrs;
+       ctx::json options;
+       std::list<std::string> attr_keys;
+       std::list<std::string> option_keys;
 
-       script += e_name;
-       script += " ";
+       event_tmpl.get(NULL, "name", &e_name);
+       event_tmpl.get(NULL, "attributes", &attrs);
+       event_tmpl.get(NULL, "options", &options);
+
+       attrs.get_keys(&attr_keys);
+       options.get_keys(&option_keys);
 
+       script += "(" + e_name + " ";
        // options
-       std::string opt_key;
-       for (int i = 0; event_template.get_array_elem(NULL, "option", i, &opt_key); i++) {
-               script += "(";
-               script += opt_key;
-               script += " ";
+       for (std::list<std::string>::iterator it = option_keys.begin(); it != option_keys.end(); ++it) {
+               std::string opt_key = (*it);
+               script += "(" + opt_key + " ";
 
                std::string val_str;
                int val;
@@ -226,28 +240,22 @@ std::string generate_initial_fact(ctx::json event_template, ctx::json option)
                } else if (option.get(NULL, opt_key.c_str(), &val)) {
                        script += int_to_string(val);
                } else {
-                       script += "?";
-                       script += opt_key;
+                       script += "?" + opt_key;
                }
-
                script += ")";
        }
 
        // attributes
-       std::string attr;
-       for (int i = 0; event_template.get_array_elem(NULL, "attributes", i, &attr); i++) {
-               script += "(";
-               script += attr;
-               script += " ?";
-               script += attr;
-               script += ")";
+       for (std::list<std::string>::iterator it = attr_keys.begin(); it != attr_keys.end(); ++it) {
+               std::string attr_key = (*it);
+               script += "(" + attr_key + " ?" + attr_key + ")";
        }
        script += ")";
 
        return script;
 }
 
-std::string generate_event_data(ctx::json event)
+std::string generate_event_data(ctx::json& event)
 {
        std::string ename;
        event.get(NULL, CT_RULE_EVENT_ITEM, &ename);
@@ -326,7 +334,7 @@ std::string generate_event_data(ctx::json event)
        return script;
 }
 
-std::string generate_condition_data(std::string rule_id, ctx::json conditions, std::string rule_op, ctx::json* inst_names)
+std::string generate_condition_data(std::string rule_id, ctx::json& conditions, std::string rule_op, ctx::json& inst_names)
 {
        std::string script;
 
@@ -346,7 +354,7 @@ std::string generate_condition_data(std::string rule_id, ctx::json conditions, s
                it.get(NULL, CT_RULE_CONDITION_ITEM, &cond_name);
 
                std::string inst_name;
-               (inst_names)->get(NULL, cond_name.c_str(), &inst_name);
+               inst_names.get(NULL, cond_name.c_str(), &inst_name);
 
                int data_count = it.array_get_size(NULL, CT_RULE_DATA_ARR);
 
@@ -422,22 +430,28 @@ std::string generate_condition_data(std::string rule_id, ctx::json conditions, s
        return script;
 }
 
-std::string ctx::script_generator::generate_fact(std::string item_name, ctx::json event_template, ctx::json option, ctx::json data)
+std::string ctx::script_generator::generate_fact(std::string item_name, ctx::json& event_tmpl, ctx::json& option, ctx::json& data)
 {
        // Generate Fact script for invoked event
-       std::string script = "(";
-       script += item_name;
-       script += " ";
+       std::string script = "(" + item_name + " ";
+       ctx::json attrs;
+       ctx::json options;
+       std::list<std::string> attr_keys;
+       std::list<std::string> option_keys;
 
-       std::string opt_key;
-       std::string key;
-       std::string val_str;
-       int value;
+       event_tmpl.get(NULL, "attributes", &attrs);
+       event_tmpl.get(NULL, "options", &options);
+
+       attrs.get_keys(&attr_keys);
+       options.get_keys(&option_keys);
+
+       for (std::list<std::string>::iterator it = option_keys.begin(); it != option_keys.end(); ++it) {
+               std::string opt_key = (*it);
+               std::string val_str;
+               int value;
+
+               script += "(" + opt_key + " ";
 
-       for (int i = 0; event_template.get_array_elem(NULL, "option", i, &opt_key); i++) {
-               script += "(";
-               script += opt_key;
-               script += " ";
                if (option.get(NULL, opt_key.c_str(), &val_str)) {      // string type data
                        script += val_str;
                } else if (option.get(NULL, opt_key.c_str(), &value)) { // integer type data
@@ -448,11 +462,15 @@ std::string ctx::script_generator::generate_fact(std::string item_name, ctx::jso
                script += ")";
        }
 
-       for (int i = 0; event_template.get_array_elem(NULL, "attributes", i, &key); i++) {
-               script += "(" + key + " ";
-               if (data.get(NULL, key.c_str(), &val_str)) {    // string type data
+       for (std::list<std::string>::iterator it = attr_keys.begin(); it != attr_keys.end(); ++it) {
+               std::string attr_key = (*it);
+               std::string val_str;
+               int value;
+
+               script += "(" + attr_key + " ";
+               if (data.get(NULL, attr_key.c_str(), &val_str)) {       // string type data
                        script += "\"" + val_str + "\"";
-               } else if (data.get(NULL, key.c_str(), &value)) {       // integer type data
+               } else if (data.get(NULL, attr_key.c_str(), &value)) {  // integer type data
                        script += int_to_string(value);
                } else {
                        script += "nil";
@@ -464,20 +482,25 @@ std::string ctx::script_generator::generate_fact(std::string item_name, ctx::jso
        return script;
 }
 
-std::string ctx::script_generator::generate_modifyinstance(std::string instance_name, ctx::json condition_template, ctx::json data)
+std::string ctx::script_generator::generate_modifyinstance(std::string instance_name, ctx::json& cond_tmpl, ctx::json& data)
 {
-       std::string script = "(modify-instance [";
-       script += instance_name;
-       script += "] ";
-
-       std::string key;
-       std::string val_str;
-       int value;
-       for (int i = 0; condition_template.get_array_elem(NULL, "attributes", i, &key); i++) {
-               script += "(" + key + " ";
-               if (data.get(NULL, key.c_str(), &val_str)) {    // string type data
+       std::string script = "(modify-instance [" + instance_name + "] ";
+       ctx::json attrs;
+       std::list<std::string> attr_keys;
+
+       cond_tmpl.get(NULL, "attributes", &attrs);
+       attrs.get_keys(&attr_keys);
+
+       // attributes
+       for (std::list<std::string>::iterator it = attr_keys.begin(); it != attr_keys.end(); ++it) {
+               std::string attr_key = (*it);
+               std::string val_str;
+               int value;
+
+               script += "(" + attr_key + " ";
+               if (data.get(NULL, attr_key.c_str(), &val_str)) {       // string type data
                        script += "\"" + val_str + "\"";
-               } else  if (data.get(NULL, key.c_str(), &value)) {      // integer type data
+               } else  if (data.get(NULL, attr_key.c_str(), &value)) { // integer type data
                        script += int_to_string(value);
                } else {
                        script += "nil";
index 3b1a4c637743ada0f075231cf959885b985c20e3..4b2d1acdf93791a71c3be525ac247305cddd0fb6 100644 (file)
@@ -21,13 +21,13 @@ namespace ctx {
 
        namespace script_generator {
 
-               std::string generate_deftemplate(ctx::json* item);
-               std::string generate_defclass(ctx::json* item);
-               std::string generate_makeinstance(ctx::json* item);
+               std::string generate_deftemplate(ctx::json& tmpl);
+               std::string generate_defclass(ctx::json& tmpl);
+               std::string generate_makeinstance(ctx::json& tmpl);
                std::string generate_undefrule(std::string rule_id);
-               std::string generate_defrule(std::string rule_id, ctx::json event_template, ctx::json rule, ctx::json* inst_names);
-               std::string generate_fact(std::string item_name, ctx::json event_template, ctx::json option, ctx::json data);
-               std::string generate_modifyinstance(std::string instance_name, ctx::json condition_template, ctx::json data);
+               std::string generate_defrule(std::string rule_id, ctx::json& event_tmpl, ctx::json& rule, ctx::json& inst_names);
+               std::string generate_fact(std::string item_name, ctx::json& event_tmpl, ctx::json& option, ctx::json& data);
+               std::string generate_modifyinstance(std::string instance_name, ctx::json& cond_tmpl, ctx::json& data);
 
        }
 
index 152af580ac1fdd1999a9fff9045f09cc56b3ed86..33ce780a43f6318a0a67ac8a836baeed131fd36b 100644 (file)
@@ -22,6 +22,7 @@
 #include "timer.h"
 #include "trigger.h"
 #include "timer_types.h"
+#include <context_mgr.h>
 
 #define MAX_HOUR       24
 #define MAX_DAY                7
@@ -37,6 +38,7 @@ ctx::trigger_timer::ref_count_array_s::ref_count_array_s()
 ctx::trigger_timer::trigger_timer(ctx::context_trigger* tr)
        : trigger(tr)
 {
+       submit_trigger_item();
 }
 
 ctx::trigger_timer::~trigger_timer()
@@ -44,6 +46,25 @@ ctx::trigger_timer::~trigger_timer()
        clear();
 }
 
+void ctx::trigger_timer::submit_trigger_item()
+{
+       context_manager::register_trigger_item(TIMER_EVENT_SUBJECT, OPS_SUBSCRIBE,
+                       "{"
+                               "\"TimeOfDay\":{\"type\":\"integer\",\"min\":0,\"max\":1439},"
+                               "\"DayOfWeek\":{\"type\":\"string\",\"values\":[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\",\"Sun\",\"Weekday\",\"Weekend\"]}"
+                       "}",
+                       NULL);
+
+       context_manager::register_trigger_item(TIMER_CONDITION_SUBJECT, OPS_READ,
+                       "{"
+                               "\"TimeOfDay\":{\"type\":\"integer\",\"min\":0,\"max\":1439},"
+                               "\"DayOfWeek\":{\"type\":\"string\",\"values\":[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\",\"Sun\",\"Weekday\",\"Weekend\"]},"
+                               "\"DayOfMonth\":{\"type\":\"integer\",\"min\":1,\"max\":31}"
+                       "}",
+                       NULL);
+
+}
+
 int ctx::trigger_timer::merge_day_of_week(int* ref_cnt)
 {
        int day_of_week = 0;
index 8914bb7ba3f33e835880ccfd1a2b9f63d5cb4d74..9f62927af478c6d191fefc571429755ead98d62c 100644 (file)
@@ -56,6 +56,7 @@ namespace ctx {
        public:
                trigger_timer(ctx::context_trigger *tr);
                ~trigger_timer();
+               static void submit_trigger_item();
 
                bool add(int minute, int day_of_week);
                bool remove(int minute, int day_of_week);
index af03ab85823de9a61864fddbc4da5e2cf81bd345..4dbd268f6a6430290c22649e266fa7713dff735d 100644 (file)
@@ -17,8 +17,8 @@
 #ifndef __CONTEXT_TIMER_TYPES_H__
 #define __CONTEXT_TIMER_TYPES_H__
 
-#define TIMER_EVENT_SUBJECT "timer/event"
-#define TIMER_CONDITION_SUBJECT "timer/state"
+#define TIMER_EVENT_SUBJECT "time/alarm"
+#define TIMER_CONDITION_SUBJECT "time/now"
 
 #define TIMER_RESPONSE_KEY_TIME_OF_DAY "TimeOfDay"
 #define TIMER_RESPONSE_KEY_DAY_OF_WEEK "DayOfWeek"
index c85c4f13d66de0267e6aed79add5bde3321f3b07..8a841516e80f55afe49564881f0d4c2b374e9eb3 100644 (file)
@@ -171,13 +171,15 @@ void ctx::context_trigger::add_rule(ctx::request_info* request)
 {
        ctx::json rule_id;
 
-       const char* app_id = request->get_client();
-       if (app_id == NULL) {
+       const char* client = request->get_client();
+       if (client == NULL) {
                request->reply(ERR_OPERATION_FAILED);
                return;
        }
 
-       int error = rule_mgr->add_rule(app_id, request->get_description(), &rule_id);
+       const char* app_id = request->get_app_id();
+
+       int error = rule_mgr->add_rule(client, app_id, request->get_description(), &rule_id);
        _I("'%s' adds a rule (Error: %#x)", request->get_client(), error);
 
        request->reply(error, rule_id);
index 3dab603034b592afb2dcb4c717e95756fefa8028..1544bca13299f12662996806c1978979f93fef78 100644 (file)
@@ -180,6 +180,7 @@ int main(int argc, char* argv[])
        sigaction(SIGHUP, &signal_action, NULL);
        sigaction(SIGTERM, &signal_action, NULL);
        sigaction(SIGQUIT, &signal_action, NULL);
+       sigaction(SIGABRT, &signal_action, NULL);
 
 #if !defined(GLIB_VERSION_2_36)
        g_type_init();