052c3fe83e1b28686272593e5d431e49d75eb712
[platform/core/context/context-provider.git] / src / app-stats / app_inactive_detector / InactiveDetectorStorage.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 <ctime>
19 #include <string>
20 #include <memory>
21 #include <Types.h>
22 #include "InactiveDetector.h"
23 #include "InactiveDetectorStorage.h"
24 #include "InactiveDetectorStorageQueries.h"
25 #include "InactiveDetectorClassificator.h"
26 #include "AppInactiveDetectorTypes.h"
27
28 /*int ctx::inactive_detector_storage::create_table()
29 {
30         bool ret = __dbManager.createTable(0, WIFI_TABLE_NAME, WIFI_CREATE_TABLE_COLUMNS, NULL, NULL);
31         _D("Table Creation Request: %s", ret ? "SUCCESS" : "FAIL");
32         return ret;
33 }*/
34
35
36
37 // expected Json format example: {timeframe: 1; is_active: 0}
38 int ctx::inactive_detector_storage::read(
39                         const char *subject,
40                         ctx::Json filter)
41 {
42         std::string query;
43         query = query_get_apps(subject, filter);
44
45         IF_FAIL_RETURN(!query.empty(), ERR_OPERATION_FAILED);
46
47         bool ret = __dbManager.execute(
48                 STR_EQ(subject, APP_INACTIVE_SUBJ_GET_APPS_INACTIVE) ?
49                         APP_INACTIVE_QUERY_ID_GET_APPS_INACTIVE :
50                         APP_INACTIVE_QUERY_ID_GET_APPS_ACTIVE,
51                 query.c_str(),
52                 this);
53
54         IF_FAIL_RETURN(ret, ERR_OPERATION_FAILED);
55
56         return ERR_NONE;
57 }
58
59 std::string ctx::inactive_detector_storage::query_get_apps(const char *subject, ctx::Json filter)
60 {
61         double timeframe;
62         int is_active;
63
64         std::string query(GET_APP_INFO_INACTIVE_QUERY);
65         std::string placeholder_timeframe(APP_INACTIVE_DETECTOR_VALUE_PLACEHOLDER_TIMEFRAME);
66         std::string placeholder_is_active(APP_INACTIVE_DETECTOR_VALUE_PLACEHOLDER_CLUSTER);
67
68         filter.get(NULL, APP_INACTIVE_DETECTOR_DATA_TIMEFRAME, &timeframe);
69         filter.get(NULL, APP_INACTIVE_DETECTOR_DATA_ISACTIVE, &is_active);
70
71         std::stringstream timeframe_stream;
72         timeframe_stream << timeframe;
73
74         std::stringstream is_active_stream;
75         is_active_stream << is_active;
76
77         inject_params(query, placeholder_timeframe, timeframe_stream.str());
78         inject_params(query, placeholder_is_active, is_active_stream.str());
79
80         return query;
81 }
82
83 std::string ctx::inactive_detector_storage::query_update_apps(std::vector<app_t> *apps_with_weights)
84 {
85         std::string delete_query(DELETE_APP_ACTIVITY_CLASSIFIED_BY_TIMEFRAME);
86         std::string insert_query(INSERT_APP_ACTIVITY_CLASSIFIED);
87         std::string placeholder_timeframe(APP_INACTIVE_DETECTOR_VALUE_PLACEHOLDER_TIMEFRAME);
88         std::string placeholder_values(APP_INACTIVE_DETECTOR_VALUE_PLACEHOLDER_VALUES);
89         std::string placeholder_is_active(APP_INACTIVE_DETECTOR_VALUE_PLACEHOLDER_CLUSTER);
90
91         std::stringstream timeframe_stream;
92         timeframe_stream << apps_with_weights->front().timeframe;
93
94         inject_params(delete_query, placeholder_timeframe, timeframe_stream.str());
95         inject_params(insert_query, placeholder_values, subquery_form_values(apps_with_weights));
96
97         std::stringstream result;
98         result << delete_query << insert_query;
99         return result.str();
100 }
101
102 // foreach app_info id+cluster -> select for insert
103 std::string ctx::inactive_detector_storage::subquery_form_values(std::vector<app_t> *apps_with_weights)
104 {
105         std::stringstream select_elements;
106
107         for(std::vector<app_t>::iterator row = apps_with_weights->begin();
108                         row != apps_with_weights->end(); row++)
109         {
110                 //SELECT 1 as is_active, 1 as timeframe,  3964 as context_app_info_id
111                 std::stringstream select_element;
112                 select_element << " SELECT " << row->is_active << " as ";
113                 select_element << APP_INACTIVE_DETECTOR_ACTIVITYCLASSIFIED_COLUMN_IS_ACTIVE;
114                 select_element << ", " << row->timeframe << " as ";
115                 select_element << APP_INACTIVE_DETECTOR_ACTIVITYCLASSIFIED_COLUMN_TIMEFRAME;
116                 select_element << ", " << row->id << " as ";
117                 select_element << APP_INACTIVE_DETECTOR_ACTIVITYCLASSIFIED_COLUMN_CONTEXT_APP_INFO_ID;
118
119                 if ((row != apps_with_weights->end()) && (row == --apps_with_weights->end()))
120                         select_element << " UNION ";
121
122                 select_elements << select_element;
123         }
124
125         return select_elements.str();
126 }
127
128 void ctx::inactive_detector_storage::json_to_object(std::vector<Json>& records,
129         std::vector<app_t> *apps_with_weights, bool result_mode)
130 {
131         for(std::vector<Json>::iterator row = records.begin();
132                 row != records.end(); row++)
133         {
134                 app_t app_with_weight;
135                 if (result_mode)
136                 {
137                         row->get(NULL, APP_INACTIVE_DETECTOR_APPINFO_COLUMN_PACKAGE_NAME,
138                                 &app_with_weight.package_name);
139                         row->get(NULL, APP_INACTIVE_DETECTOR_APPINFO_COLUMN_IS_NODISPLAY,
140                                 &app_with_weight.is_nodisplay);
141                         row->get(NULL, APP_INACTIVE_DETECTOR_APPINFO_COLUMN_IS_ENABLED,
142                                 &app_with_weight.is_enabled);
143                         row->get(NULL, APP_INACTIVE_DETECTOR_APPINFO_COLUMN_IS_ATBOOT,
144                                 &app_with_weight.is_atboot);
145                         row->get(NULL, APP_INACTIVE_DETECTOR_APPINFO_COLUMN_IS_PRELOADED,
146                                 &app_with_weight.is_preloaded);
147                         row->get(NULL, APP_INACTIVE_DETECTOR_VIRTUAL_COLUMN_WEIGHT,
148                                 &app_with_weight.weight);
149                 }
150                 else
151                 {
152                         row->get(NULL, APP_INACTIVE_DETECTOR_APPINFO_COLUMN_ID,
153                                 &app_with_weight.id);
154                         row->get(NULL, APP_INACTIVE_DETECTOR_APPINFO_COLUMN_TIMESTAMP,
155                                 &app_with_weight.timestamp);
156                         row->get(NULL, APP_INACTIVE_DETECTOR_VIRTUAL_COLUMN_WEIGHT,
157                                 &app_with_weight.weight);
158                         row->get(NULL, APP_INACTIVE_DETECTOR_ACTIVITYCLASSIFIED_COLUMN_IS_ACTIVE,
159                                 &app_with_weight.is_active);
160                 }
161
162                 apps_with_weights->push_back(app_with_weight);
163         }
164 }
165
166 void ctx::inactive_detector_storage::onExecuted(unsigned int query_id,
167         int error,
168         std::vector<Json>& records)
169 {
170         if (error != ERR_NONE) {
171                 _E("query_id:%d, error:%d", query_id, error);
172                 return;
173         }
174
175         std::vector<app_t> *apps_with_weights = NULL;
176         if (query_id == APP_INACTIVE_QUERY_ID_GET_APPS_INACTIVE ||
177                 query_id == APP_INACTIVE_QUERY_ID_GET_APPS_ACTIVE)
178         {
179                 json_to_object(records, apps_with_weights, TRUE);
180         }
181         else if (query_id == APP_INACTIVE_QUERY_ID_GET_APPS_WEIGHT) {
182
183                 json_to_object(records, apps_with_weights, FALSE);
184
185                 if (apps_with_weights->size() > 0) {
186                         inactive_detector_classificator i_detector_classificator;
187                         int _error = i_detector_classificator.classify(apps_with_weights);
188
189                         if(_error == ERR_NONE)
190                         {
191                                 std::string query;
192                                 query = query_update_apps(apps_with_weights);
193                                 bool ret = __dbManager.execute(APP_INACTIVE_QUERY_ID_UPDATE_CLUSTERS,
194                                         query.c_str(),
195                                         this);
196                                 _D("load visits execute query result: %s", ret ? "SUCCESS" : "FAIL");
197                         }
198                         else
199                         {
200                                 _E("classification query_id:%d, error:%d",
201                                         query_id, _error);
202                         }
203                 }
204         }
205         else if (query_id == APP_INACTIVE_QUERY_ID_UPDATE_CLUSTERS) {
206                 _D("UPDATE_CLUSTERS execute query id: %d", query_id);
207         }
208         else {
209                 _E("unknown query_id:%d", query_id);
210         }
211 }
212
213 void ctx::inactive_detector_storage::inject_params(std::string& str, const std::string& from, const std::string& to)
214 {
215         if(from.empty())
216                 return;
217         size_t start_pos = 0;
218         while((start_pos = str.find(from, start_pos)) != std::string::npos) {
219                 str.replace(start_pos, from.length(), to);
220                 start_pos += to.length();
221         }
222 }
223
224 // normalzie weights
225 int ctx::inactive_detector_storage::update_ranks()
226 {
227         return ERR_NONE;
228 }
229
230 int ctx::inactive_detector_storage::get_apps_info_w_weights(
231                 double timestamp_from)
232 {
233         std::stringstream timestamp_stream;
234         timestamp_stream << timestamp_from;
235         std::string timestamp_str = timestamp_stream.str();
236
237         std::string query(GET_APP_INFO_W_WEIGHT_QUERY);
238         std::string placeholder(APP_INACTIVE_DETECTOR_VALUE_PLACEHOLDER_TIMESTAMP);
239
240         inject_params(query, placeholder, timestamp_str);
241
242         bool ret = __dbManager.execute(APP_INACTIVE_QUERY_ID_GET_APPS_WEIGHT,
243                 query.c_str(),
244                 this);
245         _D("load visits execute query result: %s", ret ? "SUCCESS" : "FAIL");
246
247         return ERR_NONE ;
248 }