Tizen 2.1 base
[platform/core/appfw/ail.git] / src / ail_filter.c
1 /*
2  * ail
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23
24 #include <stdlib.h>
25 #include <glib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include "ail.h"
29 #include "ail_private.h"
30 #include "ail_convert.h"
31 #include "ail_sql.h"
32 #include "ail_package.h"
33 #include "ail_db.h"
34
35 char *_get_where_clause(ail_filter_h filter);
36
37 struct ail_filter {
38         GSList *list;
39 };
40
41 static inline void _add_cond_to_filter(ail_filter_h filter, struct element *cond)
42 {
43         filter->list = g_slist_append(filter->list, cond);
44 }
45
46 EXPORT_API ail_error_e ail_filter_new(ail_filter_h *filter)
47 {
48         struct ail_filter *f;
49
50         retv_if (NULL == filter, AIL_ERROR_INVALID_PARAMETER);
51
52         f = (struct ail_filter *)calloc(1, sizeof(struct ail_filter));
53         retv_if (NULL == f, AIL_ERROR_OUT_OF_MEMORY);
54
55         *filter = f;
56
57         return AIL_ERROR_OK;
58 }
59
60 static inline void _destroy_cond(gpointer data, gpointer user_data)
61 {
62         if (!data)
63                 return;
64
65         struct element *cond;
66         cond  = (struct element *)data;
67
68         int t;
69         ELEMENT_TYPE(cond, t);
70         if (VAL_TYPE_STR == t) {
71                 if(ELEMENT_STR(cond)->value)
72                         free(ELEMENT_STR(cond)->value);
73         }
74         free(cond);
75         return;
76 }
77
78
79 EXPORT_API ail_error_e ail_filter_destroy(ail_filter_h filter)
80 {
81         retv_if (NULL == filter, AIL_ERROR_INVALID_PARAMETER);
82
83         if (filter->list){
84                 g_slist_foreach(filter->list, _destroy_cond, NULL);
85                 g_slist_free(filter->list);
86         }
87
88         free(filter);
89
90         return AIL_ERROR_OK;
91 }
92
93 EXPORT_API ail_error_e ail_filter_add_bool(ail_filter_h filter, const char *property, bool value)
94 {
95         struct element *c;
96         ail_prop_bool_e prop;
97
98         retv_if (NULL == filter, AIL_ERROR_INVALID_PARAMETER);
99         retv_if (NULL == property, AIL_ERROR_INVALID_PARAMETER);
100
101         prop = _ail_convert_to_prop_bool(property);
102
103         if (prop < E_AIL_PROP_BOOL_MIN || prop > E_AIL_PROP_BOOL_MAX)
104                 return AIL_ERROR_INVALID_PARAMETER;
105
106         c = (struct element *)calloc(1, sizeof(struct element_bool));
107         retv_if (NULL == c, AIL_ERROR_OUT_OF_MEMORY);
108
109         ELEMENT_BOOL(c)->prop = (int)prop;
110         ELEMENT_BOOL(c)->value = value;
111
112         _add_cond_to_filter(filter, c);
113
114         return AIL_ERROR_OK;
115 }
116
117 EXPORT_API ail_error_e ail_filter_add_int(ail_filter_h filter, const char *property, int value)
118 {
119         struct element *c;
120         ail_prop_int_e prop;
121
122         retv_if (NULL == filter, AIL_ERROR_INVALID_PARAMETER);
123         retv_if (NULL == property, AIL_ERROR_INVALID_PARAMETER);
124
125         prop = _ail_convert_to_prop_int(property);
126
127         if (prop < E_AIL_PROP_INT_MIN || prop > E_AIL_PROP_INT_MAX)
128                 return AIL_ERROR_INVALID_PARAMETER;
129
130         c = (struct element *)calloc(1, sizeof(struct element_int));
131         retv_if (NULL == c, AIL_ERROR_OUT_OF_MEMORY);
132
133         ELEMENT_INT(c)->prop = (int)prop;
134         ELEMENT_INT(c)->value = value;
135
136         _add_cond_to_filter(filter, c);
137
138         return AIL_ERROR_OK;
139 }
140
141 EXPORT_API ail_error_e ail_filter_add_str(ail_filter_h filter, const char *property, const char *value)
142 {
143         struct element *c; //condition
144         ail_prop_str_e prop;
145
146         retv_if (NULL == filter, AIL_ERROR_INVALID_PARAMETER);
147         retv_if (NULL == property, AIL_ERROR_INVALID_PARAMETER);
148
149         prop = _ail_convert_to_prop_str(property);
150
151         if (prop < E_AIL_PROP_STR_MIN || prop > E_AIL_PROP_STR_MAX)
152                 return AIL_ERROR_INVALID_PARAMETER;
153
154         retv_if (NULL == value, AIL_ERROR_INVALID_PARAMETER);
155         retv_if (strlen(value) == 0, AIL_ERROR_INVALID_PARAMETER);
156
157         c = (struct element *)calloc(1, sizeof(struct element_str));
158
159         retv_if (NULL == c, AIL_ERROR_OUT_OF_MEMORY);
160
161         ELEMENT_STR(c)->prop = (int)prop;
162         ELEMENT_STR(c)->value = strdup(value);
163         if (!ELEMENT_STR(c)->value) {
164                 free(c);
165                 return AIL_ERROR_OUT_OF_MEMORY;
166         }
167
168         _add_cond_to_filter(filter, c);
169
170         return AIL_ERROR_OK;
171 }
172
173 static void _get_condition(gpointer data, char **condition)
174 {
175         struct element *e = (struct element *)data;
176         const char *f;
177         char buf[AIL_SQL_QUERY_MAX_LEN];
178
179         f =  sql_get_filter(e->prop);
180         int t;
181         ELEMENT_TYPE(e, t);
182
183         switch (t) {
184                 case VAL_TYPE_BOOL:
185                         snprintf(buf, sizeof(buf), f, ELEMENT_BOOL(e)->value);
186                         break;
187                 case VAL_TYPE_INT:
188                         snprintf(buf, sizeof(buf), f, ELEMENT_INT(e)->value);
189                         break;
190                 case VAL_TYPE_STR:
191                         if (E_AIL_PROP_NAME_STR == e->prop) {
192                                 snprintf(buf, sizeof(buf), f, ELEMENT_STR(e)->value, ELEMENT_STR(e)->value);
193                         } else {
194                                 snprintf(buf, sizeof(buf), f, ELEMENT_STR(e)->value);
195                         }
196                         break;
197                 default:
198                         _E("Invalid property type");
199                         *condition = NULL;
200                         return;
201         }
202
203         *condition = strdup(buf);
204
205         return;
206 }
207
208 char *_get_where_clause(ail_filter_h filter)
209 {
210         char *c;
211         char w[AIL_SQL_QUERY_MAX_LEN] = {0,};
212         c = NULL;
213
214         GSList *l;
215         
216         snprintf(w, AIL_SQL_QUERY_MAX_LEN, " WHERE ");
217
218         for (l = filter->list; l; l = g_slist_next(l)) {
219                 _get_condition(l->data, &c);
220                 if (!c) return NULL;
221                 if (*c == 0) {
222                         free(c);
223                         return NULL;
224                 }
225
226                 strncat(w, c, sizeof(w)-strlen(w)-1);
227                 w[sizeof(w)-1] = '\0';
228                 if(c) free(c);
229
230                 if (g_slist_next(l)) {
231                         strncat(w, " and ", sizeof(w)-strlen(w)-1);
232                         w[sizeof(w)-1] = '\0';
233                 }
234         }
235
236         _D("where = %s", w);
237
238         return strdup(w);
239 }
240
241 EXPORT_API ail_error_e ail_filter_count_appinfo(ail_filter_h filter, int *cnt)
242 {
243         char q[AIL_SQL_QUERY_MAX_LEN];
244         char *w;
245         char *tmp_q;
246         char *l;
247         int r;
248         int n;
249         sqlite3_stmt *stmt;
250
251         retv_if(!cnt, AIL_ERROR_INVALID_PARAMETER);
252
253         if (db_open(DB_OPEN_RO) != AIL_ERROR_OK)
254                 return AIL_ERROR_DB_FAILED;
255
256         snprintf(q, sizeof(q), "SELECT COUNT (*) FROM %s", SQL_TBL_APP_INFO_WITH_LOCALNAME);
257
258         tmp_q = strdup(q);
259         retv_if (NULL == tmp_q, AIL_ERROR_OUT_OF_MEMORY);
260         l = sql_get_locale();
261         if (NULL == l) {
262                 _E("Failed to get locale string");
263                 free(tmp_q);
264                 return AIL_ERROR_FAIL;
265         }
266         snprintf(q, sizeof(q), tmp_q, l);
267         free(l);
268         free(tmp_q);
269
270         if (filter && filter->list) { 
271                 w = _get_where_clause(filter);
272                 retv_if (NULL == w, AIL_ERROR_FAIL);
273                 strncat(q, w, sizeof(q)-strlen(q)-1);
274                 q[sizeof(q)-1] = '\0';
275                 free(w);
276         }
277
278         _D("Query = %s",q);
279
280         if (db_prepare(q, &stmt) != AIL_ERROR_OK) {
281                 return AIL_ERROR_DB_FAILED;
282         }
283
284         r = db_step(stmt);
285         if (r == AIL_ERROR_OK) {
286                 db_column_int(stmt, 0, &n);
287                 *cnt = n;
288         }
289
290         db_finalize(stmt);
291
292         return r;
293 }
294
295
296
297 EXPORT_API ail_error_e ail_filter_list_appinfo_foreach(ail_filter_h filter, ail_list_appinfo_cb cb, void *user_data)
298 {
299         char q[AIL_SQL_QUERY_MAX_LEN];
300         char *tmp_q;
301         char *w;
302         char *l;
303         ail_cb_ret_e r;
304         sqlite3_stmt *stmt;
305         ail_appinfo_h ai;
306
307         retv_if (NULL == cb, AIL_ERROR_INVALID_PARAMETER);
308
309         if (db_open(DB_OPEN_RO) != AIL_ERROR_OK)
310                 return AIL_ERROR_DB_FAILED;
311
312         snprintf(q, sizeof(q), "SELECT %s FROM %s", SQL_FLD_APP_INFO_WITH_LOCALNAME, SQL_TBL_APP_INFO_WITH_LOCALNAME);
313
314         tmp_q = strdup(q);
315         retv_if (NULL == tmp_q, AIL_ERROR_OUT_OF_MEMORY);
316         l = sql_get_locale();
317         if (NULL == l) {
318                 _E("Failed to get locale string");
319                 free(tmp_q);
320                 return AIL_ERROR_FAIL;
321         }
322         snprintf(q, sizeof(q), tmp_q, l);
323         free(l);
324         free(tmp_q);
325
326         if (filter && filter->list) {
327                 w = _get_where_clause(filter);
328                 retv_if (NULL == w, AIL_ERROR_FAIL);
329                 strncat(q, w, sizeof(q)-strlen(q)-1);
330                 q[sizeof(q)-1] = '\0';
331                 strncat(q, " order by app_info.package", sizeof(q)-strlen(q)-1);
332                 q[sizeof(q)-1] = '\0';
333                 free(w);
334         }
335         else
336                 _D("No filter exists. All records are retreived");
337
338         _D("Query = %s",q);
339
340         if (db_prepare(q, &stmt) != AIL_ERROR_OK) {
341                 return AIL_ERROR_DB_FAILED;
342         }
343
344         ai = appinfo_create();
345
346         appinfo_set_stmt(ai, stmt);
347         while (db_step(stmt) == AIL_ERROR_OK) {
348
349                 r = cb(ai, user_data);
350                 if (AIL_CB_RET_CANCEL == r)
351                         break;
352         }
353         appinfo_destroy(ai);
354
355         db_finalize(stmt);
356
357         return AIL_ERROR_OK;
358 }
359