[Contact] Refactoring API structures
[profile/ivi/wrt-plugins-tizen.git] / src / platform / Tizen / Calendar / CalendarFilter.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
18 #include <dpl/log/log.h>
19 #include "CalendarFilter.h"
20 #include "CalendarQuery.h"
21 #include <calendar-svc-provider.h>
22 #include <map>
23 #include <sstream>
24 #include <time.h>
25
26 using namespace TizenApis::Api::Calendar;
27 using namespace WrtDeviceApis::Commons;
28
29 namespace TizenApis {
30 namespace Platform {
31 namespace Calendar {
32
33 // The selected fields for the generic filter support.
34 std::map<std::string, std::string> CalendarFilter::m_attributeMap = {
35     {CALENDAR_FILTER_ATTRIBUTE_ID_UID,                          CAL_VALUE_INT_INDEX},
36     {CALENDAR_FILTER_ATTRIBUTE_ID,                              CAL_VALUE_INT_INDEX},
37     {CALENDAR_FILTER_ATTRIBUTE_LAST_MODIFIED_DATE,              CALS_VALUE_LLI_LASTMOD},
38     {CALENDAR_FILTER_ATTRIBUTE_DESCRIPTION,                     CAL_VALUE_TXT_DESCRIPTION},
39     {CALENDAR_FILTER_ATTRIBUTE_SUMMARY,                         CAL_VALUE_TXT_SUMMARY},
40     {CALENDAR_FILTER_ATTRIBUTE_START_DATE,                      CALS_VALUE_LLI_DTSTART_UTIME},
41     {CALENDAR_FILTER_ATTRIBUTE_LOCATION,                        CAL_VALUE_TXT_LOCATION},
42     {CALENDAR_FILTER_ATTRIBUTE_LATITUDE,                        CAL_VALUE_DBL_LATITUDE},
43     {CALENDAR_FILTER_ATTRIBUTE_LONGITUDE,                       CAL_VALUE_DBL_LONGITUDE},
44     {CALENDAR_FILTER_ATTRIBUTE_ORGANIZER,                       CAL_VALUE_TXT_ORGANIZER_NAME},
45     {CALENDAR_FILTER_ATTRIBUTE_VISIBILITY,                      CAL_VALUE_INT_SENSITIVITY},
46     {CALENDAR_FILTER_ATTRIBUTE_STATUS,                          CAL_VALUE_INT_TASK_STATUS},
47     //{"alarms",                          CAL_VALUE_INT_ALARMS_TICK}, // object interface
48     {CALENDAR_FILTER_ATTRIBUTE_CATEGORIES,                      CAL_VALUE_TXT_CATEGORIES}, // string array
49     {CALENDAR_FILTER_ATTRIBUTE_PRIORITY,                        CAL_VALUE_INT_PRIORITY},
50     {CALENDAR_FILTER_ATTRIBUTE_DUE_DATE,                        CALS_VALUE_LLI_DTEND_UTIME},
51     {CALENDAR_FILTER_ATTRIBUTE_COMPLETED_DATE,                                  CAL_VALUE_LLI_COMPLETED_TIME},
52     {CALENDAR_FILTER_ATTRIBUTE_PROGRESS,                                                CAL_VALUE_INT_PROGRESS},
53     {CALENDAR_FILTER_ATTRIBUTE_IS_DETACHED,                     CAL_VALUE_INT_ORIGINAL_EVENT_ID},
54     {CALENDAR_FILTER_ATTRIBUTE_IS_ALL_DAY,                      CALS_VALUE_INT_DTSTART_TYPE},
55     //{CALENDAR_FILTER_ATTRIBUTE_DURATION,                        CALS_VALUE_LLI_DTEND_UTIME}, // needs end date calculation
56     //{"attendees",                       CAL_VALUE_TXT_ATTENDEE_DETAIL_NAME}, // object array interface
57     {CALENDAR_FILTER_ATTRIBUTE_END_DATE,                        CALS_VALUE_LLI_DTEND_UTIME},
58     {CALENDAR_FILTER_ATTRIBUTE_AVAILABILITY,                    CAL_VALUE_INT_AVAILABILITY},
59     {CALENDAR_FILTER_ATTRIBUTE_RECURRENCE_RULE,                 CALS_VALUE_INT_RRULE_FREQ}
60 };
61
62 CalendarFilter::CalendarFilter()
63 {
64         LogDebug("entered");
65         m_query.clear();
66         m_query.append(" WHERE");
67 }
68
69 CalendarFilter::~CalendarFilter()
70 {
71 }
72
73 void CalendarFilter::visitPreComposite(TizenApis::Api::Tizen::FilterType& type, int depth)
74 {
75         LogDebug("entered");
76         m_query.append(" (");
77 }
78
79 void CalendarFilter::visitInComposite(TizenApis::Api::Tizen::FilterType& type, int depth)
80 {
81         LogDebug("entered");
82         if(type == TizenApis::Api::Tizen::UNION_FILTER)
83                 m_query.append(" OR ");
84         else if(type == TizenApis::Api::Tizen::INTERSECTION_FILTER)
85                 m_query.append(" AND ");
86 }
87
88 void CalendarFilter::visitPostComposite(TizenApis::Api::Tizen::FilterType& type, int depth)
89 {
90         LogDebug("entered");
91         m_query.append(" )");
92 }
93
94 void CalendarFilter::visitAttribute(std::string& attrName, TizenApis::Api::Tizen::MatchFlag& matchFlag, TizenApis::Api::Tizen::AnyPtr& matchValue, int depth)
95 {
96         if(matchValue == NULL)
97                 return;
98
99         LogDebug("attrName: "<<attrName<<", value length: "<<matchValue->toString()<<", matchFlag: "<<matchFlag<<", depth:"<<depth);
100
101         std::string conditionQuery;
102         std::string matchString;
103     std::string valueString;
104
105         if(matchValue->isType(TizenApis::Api::Tizen::PrimitiveType_Time))
106         {
107                 tm date = matchValue->getDateTm();
108                 std::stringstream time;
109                 time << timegm(&date);
110                 valueString = time.str();
111         }
112         else if(matchValue->isType(TizenApis::Api::Tizen::PrimitiveType_Boolean))
113         {
114                 if (matchValue->getBool()) {
115                         valueString = std::string("1");
116                 } else {
117                         valueString = std::string("0");
118                 }
119         }
120         else
121         {
122                 valueString = matchValue->toString();
123         }
124
125         if(attrName==CALENDAR_FILTER_ATTRIBUTE_VISIBILITY
126         || attrName==CALENDAR_FILTER_ATTRIBUTE_STATUS
127         || attrName==CALENDAR_FILTER_ATTRIBUTE_PRIORITY
128         || attrName==CALENDAR_FILTER_ATTRIBUTE_AVAILABILITY
129         || attrName==CALENDAR_FILTER_ATTRIBUTE_RECURRENCE_RULE) {
130                 valueString = convertStringToValue(attrName, valueString);
131         }
132
133         if( matchFlag==TizenApis::Api::Tizen::MATCH_EXACTLY ) {
134                 matchString = " = \'" + valueString + "\'"; // case-sensitive
135         } else if( matchFlag==TizenApis::Api::Tizen::MATCH_FULLSTRING ) {
136                         matchString = " like \'" + valueString + "\'"; // case-insensitive
137         } else if( matchFlag==TizenApis::Api::Tizen::MATCH_CONTAINS) {
138                 matchString = " like \'%" + valueString + "%\'";
139         } else if( matchFlag==TizenApis::Api::Tizen::MATCH_STARTSWITH) {
140                 matchString = " like \'%" + valueString + "\'";
141         } else if( matchFlag==TizenApis::Api::Tizen::MATCH_ENDSWITH) {
142                 matchString = " like \'" + valueString + "%\'";
143         }else if( matchFlag==TizenApis::Api::Tizen::MATCH_EXISTS) {
144             if(attrName==CALENDAR_FILTER_ATTRIBUTE_RECURRENCE_RULE) {
145             matchString = " is not 0";
146             } else {
147                 matchString = " is not null";
148         }
149         } else {
150                 LogError("Invalid matchFlag!");
151                 matchString = " is not null";
152         }
153
154         if (attrName==CALENDAR_FILTER_ATTRIBUTE_IS_DETACHED) {
155                 if (valueString=="1") {
156                         conditionQuery.append(" (" + m_attributeMap[attrName] + " > 0 )");
157                 } else {
158                         conditionQuery.append(" (" + m_attributeMap[attrName] + " < 0 )");
159                 }
160         } else if (attrName==CALENDAR_FILTER_ATTRIBUTE_IS_ALL_DAY) {
161                 std::stringstream ss;
162                 if (valueString=="1") {
163                         ss<<CALS_TIME_LOCALTIME;
164                 } else {
165                         ss<<CALS_TIME_UTIME;
166                 }
167                 conditionQuery.append(" (" + m_attributeMap[attrName] + " = " + ss.str() + " )");
168         } else {
169                 conditionQuery.append(" (" + m_attributeMap[attrName] + matchString + ") ");
170         }
171
172         LogInfo("Generated condition query: [" << conditionQuery << "]");
173
174         m_query.append(conditionQuery);
175 }
176
177 void CalendarFilter::visitAttributeRange(std::string& attrName, TizenApis::Api::Tizen::AnyPtr& initialValue, TizenApis::Api::Tizen::AnyPtr& endValue, int depth)
178 {
179         if(initialValue == NULL || endValue == NULL)
180                 return;
181
182     LogDebug("attrName: " <<attrName<<", initialValue: "<<initialValue->toString()<<", endValue: " <<endValue->toString()<<", depth: "<<depth);
183         std::string conditionQuery;
184     std::string initialValueStr;
185     std::string endValueStr;
186
187         if (!initialValue->isNullOrUndefined()) {
188         if( TizenApis::Api::Tizen::PrimitiveType_Time==initialValue->getType() ) {
189             tm date = initialValue->getDateTm();
190             std::stringstream time;
191             time << timegm(&date);
192             initialValueStr = time.str();
193         } else {
194             initialValueStr = initialValue->toString();
195         }
196         }
197
198         if (!endValue->isNullOrUndefined()) {
199         if( TizenApis::Api::Tizen::PrimitiveType_Time==endValue->getType() ) {
200             tm date = endValue->getDateTm();
201             std::stringstream time;
202             time << timegm(&date);
203             endValueStr = time.str();
204         } else {
205             endValueStr = endValue->toString();
206         }
207     }
208
209     if (!initialValue->isNullOrUndefined() && endValue->isNullOrUndefined() ) {
210         conditionQuery = " " + m_attributeMap[attrName] + ">" + initialValueStr + " ";
211     } else if (initialValue->isNullOrUndefined() && !endValue->isNullOrUndefined() ) {
212         conditionQuery = " " + m_attributeMap[attrName] + "<" + endValueStr + " ";
213     } else if (!initialValue->isNullOrUndefined() && !endValue->isNullOrUndefined() ) {
214         conditionQuery = " " + m_attributeMap[attrName] + ">" + initialValueStr + " AND " + m_attributeMap[attrName] + "<" + endValueStr + " ";
215     }
216
217         m_query.append(conditionQuery);
218 }
219
220 std::string CalendarFilter::getResult() const
221 {
222         LogDebug("entered");
223         return m_query;
224 }
225
226 bool CalendarFilter::convertToCalendar(calendar_query_s *queryData, CalendarEventListPtr calendarListPtr)
227 {
228     LogDebug("entered");
229
230     if (queryData == NULL)
231        return false;
232
233     CalendarEventPtr calendarEvent(new CalendarEvent());
234
235     // Convert query results to the event struct.
236     calendarEvent->setId(queryData->id);
237
238     calendarListPtr->push_back(calendarEvent);
239
240     return true;
241 }
242
243 bool CalendarFilter::executeQuery(std::string &query, CalendarEventListPtr calendarListPtr)
244 {    
245         LogDebug("entered");
246
247         calendar_query_s query_data;
248
249         stmt hstmt = NULL;
250         int ret = 0;
251
252         hstmt = calendar_query_prepare((char *)(query.c_str()));
253     if( NULL==hstmt) {
254         ThrowMsg(PlatformException, "Can't prepare query!");
255     }
256
257         do {
258                 ret = calendar_query_step(hstmt);
259                 LogDebug("Query result : [" << ret << "]");
260                 if (ret == SQLITE_ROW) { // 100
261                         query_data.id = calendar_query_column_int(hstmt, 0);
262
263                         convertToCalendar(&query_data, calendarListPtr);
264                 } else if (ret == SQLITE_DONE) { // 101
265                         LogDebug("Query done [" << ret << "]");
266                         break;
267                 } else { //if (ret == SQLITE_DONE || ret == SQLITE_IOERR || ret == SQLITE_BUSY || ret == SQLITE_ERROR || ret == SQLITE_MISUSE)
268                         LogDebug("Query error [" << ret << "]");
269                         break;
270                 }
271         } while (1);
272
273         calendar_query_finalize(hstmt);
274
275         return true;
276 }
277
278 std::string CalendarFilter::makeQuerySortMode(TizenApis::Api::Tizen::SortModeArrayPtr attr)
279 {    
280         LogDebug("entered");
281
282         std::string query("");
283         std::string attriName;
284         int cnt = 0;
285         TizenApis::Api::Tizen::SortModeArray::iterator it = attr->begin();
286
287         for (;it!=attr->end(); ++it) {
288                 attriName = (*it)->getAttributeName();
289                 if (attriName.compare("") != 0) { 
290                         if (cnt == 0) {
291                                 query.append(" ORDER BY ");
292                         } else {
293                                 query.append(", ");
294                         }
295                         query.append(attriName);
296
297                         if ((*it)->getOrder()==TizenApis::Api::Tizen::ASCENDING_SORT_ORDER) {
298                                 query.append(" ASC");
299                         } else {
300                                 query.append(" DESC");
301                         }
302                         cnt++;
303                 }
304         }
305
306         return query;
307 }
308
309 std::string CalendarFilter::convertStringToValue(const std::string attrName, const std::string valueString)
310 {
311         LogDebug("entered");
312
313     std::stringstream ss;
314
315     if(attrName==CALENDAR_FILTER_ATTRIBUTE_VISIBILITY)
316     {
317         if(valueString=="PUBLIC") {
318             ss<<PUBLIC_VISIBILITY;
319             return ss.str();
320         } else if(valueString=="PRIVATE") {
321             ss<<PRIVATE_VISIBILITY;
322             return ss.str();
323         } else if(valueString=="CONFIDENTIAL") {
324             ss<<CONFIDENTIAL_VISIBILITY;
325             return ss.str();
326         } else {
327             return valueString;
328         }
329     }
330     else if(attrName==CALENDAR_FILTER_ATTRIBUTE_STATUS)
331     {
332         if(valueString=="TENTATIVE") {
333             ss<<CALS_EVENT_STATUS_TENTATIVE;
334             return ss.str();
335         } else if(valueString=="CONFIRMED") {
336             ss<<CALS_EVENT_STATUS_CONFIRMED;
337             return ss.str();
338         } else if(valueString=="CANCELLED") {
339             ss<<CALS_EVENT_STATUS_CANCELLED;
340             return ss.str();
341         } else if(valueString=="NEEDS_ACTION") {
342             ss<<CALS_TODO_STATUS_NEEDS_ACTION;
343             return ss.str();
344         } else if(valueString=="IN_PROCESS") {
345             ss<<CALS_TODO_STATUS_IN_PROCESS;
346
347         } else if(valueString=="COMPLETED") {
348             ss<<CALS_TODO_STATUS_COMPLETED;
349             return ss.str();
350         } else {
351             return valueString;
352         }
353     }
354     else if(attrName==CALENDAR_FILTER_ATTRIBUTE_PRIORITY)
355     {
356         if(valueString=="HIGH") {
357             ss<<EVENT_PRIORITY_HIGH;
358             return ss.str();
359         } else if(valueString=="MEDIUM") {
360             ss<<EVENT_PRIORITY_NORMAL;
361             return ss.str();
362         } else if(valueString=="LOW") {
363             ss<<EVENT_PRIORITY_LOW;
364             return ss.str();
365         } else {
366             return valueString;
367         }
368     }
369     else if(attrName==CALENDAR_FILTER_ATTRIBUTE_AVAILABILITY)
370     {
371         if(valueString=="BUSY") {
372             ss<<EVENT_BUSY_FB;
373             return ss.str();
374         } else if(valueString=="FREE") {
375             ss<<EVENT_FREE_FB;
376             return ss.str();
377         } else {
378             return valueString;
379         }
380     }
381     else if(attrName==CALENDAR_FILTER_ATTRIBUTE_RECURRENCE_RULE)
382     {
383         if(valueString=="DAILY") {
384             ss<<CAL_REPEAT_EVERY_DAY;
385             return ss.str();
386         } else if(valueString=="WEEKLY") {
387             ss<<CAL_REPEAT_EVERY_WEEK;
388             return ss.str();
389         } else if(valueString=="MONTHLY") {
390             ss<<CAL_REPEAT_EVERY_MONTH;
391             return ss.str();
392         } else if(valueString=="YEARLY") {
393             ss<<CAL_REPEAT_EVERY_YEAR;
394             return ss.str();
395         } else {
396             return valueString;
397         }
398     }
399     else
400     {
401         LogWarning("Invalid attrName");
402     }
403
404     return valueString;
405 }
406
407 std::string CalendarFilter::concatenateFilterAttributes()
408 {
409         LogDebug("entered");
410
411     std::string attributes;
412     std::map<std::string, std::string>::iterator iter;
413     unsigned int i = 0;
414     for( iter=m_attributeMap.begin(); iter!=m_attributeMap.end(); iter++) {
415         attributes.append((*iter).second);
416         if( i+1<m_attributeMap.size() ) {
417             attributes.append(", ");
418         }
419         i++;
420     }
421
422     return attributes;
423 }
424
425 }
426 }
427 }