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