Remove memory leak
[platform/core/context/context-service.git] / src / trigger / RuleManager.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <sstream>
18 #include <context_trigger_types_internal.h>
19 #include <package_manager.h>
20 #include <Json.h>
21 #include "RuleManager.h"
22 #include "ContextMonitor.h"
23 #include "Rule.h"
24 #include "Timer.h"
25
26 #define RULE_TABLE "context_trigger_rule"
27
28 using namespace ctx;
29 using namespace ctx::trigger;
30
31 static int __stringToInt(std::string str)
32 {
33         int i;
34         std::istringstream convert(str);
35
36         if (!(convert >> i))
37                 i = 0;
38
39         return i;
40 }
41
42 static std::string __intToString(int i)
43 {
44         std::ostringstream convert;
45         convert << i;
46         std::string str = convert.str();
47         return str;
48 }
49
50 RuleManager::RuleManager()
51 {
52 }
53
54 RuleManager::~RuleManager()
55 {
56         // Release rule instances
57         _D("Release rule instances");
58         for (auto it = __ruleMap.begin(); it != __ruleMap.end(); ++it) {
59                 Rule* rule = static_cast<Rule*>(it->second);
60
61                 int error = rule->stop();
62                 if (error != ERR_NONE) {
63                         _E("Failed to stop rule%d", it->first);
64                 }
65
66                 delete rule;
67         }
68         __ruleMap.clear();
69 }
70
71 bool RuleManager::init()
72 {
73         bool ret;
74         int error;
75
76         // Create tables into db (rule, template)
77         std::string q1 = std::string("status INTEGER DEFAULT 0 NOT NULL, creator TEXT DEFAULT '' NOT NULL,")
78                         + "package_id TEXT DEFAULT '' NOT NULL, description TEXT DEFAULT '',"
79                         + "details TEXT DEFAULT '' NOT NULL";
80         ret = __dbManager.createTableSync(RULE_TABLE, q1.c_str(), NULL);
81         IF_FAIL_RETURN_TAG(ret, false, _E, "Create rule table failed");
82
83         // Before re-enable rules, handle uninstalled app's rules
84         if (__getUninstalledApp() > 0) {
85                 error = __clearRuleOfUninstalledPackage(true);
86                 IF_FAIL_RETURN_TAG(error == ERR_NONE, false, _E, "Failed to remove uninstalled apps' rules while initialization");
87         }
88         ret = __reenableRule();
89
90         return ret;
91 }
92
93 void RuleManager::handleRuleOfUninstalledPackage(std::string pkgId)
94 {
95         __uninstalledPackages.insert(pkgId);
96         __clearRuleOfUninstalledPackage();
97 }
98
99 int RuleManager::__getUninstalledApp(void)
100 {
101         // Return number of uninstalled apps
102         std::string q1 = "SELECT DISTINCT package_id FROM context_trigger_rule";
103
104         std::vector<Json> record;
105         bool ret = __dbManager.executeSync(q1.c_str(), &record);
106         IF_FAIL_RETURN_TAG(ret, -1, _E, "Query package ids of registered rules failed");
107
108         std::vector<Json>::iterator vecEnd = record.end();
109         for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
110                 Json elem = *vecPos;
111                 std::string pkgId;
112                 elem.get(NULL, "package_id", &pkgId);
113
114                 if (isUninstalledPackage(pkgId)) {
115                         __uninstalledPackages.insert(pkgId);
116                 }
117         }
118
119         return __uninstalledPackages.size();
120 }
121
122 bool RuleManager::isUninstalledPackage(std::string pkgId)
123 {
124         IF_FAIL_RETURN_TAG(!pkgId.empty(), false, _D, "Empty package id");
125
126         package_info_h pkgInfo;
127         int error = package_manager_get_package_info(pkgId.c_str(), &pkgInfo);
128
129         if (error == PACKAGE_MANAGER_ERROR_NONE) {
130                 package_info_destroy(pkgInfo);
131         } else if (error == PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE) {
132                 // Uninstalled package found
133                 _D("Uninstalled package found: %s", pkgId.c_str());
134                 return true;
135         } else {
136                 _E("Failed to get package info(%s): %d", pkgId.c_str(), error);
137         }
138
139         return false;
140 }
141
142 int RuleManager::__clearRuleOfUninstalledPackage(bool isInit)
143 {
144         if (__uninstalledPackages.size() <= 0) {
145                 return ERR_NONE;
146         }
147
148         int error;
149         bool ret;
150
151         _D("Clear uninstalled packages' rule started");
152         // Package list
153         std::string pkgList = "(";
154         std::set<std::string>::iterator it = __uninstalledPackages.begin();
155         pkgList += "package_id = '" + *it + "'";
156         it++;
157         for (; it != __uninstalledPackages.end(); ++it) {
158                 pkgList += " OR package_id = '" + *it + "'";
159         }
160         pkgList += ")";
161
162         // After event received, disable all the enabled rules of uninstalled apps
163         if (!isInit) {
164                 std::string q1 = "SELECT row_id FROM context_trigger_rule WHERE status = 2 and (";
165                 q1 += pkgList;
166                 q1 += ")";
167
168                 std::vector<Json> record;
169                 ret = __dbManager.executeSync(q1.c_str(), &record);
170                 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query enabled rules of uninstalled packages");
171
172                 std::vector<Json>::iterator vecEnd = record.end();
173                 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
174                         Json elem = *vecPos;
175                         int ruleId;
176                         elem.get(NULL, "row_id", &ruleId);
177                         error = disableRule(ruleId);
178                         IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to disable rule");
179                 }
180                 _D("Uninstalled packages' rules are disabled");
181         }
182
183         // Delete rules of uninstalled packages from DB
184         std::string q2 = "DELETE FROM context_trigger_rule WHERE " + pkgList;
185         std::vector<Json> dummy;
186         ret = __dbManager.executeSync(q2.c_str(), &dummy);
187         IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to remove rules from db");
188         _D("Uninstalled packages' rules are deleted from db");
189
190         __uninstalledPackages.clear();
191
192         return ERR_NONE;
193 }
194
195 int RuleManager::pauseRuleWithItem(std::string& subject)
196 {
197         std::string q = "SELECT row_id FROM context_trigger_rule WHERE (status=2) AND (details LIKE '%\"ITEM_NAME\":\"" + subject + "\"%');";
198         std::vector<Json> record;
199         bool ret = __dbManager.executeSync(q.c_str(), &record);
200         IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query row_ids to be paused");
201         IF_FAIL_RETURN(record.size() > 0, ERR_NONE);
202
203         _D("Pause rules related to %s", subject.c_str());
204         std::vector<Json>::iterator vecEnd = record.end();
205         for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
206                 Json elem = *vecPos;
207                 int rowId;
208                 elem.get(NULL, "row_id", &rowId);
209
210                 int error = pauseRule(rowId);
211                 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to disable rules using custom item");
212         }
213
214         return ERR_NONE;
215 }
216
217 int RuleManager::resumeRuleWithItem(std::string& subject)
218 {
219         std::string q = "SELECT row_id FROM context_trigger_rule WHERE (status=1) AND (details LIKE '%\"ITEM_NAME\":\"" + subject + "\"%');";
220         std::vector<Json> record;
221         bool ret = __dbManager.executeSync(q.c_str(), &record);
222         IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Query paused rule ids failed");
223         IF_FAIL_RETURN(record.size() > 0, ERR_NONE);
224
225         _D("Resume rules related to %s", subject.c_str());
226         std::string qRowId;
227         std::vector<Json>::iterator vecEnd = record.end();
228         for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
229                 Json elem = *vecPos;
230                 int rowId;
231                 elem.get(NULL, "row_id", &rowId);
232
233                 int error = enableRule(rowId);
234                 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to resume rule");
235         }
236
237         return ERR_NONE;
238 }
239
240 bool RuleManager::__reenableRule(void)
241 {
242         int error;
243         std::string q = "SELECT row_id FROM context_trigger_rule WHERE status = 2";
244
245         std::vector<Json> record;
246         bool ret = __dbManager.executeSync(q.c_str(), &record);
247         IF_FAIL_RETURN_TAG(ret, false, _E, "Query row_ids of enabled rules failed");
248         IF_FAIL_RETURN_TAG(record.size() > 0, true, _D, "No rule to re-enable");
249
250         _D(YELLOW("Re-enable rule started"));
251
252         std::string qRowId;
253         qRowId.clear();
254         std::vector<Json>::iterator vecEnd = record.end();
255         for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
256                 Json elem = *vecPos;
257                 int rowId;
258                 elem.get(NULL, "row_id", &rowId);
259
260                 error = enableRule(rowId);
261                 if (error == ERR_NOT_SUPPORTED) {
262                         qRowId += "(row_id = " + __intToString(rowId) + ") OR ";
263                 } else if (error != ERR_NONE) {
264                         _E("Re-enable rule%d failed(%d)", rowId, error);
265                 }
266         }
267         IF_FAIL_RETURN(!qRowId.empty(), true);
268         qRowId = qRowId.substr(0, qRowId.length() - 4);
269
270         // For rules which is failed to re-enable
271         std::string qUpdate = "UPDATE context_trigger_rule SET status = 1 WHERE " + qRowId;
272         std::vector<Json> record2;
273         ret = __dbManager.executeSync(qUpdate.c_str(), &record2);
274         IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to update rules as paused");
275
276         return true;
277 }
278
279 bool RuleManager::__ruleDataArrElemEquals(Json& lElem, Json& rElem)
280 {
281         std::string lKey, rKey;
282         lElem.get(NULL, CT_RULE_DATA_KEY, &lKey);
283         rElem.get(NULL, CT_RULE_DATA_KEY, &rKey);
284         if (lKey.compare(rKey))
285                 return false;
286
287         int lValCnt, rValCnt, lValOpCnt, rValOpCnt;
288         lValCnt = lElem.getSize(NULL, CT_RULE_DATA_VALUE_ARR);
289         rValCnt = rElem.getSize(NULL, CT_RULE_DATA_VALUE_ARR);
290         lValOpCnt = lElem.getSize(NULL, CT_RULE_DATA_VALUE_OPERATOR_ARR);
291         rValOpCnt = rElem.getSize(NULL, CT_RULE_DATA_VALUE_OPERATOR_ARR);
292         if (!((lValCnt == rValCnt) && (lValCnt == lValOpCnt) && (lValCnt && rValOpCnt)))
293                 return false;
294
295         if (lValCnt > 1) {
296                 std::string lOp, rOp;
297                 lElem.get(NULL, CT_RULE_DATA_KEY_OPERATOR, &lOp);
298                 rElem.get(NULL, CT_RULE_DATA_KEY_OPERATOR, &rOp);
299                 if (lOp.compare(rOp))
300                         return false;
301         }
302
303         for (int i = 0; i < lValCnt; i++) {
304                 bool found = false;
305                 std::string lVal, lValOp;
306                 lElem.getAt(NULL, CT_RULE_DATA_VALUE_ARR, i, &lVal);
307                 lElem.getAt(NULL, CT_RULE_DATA_VALUE_OPERATOR_ARR, i, &lValOp);
308
309                 for (int j = 0; j < lValCnt; j++) {
310                         std::string rVal, rValOp;
311                         rElem.getAt(NULL, CT_RULE_DATA_VALUE_ARR, j, &rVal);
312                         rElem.getAt(NULL, CT_RULE_DATA_VALUE_OPERATOR_ARR, j, &rValOp);
313
314                         if (!lVal.compare(rVal) && !lValOp.compare(rValOp)) {
315                                 found = true;
316                                 break;
317                         }
318                 }
319                 if (!found)
320                         return false;
321         }
322
323         return true;
324 }
325
326 bool RuleManager::__ruleItemEquals(Json& lItem, Json& rItem)
327 {
328         // Compare item name
329         std::string lItemName, rItemName;
330         lItem.get(NULL, CT_RULE_EVENT_ITEM, &lItemName);
331         rItem.get(NULL, CT_RULE_EVENT_ITEM, &rItemName);
332         if (lItemName.compare(rItemName))
333                 return false;
334
335         // Compare option
336         Json lOption, rOption;
337         lItem.get(NULL, CT_RULE_EVENT_OPTION, &lOption);
338         rItem.get(NULL, CT_RULE_EVENT_OPTION, &rOption);
339         if (lOption != rOption)
340                 return false;
341
342         int lDataArrCnt, rDataArrCnt;
343         lDataArrCnt = lItem.getSize(NULL, CT_RULE_DATA_ARR);
344         rDataArrCnt = rItem.getSize(NULL, CT_RULE_DATA_ARR);
345         if (lDataArrCnt != rDataArrCnt)
346                 return false;
347
348         // Compare item operator;
349         if (lDataArrCnt > 1) {
350                 std::string lOp, rOp;
351                 lItem.get(NULL, CT_RULE_EVENT_OPERATOR, &lOp);
352                 rItem.get(NULL, CT_RULE_EVENT_OPERATOR, &rOp);
353                 if (lOp.compare(rOp))
354                         return false;
355         }
356
357         for (int i = 0; i < lDataArrCnt; i++) {
358                 bool found = false;
359                 Json lElem;
360                 lItem.getAt(NULL, CT_RULE_DATA_ARR, i, &lElem);
361
362                 for (int j = 0; j < lDataArrCnt; j++) {
363                         Json rElem;
364                         rItem.getAt(NULL, CT_RULE_DATA_ARR, j, &rElem);
365
366                         if (__ruleDataArrElemEquals(lElem, rElem)) {
367                                 found = true;
368                                 break;
369                         }
370                 }
371                 if (!found)
372                         return false;
373         }
374
375         return true;
376 }
377
378 bool RuleManager::__ruleEquals(Json& lRule, Json& rRule)
379 {
380         // Compare event
381         Json lEvent, rEvent;
382         lRule.get(NULL, CT_RULE_EVENT, &lEvent);
383         rRule.get(NULL, CT_RULE_EVENT, &rEvent);
384         if (!__ruleItemEquals(lEvent, rEvent))
385                 return false;
386
387         // Compare conditions
388         int lCondCnt, rCondCnt;
389         lCondCnt = lRule.getSize(NULL, CT_RULE_CONDITION);
390         rCondCnt = rRule.getSize(NULL, CT_RULE_CONDITION);
391         if (lCondCnt != rCondCnt)
392                 return false;
393
394         if (lCondCnt > 1) {
395                 std::string lOp, rOp;
396                 lRule.get(NULL, CT_RULE_OPERATOR, &lOp);
397                 rRule.get(NULL, CT_RULE_OPERATOR, &rOp);
398                 if (lOp.compare(rOp))
399                         return false;
400         }
401
402         for (int i = 0; i < lCondCnt; i++) {
403                 bool found = false;
404                 Json lCond;
405                 lRule.getAt(NULL, CT_RULE_CONDITION, i, &lCond);
406
407                 for (int j = 0; j < lCondCnt; j++) {
408                         Json rCond;
409                         rRule.getAt(NULL, CT_RULE_CONDITION, j, &rCond);
410
411                         if (__ruleItemEquals(lCond, rCond)) {
412                                 found = true;
413                                 break;
414                         }
415                 }
416                 if (!found)
417                         return false;
418         }
419
420         // Compare action
421         Json lAction, rAction;
422         lRule.get(NULL, CT_RULE_ACTION, &lAction);
423         rRule.get(NULL, CT_RULE_ACTION, &rAction);
424         if (lAction != rAction)
425                 return false;
426
427         return true;
428 }
429
430 int64_t RuleManager::__getDuplicatedRuleId(std::string pkgId, Json& rule)
431 {
432         std::string q = "SELECT row_id, description, details FROM context_trigger_rule WHERE package_id = '";
433         q += pkgId;
434         q += "'";
435
436         std::vector<Json> record;
437         bool ret = __dbManager.executeSync(q.c_str(), &record);
438         IF_FAIL_RETURN_TAG(ret, false, _E, "Query row_id, details by package id failed");
439
440         Json rDetails;
441         rule.get(NULL, CT_RULE_DETAILS, &rDetails);
442         std::string rDesc;
443         rule.get(NULL, CT_RULE_DESCRIPTION, &rDesc);
444         std::vector<Json>::iterator vecEnd = record.end();
445
446         for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
447                 Json elem = *vecPos;
448                 std::string dStr;
449                 Json details;
450
451                 elem.get(NULL, "details", &dStr);
452                 details = dStr;
453
454                 if (__ruleEquals(rDetails, details)) {
455                         int64_t rowId;
456                         elem.get(NULL, "row_id", &rowId);
457
458                         // Description comparison
459                         std::string desc;
460                         elem.get(NULL, "description", &desc);
461                         if (rDesc.compare(desc)) {
462                                 // Only description is changed
463                                 std::string qUpdate = "UPDATE context_trigger_rule SET description='" + rDesc + "' WHERE row_id = " + __intToString(rowId);
464
465                                 std::vector<Json> dummy;
466                                 ret = __dbManager.executeSync(qUpdate.c_str(), &dummy);
467                                 if (ret) {
468                                         _D("Rule%lld description is updated", rowId);
469                                 } else {
470                                         _W("Failed to update description of rule%lld", rowId);
471                                 }
472                         }
473
474                         return rowId;
475                 }
476         }
477
478         return -1;
479 }
480
481 int RuleManager::__verifyRule(Json& rule, const char* creator)
482 {
483         Json details;
484         rule.get(NULL, CT_RULE_DETAILS, &details);
485
486         std::string eventName;
487         rule.get(CT_RULE_DETAILS "." CT_RULE_EVENT, CT_RULE_EVENT_ITEM, &eventName);
488
489         ContextMonitor* ctxMonitor = ContextMonitor::getInstance();
490         IF_FAIL_RETURN_TAG(ctxMonitor, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
491
492         IF_FAIL_RETURN_TAG(ctxMonitor->isSupported(eventName), ERR_NOT_SUPPORTED, _I, "Event(%s) is not supported", eventName.c_str());
493
494         if (creator) {
495                 if (!ctxMonitor->isAllowed(creator, eventName.c_str())) {
496                         _W("Permission denied for '%s'", eventName.c_str());
497                         return ERR_PERMISSION_DENIED;
498                 }
499         }
500
501         Json it;
502         for (int i = 0; rule.getAt(CT_RULE_DETAILS, CT_RULE_CONDITION, i, &it); i++) {
503                 std::string condName;
504                 it.get(NULL, CT_RULE_CONDITION_ITEM, &condName);
505
506                 IF_FAIL_RETURN_TAG(ctxMonitor->isSupported(condName), ERR_NOT_SUPPORTED, _I, "Condition(%s) is not supported", condName.c_str());
507
508                 if (!ctxMonitor->isAllowed(creator, condName.c_str())) {
509                         _W("Permission denied for '%s'", condName.c_str());
510                         return ERR_PERMISSION_DENIED;
511                 }
512         }
513
514         return ERR_NONE;
515 }
516
517 int RuleManager::addRule(std::string creator, const char* pkgId, Json rule, Json* ruleId)
518 {
519         bool ret;
520         int64_t rid;
521
522         // Check if all items are supported && allowed to access
523         int err = __verifyRule(rule, creator.c_str());
524         IF_FAIL_RETURN(err == ERR_NONE, err);
525
526         // Check if duplicated rule exits
527         if ((rid = __getDuplicatedRuleId(pkgId, rule)) > 0) {
528                 // Save rule id
529                 ruleId->set(NULL, CT_RULE_ID, rid);
530                 _D("Duplicated rule found");
531                 return ERR_NONE;
532         }
533
534         // Insert rule to rule table, get rule id
535         Json record;
536         std::string description;
537         Json details;
538         rule.get(NULL, CT_RULE_DESCRIPTION, &description);
539         rule.get(NULL, CT_RULE_DETAILS, &details);
540         record.set(NULL, "creator", creator);
541         if (pkgId) {
542                 record.set(NULL, "package_id", pkgId);
543         }
544         record.set(NULL, "description", description);
545
546         // Handle timer event
547         trigger::timer::handleTimerEvent(details);
548
549         record.set(NULL, "details", details.str());
550         ret = __dbManager.insertSync(RULE_TABLE, record, &rid);
551         IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Insert rule to db failed");
552
553         // Save rule id
554         ruleId->set(NULL, CT_RULE_ID, rid);
555
556         _D("Add rule%d succeeded", (int)rid);
557         return ERR_NONE;
558 }
559
560
561 int RuleManager::removeRule(int ruleId)
562 {
563         bool ret;
564
565         // Delete rule from DB
566         std::string query = "DELETE FROM 'context_trigger_rule' where row_id = ";
567         query += __intToString(ruleId);
568
569         std::vector<Json> record;
570         ret = __dbManager.executeSync(query.c_str(), &record);
571         IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Remove rule from db failed");
572
573         _D("Remove rule%d succeeded", ruleId);
574
575         return ERR_NONE;
576 }
577
578 int RuleManager::enableRule(int ruleId)
579 {
580         int error;
581         std::string query;
582         std::vector<Json> record;
583         std::vector<Json> dummy;
584         std::string pkgId;
585         Json jRule;
586         std::string tmp;
587         std::string idStr = __intToString(ruleId);
588
589         Rule* rule;
590
591         // Get rule Json by rule id;
592         query = "SELECT details, package_id FROM context_trigger_rule WHERE row_id = ";
593         query += idStr;
594         error = (__dbManager.executeSync(query.c_str(), &record))? ERR_NONE : ERR_OPERATION_FAILED;
595         IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Query rule by rule id failed");
596
597         record[0].get(NULL, "details", &tmp);
598         jRule = tmp;
599         record[0].get(NULL, "package_id", &pkgId);
600
601         // Create a rule instance
602         rule = new(std::nothrow) Rule(ruleId, jRule, pkgId.c_str(), this);
603         IF_FAIL_RETURN_TAG(rule, ERR_OUT_OF_MEMORY, _E, "Failed to create rule instance");
604
605         // Start the rule
606         error = rule->start();
607         IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Failed to start rule%d", ruleId);
608
609         // Update db to set 'enabled'
610         query = "UPDATE context_trigger_rule SET status = 2 WHERE row_id = ";
611         query += idStr;
612         error = (__dbManager.executeSync(query.c_str(), &dummy))? ERR_NONE : ERR_OPERATION_FAILED;
613         IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Update db failed");
614
615         // Add rule instance to __ruleMap
616         __ruleMap[ruleId] = rule;
617
618         _D(YELLOW("Enable Rule%d succeeded"), ruleId);
619         return ERR_NONE;
620
621 CATCH:
622         delete rule;
623         rule = NULL;
624
625         return error;
626 }
627
628 int RuleManager::disableRule(int ruleId)
629 {
630         bool ret;
631         int error;
632
633         auto it = __ruleMap.find(ruleId);
634         bool paused = (it == __ruleMap.end());
635
636         // For 'enabled' rule, not 'paused'
637         if (!paused) {
638                 // Stop the rule
639                 Rule* rule = static_cast<Rule*>(it->second);
640                 error = rule->stop();
641                 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to stop rule%d", ruleId);
642
643                 // Remove rule instance from __ruleMap
644                 delete rule;
645                 __ruleMap.erase(it);
646         }
647
648         // Update db to set 'disabled'  // TODO skip while clear uninstalled rule
649         std::string query = "UPDATE context_trigger_rule SET status = 0 WHERE row_id = ";
650         query += __intToString(ruleId);
651         std::vector<Json> record;
652         ret = __dbManager.executeSync(query.c_str(), &record);
653         IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Update db failed");
654
655         _D(YELLOW("Disable Rule%d succeeded"), ruleId);
656         return ERR_NONE;
657 }
658
659 int RuleManager::pauseRule(int ruleId)
660 {
661         bool ret;
662         int error;
663
664         auto it = __ruleMap.find(ruleId);
665         IF_FAIL_RETURN_TAG(it != __ruleMap.end(), ERR_OPERATION_FAILED, _E, "Rule instance not found");
666
667         // Stop the rule
668         Rule* rule = static_cast<Rule*>(it->second);
669         error = rule->stop();
670         IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to stop rule%d", ruleId);
671
672         // Update db to set 'paused'
673         std::string query = "UPDATE context_trigger_rule SET status = 1 WHERE row_id = ";
674
675         query += __intToString(ruleId);
676         std::vector<Json> record;
677         ret = __dbManager.executeSync(query.c_str(), &record);
678         IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Update db failed");
679
680         // Remove rule instance from __ruleMap
681         delete rule;
682         __ruleMap.erase(it);
683
684         _D(YELLOW("Pause Rule%d"), ruleId);
685         return ERR_NONE;
686 }
687
688 int RuleManager::checkRule(std::string pkgId, int ruleId)
689 {
690         // Get package id
691         std::string q = "SELECT package_id FROM context_trigger_rule WHERE row_id =";
692         q += __intToString(ruleId);
693
694         std::vector<Json> record;
695         bool ret = __dbManager.executeSync(q.c_str(), &record);
696         IF_FAIL_RETURN_TAG(ret, false, _E, "Query package id by rule id failed");
697
698         if (record.size() == 0) {
699                 return ERR_NO_DATA;
700         }
701
702         std::string p;
703         record[0].get(NULL, "package_id", &p);
704
705         if (p.compare(pkgId) == 0) {
706                 return ERR_NONE;
707         }
708
709         return ERR_NO_DATA;
710 }
711
712 bool RuleManager::isRuleEnabled(int ruleId)
713 {
714         std::string q = "SELECT status FROM context_trigger_rule WHERE row_id =";
715         q += __intToString(ruleId);
716
717         std::vector<Json> record;
718         bool ret = __dbManager.executeSync(q.c_str(), &record);
719         IF_FAIL_RETURN_TAG(ret, false, _E, "Query enabled by rule id failed");
720
721         int status;
722         record[0].get(NULL, "status", &status);
723
724         return (status != 0);
725 }
726
727 int RuleManager::getRuleById(std::string pkgId, int ruleId, Json* requestResult)
728 {
729         std::string q = "SELECT description FROM context_trigger_rule WHERE (package_id = '";
730         q += pkgId;
731         q += "') and (row_id = ";
732         q += __intToString(ruleId);
733         q += ")";
734
735         std::vector<Json> record;
736         bool ret = __dbManager.executeSync(q.c_str(), &record);
737         IF_FAIL_RETURN_TAG(ret, false, _E, "Query rule by rule id failed");
738
739         if (record.size() == 0) {
740                 return ERR_NO_DATA;
741         } else if (record.size() != 1) {
742                 return ERR_OPERATION_FAILED;
743         }
744
745         std::string description;
746         record[0].get(NULL, "description", &description);
747
748         (*requestResult).set(NULL, CT_RULE_ID, ruleId);
749         (*requestResult).set(NULL, CT_RULE_DESCRIPTION, description);
750
751         return ERR_NONE;
752 }
753
754 int RuleManager::getRuleIds(std::string pkgId, Json* requestResult)
755 {
756         (*requestResult) = "{ \"" CT_RULE_ARRAY_ENABLED "\" : [ ] , \"" CT_RULE_ARRAY_DISABLED "\" : [ ] }";
757
758         std::string q = "SELECT row_id, status FROM context_trigger_rule WHERE (package_id = '";
759         q += pkgId;
760         q += "')";
761
762         std::vector<Json> record;
763         bool ret = __dbManager.executeSync(q.c_str(), &record);
764         IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Query rules failed");
765
766         std::vector<Json>::iterator vecEnd = record.end();
767         for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
768                 Json elem = *vecPos;
769                 std::string id;
770                 int status;
771
772                 elem.get(NULL, "row_id", &id);
773                 elem.get(NULL, "status", &status);
774
775                 if (status >= 1) {
776                         (*requestResult).append(NULL, CT_RULE_ARRAY_ENABLED, __stringToInt(id));
777                 } else if (status == 0) {
778                         (*requestResult).append(NULL, CT_RULE_ARRAY_DISABLED, __stringToInt(id));
779                 }
780         }
781
782         return ERR_NONE;
783 }