Initialize Tizen 2.3
[framework/osp/social.git] / src / FScl_CalEventImpl.cpp
1 //
2 // Copyright (c) 2012 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  * @file                FScl_CalEventImpl.cpp
18  * @brief               This is the implementation for _CalEventImpl class.
19  *
20  * This file contains definitions of @e _CalEventImpl class.
21  */
22
23 #include <new>
24 #include <string.h>
25 #include <FApp_AppInfo.h>
26 #include <FBaseColArrayList.h>
27 #include <FBaseSysLog.h>
28 #include <FBase_StringConverter.h>
29 #include <FLclCalendar.h>
30 #include <FLclGregorianCalendar.h>
31 #include <FLclTimeZone.h>
32 #include <FSclAttendee.h>
33 #include <FSclCalEvent.h>
34 #include <FSclRecord.h>
35 #include <FSysSystemTime.h>
36 #include "FScl_RecordImpl.h"
37 #include "FScl_CalEventImpl.h"
38 #include "FScl_RecurrenceImpl.h"
39 #include "FScl_CalendarbookImpl.h"
40 #include "FScl_CalendarbookDbConnector.h"
41
42 using namespace Tizen::App;
43 using namespace Tizen::Base;
44 using namespace Tizen::Base::Collection;
45 using namespace Tizen::Base::Utility;
46 using namespace Tizen::Locales;
47 using namespace Tizen::System;
48
49 namespace Tizen { namespace Social
50 {
51
52 static const int _DEFAULT_ADDED_HOUR = 1;
53 static const int _INVALID_ATTENDEE_INDEX = -1;
54
55 static const int _TERM_LIMIT_DAILY = 1;
56 static const int _TERM_LIMIT_WEEKLY = 7;
57 static const int _TERM_LIMIT_MONTHLY = 31;
58 static const int _TERM_LIMIT_YEARLY = 366;
59 static const int _NUMBER_OF_DAYS_OF_WEEK = 7;
60
61 static const wchar_t* _EVENT_CATEGORY_APPOINTMENT_STRING = L"Appointment";
62 static const wchar_t* _EVENT_CATEGORY_ANNIVERSARY_STRING = L"Anniversary";
63
64 static const wchar_t* _RECURRENCE_KEYWORD_SUNDAY = L"SU";
65 static const wchar_t* _RECURRENCE_KEYWORD_MONDAY = L"MO";
66 static const wchar_t* _RECURRENCE_KEYWORD_TUESDAY = L"TU";
67 static const wchar_t* _RECURRENCE_KEYWORD_WEDNESDAY = L"WE";
68 static const wchar_t* _RECURRENCE_KEYWORD_THURSDAY = L"TH";
69 static const wchar_t* _RECURRENCE_KEYWORD_FRIDAY = L"FR";
70 static const wchar_t* _RECURRENCE_KEYWORD_SATURDAY = L"SA";
71
72 static const wchar_t* _RECURRENCE_DELIMITER = L",";
73 static const int _RECURRENCE_DELIMITER_LENGTH = 1;
74 static const wchar_t _RECURRENCE_BY_DAY_CHAR_PLUS = L'+';
75 static const wchar_t _RECURRENCE_BY_DAY_CHAR_MINUS = L'-';
76 static const wchar_t _RECURRENCE_BY_DAY_CHAR_ONE = L'1';
77 static const int _RECURRENCE_BY_DAY_FIRST_INDEX = 0;
78 static const int _RECURRENCE_BY_DAY_SECOND_INDEX = 1;
79 static const int _MAX_WEEK_OF_MONTH = 5;
80
81 static const double _MIN_LATITUDE = -90.0;
82 static const double _MAX_LATITUDE = 90.0;
83 static const double _MIN_LONGITUDE = -180.0;
84 static const double _MAX_LONGITUDE = 180.0;
85
86 _CalEventImpl::_CalEventImpl(void)
87         : __originalEventId(INVALID_RECORD_ID)
88         , __isInstance(false)
89         , __reminderListUpdated(false)
90 {
91         // Set default start and end time
92         DateTime startTime;
93         SystemTime::GetCurrentTime(startTime);
94         if (IsFailed(GetLastResult()))
95         {
96                 startTime = _CalendarbookImpl::GetMinDateTime();
97                 ClearLastResult();
98         }
99
100         DateTime endTime(startTime);
101         result r = endTime.AddHours(_DEFAULT_ADDED_HOUR);
102         SysTryReturnVoidResult(NID_SCL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
103
104         calendar_time_s startCalendarTime;
105         calendar_time_s endCalendarTime;
106         startCalendarTime.type = CALENDAR_TIME_UTIME;
107         endCalendarTime.type = CALENDAR_TIME_UTIME;
108         startCalendarTime.time.utime = _CalendarbookUtil::ConvertDateTimeToEpochTime(startTime);
109         endCalendarTime.time.utime = _CalendarbookUtil::ConvertDateTimeToEpochTime(endTime);
110
111         r = _CalendarbookDbConnector::Connect();
112         SysTryReturnVoidResult(NID_SCL, r == E_SUCCESS, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
113
114         calendar_record_h eventHandle = null;
115         int errorCode = calendar_record_create(_calendar_event._uri, &eventHandle);
116         SysTryReturnVoidResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
117
118         __eventRecord.ResetHandle(eventHandle);
119
120         calendar_record_set_caltime(eventHandle, _calendar_event.start_time, startCalendarTime);
121         calendar_record_set_caltime(eventHandle, _calendar_event.end_time, endCalendarTime);
122
123         // default value
124         calendar_record_set_int(eventHandle, _calendar_event.event_status, CALENDAR_EVENT_STATUS_NONE);
125         calendar_record_set_int(eventHandle, _calendar_event.busy_status, CALENDAR_EVENT_BUSY_STATUS_FREE);
126         calendar_record_set_int(eventHandle, _calendar_event.priority, CALENDAR_EVENT_PRIORITY_NORMAL);
127         calendar_record_set_int(eventHandle, _calendar_event.sensitivity, CALENDAR_SENSITIVITY_PUBLIC);
128         calendar_record_set_int(eventHandle, _calendar_event.calendar_book_id, INVALID_RECORD_ID);
129
130         r = __reminderList.Construct();
131         SysTryReturnVoidResult(NID_SCL, r == E_SUCCESS, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
132 }
133
134 _CalEventImpl::_CalEventImpl(const _CalEventImpl& rhs)
135         : __originalEventId(rhs.__originalEventId)
136         , __isInstance(rhs.__isInstance)
137         , __reminderListUpdated(false)
138 {
139         result r = _CalendarbookDbConnector::Connect();
140         SysTryReturnVoidResult(NID_SCL, r == E_SUCCESS, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
141
142         calendar_record_h eventHandle = null;
143         int errorCode = calendar_record_clone(rhs.__eventRecord.GetHandle(), &eventHandle);
144         SysTryReturnVoidResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
145
146         __eventRecord.ResetHandle(eventHandle);
147
148         r = __reminderList.Construct();
149         SysTryReturnVoidResult(NID_SCL, r == E_SUCCESS, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
150 }
151
152 _CalEventImpl::~_CalEventImpl(void)
153 {
154         calendar_record_destroy(__eventRecord.ReleaseHandle(), true);
155
156         __reminderList.RemoveAll(true);
157
158         result r = _CalendarbookDbConnector::Disconnect();
159         SysTryReturnVoidResult(NID_SCL, r == E_SUCCESS, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
160 }
161
162 _CalEventImpl&
163 _CalEventImpl::operator =(const _CalEventImpl& rhs)
164 {
165         if (this == &rhs)
166         {
167                 return *this;
168         }
169
170         __originalEventId = rhs.__originalEventId;
171         __isInstance = rhs.__isInstance;
172         __reminderList.RemoveAll(true);
173         __reminderListUpdated = false;
174
175         int errorCode = CALENDAR_ERROR_NONE;
176         calendar_record_h eventHandle = null;
177
178         errorCode = calendar_record_clone(rhs.__eventRecord.GetHandle(), &eventHandle);
179         SysTryReturn(NID_SCL, errorCode == CALENDAR_ERROR_NONE, *this, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
180
181         __eventRecord.ResetHandle(eventHandle);
182
183         return *this;
184 }
185
186 bool
187 _CalEventImpl::IsInstance(void) const
188 {
189         return __isInstance;
190 }
191
192 bool
193 _CalEventImpl::IsRecurring(void) const
194 {
195         int recurrenceFreq = CALENDAR_RECURRENCE_NONE;
196
197         calendar_record_get_int(__eventRecord.GetHandle(), _calendar_event.freq, &recurrenceFreq);
198
199         if (recurrenceFreq == CALENDAR_RECURRENCE_NONE)
200         {
201                 return false;
202         }
203
204         return true;
205 }
206
207 RecordId
208 _CalEventImpl::GetOriginalCalEventId(void)  const
209 {
210         return __originalEventId;
211 }
212
213 bool
214 _CalEventImpl::IsAllDayEvent(void)  const
215 {
216         calendar_time_s startCalendarTime;
217
218         calendar_record_get_caltime(__eventRecord.GetHandle(), _calendar_event.start_time, &startCalendarTime);
219         if (startCalendarTime.type == CALENDAR_TIME_UTIME)
220         {
221                 return false;
222         }
223
224         return true;
225 }
226
227 void
228 _CalEventImpl::SetAllDayEvent(bool isAllDayEvent)
229 {
230         if (GetCategory() == EVENT_CATEGORY_ANNIVERSARY)
231         {
232                 return;
233         }
234
235         calendar_time_s startCalendarTime;
236         calendar_time_s tmpStartCalendarTime;
237         calendar_time_s endCalendarTime;
238         calendar_time_s tmpEndCalendarTime;
239
240         bool isChanged = false;
241
242         calendar_record_get_caltime(__eventRecord.GetHandle(), _calendar_event.start_time, &startCalendarTime);
243         calendar_record_get_caltime(__eventRecord.GetHandle(), _calendar_event.end_time, &endCalendarTime);
244
245         if (isAllDayEvent && startCalendarTime.type == CALENDAR_TIME_UTIME)
246         {
247                 tmpStartCalendarTime.type = CALENDAR_TIME_LOCALTIME;
248                 DateTime tmpStartTime = _CalendarbookUtil::ConvertEpochTimeToDateTime(startCalendarTime.time.utime);
249                 tmpStartCalendarTime.time.date.year = tmpStartTime.GetYear();
250                 tmpStartCalendarTime.time.date.month = tmpStartTime.GetMonth();
251                 tmpStartCalendarTime.time.date.mday = tmpStartTime.GetDay();
252
253                 tmpEndCalendarTime.type = CALENDAR_TIME_LOCALTIME;
254                 DateTime tmpEndTime = _CalendarbookUtil::ConvertEpochTimeToDateTime(endCalendarTime.time.utime);
255                 tmpEndCalendarTime.time.date.year = tmpEndTime.GetYear();
256                 tmpEndCalendarTime.time.date.month = tmpEndTime.GetMonth();
257                 tmpEndCalendarTime.time.date.mday = tmpEndTime.GetDay();
258
259                 calendar_record_set_caltime(__eventRecord.GetHandle(), _calendar_event.start_time, tmpStartCalendarTime);
260                 calendar_record_set_caltime(__eventRecord.GetHandle(), _calendar_event.end_time, tmpEndCalendarTime);
261
262                 isChanged = true;
263         }
264         else if (!isAllDayEvent && startCalendarTime.type == CALENDAR_TIME_LOCALTIME)
265         {
266                 tmpStartCalendarTime.type = CALENDAR_TIME_UTIME;
267                 DateTime tmpStartTime;
268                 tmpStartTime.SetValue(startCalendarTime.time.date.year, startCalendarTime.time.date.month, startCalendarTime.time.date.mday);
269                 tmpStartCalendarTime.time.utime = _CalendarbookUtil::ConvertDateTimeToEpochTime(tmpStartTime);
270
271                 tmpEndCalendarTime.type = CALENDAR_TIME_UTIME;
272                 DateTime tmpEndTime;
273                 tmpEndTime.SetValue(endCalendarTime.time.date.year, endCalendarTime.time.date.month, endCalendarTime.time.date.mday);
274                 tmpEndCalendarTime.time.utime = _CalendarbookUtil::ConvertDateTimeToEpochTime(tmpEndTime);
275
276                 calendar_record_set_caltime(__eventRecord.GetHandle(), _calendar_event.start_time, tmpStartCalendarTime);
277                 calendar_record_set_caltime(__eventRecord.GetHandle(), _calendar_event.end_time, tmpEndCalendarTime);
278
279                 isChanged = true;
280         }
281
282         if (IsRecurring())
283         {
284                 int rangeType = CALENDAR_RANGE_NONE;
285                 calendar_record_get_int(__eventRecord.GetHandle(), _calendar_event.range_type, &rangeType);
286
287                 if (rangeType == CALENDAR_RANGE_UNTIL)
288                 {
289                         calendar_time_s untilCalendarTime;
290                         calendar_time_s tmpUntilCalendarTime;
291
292                         calendar_record_get_caltime(__eventRecord.GetHandle(), _calendar_event.until_time, &untilCalendarTime);
293                         if (isAllDayEvent && untilCalendarTime.type == CALENDAR_TIME_UTIME)
294                         {
295                                 tmpUntilCalendarTime.type = CALENDAR_TIME_LOCALTIME;
296                                 DateTime tmpUntilTime = _CalendarbookUtil::ConvertEpochTimeToDateTime(untilCalendarTime.time.utime);
297                                 tmpUntilCalendarTime.time.date.year = tmpUntilTime.GetYear();
298                                 tmpUntilCalendarTime.time.date.month = tmpUntilTime.GetMonth();
299                                 tmpUntilCalendarTime.time.date.mday = tmpUntilTime.GetDay();
300
301                                 calendar_record_set_caltime(__eventRecord.GetHandle(), _calendar_event.until_time, tmpUntilCalendarTime);
302                         }
303                         else if (!isAllDayEvent && untilCalendarTime.type == CALENDAR_TIME_LOCALTIME)
304                         {
305                                 tmpUntilCalendarTime.type = CALENDAR_TIME_UTIME;
306                                 DateTime tmpUntilTime;
307                                 tmpUntilTime.SetValue(untilCalendarTime.time.date.year, untilCalendarTime.time.date.month, untilCalendarTime.time.date.mday);
308                                 tmpUntilCalendarTime.time.utime = _CalendarbookUtil::ConvertDateTimeToEpochTime(tmpUntilTime);
309
310                                 calendar_record_set_caltime(__eventRecord.GetHandle(), _calendar_event.until_time, tmpUntilCalendarTime);
311                         }
312                 }
313
314                 if (isChanged)
315                 {
316                         if (__pRecurrence == null)
317                         {
318                                 __pRecurrence.reset(ConvertEventHandleToRecurrenceN(__eventRecord.GetHandle()));
319                         }
320
321                         std::unique_ptr<char[]> pExDates(_StringConverter::CopyToCharArrayN(ConvertRecurrenceToRRuleExDateString(*__pRecurrence.get(), isAllDayEvent)));
322                         int errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.exdate, pExDates.get());
323                         SysTryReturnVoidResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
324                 }
325         }
326 }
327
328 ByteBuffer*
329 _CalEventImpl::GetUIDN(void) const
330 {
331         ClearLastResult();
332
333         char* pStrUid = null;
334         calendar_record_get_str_p(__eventRecord.GetHandle(), _calendar_event.uid, &pStrUid);
335
336         if (pStrUid == null || strlen(pStrUid) == 0)
337         {
338                 return null;
339         }
340
341         ByteBuffer* pConvertedUidBuffer = _CalendarbookUtil::ConvertCharArrayToByteBufferN(pStrUid);
342         SysTryReturn(NID_SCL, pConvertedUidBuffer != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
343
344         return pConvertedUidBuffer;
345 }
346
347 result
348 _CalEventImpl::SetUID(const ByteBuffer* pUid)
349 {
350         int errorCode = CALENDAR_ERROR_NONE;
351
352         if (pUid != null)
353         {
354                 std::unique_ptr<char[]> pConvertedUidArray(_CalendarbookUtil::ConvertByteBufferToCharArrayN(*pUid));
355                 SysTryReturn(NID_SCL, pConvertedUidArray != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
356
357                 errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.uid, pConvertedUidArray.get());
358                 SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
359         }
360         else
361         {
362                 errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.uid, null);
363                 SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
364         }
365
366         return E_SUCCESS;
367 }
368
369 String
370 _CalEventImpl::GetUid(void) const
371 {
372         char* pStrUid = null;
373         calendar_record_get_str_p(__eventRecord.GetHandle(), _calendar_event.uid, &pStrUid);
374
375         return String(pStrUid);
376 }
377
378 void
379 _CalEventImpl::SetUid(const String& uid)
380 {
381         std::unique_ptr<char[]> pStrUid(_StringConverter::CopyToCharArrayN(uid));
382         SysTryReturnVoidResult(NID_SCL, pStrUid != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
383
384         int errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.uid, pStrUid.get());
385         SysTryReturnVoidResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
386 }
387
388 EventStatus
389 _CalEventImpl::GetStatus(void) const
390 {
391         int srcEventStatus = CALENDAR_EVENT_STATUS_NONE;
392
393         EventStatus eventStatus = EVENT_STATUS_NONE;
394
395         calendar_record_get_int(__eventRecord.GetHandle(), _calendar_event.event_status, &srcEventStatus);
396
397         switch (srcEventStatus)
398         {
399         case CALENDAR_EVENT_STATUS_NONE:
400                 eventStatus = EVENT_STATUS_NONE;
401                 break;
402         case CALENDAR_EVENT_STATUS_TENTATIVE:
403                 eventStatus = EVENT_STATUS_TENTATIVE;
404                 break;
405         case CALENDAR_EVENT_STATUS_CONFIRMED:
406                 eventStatus = EVENT_STATUS_CONFIRMED;
407                 break;
408         case CALENDAR_EVENT_STATUS_CANCELLED:
409                 eventStatus = EVENT_STATUS_CANCELLED;
410                 break;
411         default :
412                 SysLog(NID_SCL, "The status value is invalid.");
413                 return EVENT_STATUS_NONE;
414         }
415
416         return eventStatus;
417 }
418
419 void
420 _CalEventImpl::SetStatus(EventStatus status)
421 {
422         calendar_record_set_int(__eventRecord.GetHandle(), _calendar_event.event_status, _CalendarbookUtil::ConvertEventStatusToCSEventStatus(status));
423 }
424
425 BusyStatus
426 _CalEventImpl::GetBusyStatus(void) const
427 {
428         int srcEventBusyStatus = CALENDAR_EVENT_BUSY_STATUS_FREE;
429
430         BusyStatus busyStatus = BUSY_STATUS_FREE;
431
432         calendar_record_get_int(__eventRecord.GetHandle(), _calendar_event.busy_status, &srcEventBusyStatus);
433
434         switch (srcEventBusyStatus)
435         {
436         case CALENDAR_EVENT_BUSY_STATUS_FREE:
437                 busyStatus = BUSY_STATUS_FREE;
438                 break;
439         case CALENDAR_EVENT_BUSY_STATUS_BUSY:
440                 busyStatus = BUSY_STATUS_BUSY;
441                 break;
442         case CALENDAR_EVENT_BUSY_STATUS_UNAVAILABLE:
443                 busyStatus = BUSY_STATUS_UNAVAILABLE;
444                 break;
445         case CALENDAR_EVENT_BUSY_STATUS_TENTATIVE:
446                 busyStatus = BUSY_STATUS_TENTATIVE;
447                 break;
448         default :
449                 SysLog(NID_SCL, "The busy status value is invalid.");
450                 busyStatus = BUSY_STATUS_FREE;
451                 break;
452         }
453
454         return busyStatus;
455 }
456
457 void
458 _CalEventImpl::SetBusyStatus(BusyStatus busyStatus)
459 {
460         calendar_record_set_int(__eventRecord.GetHandle(), _calendar_event.busy_status, _CalendarbookUtil::ConvertBusyStatusToCSEventBusyStatus(busyStatus));
461 }
462
463 EventPriority
464 _CalEventImpl::GetPriority(void) const
465 {
466         int srcPriority = CALENDAR_EVENT_PRIORITY_LOW;
467
468         EventPriority priority = EVENT_PRIORITY_NORMAL;
469
470         calendar_record_get_int(__eventRecord.GetHandle(), _calendar_event.priority, &srcPriority);
471
472         switch (srcPriority)
473         {
474         case CALENDAR_EVENT_PRIORITY_LOW:
475                 priority = EVENT_PRIORITY_LOW;
476                 break;
477         case CALENDAR_EVENT_PRIORITY_NONE:
478                 // fall through
479         case CALENDAR_EVENT_PRIORITY_NORMAL:
480                 priority = EVENT_PRIORITY_NORMAL;
481                 break;
482         case CALENDAR_EVENT_PRIORITY_HIGH:
483                 priority = EVENT_PRIORITY_HIGH;
484                 break;
485         default :
486                 SysLog(NID_SCL, "The priority value is invalid.");
487                 priority = EVENT_PRIORITY_NORMAL;
488         }
489
490         return priority;
491 }
492
493 void
494 _CalEventImpl::SetPriority(EventPriority priority)
495 {
496         calendar_record_set_int(__eventRecord.GetHandle(), _calendar_event.priority, _CalendarbookUtil::ConvertEventPriorityToCSEventPriority(priority));
497 }
498
499 result
500 _CalEventImpl::AddAttendee(const Attendee& attendee)
501 {
502         if (_AppInfo::GetApiVersion() == _API_VERSION_2_0)
503         {
504                 SysTryReturnResult(NID_SCL, !attendee.GetEmail().IsEmpty(), E_OBJ_ALREADY_EXIST
505                                         , "The attendee's email string is empty.");
506         }
507         else
508         {
509                 SysTryReturnResult(NID_SCL, !attendee.GetEmail().IsEmpty(), E_INVALID_ARG
510                                         , "The attendee's email string is empty.");
511         }
512
513         std::unique_ptr<char[]> pConvertedEmail(_StringConverter::CopyToCharArrayN(attendee.GetEmail()));
514         SysTryReturnResult(NID_SCL, pConvertedEmail != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
515
516         SysTryReturnResult(NID_SCL, GetAttendeeIndex(pConvertedEmail.get()) == _INVALID_ATTENDEE_INDEX, E_OBJ_ALREADY_EXIST
517                                 , "The specified attendee already exists as this email is already registered.");
518
519         std::unique_ptr<char[]> pConvertedName(_StringConverter::CopyToCharArrayN(attendee.GetName()));
520         SysTryReturnResult(NID_SCL, pConvertedName != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
521
522         std::unique_ptr<char[]> pConvertedPhoneNumber(_StringConverter::CopyToCharArrayN(attendee.GetPhoneNumber()));
523         SysTryReturnResult(NID_SCL, pConvertedPhoneNumber != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
524
525         calendar_attendee_status_e convertedStatus = CALENDAR_ATTENDEE_STATUS_TENTATIVE;
526         switch (attendee.GetStatus())
527         {
528         case ATTENDEE_STATUS_NONE:
529                 convertedStatus = CALENDAR_ATTENDEE_STATUS_COMPLETED;
530                 break;
531         case ATTENDEE_STATUS_NOT_RESPONDED:
532                 convertedStatus = CALENDAR_ATTENDEE_STATUS_PENDING;
533                 break;
534         case ATTENDEE_STATUS_ACCEPTED:
535                 convertedStatus = CALENDAR_ATTENDEE_STATUS_ACCEPTED;
536                 break;
537         case ATTENDEE_STATUS_DECLINED:
538                 convertedStatus = CALENDAR_ATTENDEE_STATUS_DECLINED;
539                 break;
540         case ATTENDEE_STATUS_TENTATIVE:
541                 convertedStatus = CALENDAR_ATTENDEE_STATUS_TENTATIVE;
542                 break;
543         default:
544                 SysLog(NID_SCL, "The attendee status value is invalid. attendee status = %d", attendee.GetStatus());
545                 convertedStatus = CALENDAR_ATTENDEE_STATUS_TENTATIVE;
546                 break;
547         }
548
549         calendar_attendee_role_e convertedRole = CALENDAR_ATTENDEE_ROLE_NON_PARTICIPANT;
550         switch (attendee.GetRole())
551         {
552         case ATTENDEE_ROLE_ATTENDEE:
553                 convertedRole = CALENDAR_ATTENDEE_ROLE_OPT_PARTICIPANT;
554                 break;
555         case ATTENDEE_ROLE_REQUIRED_ATTENDEE:
556                 convertedRole = CALENDAR_ATTENDEE_ROLE_REQ_PARTICIPANT;
557                 break;
558         case ATTENDEE_ROLE_ORGANIZER:
559                 convertedRole = CALENDAR_ATTENDEE_ROLE_CHAIR;
560                 break;
561         default:
562                 SysLog(NID_SCL, "The attendee role value is invalid. attendee role = %d", attendee.GetRole());
563                 convertedRole = CALENDAR_ATTENDEE_ROLE_OPT_PARTICIPANT;
564                 break;
565         }
566
567         calendar_record_h attendeeHandle = null;
568         int errorCode = calendar_record_create(_calendar_attendee._uri, &attendeeHandle);
569         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
570
571         errorCode = calendar_record_set_str(attendeeHandle, _calendar_attendee.name, pConvertedName.get());
572         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
573         errorCode = calendar_record_set_str(attendeeHandle, _calendar_attendee.email, pConvertedEmail.get());
574         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
575         errorCode = calendar_record_set_str(attendeeHandle, _calendar_attendee.number, pConvertedPhoneNumber.get());
576         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
577         calendar_record_set_int(attendeeHandle, _calendar_attendee.status, convertedStatus);
578         calendar_record_set_int(attendeeHandle, _calendar_attendee.role, convertedRole);
579         calendar_record_set_int(attendeeHandle, _calendar_attendee.person_id, attendee.GetPersonId());
580
581         errorCode = calendar_record_add_child_record(__eventRecord.GetHandle(), _calendar_event.calendar_attendee, attendeeHandle);
582         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
583
584         return E_SUCCESS;
585 }
586
587 result
588 _CalEventImpl::RemoveAttendee(const Attendee& attendee)
589 {
590         std::unique_ptr<char[]> pConvertedEmail(_StringConverter::CopyToCharArrayN(attendee.GetEmail()));
591         SysTryReturnResult(NID_SCL, pConvertedEmail != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
592
593         int index = GetAttendeeIndex(pConvertedEmail.get());
594         SysTryReturnResult(NID_SCL, index != _INVALID_ATTENDEE_INDEX, E_OBJ_NOT_FOUND, "The specified attendee does not exist.");
595
596         calendar_record_h tmpAttendeeHandle = null;
597         calendar_record_get_child_record_at_p(__eventRecord.GetHandle(), _calendar_event.calendar_attendee, index, &tmpAttendeeHandle);
598         calendar_record_remove_child_record(__eventRecord.GetHandle(), _calendar_event.calendar_attendee, tmpAttendeeHandle);
599
600         return E_SUCCESS;
601 }
602
603 IList*
604 _CalEventImpl::GetAllAttendeesN(void) const
605 {
606         ClearLastResult();
607
608         std::unique_ptr<ArrayList, AllElementsDeleter> pList(new (std::nothrow) ArrayList());
609         SysTryReturn(NID_SCL, pList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
610         result r = pList->Construct();
611         SysTryReturn(NID_SCL, !IsFailed(r), null, r, "[%s] Propagating.", GetErrorMessage(r));
612
613         unsigned int attendeeCount = 0;
614         calendar_record_get_child_record_count(__eventRecord.GetHandle(), _calendar_event.calendar_attendee, &attendeeCount);
615
616         for (unsigned int i = 0; i < attendeeCount; i++)
617         {
618                 calendar_record_h tmpAttendeeHandle = null;
619                 char* pTmpEmail = null;
620                 char* pTmpName = null;
621                 char* pTmpPhoneNumber = null;
622                 int tmpStatus = 0;
623                 int tmpRole = 0;
624                 int tmpPersonId = -1;
625                 AttendeeStatus attendeeStatus = ATTENDEE_STATUS_NONE;
626                 AttendeeRole attendeeRole = ATTENDEE_ROLE_ATTENDEE;
627
628                 calendar_record_get_child_record_at_p(__eventRecord.GetHandle(), _calendar_event.calendar_attendee, i, &tmpAttendeeHandle);
629                 calendar_record_get_str_p(tmpAttendeeHandle, _calendar_attendee.email, &pTmpEmail);
630                 calendar_record_get_str_p(tmpAttendeeHandle, _calendar_attendee.name, &pTmpName);
631                 calendar_record_get_str_p(tmpAttendeeHandle, _calendar_attendee.number, &pTmpPhoneNumber);
632                 calendar_record_get_int(tmpAttendeeHandle, _calendar_attendee.status, &tmpStatus);
633                 calendar_record_get_int(tmpAttendeeHandle, _calendar_attendee.role, &tmpRole);
634                 calendar_record_get_int(tmpAttendeeHandle, _calendar_attendee.person_id, &tmpPersonId);
635
636                 switch (tmpStatus)
637                 {
638                 case CALENDAR_ATTENDEE_STATUS_PENDING:
639                         attendeeStatus = ATTENDEE_STATUS_NOT_RESPONDED;
640                         break;
641                 case CALENDAR_ATTENDEE_STATUS_ACCEPTED:
642                         attendeeStatus = ATTENDEE_STATUS_ACCEPTED;
643                         break;
644                 case CALENDAR_ATTENDEE_STATUS_DECLINED:
645                         attendeeStatus = ATTENDEE_STATUS_DECLINED;
646                         break;
647                 case CALENDAR_ATTENDEE_STATUS_TENTATIVE:
648                         attendeeStatus = ATTENDEE_STATUS_TENTATIVE;
649                         break;
650                 case CALENDAR_ATTENDEE_STATUS_DELEGATED:
651                         attendeeStatus = ATTENDEE_STATUS_NONE;
652                         break;
653                 case CALENDAR_ATTENDEE_STATUS_COMPLETED:
654                         attendeeStatus = ATTENDEE_STATUS_NONE;
655                         break;
656                 case CALENDAR_ATTENDEE_STATUS_IN_PROCESS:
657                         attendeeStatus = ATTENDEE_STATUS_NOT_RESPONDED;
658                         break;
659                 default:
660                         SysLog(NID_SCL, "The attendee status value is invalid. attendee status = %d", tmpStatus);
661                         attendeeStatus = ATTENDEE_STATUS_NONE;
662                         break;
663                 }
664
665                 switch (tmpRole)
666                 {
667                 case CALENDAR_ATTENDEE_ROLE_REQ_PARTICIPANT:
668                         attendeeRole = ATTENDEE_ROLE_REQUIRED_ATTENDEE;
669                         break;
670                 case CALENDAR_ATTENDEE_ROLE_OPT_PARTICIPANT:
671                         attendeeRole = ATTENDEE_ROLE_ATTENDEE;
672                         break;
673                 case CALENDAR_ATTENDEE_ROLE_NON_PARTICIPANT:
674                         attendeeRole = ATTENDEE_ROLE_ATTENDEE;
675                         break;
676                 case CALENDAR_ATTENDEE_ROLE_CHAIR:
677                         attendeeRole = ATTENDEE_ROLE_ORGANIZER;
678                         break;
679                 default:
680                         SysLog(NID_SCL, "The attendee role value is invalid. attendee role = %d", tmpRole);
681                         attendeeRole = ATTENDEE_ROLE_ATTENDEE;
682                         break;
683                 }
684
685                 std::unique_ptr<Attendee> pTmpAttendee(new (std::nothrow) Attendee(pTmpEmail));
686                 SysTryReturn(NID_SCL, pTmpAttendee != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
687
688                 if (pTmpName != null && strlen(pTmpName) > 0)
689                 {
690                         pTmpAttendee->SetName(pTmpName);
691                 }
692
693                 if (pTmpPhoneNumber != null && strlen(pTmpPhoneNumber) > 0)
694                 {
695                         pTmpAttendee->SetPhoneNumber(pTmpPhoneNumber);
696                 }
697
698                 pTmpAttendee->SetStatus(attendeeStatus);
699                 pTmpAttendee->SetRole(attendeeRole);
700                 pTmpAttendee->SetPersonId(tmpPersonId);
701
702                 r = pList->Add(pTmpAttendee.get());
703                 SysTryReturn(NID_SCL, !IsFailed(r), null, r, "[%s] Propagating.", GetErrorMessage(r));
704
705                 pTmpAttendee.release();
706         }
707
708         return pList.release();
709 }
710
711 TimeZone
712 _CalEventImpl::GetTimeZone(void) const
713 {
714         char* pTimeZoneId = null;
715         TimeZone timeZone;
716
717         calendar_record_get_str_p(__eventRecord.GetHandle(), _calendar_event.start_tzid, &pTimeZoneId);
718         if (pTimeZoneId != null && strlen(pTimeZoneId) > 0)
719         {
720                 DateTime startTime = GetStartTime();
721
722                 TimeZone::GetTimeZone(pTimeZoneId, startTime, timeZone);
723         }
724
725         return timeZone;
726 }
727
728 result
729 _CalEventImpl::SetTimeZone(const TimeZone& timeZone)
730 {
731         std::unique_ptr<char[]> pConvertedTimeZoneId(_StringConverter::CopyToCharArrayN(timeZone.GetId()));
732         SysTryReturnResult(NID_SCL, pConvertedTimeZoneId != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
733
734         int errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.start_tzid, pConvertedTimeZoneId.get());
735         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
736         errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.end_tzid, pConvertedTimeZoneId.get());
737         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
738
739         return E_SUCCESS;
740 }
741
742 RecurrenceId
743 _CalEventImpl::GetRecurrenceId(void) const
744 {
745         ClearLastResult();
746         SysTryReturn(NID_SCL, __isInstance, DateTime(), E_INVALID_STATE,
747                                 "[%s] The instance does not have a recurrence or is not a CalEvent instance which doesn't have a RecurrenceId.", GetErrorMessage(E_INVALID_STATE));
748
749         return GetStartTime();
750 }
751
752 String
753 _CalEventImpl::GetSubject(void) const
754 {
755         char* pSubject = null;
756
757         calendar_record_get_str_p(__eventRecord.GetHandle(), _calendar_event.summary, &pSubject);
758
759         return String(pSubject);
760 }
761
762 String
763 _CalEventImpl::GetDescription(void) const
764 {
765         char* pDescription = null;
766
767         calendar_record_get_str_p(__eventRecord.GetHandle(), _calendar_event.description, &pDescription);
768
769         return String(pDescription);
770 }
771 DateTime
772 _CalEventImpl::GetStartTime(void) const
773 {
774         calendar_time_s startCalendarTime;
775         DateTime tmpStartTime;
776
777         calendar_record_get_caltime(__eventRecord.GetHandle(), _calendar_event.start_time, &startCalendarTime);
778
779         if (startCalendarTime.type == CALENDAR_TIME_UTIME)
780         {
781                 tmpStartTime = _CalendarbookUtil::ConvertEpochTimeToDateTime(startCalendarTime.time.utime);
782         }
783         else
784         {
785                 tmpStartTime.SetValue(startCalendarTime.time.date.year, startCalendarTime.time.date.month, startCalendarTime.time.date.mday);
786         }
787
788         return tmpStartTime;
789 }
790
791 DateTime
792 _CalEventImpl::GetEndTime(void) const
793 {
794         calendar_time_s endCalendarTime;
795         DateTime tmpEndTime;
796
797         calendar_record_get_caltime(__eventRecord.GetHandle(), _calendar_event.end_time, &endCalendarTime);
798
799         if (endCalendarTime.type == CALENDAR_TIME_UTIME)
800         {
801                 tmpEndTime = _CalendarbookUtil::ConvertEpochTimeToDateTime(endCalendarTime.time.utime);
802         }
803         else if (endCalendarTime.type == CALENDAR_TIME_LOCALTIME)
804         {
805                 tmpEndTime.SetValue(endCalendarTime.time.date.year, endCalendarTime.time.date.month, endCalendarTime.time.date.mday);
806         }
807
808         return tmpEndTime;
809 }
810
811 String
812 _CalEventImpl::GetLocation(void) const
813 {
814         char* pLocation = null;
815
816         calendar_record_get_str_p(__eventRecord.GetHandle(), _calendar_event.location, &pLocation);
817
818         return String(pLocation);
819 }
820
821 EventCategory
822 _CalEventImpl::GetCategory(void) const
823 {
824         char* pCategories = null;
825
826         calendar_record_get_str_p(__eventRecord.GetHandle(), _calendar_event.categories, &pCategories);
827
828         return _CalendarbookUtil::ConvertCSCategoriesToEventCategory(pCategories);
829 }
830
831 RecordSensitivity
832 _CalEventImpl::GetSensitivity(void) const
833 {
834         int srcSensitivity = CALENDAR_SENSITIVITY_PUBLIC;
835         RecordSensitivity sensitivity = SENSITIVITY_PUBLIC;
836
837         calendar_record_get_int(__eventRecord.GetHandle(), _calendar_event.sensitivity, &srcSensitivity);
838
839         switch (srcSensitivity)
840         {
841         case CALENDAR_SENSITIVITY_PUBLIC:
842                 sensitivity = SENSITIVITY_PUBLIC;
843                 break;
844         case CALENDAR_SENSITIVITY_PRIVATE:
845                 sensitivity = SENSITIVITY_PRIVATE;
846                 break;
847         case CALENDAR_SENSITIVITY_CONFIDENTIAL:
848                 sensitivity = SENSITIVITY_CONFIDENTIAL;
849                 break;
850         default :
851                 SysLogException(NID_SCL, E_INVALID_ARG, "[%s] Invalid argument is used. sensitivity = %d", GetErrorMessage(E_INVALID_ARG), srcSensitivity);
852                 sensitivity = SENSITIVITY_PUBLIC;
853         }
854
855         return sensitivity;
856 }
857
858 const Reminder*
859 _CalEventImpl::GetReminder(void) const
860 {
861         if (__reminderListUpdated == false)
862         {
863                 result r = _CalendarbookUtil::ConvertEventAlarmsToReminderList(__eventRecord.GetHandle(), __reminderList);
864                 SysTryReturn(NID_SCL, r == E_SUCCESS, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
865
866                 __reminderListUpdated = true;
867         }
868
869         if (__reminderList.GetCount() > 0)
870         {
871                 return static_cast<const Reminder*>(__reminderList.GetAt(0));
872         }
873
874         return null;
875 }
876
877 const Recurrence*
878 _CalEventImpl::GetRecurrence(void) const
879 {
880         if (__pRecurrence == null)
881         {
882                 __pRecurrence.reset(ConvertEventHandleToRecurrenceN(__eventRecord.GetHandle()));
883         }
884
885         return __pRecurrence.get();
886 }
887
888 Recurrence*
889 _CalEventImpl::ConvertEventHandleToRecurrenceN(calendar_record_h eventHandle) const
890 {
891         int srcFrequency = CALENDAR_RECURRENCE_NONE;
892         calendar_time_s untilCalendarTime;
893         int rangeType = CALENDAR_RANGE_NONE;
894         int count = 0;
895         int interval = 0;
896         char* pByDay = null;
897         char* pByMonthDay = null;
898         char* pByMonth = null;
899         int weekStart = 0;
900         char* pExDates = null;
901
902         result r = E_SUCCESS;
903         int dayOfWeek = 0;
904         int monthOfYear = 0;
905         int dayOfMonth = 0;
906         int weekOfMonth = 0;
907         CalDayOfWeek convertedWeekStart = CAL_SUNDAY;
908
909         std::unique_ptr<Recurrence> pRecurrence(new (std::nothrow) Recurrence());
910
911         calendar_record_get_int(eventHandle, _calendar_event.freq, &srcFrequency);
912
913         if (srcFrequency == CALENDAR_RECURRENCE_NONE)
914         {
915                 return null;
916         }
917
918         calendar_record_get_int(eventHandle, _calendar_event.range_type, &rangeType);
919         calendar_record_get_int(eventHandle, _calendar_event.count, &count);
920         calendar_record_get_int(eventHandle, _calendar_event.interval, &interval);
921         calendar_record_get_caltime(eventHandle, _calendar_event.until_time, &untilCalendarTime);
922         calendar_record_get_int(eventHandle, _calendar_event.wkst, &weekStart);
923
924         calendar_record_get_str_p(eventHandle, _calendar_event.byday, &pByDay);
925         calendar_record_get_str_p(eventHandle, _calendar_event.bymonthday, &pByMonthDay);
926         if (pByMonthDay != null)
927         {
928                 r = Integer::Parse(pByMonthDay, dayOfMonth);
929                 SysTryReturn(NID_SCL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
930         }
931         calendar_record_get_str_p(eventHandle, _calendar_event.bymonth, &pByMonth);
932         if (pByMonth != null)
933         {
934                 r = Integer::Parse(pByMonth, monthOfYear);
935                 SysTryReturn(NID_SCL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
936         }
937
938         switch (srcFrequency)
939         {
940         case CALENDAR_RECURRENCE_DAILY:
941                 pRecurrence->SetFrequency(FREQ_DAILY);
942                 break;
943
944         case CALENDAR_RECURRENCE_WEEKLY:
945                 pRecurrence->SetFrequency(FREQ_WEEKLY);
946
947                 dayOfWeek = ConvertRRuleByDayStringToDayOfWeek(pByDay);
948                 SysTryReturn(NID_SCL, GetLastResult() == E_SUCCESS, null, E_INVALID_ARG, "[%s] Invalid argument is used. byday = %s", GetErrorMessage(E_INVALID_ARG), pByDay);
949
950                 pRecurrence->SetDayOfWeek(dayOfWeek);
951                 break;
952
953         case CALENDAR_RECURRENCE_MONTHLY:
954                 pRecurrence->SetFrequency(FREQ_MONTHLY);
955
956                 if (dayOfMonth != 0)
957                 {
958                         if (dayOfMonth < 0)
959                         {
960                                 int maxDaysOfMonth = _CalendarbookUtil::GetMaxDaysOfMonth(untilCalendarTime.time.date.year, monthOfYear);
961                                 pRecurrence->SetDayOfMonth(maxDaysOfMonth + dayOfMonth);
962                         }
963                         else
964                         {
965                                 pRecurrence->SetDayOfMonth(dayOfMonth);
966                         }
967                 }
968                 else
969                 {
970                         if(pByDay != null)
971                         {
972                                 r = ConvertRRuleByDayStringToDayOfWeekAndWeekOfMonth(pByDay, weekOfMonth, dayOfWeek);
973                                 SysTryReturn(NID_SCL, r == E_SUCCESS, null, E_INVALID_ARG, "[%s] Invalid argument is used. byday = %s", GetErrorMessage(E_INVALID_ARG), pByDay);
974
975                                 pRecurrence->SetWeekOfMonth(weekOfMonth);
976                                 pRecurrence->SetDayOfWeek(dayOfWeek);
977                         }
978                         else
979                         {
980                                 DateTime startTime = GetStartTime();
981
982                                 dayOfMonth = startTime.GetDay();
983                                 pRecurrence->SetDayOfMonth(dayOfMonth);
984                         }
985                 }
986
987                 break;
988
989         case CALENDAR_RECURRENCE_YEARLY:
990                 pRecurrence->SetFrequency(FREQ_YEARLY);
991
992                 if (dayOfMonth != 0)
993                 {
994                         if (dayOfMonth < 0)
995                         {
996                                 int maxDaysOfMonth = _CalendarbookUtil::GetMaxDaysOfMonth(untilCalendarTime.time.date.year, monthOfYear);
997                                 pRecurrence->SetDayOfMonth(maxDaysOfMonth + dayOfMonth);
998                         }
999                         else
1000                         {
1001                                 pRecurrence->SetDayOfMonth(dayOfMonth);
1002                         }
1003                 }
1004                 else
1005                 {
1006                         if(pByDay != null)
1007                         {
1008                                 r = ConvertRRuleByDayStringToDayOfWeekAndWeekOfMonth(pByDay, weekOfMonth, dayOfWeek);
1009                                 SysTryReturn(NID_SCL, r == E_SUCCESS, null, E_INVALID_ARG, "[%s] Invalid argument is used. byday = %s", GetErrorMessage(E_INVALID_ARG), pByDay);
1010
1011                                 pRecurrence->SetWeekOfMonth(weekOfMonth);
1012                                 pRecurrence->SetDayOfWeek(dayOfWeek);
1013                         }
1014                         else
1015                         {
1016                                 DateTime startTime = GetStartTime();
1017
1018                                 dayOfMonth = startTime.GetDay();
1019                                 monthOfYear = startTime.GetMonth();
1020
1021                                 pRecurrence->SetDayOfMonth(dayOfMonth);
1022                         }
1023                 }
1024                 pRecurrence->SetMonthOfYear(monthOfYear);
1025
1026                 break;
1027
1028         default :
1029                 SysLogException(NID_SCL, E_INVALID_ARG, "Invalid argument is passed. frequency = %d", srcFrequency);
1030                 return null;
1031         }
1032
1033         if (rangeType == CALENDAR_RANGE_NONE)
1034         {
1035                 pRecurrence->SetUntil(&DateTime::GetMaxValue());
1036         }
1037         else if (rangeType == CALENDAR_RANGE_UNTIL)
1038         {
1039                 DateTime until;
1040
1041                 if (untilCalendarTime.type == CALENDAR_TIME_LOCALTIME)
1042                 {
1043                         until.SetValue(untilCalendarTime.time.date.year, untilCalendarTime.time.date.month, untilCalendarTime.time.date.mday);
1044                 }
1045                 else
1046                 {
1047                         until = _CalendarbookUtil::ConvertEpochTimeToDateTime(untilCalendarTime.time.utime);
1048                 }
1049
1050                 if (until < _CalendarbookImpl::GetMinDateTime())
1051                 {
1052                         until = _CalendarbookImpl::GetMinDateTime();
1053                 }
1054                 else if(until > _CalendarbookImpl::GetMaxDateTime())
1055                 {
1056                         until = _CalendarbookImpl::GetMaxDateTime();
1057                 }
1058
1059                 pRecurrence->SetUntil(&until);
1060         }
1061         else
1062         {
1063                 pRecurrence->SetCounts(count);
1064         }
1065         pRecurrence->SetInterval(interval);
1066
1067         switch (weekStart)
1068         {
1069         case CALENDAR_SUNDAY:
1070                 convertedWeekStart = CAL_SUNDAY;
1071                 break;
1072
1073         case CALENDAR_MONDAY:
1074                 convertedWeekStart = CAL_MONDAY;
1075                 break;
1076
1077         default:
1078                 SysLogException(NID_SCL, E_INVALID_ARG, "Invalid argument is passed. week start = %d", weekStart);
1079                 return null;
1080         }
1081         pRecurrence->SetWeekStart(convertedWeekStart);
1082
1083         calendar_record_get_str_p(eventHandle, _calendar_event.exdate, &pExDates);
1084         if (pExDates != null && strlen(pExDates) != 0)
1085         {
1086                 r = ConvertRRuleExDateStringToRecurrence(pExDates, *pRecurrence.get());
1087                 SysTryReturn(NID_SCL, r == E_SUCCESS, null, E_INVALID_ARG, "[%s] Invalid argument is used. exdate = %s", GetErrorMessage(E_INVALID_ARG), pExDates);
1088         }
1089
1090         return pRecurrence.release();
1091 }
1092
1093 DateTime
1094 _CalEventImpl::GetLastRevisedTime(void) const
1095 {
1096         long long lastModifiedTime = 0;
1097         DateTime tmpLastRevisedTime;
1098
1099         calendar_record_get_lli(__eventRecord.GetHandle(), _calendar_event.last_modified_time, &lastModifiedTime);
1100
1101         tmpLastRevisedTime = _CalendarbookUtil::ConvertEpochTimeToDateTime(lastModifiedTime);
1102
1103         return tmpLastRevisedTime;
1104 }
1105
1106 result
1107 _CalEventImpl::SetSubject(const String& subject)
1108 {
1109         if (_AppInfo::GetApiVersion() == _API_VERSION_2_0 && _AppInfo::IsOspCompat())
1110         {
1111                 SysTryReturnResult(NID_SCL, subject.GetLength() <= MAX_EVENT_SUBJECT_LENGTH, E_INVALID_ARG
1112                                 , "The length of the value exceeds MAX_EVENT_SUBJECT_LENGTH.");
1113         }
1114
1115         std::unique_ptr<char[]> pConvertedSubject(_StringConverter::CopyToCharArrayN(subject));
1116         SysTryReturnResult(NID_SCL, pConvertedSubject != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1117
1118         int errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.summary, pConvertedSubject.get());
1119         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1120
1121         return E_SUCCESS;
1122 }
1123
1124 result
1125 _CalEventImpl::SetDescription(const String& description)
1126 {
1127         if (_AppInfo::GetApiVersion() == _API_VERSION_2_0 && _AppInfo::IsOspCompat())
1128         {
1129                 SysTryReturnResult(NID_SCL, description.GetLength() <= MAX_EVENT_DESCRIPTION_LENGTH, E_INVALID_ARG
1130                                 , "The length of the value exceeds MAX_EVENT_DESCRIPTION_LENGTH.");
1131         }
1132
1133         std::unique_ptr<char[]> pConvertedDescription(_StringConverter::CopyToCharArrayN(description));
1134         SysTryReturnResult(NID_SCL, pConvertedDescription != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1135
1136         int errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.description, pConvertedDescription.get());
1137         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1138
1139         return E_SUCCESS;
1140 }
1141
1142 result
1143 _CalEventImpl::SetLocation(const String& location)
1144 {
1145         if (_AppInfo::GetApiVersion() == _API_VERSION_2_0 && _AppInfo::IsOspCompat())
1146         {
1147                 SysTryReturnResult(NID_SCL, location.GetLength() <= MAX_EVENT_LOCATION_LENGTH, E_INVALID_ARG
1148                                 , "The length of the value exceeds MAX_EVENT_LOCATION_LENGTH.");
1149         }
1150
1151         std::unique_ptr<char[]> pConvertedLocation(_StringConverter::CopyToCharArrayN(location));
1152         SysTryReturnResult(NID_SCL, pConvertedLocation != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1153
1154         int errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.location, pConvertedLocation.get());
1155         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1156
1157         return E_SUCCESS;
1158 }
1159
1160 result
1161 _CalEventImpl::SetStartAndEndTime(const DateTime& start, const DateTime& end)
1162 {
1163         int recurrenceFrequency = 0;
1164
1165         calendar_record_get_int(__eventRecord.GetHandle(), _calendar_event.freq, &recurrenceFrequency);
1166
1167         SysTryReturnResult(NID_SCL, recurrenceFrequency == CALENDAR_RECURRENCE_NONE, E_INVALID_CONDITION
1168                         , "The recurrence date is already set. Cannot modify the start and end date/time.");
1169         SysTryReturnResult(NID_SCL, _CalendarbookUtil::CheckValidDateTime(start), E_INVALID_ARG, "Invalid argument is used. start = %S", start.ToString().GetPointer());
1170         SysTryReturnResult(NID_SCL, _CalendarbookUtil::CheckValidDateTime(end), E_INVALID_ARG, "Invalid argument is used. end = %S", end.ToString().GetPointer());
1171         SysTryReturnResult(NID_SCL, start <= end, E_INVALID_ARG, "Invalid argument is used. The end date is earlier than the start date.");
1172
1173         return SetStartAndEndTimeCommon(start, end);
1174 }
1175
1176 result
1177 _CalEventImpl::SetStartAndEndTimeCommon(const DateTime& start, const DateTime& end)
1178 {
1179         calendar_time_s startCalendarTime;
1180         calendar_time_s endCalendarTime;
1181
1182         calendar_record_get_caltime(__eventRecord.GetHandle(), _calendar_event.start_time, &startCalendarTime);
1183
1184         if (startCalendarTime.type == CALENDAR_TIME_LOCALTIME)
1185         {
1186                 startCalendarTime.time.date.year = start.GetYear();
1187                 startCalendarTime.time.date.month = start.GetMonth();
1188                 startCalendarTime.time.date.mday = start.GetDay();
1189
1190                 endCalendarTime.type = CALENDAR_TIME_LOCALTIME;
1191                 endCalendarTime.time.date.year = end.GetYear();
1192                 endCalendarTime.time.date.month = end.GetMonth();
1193                 endCalendarTime.time.date.mday = end.GetDay();
1194         }
1195         else
1196         {
1197                 startCalendarTime.time.utime = _CalendarbookUtil::ConvertDateTimeToEpochTime(start);
1198
1199                 endCalendarTime.type = CALENDAR_TIME_UTIME;
1200                 endCalendarTime.time.utime = _CalendarbookUtil::ConvertDateTimeToEpochTime(end);
1201         }
1202
1203         calendar_record_set_caltime(__eventRecord.GetHandle(), _calendar_event.start_time, startCalendarTime);
1204         calendar_record_set_caltime(__eventRecord.GetHandle(), _calendar_event.end_time, endCalendarTime);
1205
1206         return E_SUCCESS;
1207 }
1208
1209 void
1210 _CalEventImpl::SetCategory(EventCategory category)
1211 {
1212         std::unique_ptr<char[]> pConvertedCategory;
1213
1214         if (category == EVENT_CATEGORY_ANNIVERSARY)
1215         {
1216                 SetAllDayEvent(true);
1217
1218                 pConvertedCategory.reset(_StringConverter::CopyToCharArrayN(_EVENT_CATEGORY_ANNIVERSARY_STRING));
1219                 SysTryReturnVoidResult(NID_SCL, pConvertedCategory != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1220         }
1221         else
1222         {
1223                 pConvertedCategory.reset(_StringConverter::CopyToCharArrayN(_EVENT_CATEGORY_APPOINTMENT_STRING));
1224                 SysTryReturnVoidResult(NID_SCL, pConvertedCategory != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1225         }
1226
1227         int errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.categories, pConvertedCategory.get());
1228         SysTryReturnVoidResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1229 }
1230
1231 void
1232 _CalEventImpl::SetSensitivity(RecordSensitivity sensitivity)
1233 {
1234         calendar_record_set_int(__eventRecord.GetHandle(), _calendar_event.sensitivity, _CalendarbookUtil::ConvertSensitivityToCSSensitivity(sensitivity));
1235 }
1236
1237 result
1238 _CalEventImpl::SetCoordinates(double latitude, double longitude)
1239 {
1240         SysTryReturnResult(NID_SCL, latitude >= _MIN_LATITUDE && latitude <= _MAX_LATITUDE, E_INVALID_ARG, "Invalid argument is used. The latitude is out of range.");
1241         SysTryReturnResult(NID_SCL, longitude >= _MIN_LONGITUDE && longitude <= _MAX_LONGITUDE, E_INVALID_ARG, "Invalid argument is used. The longitude is out of range.");
1242
1243         calendar_record_set_double(__eventRecord.GetHandle(), _calendar_event.latitude, latitude);
1244         calendar_record_set_double(__eventRecord.GetHandle(), _calendar_event.longitude, longitude);
1245
1246         return E_SUCCESS;
1247 }
1248
1249 void
1250 _CalEventImpl::GetCoordinates(double& latitude, double& longitude) const
1251 {
1252         calendar_record_get_double(__eventRecord.GetHandle(), _calendar_event.latitude, &latitude);
1253         calendar_record_get_double(__eventRecord.GetHandle(), _calendar_event.longitude, &longitude);
1254 }
1255
1256 result
1257 _CalEventImpl::SetReminder(const Reminder* pReminder)
1258 {
1259         unsigned int reminderCount = 0;
1260         calendar_record_h tmpAlarmHandle = null;
1261
1262         calendar_record_get_child_record_count(__eventRecord.GetHandle(), _calendar_event.calendar_alarm, &reminderCount);
1263
1264         if (pReminder != null)
1265         {
1266                 int convertedTimeUnit = 0;
1267                 switch (pReminder->GetTimeUnit())
1268                 {
1269                 case REMINDER_TIME_UNIT_MINUTE:
1270                         convertedTimeUnit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
1271                         break;
1272                 case REMINDER_TIME_UNIT_HOUR:
1273                         convertedTimeUnit = CALENDAR_ALARM_TIME_UNIT_HOUR;
1274                         break;
1275                 case REMINDER_TIME_UNIT_DAY:
1276                         convertedTimeUnit = CALENDAR_ALARM_TIME_UNIT_DAY;
1277                         break;
1278                 case REMINDER_TIME_UNIT_WEEK:
1279                         convertedTimeUnit = CALENDAR_ALARM_TIME_UNIT_WEEK;
1280                         break;
1281                 default:
1282                         break;
1283                 }
1284
1285                 calendar_record_h tmpAlarmHandle = null;
1286                 int errorCode = CALENDAR_ERROR_NONE;
1287
1288                 if (reminderCount > 0)
1289                 {
1290                         calendar_record_get_child_record_at_p(__eventRecord.GetHandle(), _calendar_event.calendar_alarm, 0, &tmpAlarmHandle);
1291                         calendar_record_set_int(tmpAlarmHandle, _calendar_alarm.tick_unit, convertedTimeUnit);
1292                         calendar_record_set_int(tmpAlarmHandle, _calendar_alarm.tick, pReminder->GetTimeOffset());
1293
1294                         std::unique_ptr<char[]> pTmpAlarmTone(_StringConverter::CopyToCharArrayN(pReminder->GetSoundFile()));
1295                         SysTryReturnResult(NID_SCL, pTmpAlarmTone != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1296
1297                         errorCode = calendar_record_set_str(tmpAlarmHandle, _calendar_alarm.tone, pTmpAlarmTone.get());
1298                         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1299                 }
1300                 else
1301                 {
1302                         std::unique_ptr<char[]> pTmpAlarmTone(_StringConverter::CopyToCharArrayN(pReminder->GetSoundFile()));
1303                         SysTryReturnResult(NID_SCL, pTmpAlarmTone != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1304
1305                         errorCode = calendar_record_create(_calendar_alarm._uri, &tmpAlarmHandle);
1306                         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1307
1308                         calendar_record_set_int(tmpAlarmHandle, _calendar_alarm.tick_unit, convertedTimeUnit);
1309                         calendar_record_set_int(tmpAlarmHandle, _calendar_alarm.tick, pReminder->GetTimeOffset());
1310                         errorCode = calendar_record_set_str(tmpAlarmHandle, _calendar_alarm.tone, pTmpAlarmTone.get());
1311                         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1312
1313                         errorCode = calendar_record_add_child_record(__eventRecord.GetHandle(), _calendar_event.calendar_alarm, tmpAlarmHandle);
1314                         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1315                 }
1316         }
1317         else
1318         {
1319                 if (reminderCount > 0)
1320                 {
1321                         calendar_record_get_child_record_at_p(__eventRecord.GetHandle(), _calendar_event.calendar_alarm, 0, &tmpAlarmHandle);
1322                         calendar_record_remove_child_record(__eventRecord.GetHandle(), _calendar_event.calendar_alarm, tmpAlarmHandle);
1323                 }
1324         }
1325
1326         __reminderList.RemoveAll(true);
1327         __reminderListUpdated = false;
1328
1329         return E_SUCCESS;
1330 }
1331
1332 result
1333 _CalEventImpl::SetRecurrence(const Recurrence* pRecurrence)
1334 {
1335         if (pRecurrence != null)
1336         {
1337                 result r = VerifyRecurrence(*pRecurrence);
1338                 SysTryReturn(NID_SCL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1339
1340                 r = ResetStartAndEndTimeByRecurrence(*pRecurrence);
1341                 SysTryReturn(NID_SCL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1342
1343                 r = ConvertRecurrenceToEventHandle(*pRecurrence, __eventRecord.GetHandle());
1344                 SysTryReturn(NID_SCL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1345
1346                 std::unique_ptr<char[]> pExDates(_StringConverter::CopyToCharArrayN(ConvertRecurrenceToRRuleExDateString(*pRecurrence, IsAllDayEvent())));
1347                 int errorCode = calendar_record_set_str(__eventRecord.GetHandle(), _calendar_event.exdate, pExDates.get());
1348                 SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1349
1350                 __pRecurrence.reset(new (std::nothrow) Recurrence(*pRecurrence));
1351                 SysTryReturnResult(NID_SCL, __pRecurrence != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1352         }
1353         else
1354         {
1355                 calendar_record_set_int(__eventRecord.GetHandle(), _calendar_event.freq, CALENDAR_RECURRENCE_NONE);
1356
1357                 __pRecurrence.reset(null);
1358         }
1359
1360         return E_SUCCESS;
1361 }
1362
1363 result
1364 _CalEventImpl::AddReminder(const Reminder& reminder)
1365 {
1366         calendar_record_h tmpAlarmHandle = null;
1367
1368         std::unique_ptr<char[]> pTmpAlarmTone(_StringConverter::CopyToCharArrayN(reminder.GetSoundFile()));
1369         SysTryReturnResult(NID_SCL, pTmpAlarmTone != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1370
1371         int errorCode = calendar_record_create(_calendar_alarm._uri, &tmpAlarmHandle);
1372         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1373
1374         int convertedTimeUnit = 0;
1375
1376         ReminderTimeUnit timeUnit = reminder.GetTimeUnit();
1377         switch (timeUnit)
1378         {
1379         case REMINDER_TIME_UNIT_MINUTE:
1380                 convertedTimeUnit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
1381                 break;
1382
1383         case REMINDER_TIME_UNIT_HOUR:
1384                 convertedTimeUnit = CALENDAR_ALARM_TIME_UNIT_HOUR;
1385                 break;
1386
1387         case REMINDER_TIME_UNIT_DAY:
1388                 convertedTimeUnit = CALENDAR_ALARM_TIME_UNIT_DAY;
1389                 break;
1390
1391         case REMINDER_TIME_UNIT_WEEK:
1392                 convertedTimeUnit = CALENDAR_ALARM_TIME_UNIT_WEEK;
1393                 break;
1394
1395         case REMINDER_TIME_UNIT_NONE:
1396                 convertedTimeUnit = CALENDAR_ALARM_TIME_UNIT_SPECIFIC;
1397                 break;
1398
1399         default:
1400                 break;
1401         }
1402
1403         calendar_record_set_int(tmpAlarmHandle, _calendar_alarm.tick_unit, convertedTimeUnit);
1404         calendar_record_set_int(tmpAlarmHandle, _calendar_alarm.tick, reminder.GetTimeOffset());
1405         errorCode = calendar_record_set_str(tmpAlarmHandle, _calendar_alarm.tone, pTmpAlarmTone.get());
1406         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1407
1408         if (convertedTimeUnit == CALENDAR_ALARM_TIME_UNIT_SPECIFIC)
1409         {
1410                 calendar_record_set_lli(tmpAlarmHandle, _calendar_alarm.time, _CalendarbookUtil::ConvertDateTimeToEpochTime(reminder.GetAbsoluteTime()));
1411         }
1412
1413         errorCode = calendar_record_add_child_record(__eventRecord.GetHandle(), _calendar_event.calendar_alarm, tmpAlarmHandle);
1414         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1415
1416         __reminderList.RemoveAll(true);
1417         __reminderListUpdated = false;
1418
1419         return E_SUCCESS;
1420 }
1421
1422 result
1423 _CalEventImpl::RemoveReminderAt(int index)
1424 {
1425         calendar_record_h tmpAlarmHandle = null;
1426
1427         calendar_record_get_child_record_at_p(__eventRecord.GetHandle(), _calendar_event.calendar_alarm, index, &tmpAlarmHandle);
1428         SysTryReturnResult(NID_SCL, tmpAlarmHandle != null, E_OUT_OF_RANGE, "The index is out of range. index = %d", index);
1429
1430         calendar_record_remove_child_record(__eventRecord.GetHandle(), _calendar_event.calendar_alarm, tmpAlarmHandle);
1431
1432         __reminderList.RemoveAll(true);
1433         __reminderListUpdated = false;
1434
1435         return E_SUCCESS;
1436 }
1437
1438 const IList&
1439 _CalEventImpl::GetAllReminders(void) const
1440 {
1441         ClearLastResult();
1442
1443         if (__reminderListUpdated == false)
1444         {
1445                 result r = _CalendarbookUtil::ConvertEventAlarmsToReminderList(__eventRecord.GetHandle(), __reminderList);
1446                 SysTryReturn(NID_SCL, r == E_SUCCESS, __reminderList, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1447
1448                 __reminderListUpdated = true;
1449         }
1450
1451         return __reminderList;
1452 }
1453
1454 result
1455 _CalEventImpl::ConvertRecurrenceToEventHandle(const Recurrence& recurrence, calendar_record_h eventHandle) const
1456 {
1457         result r = E_SUCCESS;
1458
1459         int weekStart = CALENDAR_SUNDAY;
1460         std::unique_ptr<char[]> pByDay;
1461         std::unique_ptr<char[]> pByMonth;
1462         std::unique_ptr<char[]> pByMonthDay;
1463
1464         int dayOfWeek = 0;
1465         String dayOfWeekString;
1466         String exDateString;
1467
1468         switch (recurrence.GetWeekStart())
1469         {
1470         case CAL_SUNDAY:
1471                 weekStart = CALENDAR_SUNDAY;
1472                 break;
1473
1474         case CAL_MONDAY:
1475                 weekStart = CALENDAR_MONDAY;
1476                 break;
1477
1478         default:
1479                 SysLogException(NID_SCL, E_INVALID_ARG, "Invalid argument is passed. week start = %d", recurrence.GetWeekStart());
1480                 return E_INVALID_ARG;
1481         }
1482
1483         int errorCode = calendar_record_set_int(eventHandle, _calendar_event.wkst, weekStart);
1484         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_INVALID_ARG, "Invalid argument is passed. week start = %d", weekStart);
1485
1486         if (recurrence.GetUntil() != null)
1487         {
1488                 if (*recurrence.GetUntil() == DateTime::GetMaxValue())
1489                 {
1490                         calendar_record_set_int(eventHandle, _calendar_event.range_type, CALENDAR_RANGE_NONE);
1491                 }
1492                 else
1493                 {
1494                         calendar_time_s startCalendarTime;
1495                         calendar_time_s untilCalendarTime;
1496
1497                         calendar_record_get_caltime(eventHandle, _calendar_event.start_time, &startCalendarTime);
1498                         if (startCalendarTime.type == CALENDAR_TIME_LOCALTIME)
1499                         {
1500                                 untilCalendarTime.type = CALENDAR_TIME_LOCALTIME;
1501                                 untilCalendarTime.time.date.year = recurrence.GetUntil()->GetYear();
1502                                 untilCalendarTime.time.date.month = recurrence.GetUntil()->GetMonth();
1503                                 untilCalendarTime.time.date.mday = recurrence.GetUntil()->GetDay();
1504                         }
1505                         else
1506                         {
1507                                 untilCalendarTime.type = CALENDAR_TIME_UTIME;
1508                                 untilCalendarTime.time.utime = _CalendarbookUtil::ConvertDateTimeToEpochTime(*recurrence.GetUntil());
1509                         }
1510
1511                         calendar_record_set_int(eventHandle, _calendar_event.range_type, CALENDAR_RANGE_UNTIL);
1512                         calendar_record_set_caltime(eventHandle, _calendar_event.until_time, untilCalendarTime);
1513                 }
1514         }
1515         else
1516         {
1517                 calendar_record_set_int(eventHandle, _calendar_event.range_type, CALENDAR_RANGE_COUNT);
1518                 calendar_record_set_int(eventHandle, _calendar_event.count, recurrence.GetCounts());
1519         }
1520
1521         calendar_record_set_int(eventHandle, _calendar_event.interval, recurrence.GetInterval());
1522
1523         switch (recurrence.GetFrequency())
1524         {
1525         case FREQ_DAILY:
1526                 calendar_record_set_int(eventHandle, _calendar_event.freq, CALENDAR_RECURRENCE_DAILY);
1527                 break;
1528
1529         case FREQ_WEEKLY:
1530                 calendar_record_set_int(eventHandle, _calendar_event.freq, CALENDAR_RECURRENCE_WEEKLY);
1531
1532                 dayOfWeek = recurrence.GetDayOfWeek();
1533                 r = ConvertDayOfWeekToRRuleByDayString(dayOfWeek, 0, dayOfWeekString);
1534                 SysTryReturnResult(NID_SCL, r == E_SUCCESS, E_INVALID_ARG, "Invalid argument is passed. day of week = %d", dayOfWeek);
1535
1536                 pByDay.reset(_StringConverter::CopyToCharArrayN(dayOfWeekString));
1537
1538                 break;
1539
1540         case FREQ_MONTHLY:
1541                 calendar_record_set_int(eventHandle, _calendar_event.freq, CALENDAR_RECURRENCE_MONTHLY);
1542
1543                 if (recurrence.GetDayOfMonth() != 0)
1544                 {
1545                         pByMonthDay.reset(_StringConverter::CopyToCharArrayN(Integer::ToString(recurrence.GetDayOfMonth())));
1546                 }
1547                 else
1548                 {
1549                         dayOfWeek = recurrence.GetDayOfWeek();
1550                         r = ConvertDayOfWeekToRRuleByDayString(dayOfWeek, recurrence.GetWeekOfMonth(), dayOfWeekString);
1551                         SysTryReturnResult(NID_SCL, r == E_SUCCESS, E_INVALID_ARG, "Invalid argument is passed. day of week = %d", dayOfWeek);
1552
1553                         pByDay.reset(_StringConverter::CopyToCharArrayN(dayOfWeekString));
1554                 }
1555
1556                 break;
1557
1558         case FREQ_YEARLY:
1559                 calendar_record_set_int(eventHandle, _calendar_event.freq, CALENDAR_RECURRENCE_YEARLY);
1560
1561                 pByMonth.reset(_StringConverter::CopyToCharArrayN(Integer::ToString(recurrence.GetMonthOfYear())));
1562
1563                 if (recurrence.GetDayOfMonth() != 0)
1564                 {
1565                         pByMonthDay.reset(_StringConverter::CopyToCharArrayN(Integer::ToString(recurrence.GetDayOfMonth())));
1566                 }
1567                 else
1568                 {
1569                         dayOfWeek = recurrence.GetDayOfWeek();
1570                         r = ConvertDayOfWeekToRRuleByDayString(dayOfWeek, recurrence.GetWeekOfMonth(), dayOfWeekString);
1571                         SysTryReturnResult(NID_SCL, r == E_SUCCESS, E_INVALID_ARG, "Invalid argument is passed. day of week = %d", dayOfWeek);
1572
1573                         pByDay.reset(_StringConverter::CopyToCharArrayN(dayOfWeekString));
1574                 }
1575
1576                 break;
1577
1578         default:
1579                 SysLogException(NID_SCL, E_INVALID_ARG, "[%s] Invalid argument is used. frequency = %d", GetErrorMessage(E_INVALID_ARG), recurrence.GetFrequency());
1580                 return E_INVALID_ARG;
1581         }
1582
1583         errorCode = calendar_record_set_str(eventHandle, _calendar_event.byday, pByDay.get());
1584         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1585         errorCode = calendar_record_set_str(eventHandle, _calendar_event.bymonth, pByMonth.get());
1586         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1587         errorCode = calendar_record_set_str(eventHandle, _calendar_event.bymonthday, pByMonthDay.get());
1588         SysTryReturnResult(NID_SCL, errorCode == CALENDAR_ERROR_NONE, E_OUT_OF_MEMORY, "Memory allocation failed.");
1589
1590         return E_SUCCESS;
1591 }
1592
1593 result
1594 _CalEventImpl::ConvertDayOfWeekToRRuleByDayString(int dayOfWeek, int weekOfMonth, String& byDayString) const
1595 {
1596         int tmpDayOfWeek = CAL_SUNDAY;
1597
1598         byDayString.Clear();
1599         for (int i = 0; i < _NUMBER_OF_DAYS_OF_WEEK; i++)
1600         {
1601                 if (dayOfWeek & tmpDayOfWeek)
1602                 {
1603                         if (weekOfMonth != 0)
1604                         {
1605                                 byDayString.Append(weekOfMonth);
1606                         }
1607
1608                         switch (tmpDayOfWeek)
1609                         {
1610                         case CAL_SUNDAY:
1611                                 byDayString.Append(_RECURRENCE_KEYWORD_SUNDAY);
1612                                 break;
1613                         case CAL_MONDAY:
1614                                 byDayString.Append(_RECURRENCE_KEYWORD_MONDAY);
1615                                 break;
1616                         case CAL_TUESDAY:
1617                                 byDayString.Append(_RECURRENCE_KEYWORD_TUESDAY);
1618                                 break;
1619                         case CAL_WEDNESDAY:
1620                                 byDayString.Append(_RECURRENCE_KEYWORD_WEDNESDAY);
1621                                 break;
1622                         case CAL_THURSDAY:
1623                                 byDayString.Append(_RECURRENCE_KEYWORD_THURSDAY);
1624                                 break;
1625                         case CAL_FRIDAY:
1626                                 byDayString.Append(_RECURRENCE_KEYWORD_FRIDAY);
1627                                 break;
1628                         case CAL_SATURDAY:
1629                                 byDayString.Append(_RECURRENCE_KEYWORD_SATURDAY);
1630                                 break;
1631                         }
1632                         byDayString.Append(_RECURRENCE_DELIMITER);
1633                 }
1634
1635                 tmpDayOfWeek <<= 1;
1636         }
1637
1638         byDayString.Remove(byDayString.GetLength() - 1, _RECURRENCE_DELIMITER_LENGTH);
1639
1640         return E_SUCCESS;
1641 }
1642
1643 RecordId
1644 _CalEventImpl::GetCalendarId(void) const
1645 {
1646         int srcCalendarbookId = 0;
1647
1648         calendar_record_get_int(__eventRecord.GetHandle(), _calendar_event.calendar_book_id, &srcCalendarbookId);
1649
1650         return srcCalendarbookId;
1651 }
1652
1653 RecordId
1654 _CalEventImpl::GetBaseEventId(void) const
1655 {
1656         int srcBaseEventId = INVALID_RECORD_ID;
1657
1658         calendar_record_get_int(__eventRecord.GetHandle(), _calendar_event.original_event_id, &srcBaseEventId);
1659
1660         return srcBaseEventId;
1661 }
1662
1663 void
1664 _CalEventImpl::SetOriginalCalEventId(RecordId originalEventId)
1665 {
1666         __originalEventId = originalEventId;
1667         __isInstance = true;
1668 }
1669
1670 int
1671 _CalEventImpl::GetAttendeeIndex(const char* pAttendeeEmail)
1672 {
1673         int index = _INVALID_ATTENDEE_INDEX;
1674         unsigned int attendeeCount = 0;
1675
1676         calendar_record_get_child_record_count(__eventRecord.GetHandle(), _calendar_event.calendar_attendee, &attendeeCount);
1677
1678         calendar_record_h tmpAttendeeHandle = null;
1679         char* pTmpAttendeeEmail = null;
1680         for (unsigned int i = 0; i < attendeeCount; i++)
1681         {
1682                 calendar_record_get_child_record_at_p(__eventRecord.GetHandle(), _calendar_event.calendar_attendee, i, &tmpAttendeeHandle);
1683                 calendar_record_get_str_p(tmpAttendeeHandle, _calendar_attendee.email, &pTmpAttendeeEmail);
1684
1685                 if (strcmp(pAttendeeEmail, pTmpAttendeeEmail) == 0)
1686                 {
1687                         index = i;
1688                         break;
1689                 }
1690         }
1691
1692         return index;
1693 }
1694
1695 result
1696 _CalEventImpl::VerifyRecurrence(const Recurrence& recurrence)
1697 {
1698         const DateTime* pUntil = recurrence.GetUntil();
1699         RecurFrequency frequency = recurrence.GetFrequency();
1700         int durationLimit = 0;
1701         int interval = recurrence.GetInterval();
1702
1703         DateTime startTime = GetStartTime();
1704         DateTime endTime = GetEndTime();
1705         EventCategory category = GetCategory();
1706
1707         if (pUntil != null)
1708         {
1709                 SysTryReturnResult(NID_SCL, startTime <= *pUntil, E_INVALID_CONDITION, "The until date of recurrence is earlier than start date.");
1710         }
1711
1712         if (_AppInfo::GetApiVersion() == _API_VERSION_2_0 && _AppInfo::IsOspCompat())
1713         {
1714                 if (category == EVENT_CATEGORY_ANNIVERSARY)
1715                 {
1716                         SysTryReturnResult(NID_SCL, frequency == FREQ_YEARLY, E_TYPE_MISMATCH
1717                                         , "The recurrence pattern is not a yearly pattern in case of the event being an Anniversary.");
1718                 }
1719         }
1720
1721         if (frequency == FREQ_DAILY)
1722         {
1723                 durationLimit = _TERM_LIMIT_DAILY * interval;
1724         }
1725         else if (frequency == FREQ_WEEKLY)
1726         {
1727                 SysTryReturnResult(NID_SCL, recurrence.GetDayOfWeek() != 0, E_INVALID_ARG, "Invalid argument is used. The day of week is not set.");
1728                 durationLimit = _TERM_LIMIT_WEEKLY * interval;
1729         }
1730         else if (frequency == FREQ_MONTHLY)
1731         {
1732                 SysTryReturnResult(NID_SCL, recurrence.GetDayOfMonth() != 0 || (recurrence.GetDayOfWeek() != 0 && recurrence.GetWeekOfMonth() != 0)
1733                                 , E_INVALID_ARG, "Invalid argument is used. The day of month or day of week/week of month is not set.");
1734                 durationLimit = _TERM_LIMIT_MONTHLY * interval;
1735         }
1736         else if (frequency == FREQ_YEARLY)
1737         {
1738                 int dayOfMonth = recurrence.GetDayOfMonth();
1739                 int monthOfYear = recurrence.GetMonthOfYear();
1740                 SysTryReturnResult(NID_SCL, monthOfYear != 0, E_INVALID_ARG, "Invalid argument is used. The month of year is not set.");
1741                 SysTryReturnResult(NID_SCL, dayOfMonth != 0 || (recurrence.GetDayOfWeek() != 0 && recurrence.GetWeekOfMonth() != 0)
1742                                 , E_INVALID_ARG, "Invalid argument is used. The day of month or day of week/week of month is not set.");
1743
1744                 SysTryReturnResult(NID_SCL, monthOfYear != 2 || dayOfMonth < 30
1745                                 , E_INVALID_ARG, "Invalid argument is used. If the frequency is yearly, the max days of the February is less than 30.");
1746                 if (dayOfMonth > 30)
1747                 {
1748                         SysTryReturnResult(NID_SCL, monthOfYear != 4 && monthOfYear != 6 && monthOfYear != 9 && monthOfYear != 11
1749                                         , E_INVALID_ARG, "Invalid argument is used. If the frequency is yearly, the max days of the April, June, September and November is less than 31.");
1750                 }
1751
1752                 durationLimit = _TERM_LIMIT_YEARLY * interval;
1753         }
1754
1755         TimeSpan duration = endTime.GetTime() - startTime.GetTime();
1756         SysTryReturnResult(NID_SCL, duration.GetDays() <= durationLimit, E_INVALID_CONDITION
1757                         , "The duration of the event is greater than (interval x frequency) days. duration days = %d", duration.GetDays());
1758
1759         return E_SUCCESS;
1760 }
1761
1762 result
1763 _CalEventImpl::ResetStartAndEndTimeByRecurrence(const Recurrence& recurrence)
1764 {
1765         DateTime startTime;
1766         DateTime endTime;
1767
1768         bool isAllDay = IsAllDayEvent();
1769         Locales::TimeZone timeZone;
1770
1771         if (!isAllDay)
1772         {
1773                 timeZone = GetTimeZone();
1774                 startTime = timeZone.UtcTimeToWallTime(GetStartTime());
1775                 endTime = timeZone.UtcTimeToWallTime(GetEndTime());
1776         }
1777         else
1778         {
1779                 startTime = GetStartTime();
1780                 endTime = GetEndTime();
1781         }
1782
1783         DateTime calculatedStartTime(startTime);
1784         DateTime calculatedEndTime(endTime);
1785         RecurFrequency frequency = recurrence.GetFrequency();
1786         int interval = recurrence.GetInterval();
1787         int dayOfMonth = recurrence.GetDayOfMonth();
1788         int dayOfWeek = recurrence.GetDayOfWeek();
1789         int weekOfMonth = recurrence.GetWeekOfMonth();
1790         int monthOfYear = recurrence.GetMonthOfYear();
1791         CalDayOfWeek weekStart = recurrence.GetWeekStart();
1792         CalDayOfWeek weekEnd = CAL_SATURDAY;
1793         DateTime until;
1794         TimeSpan duration = endTime.GetTime() - startTime.GetTime();
1795
1796         if (weekStart == CAL_MONDAY)
1797         {
1798                 weekEnd = CAL_SUNDAY;
1799         }
1800
1801         if (recurrence.GetUntil() != null)
1802         {
1803                 until = *(recurrence.GetUntil());
1804                 if (!isAllDay)
1805                 {
1806                         until = timeZone.UtcTimeToWallTime(until);
1807                 }
1808         }
1809         else
1810         {
1811                 until = _CalendarbookImpl::GetMaxDateTime();
1812         }
1813
1814         CalDayOfWeek dayOfStartTime = GetDayOfWeek(startTime, timeZone);
1815
1816         if (frequency == FREQ_WEEKLY)
1817         {
1818                 int count = 0;
1819
1820                 for (int i = 0; i < _NUMBER_OF_DAYS_OF_WEEK; i++)
1821                 {
1822                         if ((dayOfStartTime & dayOfWeek) != 0)
1823                         {
1824                                 break;
1825                         }
1826
1827                         if ((dayOfStartTime & weekEnd) != 0)
1828                         {
1829                                 count += (interval - 1) * _NUMBER_OF_DAYS_OF_WEEK;
1830                         }
1831
1832                         dayOfStartTime = GetNextDayOfWeek(dayOfStartTime);
1833                         count++;
1834                 }
1835
1836                 result r = calculatedStartTime.AddDays(count);
1837                 SysTryReturnResult(NID_SCL, !IsFailed(r), r, "[%s][Propagating]", GetErrorMessage(r));
1838                 r = calculatedEndTime.AddDays(count);
1839                 SysTryReturnResult(NID_SCL, !IsFailed(r), r, "[%s][Propagating]", GetErrorMessage(r));
1840
1841         }
1842         else if (frequency == FREQ_MONTHLY)
1843         {
1844                 if (dayOfMonth != 0)
1845                 {
1846                         bool isDone = false;
1847                         while (calculatedStartTime <= until)
1848                         {
1849                                 if (calculatedStartTime.SetValue(calculatedStartTime.GetYear(), calculatedStartTime.GetMonth(), dayOfMonth, calculatedStartTime.GetHour(), calculatedStartTime.GetMinute(), calculatedStartTime.GetSecond()) == E_SUCCESS)
1850                                 {
1851                                         if (calculatedStartTime >= startTime)
1852                                         {
1853                                                 isDone = true;
1854                                                 break;
1855                                         }
1856                                 }
1857                                 calculatedStartTime.AddMonths(interval);
1858                         }
1859                         SysTryReturnResult(NID_SCL, isDone, E_INVALID_ARG, "Invalid argument is used. There is no instance of the recurrence.");
1860                         calculatedEndTime = calculatedStartTime;
1861                         calculatedEndTime.Add(duration);
1862                 }
1863                 else
1864                 {
1865                         bool isDone = false;
1866                         int dayCount = 0;
1867                         CalDayOfWeek tmpDayOfWeek = GetFirstDay(weekStart, dayOfWeek, dayCount);
1868                         while (calculatedStartTime <= until)
1869                         {
1870                                 for (int i = 0; i < dayCount; i++)
1871                                 {
1872                                         calculatedStartTime = GetDate(calculatedStartTime.GetYear(), calculatedStartTime.GetMonth(), weekOfMonth, tmpDayOfWeek, calculatedStartTime, timeZone);
1873                                         if (calculatedStartTime >= startTime)
1874                                         {
1875                                                 isDone = true;
1876                                                 break;
1877                                         }
1878                                         tmpDayOfWeek = GetNextDay(dayOfWeek, tmpDayOfWeek);
1879                                 }
1880                                 if (isDone)
1881                                 {
1882                                         break;
1883                                 }
1884                                 calculatedStartTime.AddMonths(interval);
1885                         }
1886
1887                         SysTryReturnResult(NID_SCL, isDone, E_INVALID_ARG, "Invalid argument is used. There is no instance of the recurrence.");
1888                         calculatedEndTime = calculatedStartTime;
1889                         calculatedEndTime.Add(duration);
1890                 }
1891         }
1892         else if (frequency == FREQ_YEARLY)
1893         {
1894                 if (dayOfMonth != 0)
1895                 {
1896                         bool isDone = false;
1897                         while (calculatedStartTime <= until)
1898                         {
1899                                 if (calculatedStartTime.SetValue(calculatedStartTime.GetYear(), monthOfYear, dayOfMonth, calculatedStartTime.GetHour(), calculatedStartTime.GetMinute(), calculatedStartTime.GetSecond()) == E_SUCCESS)
1900                                 {
1901                                         if (calculatedStartTime >= startTime)
1902                                         {
1903                                                 isDone = true;
1904                                                 break;
1905                                         }
1906                                 }
1907                                 calculatedStartTime.AddYears(interval);
1908                         }
1909                         SysTryReturnResult(NID_SCL, isDone, E_INVALID_ARG, "Invalid argument is used. There is no instance of the recurrence.");
1910                         calculatedEndTime = calculatedStartTime;
1911                         calculatedEndTime.Add(duration);
1912                 }
1913                 else
1914                 {
1915                         bool isDone = false;
1916                         int dayCount = 0;
1917                         CalDayOfWeek tmpDayOfWeek = GetFirstDay(weekStart, dayOfWeek, dayCount);
1918                         while (calculatedStartTime <= until)
1919                         {
1920                                 for (int i = 0; i < dayCount; i++)
1921                                 {
1922                                         calculatedStartTime = GetDate(calculatedStartTime.GetYear(), monthOfYear, weekOfMonth, tmpDayOfWeek, calculatedStartTime, timeZone);
1923                                         if (calculatedStartTime >= startTime)
1924                                         {
1925                                                 isDone = true;
1926                                                 break;
1927                                         }
1928                                         tmpDayOfWeek = GetNextDay(dayOfWeek, tmpDayOfWeek);
1929                                 }
1930                                 if (isDone)
1931                                 {
1932                                         break;
1933                                 }
1934                                 calculatedStartTime.AddYears(interval);
1935                         }
1936
1937                         SysTryReturnResult(NID_SCL, isDone, E_INVALID_ARG, "Invalid argument is used. There is no instance of the recurrence.");
1938                         calculatedEndTime = calculatedStartTime;
1939                         calculatedEndTime.Add(duration);
1940                 }
1941         }
1942
1943         if (!isAllDay)
1944         {
1945                 calculatedStartTime = timeZone.WallTimeToUtcTime(calculatedStartTime);
1946                 calculatedEndTime = timeZone.WallTimeToUtcTime(calculatedEndTime);
1947         }
1948
1949         SysTryReturnResult(NID_SCL, calculatedStartTime <= until, E_INVALID_ARG, "Invalid argument is used. There is no instance of the recurrence.");
1950         SysTryReturnResult(NID_SCL, calculatedEndTime <= _CalendarbookImpl::GetMaxDateTime(), E_INVALID_ARG, "Invalid argument is used. There is no instance of the recurrence.");
1951
1952         SysLog(NID_SCL, "Reset start time : %S", calculatedStartTime.ToString().GetPointer());
1953         SetStartAndEndTimeCommon(calculatedStartTime, calculatedEndTime);
1954
1955         return E_SUCCESS;
1956 }
1957
1958 int
1959 _CalEventImpl::ConvertRRuleByDayStringToDayOfWeek(const String& byDay) const
1960 {
1961         int dayOfWeek = 0;
1962         ClearLastResult();
1963
1964         SysTryReturn(NID_SCL, !byDay.IsEmpty(), 0, E_INVALID_ARG, "[%s] Invalid argument is used. The byDay is empty.", GetErrorMessage(E_INVALID_ARG));
1965
1966         String delim(_RECURRENCE_DELIMITER);
1967         String token;
1968
1969         StringTokenizer strTok(byDay, delim);
1970         while (strTok.HasMoreTokens())
1971         {
1972                 result r = strTok.GetNextToken(token);
1973                 SysTryReturn(NID_SCL, r == E_SUCCESS, 0, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1974
1975                 if (token == String(_RECURRENCE_KEYWORD_SUNDAY))
1976                 {
1977                         dayOfWeek |= CAL_SUNDAY;
1978                 }
1979                 else    if (token == String(_RECURRENCE_KEYWORD_MONDAY))
1980                 {
1981                         dayOfWeek |= CAL_MONDAY;
1982                 }
1983                 else    if (token == String(_RECURRENCE_KEYWORD_TUESDAY))
1984                 {
1985                         dayOfWeek |= CAL_TUESDAY;
1986                 }
1987                 else    if (token == String(_RECURRENCE_KEYWORD_WEDNESDAY))
1988                 {
1989                         dayOfWeek |= CAL_WEDNESDAY;
1990                 }
1991                 else    if (token == String(_RECURRENCE_KEYWORD_THURSDAY))
1992                 {
1993                         dayOfWeek |= CAL_THURSDAY;
1994                 }
1995                 else    if (token == String(_RECURRENCE_KEYWORD_FRIDAY))
1996                 {
1997                         dayOfWeek |= CAL_FRIDAY;
1998                 }
1999                 else    if (token == String(_RECURRENCE_KEYWORD_SATURDAY))
2000                 {
2001                         dayOfWeek |= CAL_SATURDAY;
2002                 }
2003                 else
2004                 {
2005                         SysLogException(NID_SCL, E_INVALID_ARG, "[%s] Invalid argument is used. byday = %S", GetErrorMessage(E_INVALID_ARG), byDay.GetPointer());
2006                         return 0;
2007                 }
2008         }
2009
2010         return dayOfWeek;
2011 }
2012
2013 result
2014 _CalEventImpl::ConvertRRuleByDayStringToDayOfWeekAndWeekOfMonth(const String& byDay, int& weekOfMonth, int& dayOfWeek) const
2015 {
2016         String delim(_RECURRENCE_DELIMITER);
2017         String token;
2018         wchar_t tmpChar = 0;
2019         int tmpWeekOfMonth = 0;
2020         int weekStringStartIndex = 0;
2021         String tmpString;
2022
2023         weekOfMonth = 0;
2024         dayOfWeek = 0;
2025
2026         SysTryReturnResult(NID_SCL, !byDay.IsEmpty(), E_INVALID_ARG, "Invalid argument is passed. The byDay is empty.");
2027
2028         StringTokenizer strTok(byDay, delim);
2029
2030         while (strTok.HasMoreTokens())
2031         {
2032                 result r = strTok.GetNextToken(token);
2033                 SysTryReturnResult(NID_SCL, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
2034
2035                 r = token.GetCharAt(_RECURRENCE_BY_DAY_FIRST_INDEX, tmpChar);
2036                 if (tmpChar == _RECURRENCE_BY_DAY_CHAR_MINUS)
2037                 {
2038                         SysTryReturnResult(NID_SCL, weekOfMonth == 0 || weekOfMonth == _MAX_WEEK_OF_MONTH
2039                                         , E_INVALID_ARG, "Invalid argument is passed. byday = %S", byDay.GetPointer());
2040
2041                         if (weekOfMonth == 0)
2042                         {
2043                                 tmpChar = 0;
2044                                 r = token.GetCharAt(_RECURRENCE_BY_DAY_SECOND_INDEX, tmpChar);
2045                                 SysTryReturnResult(NID_SCL, tmpChar == _RECURRENCE_BY_DAY_CHAR_ONE
2046                                                 , E_INVALID_ARG, "Invalid argument is passed. byday = %S", byDay.GetPointer());
2047
2048                                 weekOfMonth = _MAX_WEEK_OF_MONTH;
2049                         }
2050                         weekStringStartIndex = _RECURRENCE_BY_DAY_SECOND_INDEX + 1;
2051                 }
2052                 else if (tmpChar == _RECURRENCE_BY_DAY_CHAR_PLUS)
2053                 {
2054                         if (weekOfMonth == 0)
2055                         {
2056                                 tmpChar = 0;
2057                                 r = token.GetCharAt(_RECURRENCE_BY_DAY_SECOND_INDEX, tmpChar);
2058                                 tmpWeekOfMonth = Character::ToDigit(tmpChar, Character::RADIX_DECIMAL);
2059                                 SysTryReturnResult(NID_SCL, tmpWeekOfMonth > 0 && tmpWeekOfMonth <= _MAX_WEEK_OF_MONTH
2060                                                 , E_INVALID_ARG, "Invalid argument is passed. byday = %S", byDay.GetPointer());
2061
2062                                 weekOfMonth = tmpWeekOfMonth;
2063                         }
2064                         else
2065                         {
2066                                 SysTryReturnResult(NID_SCL, weekOfMonth == tmpWeekOfMonth
2067                                                 , E_INVALID_ARG, "Invalid argument is passed. byday = %S", byDay.GetPointer());
2068                         }
2069
2070                         weekStringStartIndex = _RECURRENCE_BY_DAY_SECOND_INDEX + 1;
2071                 }
2072                 else
2073                 {
2074                         if (weekOfMonth == 0)
2075                         {
2076                                 tmpWeekOfMonth = Character::ToDigit(tmpChar, Character::RADIX_DECIMAL);
2077                                 SysTryReturnResult(NID_SCL, tmpWeekOfMonth > 0 && tmpWeekOfMonth <= _MAX_WEEK_OF_MONTH
2078                                                 , E_INVALID_ARG, "Invalid argument is passed. byday = %S", byDay.GetPointer());
2079
2080                                 weekOfMonth = tmpWeekOfMonth;
2081                         }
2082                         else
2083                         {
2084                                 SysTryReturnResult(NID_SCL, weekOfMonth == tmpWeekOfMonth
2085                                                 , E_INVALID_ARG, "Invalid argument is passed. byday = %S", byDay.GetPointer());
2086                         }
2087
2088                         weekStringStartIndex = _RECURRENCE_BY_DAY_FIRST_INDEX + 1;
2089                 }
2090
2091                 token.SubString(weekStringStartIndex, tmpString);
2092
2093                 if (tmpString == String(_RECURRENCE_KEYWORD_SUNDAY))
2094                 {
2095                         dayOfWeek |= CAL_SUNDAY;
2096                 }
2097                 else    if (tmpString == String(_RECURRENCE_KEYWORD_MONDAY))
2098                 {
2099                         dayOfWeek |= CAL_MONDAY;
2100                 }
2101                 else    if (tmpString == String(_RECURRENCE_KEYWORD_TUESDAY))
2102                 {
2103                         dayOfWeek |= CAL_TUESDAY;
2104                 }
2105                 else    if (tmpString == String(_RECURRENCE_KEYWORD_WEDNESDAY))
2106                 {
2107                         dayOfWeek |= CAL_WEDNESDAY;
2108                 }
2109                 else    if (tmpString == String(_RECURRENCE_KEYWORD_THURSDAY))
2110                 {
2111                         dayOfWeek |= CAL_THURSDAY;
2112                 }
2113                 else    if (tmpString == String(_RECURRENCE_KEYWORD_FRIDAY))
2114                 {
2115                         dayOfWeek |= CAL_FRIDAY;
2116                 }
2117                 else    if (tmpString == String(_RECURRENCE_KEYWORD_SATURDAY))
2118                 {
2119                         dayOfWeek |= CAL_SATURDAY;
2120                 }
2121                 else
2122                 {
2123                         SysLogException(NID_SCL, E_INVALID_ARG, "[%s] Invalid argument is used. byday = %S", GetErrorMessage(E_INVALID_ARG), byDay.GetPointer());
2124                 }
2125         }
2126
2127         return E_SUCCESS;
2128 }
2129
2130 result
2131 _CalEventImpl::ConvertRRuleExDateStringToRecurrence(const String& exdate, Recurrence& recurrence) const
2132 {
2133         String delim(_RECURRENCE_DELIMITER);
2134         String token;
2135         DateTime tmpDateTime;
2136         TimeZone tmpTimeZone;
2137         TimeZone utcTimeZone = TimeZone::GetGmtTimeZone();
2138         bool isDate = false;
2139
2140         SysTryReturnResult(NID_SCL, !exdate.IsEmpty(), E_INVALID_ARG, "Invalid argument is passed. The exdate is empty.");
2141
2142         StringTokenizer strTok(exdate, delim);
2143         while (strTok.HasMoreTokens())
2144         {
2145                 result r = strTok.GetNextToken(token);
2146                 SysTryReturnResult(NID_SCL, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
2147
2148                 r = _CalendarbookUtil::ConvertRRuleDateTimeStringToDateTime(token, tmpDateTime, tmpTimeZone, isDate);
2149                 SysTryReturnResult(NID_SCL, r == E_SUCCESS, E_INVALID_ARG, "Invalid argument is passed. exdate = %S", exdate.GetPointer());
2150
2151                 if (!isDate && tmpTimeZone != utcTimeZone)
2152                 {
2153                         tmpDateTime = tmpTimeZone.WallTimeToUtcTime(tmpDateTime);
2154                 }
2155
2156                 r = recurrence.AddExceptionDate(tmpDateTime);
2157                 SysTryReturnResult(NID_SCL, r == E_SUCCESS, E_INVALID_ARG, "Invalid argument is passed. exdate = %S", exdate.GetPointer());
2158         }
2159
2160         return E_SUCCESS;
2161 }
2162
2163 String
2164 _CalEventImpl::ConvertRecurrenceToRRuleExDateString(const Recurrence& recurrence, bool isDate) const
2165 {
2166         bool isNotFirst = false;
2167         String exdateString;
2168
2169         std::unique_ptr<IList, AllElementsDeleter> pExDateList(recurrence.GetExceptionDatesN());
2170
2171         std::unique_ptr<IEnumerator> pEnum(pExDateList->GetEnumeratorN());
2172         while (pEnum->MoveNext() == E_SUCCESS)
2173         {
2174                 DateTime* pDateTime = static_cast<DateTime*>(pEnum->GetCurrent());
2175
2176                 if (isNotFirst)
2177                 {
2178                         exdateString.Append(_RECURRENCE_DELIMITER);
2179                 }
2180
2181                 exdateString.Append(_CalendarbookUtil::ConvertDateTimeToRRuleDateTimeString(*pDateTime, isDate));
2182
2183                 isNotFirst = true;
2184         }
2185
2186         return exdateString;
2187 }
2188
2189 CalDayOfWeek
2190 _CalEventImpl::GetNextDayOfWeek(CalDayOfWeek currentDay)
2191 {
2192         int tmpDay = currentDay;
2193
2194         tmpDay <<= 1;
2195         if (tmpDay > CAL_SATURDAY)
2196         {
2197                 tmpDay = CAL_SUNDAY;
2198         }
2199
2200         return static_cast<CalDayOfWeek>(tmpDay);
2201 }
2202
2203 DateTime
2204 _CalEventImpl::GetDate(int year, int month, int weekOfMonth, CalDayOfWeek dayOfWeek, const DateTime& time, const TimeZone& timeZone)
2205 {
2206         ClearLastResult();
2207
2208         Tizen::Locales::DayOfWeek dayOfWeekByGregorianCalendar = Tizen::Locales::DAY_OF_WEEK_UNDEFINED;
2209
2210         switch (dayOfWeek)
2211         {
2212         case CAL_SUNDAY:
2213                 dayOfWeekByGregorianCalendar = Tizen::Locales::SUNDAY;
2214                 break;
2215
2216         case CAL_MONDAY:
2217                 dayOfWeekByGregorianCalendar = Tizen::Locales::MONDAY;
2218                 break;
2219
2220         case CAL_TUESDAY:
2221                 dayOfWeekByGregorianCalendar = Tizen::Locales::TUESDAY;
2222                 break;
2223
2224         case CAL_WEDNESDAY:
2225                 dayOfWeekByGregorianCalendar = Tizen::Locales::WEDNESDAY;
2226                 break;
2227
2228         case CAL_THURSDAY:
2229                 dayOfWeekByGregorianCalendar = Tizen::Locales::THURSDAY;
2230                 break;
2231
2232         case CAL_FRIDAY:
2233                 dayOfWeekByGregorianCalendar = Tizen::Locales::FRIDAY;
2234                 break;
2235
2236         case CAL_SATURDAY:
2237                 dayOfWeekByGregorianCalendar = Tizen::Locales::SATURDAY;
2238                 break;
2239
2240         default:
2241                 break;
2242         }
2243
2244         std::unique_ptr<Tizen::Locales::Calendar> pGregorianCalendar(Tizen::Locales::Calendar::CreateInstanceN(timeZone, Tizen::Locales::CALENDAR_GREGORIAN));
2245         SysTryReturn(NID_SCL, pGregorianCalendar != null, DateTime(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
2246
2247         pGregorianCalendar->SetTimeField(Tizen::Locales::TIME_FIELD_YEAR, year);
2248         pGregorianCalendar->SetTimeField(Tizen::Locales::TIME_FIELD_MONTH, month);
2249         pGregorianCalendar->SetTimeField(Tizen::Locales::TIME_FIELD_DAY_OF_MONTH, 1);
2250
2251         Tizen::Locales::DayOfWeek tmpDayOfWeek = static_cast<Tizen::Locales::DayOfWeek>(pGregorianCalendar->GetTimeField(TIME_FIELD_DAY_OF_WEEK));
2252         int maxDaysOfMonth = pGregorianCalendar->GetActualMaxTimeField(TIME_FIELD_DAY_OF_MONTH);
2253         int tmpDayOfMonth = ((_NUMBER_OF_DAYS_OF_WEEK + dayOfWeekByGregorianCalendar) - tmpDayOfWeek) % _NUMBER_OF_DAYS_OF_WEEK + 1;
2254
2255         tmpDayOfMonth += ((weekOfMonth - 1) * _NUMBER_OF_DAYS_OF_WEEK);
2256         if (tmpDayOfMonth > maxDaysOfMonth)
2257         {
2258                 tmpDayOfMonth -= _NUMBER_OF_DAYS_OF_WEEK;
2259         }
2260
2261         DateTime resultTime;
2262         resultTime.SetValue(year, month, tmpDayOfMonth, time.GetHour(), time.GetMinute(), time.GetSecond());
2263
2264         return resultTime;
2265 }
2266
2267 CalDayOfWeek
2268 _CalEventImpl::GetDayOfWeek(const DateTime& date, const Locales::TimeZone& timeZone)
2269 {
2270         ClearLastResult();
2271
2272         CalDayOfWeek dayOfWeek = CAL_SUNDAY;
2273
2274         std::unique_ptr<Tizen::Locales::Calendar> pGregorianCalendar(Tizen::Locales::Calendar::CreateInstanceN(timeZone, Tizen::Locales::CALENDAR_GREGORIAN));
2275         SysTryReturn(NID_SCL, pGregorianCalendar != null, dayOfWeek, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
2276
2277         pGregorianCalendar->SetTime(date);
2278         int dayOfWeekByGregorianCalendar = pGregorianCalendar->GetTimeField(Tizen::Locales::TIME_FIELD_DAY_OF_WEEK);
2279
2280         switch (dayOfWeekByGregorianCalendar)
2281         {
2282         case Tizen::Locales::SUNDAY:
2283                 dayOfWeek = CAL_SUNDAY;
2284                 break;
2285
2286         case Tizen::Locales::MONDAY:
2287                 dayOfWeek = CAL_MONDAY;
2288                 break;
2289
2290         case Tizen::Locales::TUESDAY:
2291                 dayOfWeek = CAL_TUESDAY;
2292                 break;
2293
2294         case Tizen::Locales::WEDNESDAY:
2295                 dayOfWeek = CAL_WEDNESDAY;
2296                 break;
2297
2298         case Tizen::Locales::THURSDAY:
2299                 dayOfWeek = CAL_THURSDAY;
2300                 break;
2301
2302         case Tizen::Locales::FRIDAY:
2303                 dayOfWeek = CAL_FRIDAY;
2304                 break;
2305
2306         case Tizen::Locales::SATURDAY:
2307                 dayOfWeek = CAL_SATURDAY;
2308                 break;
2309
2310         default:
2311                 break;
2312         }
2313
2314         return dayOfWeek;
2315 }
2316
2317 CalDayOfWeek
2318 _CalEventImpl::GetFirstDay(CalDayOfWeek weekStart, int dayOfWeek, int& count)
2319 {
2320         int firstDay = 0;
2321         int tmpDay = weekStart;
2322
2323         count = 0;
2324         for (int i = 0; i < _NUMBER_OF_DAYS_OF_WEEK; i++)
2325         {
2326                 if ((tmpDay & dayOfWeek) != 0)
2327                 {
2328                         if (firstDay == 0)
2329                         {
2330                                 firstDay = tmpDay;
2331                         }
2332
2333                         count++;
2334                 }
2335
2336                 tmpDay = GetNextDayOfWeek(static_cast<CalDayOfWeek>(tmpDay));
2337         }
2338
2339         return static_cast<CalDayOfWeek>(firstDay);
2340 }
2341
2342 CalDayOfWeek
2343 _CalEventImpl::GetNextDay(int dayOfWeek, CalDayOfWeek currentDay)
2344 {
2345         int tmpDay = currentDay;
2346
2347         for (int i = 0; i < _NUMBER_OF_DAYS_OF_WEEK; i++)
2348         {
2349                 tmpDay = GetNextDayOfWeek(static_cast<CalDayOfWeek>(tmpDay));
2350
2351                 if ((tmpDay & dayOfWeek) != 0)
2352                 {
2353                         break;
2354                 }
2355         }
2356
2357         return static_cast<CalDayOfWeek>(tmpDay);
2358 }
2359
2360 void
2361 _CalEventImpl::SetRecordHandle(calendar_record_h eventHandle)
2362 {
2363         __eventRecord.ResetHandle(eventHandle);
2364 }
2365
2366 calendar_record_h
2367 _CalEventImpl::GetRecordHandle(void) const
2368 {
2369         return __eventRecord.GetHandle();
2370 }
2371
2372 CalEvent*
2373 _CalEventImpl::CreateDefaultInstanceN(void)
2374 {
2375         return new (std::nothrow) CalEvent();
2376 }
2377
2378 _CalEventImpl*
2379 _CalEventImpl::GetInstance(CalEvent& event)
2380 {
2381         return event.__pCalEventImpl;
2382 }
2383
2384 const _CalEventImpl*
2385 _CalEventImpl::GetInstance(const CalEvent& event)
2386 {
2387         return event.__pCalEventImpl;
2388 }
2389
2390 }} //Tizen::Social