• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <sstream>
16 #include <iomanip>
17 #include "calendar_log.h"
18 #include "native_util.h"
19 
20 namespace OHOS::CalendarApi::Native {
21 const int MIN_DAY_OF_WEEK = 1;
22 const int MAX_DAY_OF_WEEK = 7;
23 const int MIN_MONTH_OF_YEAR = -12;
24 const int MAX_MONTH_OF_YEAR = 12;
25 const int MIN_DAY_OF_MONTH = -31;
26 const int MAX_DAY_OF_MONTH = 31;
27 const int MIN_DAY_OF_YEAR = -366;
28 const int MAX_DAY_OF_YEAR = 366;
29 const int MIN_WEEK_OF_YEAR = -53;
30 const int MAX_WEEK_OF_YEAR = 53;
31 const int MIN_WEEK_OF_MONTH = -5;
32 const int MAX_WEEK_OF_MONTH = 5;
DumpCalendarAccount(const CalendarAccount & account)33 void DumpCalendarAccount(const CalendarAccount &account)
34 {
35     LOG_DEBUG("account.name:%{public}s", account.name.c_str());
36     LOG_DEBUG("account.type:%{public}s", account.type.c_str());
37     LOG_DEBUG("account.displayName:%{public}s", account.displayName.value_or("").c_str());
38 }
39 
DumpEvent(const Event & event)40 void DumpEvent(const Event &event)
41 {
42     LOG_DEBUG("id       :%{public}d", event.id.value_or(-1));
43     LOG_DEBUG("type     :%{public}d", event.type);
44     LOG_DEBUG("title    :%{public}s", event.title.value_or("[null]").c_str());
45     if (event.location) {
46         auto location = event.location.value();
47         LOG_DEBUG("location.location  :%{public}s", location.location.value_or("[null]").c_str());
48         LOG_DEBUG("location.longitude :%{public}lf", location.longitude.value_or(-1));
49         LOG_DEBUG("location.latitude  :%{public}lf", location.latitude.value_or(-1));
50     } else {
51         LOG_DEBUG("location [null]");
52     }
53     if (event.service) {
54         auto service = event.service.value();
55         LOG_DEBUG("service.type  :%{public}s", service.type.c_str());
56         LOG_DEBUG("service.description :%{public}s", service.description.value_or("[null]").c_str());
57         LOG_DEBUG("service.uri  :%{public}s", service.uri.c_str());
58     } else {
59         LOG_DEBUG("service [null]");
60     }
61     if (event.recurrenceRule.has_value()) {
62         LOG_DEBUG("recurrenceRule.recurrenceFrequency: %{public}d", event.recurrenceRule.value().recurrenceFrequency);
63     }
64     LOG_DEBUG("startTime    :%{public}s", std::to_string(event.startTime).c_str());
65     LOG_DEBUG("endTime      :%{public}s", std::to_string(event.endTime).c_str());
66     LOG_DEBUG("isAllDay :%{public}d", event.isAllDay.value_or(0));
67 
68     for (const auto &attendee : event.attendees) {
69         LOG_DEBUG("attendee.name   :%{public}s", attendee.name.c_str());
70         LOG_DEBUG("attendee.email  :%{public}s", attendee.email.c_str());
71     }
72 
73     LOG_DEBUG("timeZone     :%{public}s", event.timeZone.value_or("[null]").c_str());
74     LOG_DEBUG("description  :%{public}s", event.description.value_or("[null]").c_str());
75 }
76 
BuildEventLocation(DataShare::DataShareValuesBucket & valuesBucket,const Event & event)77 void BuildEventLocation(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
78 {
79     if (!event.location) {
80         return;
81     }
82     auto location = event.location.value();
83     if (location.location) {
84         valuesBucket.Put("eventLocation", location.location.value());
85     }
86     if (location.longitude) {
87         // longitude is string in db
88         valuesBucket.Put("location_longitude", std::to_string(location.longitude.value()));
89     }
90     if (location.latitude) {
91         // latitude is string in db
92         valuesBucket.Put("location_latitude", std::to_string(location.latitude.value()));
93     }
94 }
95 
BuildEventService(DataShare::DataShareValuesBucket & valuesBucket,const Event & event)96 void BuildEventService(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
97 {
98     if (!event.service) {
99         return;
100     }
101     const auto service = event.service.value();
102     if (service.description) {
103         valuesBucket.Put("service_description", service.description.value());
104     }
105     valuesBucket.Put("service_type", service.type);
106     valuesBucket.Put("service_cp_bz_uri", service.uri);
107 }
108 
GetUTCTime(const int64_t & timeValue)109 std::string GetUTCTime(const int64_t &timeValue)
110 {
111     const int monOffset = 1;
112     const int strLen = 2;
113     const int baseYear = 1900;
114     time_t expire = timeValue / 1000;
115     std::tm* expireTime = std::gmtime(&expire);
116     std::stringstream out;
117     out << (expireTime->tm_year + baseYear);
118     out << std::setfill('0') << std::setw(strLen) << expireTime->tm_mon + monOffset;
119     out << std::setfill('0') << std::setw(strLen) << expireTime->tm_mday;
120     out << "T";
121     out << std::setfill('0') << std::setw(strLen) << expireTime->tm_hour;
122     out << std::setfill('0') << std::setw(strLen) << expireTime->tm_min;
123     out << std::setfill('0') << std::setw(strLen) << expireTime->tm_sec;
124     out << "Z";
125 
126     return out.str();
127 }
128 
GetUTCTimes(const std::vector<int64_t> & timeValues)129 std::string GetUTCTimes(const std::vector<int64_t> &timeValues)
130 {
131     std::stringstream out;
132     if (timeValues.size() == 0) {
133         return out.str();
134     }
135 
136     const auto timeLen = timeValues.size() - 1;
137     if (timeLen == 0) {
138         out << GetUTCTime(timeValues[0]);
139         return out.str();
140     }
141 
142     for (unsigned int i = 0; i <= timeLen; i++) {
143         out << GetUTCTime(timeValues[i]);
144         if (i != timeLen) {
145             out << ",";
146         }
147     }
148 
149     return out.str();
150 }
151 
GetRule(const Event & event)152 std::string GetRule(const Event &event)
153 {
154     const time_t now = event.startTime / 1000;
155     const std::tm *time = std::localtime(&now);
156     std::string rrule;
157     RecurrenceType recurrenceFrequency = event.recurrenceRule.value().recurrenceFrequency;
158     if (recurrenceFrequency == DAILY) {
159         rrule = "FREQ=DAILY" + GetEventRRule(event) + ";WKST=SU";
160     } else if (recurrenceFrequency == WEEKLY) {
161         rrule = "FREQ=WEEKLY" + GetEventRRule(event) + ";WKST=SU;BYDAY=";
162         if (time != nullptr) {
163             rrule += GetWeeklyRule(event, *time);
164         }
165     } else if (recurrenceFrequency == MONTHLY) {
166         rrule = "FREQ=MONTHLY" + GetEventRRule(event) + ";WKST=SU";
167         if (time != nullptr) {
168             rrule += GetMonthlyRule(event, *time);
169         }
170     } else if (recurrenceFrequency == YEARLY) {
171         rrule = "FREQ=YEARLY" + GetEventRRule(event) + ";WKST=SU";
172         if (time != nullptr) {
173             rrule += GetYearlyRule(event, *time);
174         }
175     }
176 
177     return rrule;
178 }
179 
GetEventRRule(const Event & event)180 std::string GetEventRRule(const Event &event)
181 {
182     auto recurrenceRule = event.recurrenceRule.value();
183     std::string rrule;
184     if (recurrenceRule.expire.has_value() && recurrenceRule.expire.value() > 0) {
185         rrule += ";UNTIL=" + GetUTCTime(event.recurrenceRule.value().expire.value());
186     }
187     if (recurrenceRule.count.has_value() && recurrenceRule.count.value() > 0) {
188         rrule += ";COUNT=" + std::to_string(recurrenceRule.count.value());
189     }
190     if (recurrenceRule.interval.has_value() && recurrenceRule.interval.value() > 0) {
191         rrule += ";INTERVAL=" + std::to_string(recurrenceRule.interval.value());
192     }
193     return rrule;
194 }
195 
GetWeeklyRule(const Event & event,const std::tm & time)196 std::string GetWeeklyRule(const Event &event, const std::tm &time)
197 {
198     std::string rrule;
199     bool isHasSetData = false;
200     auto rRuleValue = event.recurrenceRule.value();
201     const std::vector<string> weekList = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
202     if (rRuleValue.daysOfWeek.has_value()) {
203         isHasSetData = true;
204         auto daysOfWeekList = rRuleValue.daysOfWeek.value();
205         rrule = GetDaysOfWeekRule(MIN_DAY_OF_WEEK, MAX_DAY_OF_WEEK, daysOfWeekList);
206     }
207     if (isHasSetData == false) {
208         if (time.tm_wday < MAX_DAY_OF_WEEK) {
209             rrule = weekList[time.tm_wday];
210         }
211     }
212     return rrule;
213 }
214 
GetMonthlyRule(const Event & event,const std::tm & time)215 std::string GetMonthlyRule(const Event &event, const std::tm &time)
216 {
217     bool isHasSetData = false;
218     std::string rrule;
219     auto rruleValue = event.recurrenceRule.value();
220     if (rruleValue.daysOfWeek.has_value() && rruleValue.weeksOfMonth.has_value()) {
221         isHasSetData = true;
222         rrule += ";BYDAY=";
223         rrule += GetDaysOfWeekMonthRule(rruleValue.daysOfWeek.value(), rruleValue.weeksOfMonth.value());
224     }
225 
226     if (rruleValue.daysOfMonth.has_value()) {
227         isHasSetData = true;
228         rrule += ";BYMONTHDAY=";
229         auto daysOfMonthList = rruleValue.daysOfMonth.value();
230         rrule += GetRRuleSerial(MIN_DAY_OF_MONTH, MAX_DAY_OF_MONTH, daysOfMonthList);
231     }
232     if (isHasSetData == false) {
233         rrule += ";BYMONTHDAY=";
234         rrule += std::to_string(time.tm_mday);
235     }
236     return rrule;
237 }
238 
GetYearlyRule(const Event & event,const std::tm & time)239 std::string GetYearlyRule(const Event &event, const std::tm &time)
240 {
241     const int monOffset = 1;
242     bool isHasSetData = false;
243     std::string rrule;
244     auto rruleValue = event.recurrenceRule.value();
245     if (rruleValue.daysOfYear.has_value()) {
246         isHasSetData = true;
247         std::string days = GetRRuleSerial(MIN_DAY_OF_YEAR, MAX_DAY_OF_YEAR, rruleValue.daysOfYear.value());
248         rrule = ";BYYEARDAY=" + days;
249     }
250     if (rruleValue.weeksOfYear.has_value() && rruleValue.daysOfWeek.has_value()) {
251         isHasSetData = true;
252         auto weekOfYearList = rruleValue.weeksOfYear.value();
253         std::string weeks = GetRRuleSerial(MIN_WEEK_OF_YEAR, MAX_WEEK_OF_YEAR, weekOfYearList);
254         auto daysOfWeekList = rruleValue.daysOfWeek.value();
255         std::string weekdays = GetDaysOfWeekRule(MIN_DAY_OF_WEEK, MAX_DAY_OF_WEEK, daysOfWeekList);
256         rrule = ";BYWEEKNO=" + weeks + ";BYDAY=" + weekdays;
257     }
258     if (rruleValue.monthsOfYear.has_value() && rruleValue.daysOfMonth.has_value()) {
259         isHasSetData = true;
260         auto daysOfMonthList = rruleValue.daysOfMonth.value();
261         auto monthsOfYearList = rruleValue.monthsOfYear.value();
262         std::string days = GetRRuleSerial(MIN_DAY_OF_MONTH, MAX_DAY_OF_MONTH, daysOfMonthList);
263         std::string months = GetRRuleSerial(MIN_MONTH_OF_YEAR, MAX_MONTH_OF_YEAR, monthsOfYearList);
264         rrule = ";BYMONTHDAY=" + days + ";BYMONTH=" + months;
265     }
266     if (rruleValue.monthsOfYear.has_value() && rruleValue.weeksOfMonth.has_value() &&
267         rruleValue.daysOfWeek.has_value()) {
268         isHasSetData = true;
269         auto monthsOfYearList = rruleValue.monthsOfYear.value();
270         auto weeksOfMonthList = rruleValue.weeksOfMonth.value();
271         auto daysOfWeekList = rruleValue.daysOfWeek.value();
272         std::string months = GetRRuleSerial(MIN_MONTH_OF_YEAR, MAX_MONTH_OF_YEAR, monthsOfYearList);
273         std::string daysOfWeekMonth = GetDaysOfWeekMonthRule(daysOfWeekList, weeksOfMonthList);
274         rrule = ";BYDAY=" + daysOfWeekMonth + ";BYMONTH=" + months;
275     }
276     if (isHasSetData == false) {
277         rrule += ";BYMONTHDAY=";
278         rrule += std::to_string(time.tm_mday);
279         rrule += ";BYMONTH=";
280         rrule += std::to_string(time.tm_mon + monOffset);
281     }
282     return rrule;
283 }
284 
GetDaysOfWeekRule(int minValue,int maxValue,const std::vector<int64_t> & daysOfWeekList)285 std::string GetDaysOfWeekRule(int minValue, int maxValue, const std::vector<int64_t> &daysOfWeekList)
286 {
287     std::string rrule;
288     const std::vector<string> weekDayList = {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
289     for (const auto &dayOfWeek : daysOfWeekList) {
290         if (dayOfWeek <= maxValue && dayOfWeek >= minValue) {
291             if (&dayOfWeek == &daysOfWeekList.back()) {
292                 rrule = rrule + weekDayList[dayOfWeek - 1];
293                 break;
294             }
295             rrule = rrule + weekDayList[dayOfWeek - 1] + ",";
296         }
297     }
298     return rrule;
299 }
300 
GetDaysOfWeekMonthRule(const std::vector<int64_t> & daysOfWeekList,const std::vector<int64_t> & weeksOfMonthList)301 std::string GetDaysOfWeekMonthRule(
302     const std::vector<int64_t> &daysOfWeekList, const std::vector<int64_t> &weeksOfMonthList)
303 {
304     std::string rrule;
305     const std::vector<string> weekDayList = {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
306     auto daysLen = daysOfWeekList.size();
307     for (size_t i = 0; i < daysLen; i++) {
308         if (daysOfWeekList[i] >= MIN_DAY_OF_WEEK && daysOfWeekList[i] <= MAX_DAY_OF_WEEK &&
309             weeksOfMonthList[i] >= MIN_WEEK_OF_MONTH && weeksOfMonthList[i] <= MAX_WEEK_OF_MONTH) {
310             if (i == daysLen - 1) {
311                 rrule = rrule + std::to_string(weeksOfMonthList[i]) + weekDayList[daysOfWeekList[i] - 1];
312                 break;
313             } else {
314                 rrule = rrule + std::to_string(weeksOfMonthList[i]) + weekDayList[daysOfWeekList[i] - 1] + ",";
315             }
316         }
317     }
318     return rrule;
319 }
320 
GetRRuleSerial(int minValue,int maxValue,const std::vector<int64_t> & serialList)321 std::string GetRRuleSerial(int minValue, int maxValue, const std::vector<int64_t> &serialList)
322 {
323     std::string rrule;
324     for (const auto &serial : serialList) {
325         if (serial >= minValue && serial <= maxValue) {
326             if (&serial == &serialList.back()) {
327                 rrule = rrule + std::to_string(serial);
328                 break;
329             }
330             rrule = rrule + std::to_string(serial) + ",";
331         }
332     }
333     return rrule;
334 }
335 
BuildEventRecurrenceRule(DataShare::DataShareValuesBucket & valuesBucket,const Event & event)336 void BuildEventRecurrenceRule(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
337 {
338     if (!event.recurrenceRule.has_value()) {
339         return;
340     }
341 
342     std::string rrule = GetRule(event);
343     if (!rrule.empty()) {
344         valuesBucket.Put("rrule", rrule);
345     }
346 
347     if (event.recurrenceRule.value().excludedDates.has_value()) {
348         const auto excludedDateStr = GetUTCTimes(event.recurrenceRule.value().excludedDates.value());
349         valuesBucket.Put("exdate", excludedDateStr);
350     }
351 }
352 
BuildValueEvent(const Event & event,int calendarId,int channelId)353 DataShare::DataShareValuesBucket BuildValueEvent(const Event &event, int calendarId, int channelId)
354 {
355     DataShare::DataShareValuesBucket valuesBucket;
356     valuesBucket.Put("calendar_id", calendarId);
357 
358     LOG_DEBUG("title %{public}s", event.title.value_or("").c_str());
359     valuesBucket.Put("title", event.title.value_or(""));
360     valuesBucket.Put("important_event_type", event.type);
361     valuesBucket.Put("dtstart", event.startTime);
362     valuesBucket.Put("dtend", event.endTime);
363     valuesBucket.Put("channel_id", channelId);
364 
365     BuildEventLocation(valuesBucket, event);
366     BuildEventService(valuesBucket, event);
367     BuildEventRecurrenceRule(valuesBucket, event);
368 
369     LOG_DEBUG("description %{public}s", event.description.value_or("").c_str());
370 
371     if (event.description.has_value()) {
372         valuesBucket.Put("description", event.description.value());
373     }
374     if (event.timeZone.has_value()) {
375         valuesBucket.Put("eventTimezone", event.timeZone.value());
376     }
377     if (event.isAllDay.has_value()) {
378         valuesBucket.Put("allDay", event.isAllDay.value());
379     }
380     if (event.identifier.has_value()) {
381         valuesBucket.Put("identifier", event.identifier.value());
382     }
383     if (event.isLunar.has_value()) {
384         valuesBucket.Put("event_calendar_type", event.isLunar.value());
385     }
386     return valuesBucket;
387 }
388 
BuildAttendeeValue(const Attendee & attendee,int eventId)389 DataShare::DataShareValuesBucket BuildAttendeeValue(const Attendee &attendee, int eventId)
390 {
391     DataShare::DataShareValuesBucket valuesBucket;
392     valuesBucket.Put("event_id", eventId);
393     valuesBucket.Put("attendeeName", attendee.name);
394     LOG_DEBUG("attendeeName %{public}s", attendee.name.c_str());
395     valuesBucket.Put("attendeeEmail", attendee.email);
396     LOG_DEBUG("attendeeEmail %{public}s", attendee.email.c_str());
397     if (attendee.role.has_value()) {
398         valuesBucket.Put("attendeeRelationship", attendee.role.value());
399     }
400     if (attendee.status.has_value()) {
401         valuesBucket.Put("attendeeStatus", attendee.status.value());
402     }
403     if (attendee.type.has_value()) {
404         valuesBucket.Put("attendeeType", attendee.type.value());
405     }
406 
407     return valuesBucket;
408 }
409 
GetValue(DataShareResultSetPtr & resultSet,string_view fieldName,int & out)410 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, int& out)
411 {
412     int index = 0;
413     auto ret = resultSet->GetColumnIndex(string(fieldName), index);
414     if (ret != DataShare::E_OK) {
415         return ret;
416     }
417     return resultSet->GetInt(index, out);
418 }
419 
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,std::string & out)420 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, std::string& out)
421 {
422     return resultSet->GetString(index, out);
423 }
424 
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,int & out)425 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int& out)
426 {
427     return resultSet->GetInt(index, out);
428 }
429 
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,int64_t & out)430 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int64_t& out)
431 {
432     return resultSet->GetLong(index, out);
433 }
434 
GetValue(DataShareResultSetPtr & resultSet,string_view fieldName,std::string & out)435 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, std::string& out)
436 {
437     int index = 0;
438     auto fieldNameStr = string(fieldName);
439     auto ret = resultSet->GetColumnIndex(fieldNameStr, index);
440     if (ret != DataShare::E_OK) {
441         LOG_WARN("GetValue [%{public}s] failed [%{public}d]", fieldNameStr.c_str(), ret);
442         return ret;
443     }
444     return resultSet->GetString(index, out);
445 }
446 
447 
ResultSetToCalendars(DataShareResultSetPtr & resultSet)448 std::vector<std::shared_ptr<Calendar>> ResultSetToCalendars(DataShareResultSetPtr &resultSet)
449 {
450     std::vector<std::shared_ptr<Calendar>> result;
451     int rowCount = 0;
452     resultSet->GetRowCount(rowCount);
453     LOG_INFO("GetRowCount is %{public}d", rowCount);
454     if (rowCount == 0) {
455         return result;
456     }
457     auto err = resultSet->GoToFirstRow();
458     if (err != DataShare::E_OK) {
459         LOG_INFO("Failed GoToFirstRow %{public}d", err);
460         return result;
461     }
462     do {
463         int idValue = -1;
464         if (GetValue(resultSet, "_id", idValue) != DataShare::E_OK) {
465             break;
466         }
467         LOG_DEBUG("id: %{public}d", idValue);
468         std::string nameValue;
469         if (GetValue(resultSet, "account_name", nameValue) != DataShare::E_OK) {
470             break;
471         }
472         LOG_DEBUG("account_name: %{public}s", nameValue.c_str());
473         std::string typeValue;
474         if (GetValue(resultSet, "account_type", typeValue) != DataShare::E_OK) {
475             break;
476         }
477         LOG_DEBUG("account_type: %{public}s", typeValue.c_str());
478 
479         std::string displayNameValue;
480         GetValue(resultSet, "calendar_displayName", displayNameValue);
481         LOG_DEBUG("calendar_displayName: %{public}s", displayNameValue.c_str());
482 
483         int canReminder = -1;
484         GetValue(resultSet, "canReminder", canReminder);
485         LOG_DEBUG("canReminder: %{public}d", canReminder);
486 
487         int colorValue = 0;
488         GetValue(resultSet, "calendar_color", colorValue);
489         CalendarAccount curAccount {nameValue, typeValue, displayNameValue};
490         result.emplace_back(std::make_shared<Calendar>(curAccount, idValue));
491     } while (resultSet->GoToNextRow() == DataShare::E_OK);
492     return result;
493 }
494 
495 
ResultSetToLocation(DataShareResultSetPtr & resultSet)496 std::optional<Location> ResultSetToLocation(DataShareResultSetPtr &resultSet)
497 {
498     Location out;
499     string value;
500     auto ret = GetValue(resultSet, "eventLocation", value);
501     out.location = std::make_optional<string>(value);
502     ret = GetValue(resultSet, "location_longitude", value);
503     double longitudeValue = -1;
504     std::stringstream str2digit;
505     str2digit << value;
506     str2digit >> longitudeValue;
507     if (longitudeValue != -1) {
508         out.longitude = std::make_optional<double>(longitudeValue);
509     }
510     ret = GetValue(resultSet, "location_latitude", value);
511     double latitudeValue = -1;
512     str2digit.clear();
513     str2digit << value;
514     str2digit >> latitudeValue;
515     if (latitudeValue != -1) {
516         out.latitude = std::make_optional<double>(latitudeValue);
517     }
518 
519     if (ret != DataShare::E_OK) {
520         return std::nullopt;
521     }
522     return std::make_optional<Location>(out);
523 }
524 
ResultSetToEventService(DataShareResultSetPtr & resultSet)525 std::optional<EventService> ResultSetToEventService(DataShareResultSetPtr &resultSet)
526 {
527     EventService out;
528     string value;
529     auto ret = GetValue(resultSet, "service_type", value);
530     if (ret != DataShare::E_OK) {
531         return std::nullopt;
532     }
533     const std::set<std::string> serviceType = {"Meeting", "Watching", "Repayment", "Live", "Shopping",
534                                                "Trip", "Class", "SportsEvents", "SportsExercise"};
535     if (serviceType.count(value)) {
536         out.type = value;
537     } else {
538         return std::nullopt;
539     }
540     ret = GetValue(resultSet, "service_cp_bz_uri", value);
541     if (ret != DataShare::E_OK) {
542         return std::nullopt;
543     }
544     out.uri = value;
545     ret = GetValue(resultSet, "service_description", value);
546     if (ret == DataShare::E_OK) {
547         out.description = std::make_optional<string>(value);
548     }
549     return std::make_optional<EventService>(out);
550 }
551 
StringToInt(const std::string & str)552 int StringToInt(const std::string &str)
553 {
554     return std::atoi(str.c_str());
555 }
556 
TimeToUTC(const std::string & strTime)557 std::time_t TimeToUTC(const std::string &strTime)
558 {
559     const int baseYear = 1900;
560     const int offset = 2;
561     const int yearOffset = 4;
562     const int monBase = 4;
563     const int dayBase = 6;
564     const int hourBase = 9;
565     const int minBase = 11;
566     const int secBase = 13;
567     const int monCount = 12;
568     const int monRectify = 11;
569     const int micSecond = 1000;
570 
571     std::tm expireTime = { 0 };
572     expireTime.tm_year = StringToInt(strTime.substr(0, yearOffset)) - baseYear;
573     expireTime.tm_mon = (StringToInt(strTime.substr(monBase, offset)) + monRectify) % monCount;
574     expireTime.tm_mday = StringToInt(strTime.substr(dayBase, offset));
575     if (strTime.find("T") != std::string::npos) {
576         expireTime.tm_hour = StringToInt(strTime.substr(hourBase, offset));
577         expireTime.tm_min = StringToInt(strTime.substr(minBase, offset));
578         expireTime.tm_sec = StringToInt(strTime.substr(secBase,  offset));
579     } else {
580         expireTime.tm_hour = 0;
581         expireTime.tm_min = 0;
582         expireTime.tm_sec = 0;
583     }
584 
585     std::time_t utcTime = mktime(&expireTime) * micSecond; //精确到微秒
586 
587     return utcTime;
588 }
589 
SplitString(const std::string & str,const std::string & flag)590 std::vector<std::string> SplitString(const std::string &str, const std::string &flag)
591 {
592     std::vector<std::string> result;
593     std::string::size_type pos1 = 0;
594     std::string::size_type pos2 = str.find(flag);
595     while (pos2 != std::string::npos) {
596         result.push_back(str.substr(pos1, pos2 - pos1));
597         pos1 = pos2 + flag.size();
598         pos2 = str.find(flag, pos1);
599     }
600     if (pos1 != str.length()) {
601         result.push_back(str.substr(pos1));
602     }
603 
604     return result;
605 }
606 
ResultSetToExcludedDates(DataShareResultSetPtr & resultSet)607 std::optional<vector<int64_t>> ResultSetToExcludedDates(DataShareResultSetPtr &resultSet)
608 {
609     std::string value;
610     auto ret = GetValue(resultSet, "exdate", value);
611     if (ret != DataShare::E_OK) {
612         return std::nullopt;
613     }
614     std::vector<string> strListExDate = SplitString(value, ",");
615 
616     std::vector<int64_t> excludedDates;
617     for (const auto &str : strListExDate) {
618         auto exDate = TimeToUTC(str);
619         excludedDates.emplace_back(exDate);
620     }
621 
622     return std::make_optional<vector<int64_t>>(excludedDates);
623 }
624 
ConvertRecurrenceFrequency(const std::string & frequency,RecurrenceRule & rule)625 void ConvertRecurrenceFrequency(const std::string &frequency, RecurrenceRule &rule)
626 {
627     if (frequency == "YEARLY") {
628         rule.recurrenceFrequency = YEARLY;
629         return;
630     }
631     if (frequency == "MONTHLY") {
632         rule.recurrenceFrequency = MONTHLY;
633         return;
634     }
635     if (frequency == "WEEKLY") {
636         rule.recurrenceFrequency = WEEKLY;
637         return;
638     }
639     if (frequency == "DAILY") {
640         rule.recurrenceFrequency = DAILY;
641     }
642 }
643 
ResultSetToRecurrenceRule(DataShareResultSetPtr & resultSet)644 std::optional<RecurrenceRule> ResultSetToRecurrenceRule(DataShareResultSetPtr &resultSet)
645 {
646     const int strListSize = 2;
647     RecurrenceRule out;
648     out.recurrenceFrequency = NORULE;
649     std::string value;
650     auto ret = GetValue(resultSet, "rrule", value);
651     if (ret != DataShare::E_OK) {
652         return std::nullopt;
653     }
654     std::map<std::string, std::string> ruleMap;
655     std::vector<std::string> strListRule = SplitString(value, ";");
656     for (const auto &str : strListRule) {
657         std::vector<std::string> keyAndValue = SplitString(str, "=");
658         if (keyAndValue.size() == strListSize) {
659             ruleMap.insert(std::pair<std::string, std::string>(keyAndValue[0], keyAndValue[1]));
660         }
661     }
662     SetRRuleValue(ruleMap, out);
663     out.excludedDates = ResultSetToExcludedDates(resultSet);
664 
665     return std::make_optional<RecurrenceRule>(out);
666 }
667 
SetRRuleValue(const std::map<std::string,std::string> & ruleMap,RecurrenceRule & out)668 void SetRRuleValue(const std::map<std::string, std::string> &ruleMap, RecurrenceRule &out)
669 {
670     std::map<std::string, std::string>::const_iterator iter;
671     for (iter = ruleMap.begin(); iter != ruleMap.end(); iter++) {
672         if (iter->first == "FREQ") {
673             ConvertRecurrenceFrequency(iter->second, out);
674             continue;
675         }
676         if (iter->first == "COUNT") {
677             out.count = std::make_optional<int64_t>(std::stoi(iter->second));
678             continue;
679         }
680         if (iter->first == "INTERVAL") {
681             out.interval = std::make_optional<int64_t>(std::stoi(iter->second));
682             continue;
683         }
684         if (iter->first == "UNTIL") {
685             out.expire = std::make_optional<int64_t>(TimeToUTC(iter->second));
686         }
687         if (iter->first == "BYDAY") {
688             std::vector<std::string> weekDayList = SplitString(iter->second, ",");
689             SetByDayOfRRule(weekDayList, out);
690         }
691         if (iter->first == "BYWEEKNO") {
692             std::vector<std::string> weekNumList = SplitString(iter->second, ",");
693             for (const auto &weekNum : weekNumList) {
694                 out.weeksOfYear->push_back(std::stoi(weekNum));
695             }
696         }
697         if (iter->first == "BYMONTHDAY") {
698             std::vector<std::string> monthDayList = SplitString(iter->second, ",");
699             for (const auto &monthDay : monthDayList) {
700                 out.daysOfMonth.value().push_back(std::stoi(monthDay));
701             }
702         }
703         if (iter->first == "BYYEARDAY") {
704             std::vector<std::string> yearDayList = SplitString(iter->second, ",");
705             for (const auto &yearDay : yearDayList) {
706                 out.daysOfYear.value().push_back(std::stoi(yearDay));
707             }
708         }
709         if (iter->first == "BYMONTH") {
710             std::vector<std::string> monthList = SplitString(iter->second, ",");
711             for (const auto &month : monthList) {
712                 out.monthsOfYear.value().push_back(std::stoi(month));
713             }
714         }
715     }
716 }
717 
SetByDayOfRRule(const std::vector<std::string> & weekDayList,RecurrenceRule & out)718 void SetByDayOfRRule(const std::vector<std::string> &weekDayList, RecurrenceRule &out)
719 {
720     const int weekStrLen = 2;
721     const std::vector<string> dayOfWeekList = {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
722     for (const auto &weekday : weekDayList) {
723         if (weekday.length() >= weekStrLen) {
724             std::string weekDayStr = weekday.substr(weekday.length() - weekStrLen, weekStrLen);
725             std::string WeekNumStr = weekday.substr(0, weekday.length() - weekStrLen);
726             auto it = std::find(dayOfWeekList.begin(), dayOfWeekList.end(), weekDayStr);
727             if (it != dayOfWeekList.end()) {
728                 int dayNum = it - dayOfWeekList.begin();
729                 out.daysOfWeek.value().push_back(dayNum + 1);
730                 out.weeksOfMonth.value().push_back(std::stoi(WeekNumStr));
731             }
732         }
733     }
734 }
735 
ResultSetToEvent(Event & event,DataShareResultSetPtr & resultSet,const std::set<std::string> & columns)736 void ResultSetToEvent(Event &event, DataShareResultSetPtr &resultSet, const std::set<std::string>& columns)
737 {
738     GetValueOptional(resultSet, "_id", event.id);
739     if (columns.count("type")) {
740         int type = 0;
741         GetValue(resultSet, "important_event_type", type);
742         event.type = static_cast<EventType>(type);
743     }
744     if (columns.count("title")) {
745         GetValueOptional(resultSet, "title", event.title);
746     }
747     if (columns.count("startTime")) {
748         LOG_DEBUG("TLQ get startTime");
749         GetValue(resultSet, "dtstart", event.startTime);
750     }
751     if (columns.count("endTime")) {
752         LOG_DEBUG("TLQ get endTime");
753         GetValue(resultSet, "dtend", event.endTime);
754     }
755     if (columns.count("isAllDay")) {
756         int isAllDay = 0;
757         GetValue(resultSet, "allDay", isAllDay);
758         event.isAllDay = static_cast<bool>(isAllDay);
759     }
760     if (columns.count("description")) {
761         GetValueOptional(resultSet, "description", event.description);
762     }
763     if (columns.count("timeZone")) {
764         GetValueOptional(resultSet, "eventTimezone", event.timeZone);
765     }
766     if (columns.count("location")) {
767         event.location = ResultSetToLocation(resultSet);
768     }
769     if (columns.count("service")) {
770         event.service = ResultSetToEventService(resultSet);
771     }
772     if (columns.count("recurrenceRule")) {
773         event.recurrenceRule = ResultSetToRecurrenceRule(resultSet);
774     }
775 
776     if (columns.count("identifier")) {
777         GetValueOptional(resultSet, "identifier", event.identifier);
778     }
779 
780     if (columns.count("isLunar")) {
781         int isLunar = 0;
782         GetValue(resultSet, "event_calendar_type", isLunar);
783         event.isLunar = static_cast<bool>(isLunar);
784     }
785 }
786 
ResultSetToEvents(std::vector<Event> & events,DataShareResultSetPtr & resultSet,const std::set<std::string> & columns)787 int ResultSetToEvents(std::vector<Event> &events, DataShareResultSetPtr &resultSet,
788     const std::set<std::string>& columns)
789 {
790     int rowCount = 0;
791     resultSet->GetRowCount(rowCount);
792     LOG_INFO("GetRowCount is %{public}d", rowCount);
793     if (rowCount <= 0) {
794         return -1;
795     }
796     auto err = resultSet->GoToFirstRow();
797     if (err != DataShare::E_OK) {
798         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
799         return -1;
800     }
801     do {
802         Event event;
803         ResultSetToEvent(event, resultSet, columns);
804         events.emplace_back(event);
805     } while (resultSet->GoToNextRow() == DataShare::E_OK);
806     return 0;
807 }
808 
ResultSetToAttendeeStatus(Attendee & attendee,DataShareResultSetPtr & resultSet)809 void ResultSetToAttendeeStatus(Attendee &attendee, DataShareResultSetPtr &resultSet)
810 {
811     int statusValue = 0;
812     GetValue(resultSet, "attendeeStatus", statusValue);
813     if (statusValue == UNKNOWN) {
814         attendee.status = std::make_optional<AttendeeStatus>(UNKNOWN);
815     } else if (statusValue == TENTATIVE) {
816         attendee.status = std::make_optional<AttendeeStatus>(TENTATIVE);
817     } else if (statusValue == ACCEPTED) {
818         attendee.status = std::make_optional<AttendeeStatus>(ACCEPTED);
819     } else if (statusValue == DECLINED) {
820         attendee.status = std::make_optional<AttendeeStatus>(DECLINED);
821     } else {
822         attendee.status = std::make_optional<AttendeeStatus>(UNRESPONSIVE);
823     }
824 }
825 
ResultSetToAttendeeType(Attendee & attendee,DataShareResultSetPtr & resultSet)826 void ResultSetToAttendeeType(Attendee &attendee, DataShareResultSetPtr &resultSet)
827 {
828     int typeValue = 0;
829     GetValue(resultSet, "attendeeType", typeValue);
830     if (typeValue == REQUIRED) {
831         attendee.type = std::make_optional<AttendeeType>(REQUIRED);
832     } else if (typeValue == OPTIONAL) {
833         attendee.type = std::make_optional<AttendeeType>(OPTIONAL);
834     } else {
835         attendee.type = std::make_optional<AttendeeType>(RESOURCE);
836     }
837 }
838 
ResultSetToAttendees(std::vector<Attendee> & attendees,DataShareResultSetPtr & resultSet)839 int ResultSetToAttendees(std::vector<Attendee> &attendees, DataShareResultSetPtr &resultSet)
840 {
841     int rowCount = 0;
842     resultSet->GetRowCount(rowCount);
843     LOG_INFO("GetRowCount is %{public}d", rowCount);
844     if (rowCount <= 0) {
845         return -1;
846     }
847     auto err = resultSet->GoToFirstRow();
848     if (err != DataShare::E_OK) {
849         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
850         return -1;
851     }
852     int roleValue = 0;
853     do {
854         Attendee attendee;
855         GetValue(resultSet, "attendeeName", attendee.name);
856         GetValue(resultSet, "attendeeEmail", attendee.email);
857         GetValue(resultSet, "attendeeRelationship",  roleValue);
858         if (roleValue == PARTICIPANT) {
859             attendee.role = std::make_optional<RoleType>(PARTICIPANT);
860         } else if (roleValue == ORGANIZER) {
861             attendee.role = std::make_optional<RoleType>(ORGANIZER);
862         }
863         ResultSetToAttendeeStatus(attendee, resultSet);
864         ResultSetToAttendeeType(attendee, resultSet);
865         attendees.emplace_back(attendee);
866     } while (resultSet->GoToNextRow() == DataShare::E_OK);
867     return 0;
868 }
869 
ResultSetToReminders(std::vector<int> & reminders,DataShareResultSetPtr & resultSet)870 int ResultSetToReminders(std::vector<int> &reminders, DataShareResultSetPtr &resultSet)
871 {
872     int rowCount = 0;
873     resultSet->GetRowCount(rowCount);
874     LOG_INFO("GetRowCount is %{public}d", rowCount);
875     if (rowCount <= 0) {
876         return -1;
877     }
878     auto err = resultSet->GoToFirstRow();
879     if (err != DataShare::E_OK) {
880         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
881         return -1;
882     }
883     do {
884         int minutes;
885         GetValue(resultSet, "minutes", minutes);
886         reminders.emplace_back(minutes);
887     } while (resultSet->GoToNextRow() == DataShare::E_OK);
888     return 0;
889 }
890 
ResultSetToConfig(CalendarConfig & config,DataShareResultSetPtr & resultSet)891 void ResultSetToConfig(CalendarConfig &config, DataShareResultSetPtr &resultSet)
892 {
893     int rowCount = 0;
894     resultSet->GetRowCount(rowCount);
895     LOG_INFO("GetRowCount is %{public}d", rowCount);
896     auto err = resultSet->GoToFirstRow();
897     if (err != DataShare::E_OK) {
898         LOG_ERROR("Failed GoToFirstRow %{public}d", err);
899     }
900     do {
901         int enableReminder;
902         std::int64_t color;
903         GetValue(resultSet, "canReminder", enableReminder);
904         GetValue(resultSet, "calendar_color", color);
905         config.enableReminder = static_cast<bool>(enableReminder);
906         LOG_INFO("enableReminder is %{public}d", enableReminder);
907         config.color = color;
908     } while (resultSet->GoToNextRow() == DataShare::E_OK);
909 }
910 
IsValidHexString(const std::string & colorStr)911 bool IsValidHexString(const std::string& colorStr)
912 {
913     if (colorStr.empty()) {
914         return false;
915     }
916     for (char ch : colorStr) {
917         if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
918             continue;
919         }
920         return false;
921     }
922     return true;
923 }
924 
ColorParse(const std::string & colorStr,variant<string,int64_t> & colorValue)925 bool ColorParse(const std::string& colorStr, variant<string, int64_t>& colorValue)
926 {
927     if (colorStr.empty()) {
928         LOG_ERROR("color string is empty");
929         return false;
930     }
931 
932     if (colorStr[0] != '#') { // start with '#'
933         LOG_ERROR("color string not start with #");
934         return false;
935     }
936 
937     const int rgbLen = 7;
938     const int argbLen = 9;
939     if (colorStr.size() != rgbLen && colorStr.size() != argbLen) {
940         LOG_ERROR("color string length is not 7 or 9");
941         return false;
942     }
943 
944     std::string colorStrSub = colorStr.substr(1);
945     if (!IsValidHexString(colorStrSub)) {
946         LOG_DEBUG("color string is not valid hex string");
947         return false;
948     }
949 
950     LOG_DEBUG("color string size is 7 or 9");
951     colorValue.emplace<1>(std::stoll(colorStrSub, NULL, 16)); // 16 is convert hex string to number
952     if (std::get_if<1>(&colorValue)) {
953         LOG_DEBUG("colorStrSub -> colorValue colorValue:%{public}s", std::to_string(std::get<1>(colorValue)).c_str());
954         return true;
955     }
956     LOG_DEBUG("color is null");
957     return false;
958 }
959 
SetFieldInfo(const std::vector<string> & eventKey,std::vector<string> & queryField,std::set<string> & resultSetField,const std::map<string,string> eventField)960 void SetFieldInfo(const std::vector<string>& eventKey, std::vector<string>& queryField,
961     std::set<string>& resultSetField, const std::map<string, string> eventField)
962 {
963     for (const auto& field : eventKey) {
964         if (field == "location") {
965             queryField.emplace_back("eventLocation");
966             queryField.emplace_back("location_longitude");
967             queryField.emplace_back("location_latitude");
968             resultSetField.insert(field);
969             continue;
970         }
971         if (field == "service") {
972             queryField.emplace_back("service_type");
973             queryField.emplace_back("service_cp_bz_uri");
974             queryField.emplace_back("service_description");
975             resultSetField.insert(field);
976             continue;
977         }
978         if (field == "attendee") {
979             resultSetField.insert(field);
980             continue;
981         }
982         if (field == "reminderTime") {
983             resultSetField.insert(field);
984             continue;
985         }
986         if (field == "identifier") {
987             queryField.emplace_back("identifier");
988             resultSetField.insert(field);
989             continue;
990         }
991         if (field == "recurrenceRule") {
992             queryField.emplace_back("rrule");
993             queryField.emplace_back("exdate");
994             resultSetField.insert(field);
995             continue;
996         }
997         if (field == "isLunar") {
998             queryField.emplace_back("event_calendar_type");
999             resultSetField.insert(field);
1000             continue;
1001         }
1002         if (field == "id") {
1003             continue;
1004         }
1005         queryField.emplace_back(eventField.at(field));
1006         resultSetField.insert(field);
1007     }
1008 }
1009 
SetField(const std::vector<string> & eventKey,std::vector<string> & queryField,std::set<string> & resultSetField)1010 void SetField(const std::vector<string>& eventKey, std::vector<string>& queryField, std::set<string>& resultSetField)
1011 {
1012     const std::map<string, string> eventField = { { "id", "_id" },
1013                                                   { "type", "important_event_type" },
1014                                                   { "title", "title" },
1015                                                   { "startTime", "dtstart" },
1016                                                   { "endTime", "dtend" },
1017                                                   { "isAllDay", "allDay" },
1018                                                   { "timeZone", "eventTimezone" },
1019                                                   { "description", "description" }};
1020     SetFieldInfo(eventKey, queryField, resultSetField, eventField);
1021 }
1022 }
1023