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
401 return valuesBucket;
402 }
403
GetValue(DataShareResultSetPtr & resultSet,string_view fieldName,int & out)404 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, int& out)
405 {
406 int index = 0;
407 auto ret = resultSet->GetColumnIndex(string(fieldName), index);
408 if (ret != DataShare::E_OK) {
409 return ret;
410 }
411 return resultSet->GetInt(index, out);
412 }
413
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,std::string & out)414 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, std::string& out)
415 {
416 return resultSet->GetString(index, out);
417 }
418
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,int & out)419 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int& out)
420 {
421 return resultSet->GetInt(index, out);
422 }
423
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,int64_t & out)424 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int64_t& out)
425 {
426 return resultSet->GetLong(index, out);
427 }
428
GetValue(DataShareResultSetPtr & resultSet,string_view fieldName,std::string & out)429 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, std::string& out)
430 {
431 int index = 0;
432 auto fieldNameStr = string(fieldName);
433 auto ret = resultSet->GetColumnIndex(fieldNameStr, index);
434 if (ret != DataShare::E_OK) {
435 LOG_WARN("GetValue [%{public}s] failed [%{public}d]", fieldNameStr.c_str(), ret);
436 return ret;
437 }
438 return resultSet->GetString(index, out);
439 }
440
441
ResultSetToCalendars(DataShareResultSetPtr & resultSet)442 std::vector<std::shared_ptr<Calendar>> ResultSetToCalendars(DataShareResultSetPtr &resultSet)
443 {
444 std::vector<std::shared_ptr<Calendar>> result;
445 int rowCount = 0;
446 resultSet->GetRowCount(rowCount);
447 LOG_INFO("GetRowCount is %{public}d", rowCount);
448 if (rowCount == 0) {
449 return result;
450 }
451 auto err = resultSet->GoToFirstRow();
452 if (err != DataShare::E_OK) {
453 LOG_INFO("Failed GoToFirstRow %{public}d", err);
454 return result;
455 }
456 do {
457 int idValue = -1;
458 if (GetValue(resultSet, "_id", idValue) != DataShare::E_OK) {
459 break;
460 }
461 LOG_DEBUG("id: %{public}d", idValue);
462 std::string nameValue;
463 if (GetValue(resultSet, "account_name", nameValue) != DataShare::E_OK) {
464 break;
465 }
466 LOG_DEBUG("account_name: %{public}s", nameValue.c_str());
467 std::string typeValue;
468 if (GetValue(resultSet, "account_type", typeValue) != DataShare::E_OK) {
469 break;
470 }
471 LOG_DEBUG("account_type: %{public}s", typeValue.c_str());
472
473 std::string displayNameValue;
474 GetValue(resultSet, "calendar_displayName", displayNameValue);
475 LOG_DEBUG("calendar_displayName: %{public}s", displayNameValue.c_str());
476
477 int canReminder = -1;
478 GetValue(resultSet, "canReminder", canReminder);
479 LOG_DEBUG("canReminder: %{public}d", canReminder);
480
481 int colorValue = 0;
482 GetValue(resultSet, "calendar_color", colorValue);
483 CalendarAccount curAccount {nameValue, typeValue, displayNameValue};
484 result.emplace_back(std::make_shared<Calendar>(curAccount, idValue));
485 } while (resultSet->GoToNextRow() == DataShare::E_OK);
486 return result;
487 }
488
489
ResultSetToLocation(DataShareResultSetPtr & resultSet)490 std::optional<Location> ResultSetToLocation(DataShareResultSetPtr &resultSet)
491 {
492 Location out;
493 string value;
494 auto ret = GetValue(resultSet, "eventLocation", value);
495 out.location = std::make_optional<string>(value);
496 ret = GetValue(resultSet, "location_longitude", value);
497 double longitudeValue = -1;
498 std::stringstream str2digit;
499 str2digit << value;
500 str2digit >> longitudeValue;
501 if (longitudeValue != -1) {
502 out.longitude = std::make_optional<double>(longitudeValue);
503 }
504 ret = GetValue(resultSet, "location_latitude", value);
505 double latitudeValue = -1;
506 str2digit.clear();
507 str2digit << value;
508 str2digit >> latitudeValue;
509 if (latitudeValue != -1) {
510 out.latitude = std::make_optional<double>(latitudeValue);
511 }
512
513 if (ret != DataShare::E_OK) {
514 return std::nullopt;
515 }
516 return std::make_optional<Location>(out);
517 }
518
ResultSetToEventService(DataShareResultSetPtr & resultSet)519 std::optional<EventService> ResultSetToEventService(DataShareResultSetPtr &resultSet)
520 {
521 EventService out;
522 string value;
523 auto ret = GetValue(resultSet, "service_type", value);
524 if (ret != DataShare::E_OK) {
525 return std::nullopt;
526 }
527 const std::set<std::string> serviceType = {"Meeting", "Watching", "Repayment", "Live", "Shopping",
528 "Trip", "Class", "SportsEvents", "SportsExercise"};
529 if (serviceType.count(value)) {
530 out.type = value;
531 } else {
532 return std::nullopt;
533 }
534 ret = GetValue(resultSet, "service_cp_bz_uri", value);
535 if (ret != DataShare::E_OK) {
536 return std::nullopt;
537 }
538 out.uri = value;
539 ret = GetValue(resultSet, "service_description", value);
540 if (ret == DataShare::E_OK) {
541 out.description = std::make_optional<string>(value);
542 }
543 return std::make_optional<EventService>(out);
544 }
545
StringToInt(const std::string & str)546 int StringToInt(const std::string &str)
547 {
548 return std::atoi(str.c_str());
549 }
550
TimeToUTC(const std::string & strTime)551 std::time_t TimeToUTC(const std::string &strTime)
552 {
553 const int baseYear = 1900;
554 const int offset = 2;
555 const int yearOffset = 4;
556 const int monBase = 4;
557 const int dayBase = 6;
558 const int hourBase = 9;
559 const int minBase = 11;
560 const int secBase = 13;
561 const int monCount = 12;
562 const int monRectify = 11;
563 const int micSecond = 1000;
564
565 std::tm expireTime = { 0 };
566 expireTime.tm_year = StringToInt(strTime.substr(0, yearOffset)) - baseYear;
567 expireTime.tm_mon = (StringToInt(strTime.substr(monBase, offset)) + monRectify) % monCount;
568 expireTime.tm_mday = StringToInt(strTime.substr(dayBase, offset));
569 if (strTime.find("T") != std::string::npos) {
570 expireTime.tm_hour = StringToInt(strTime.substr(hourBase, offset));
571 expireTime.tm_min = StringToInt(strTime.substr(minBase, offset));
572 expireTime.tm_sec = StringToInt(strTime.substr(secBase, offset));
573 } else {
574 expireTime.tm_hour = 0;
575 expireTime.tm_min = 0;
576 expireTime.tm_sec = 0;
577 }
578
579 std::time_t utcTime = mktime(&expireTime) * micSecond; //精确到微秒
580
581 return utcTime;
582 }
583
SplitString(const std::string & str,const std::string & flag)584 std::vector<std::string> SplitString(const std::string &str, const std::string &flag)
585 {
586 std::vector<std::string> result;
587 std::string::size_type pos1 = 0;
588 std::string::size_type pos2 = str.find(flag);
589 while (std::string::npos != pos2) {
590 result.push_back(str.substr(pos1, pos2 - pos1));
591 pos1 = pos2 + flag.size();
592 pos2 = str.find(flag, pos1);
593 }
594 if (pos1 != str.length()) {
595 result.push_back(str.substr(pos1));
596 }
597
598 return result;
599 }
600
ResultSetToExcludedDates(DataShareResultSetPtr & resultSet)601 std::optional<vector<int64_t>> ResultSetToExcludedDates(DataShareResultSetPtr &resultSet)
602 {
603 std::string value;
604 auto ret = GetValue(resultSet, "exdate", value);
605 if (ret != DataShare::E_OK) {
606 return std::nullopt;
607 }
608 std::vector<string> strListExDate = SplitString(value, ",");
609
610 std::vector<int64_t> excludedDates;
611 for (const auto &str : strListExDate) {
612 auto exDate = TimeToUTC(str);
613 excludedDates.emplace_back(exDate);
614 }
615
616 return std::make_optional<vector<int64_t>>(excludedDates);
617 }
618
ConvertRecurrenceFrequency(const std::string & frequency,RecurrenceRule & rule)619 void ConvertRecurrenceFrequency(const std::string &frequency, RecurrenceRule &rule)
620 {
621 if (frequency == "YEARLY") {
622 rule.recurrenceFrequency = YEARLY;
623 return;
624 }
625 if (frequency == "MONTHLY") {
626 rule.recurrenceFrequency = MONTHLY;
627 return;
628 }
629 if (frequency == "WEEKLY") {
630 rule.recurrenceFrequency = WEEKLY;
631 return;
632 }
633 if (frequency == "DAILY") {
634 rule.recurrenceFrequency = DAILY;
635 }
636 }
637
ResultSetToRecurrenceRule(DataShareResultSetPtr & resultSet)638 std::optional<RecurrenceRule> ResultSetToRecurrenceRule(DataShareResultSetPtr &resultSet)
639 {
640 const int strListSize = 2;
641 RecurrenceRule out;
642 out.recurrenceFrequency = NORULE;
643 std::string value;
644 auto ret = GetValue(resultSet, "rrule", value);
645 if (ret != DataShare::E_OK) {
646 return std::nullopt;
647 }
648 std::map<std::string, std::string> ruleMap;
649 std::vector<std::string> strListRule = SplitString(value, ";");
650 for (const auto &str : strListRule) {
651 std::vector<std::string> keyAndValue = SplitString(str, "=");
652 if (keyAndValue.size() == strListSize) {
653 ruleMap.insert(std::pair<std::string, std::string>(keyAndValue[0], keyAndValue[1]));
654 }
655 }
656 SetRRuleValue(ruleMap, out);
657 out.excludedDates = ResultSetToExcludedDates(resultSet);
658
659 return std::make_optional<RecurrenceRule>(out);
660 }
661
SetRRuleValue(const std::map<std::string,std::string> & ruleMap,RecurrenceRule & out)662 void SetRRuleValue(const std::map<std::string, std::string> &ruleMap, RecurrenceRule &out)
663 {
664 std::map<std::string, std::string>::const_iterator iter;
665 for (iter = ruleMap.begin(); iter != ruleMap.end(); iter++) {
666 if (iter->first == "FREQ") {
667 ConvertRecurrenceFrequency(iter->second, out);
668 continue;
669 }
670 if (iter->first == "COUNT") {
671 out.count = std::make_optional<int64_t>(std::stoi(iter->second));
672 continue;
673 }
674 if (iter->first == "INTERVAL") {
675 out.interval = std::make_optional<int64_t>(std::stoi(iter->second));
676 continue;
677 }
678 if (iter->first == "UNTIL") {
679 out.expire = std::make_optional<int64_t>(TimeToUTC(iter->second));
680 }
681 if (iter->first == "BYDAY") {
682 std::vector<std::string> weekDayList = SplitString(iter->second, ",");
683 SetByDayOfRRule(weekDayList, out);
684 }
685 if (iter->first == "BYWEEKNO") {
686 std::vector<std::string> weekNumList = SplitString(iter->second, ",");
687 for (const auto &weekNum : weekNumList) {
688 out.weeksOfYear->push_back(std::stoi(weekNum));
689 }
690 }
691 if (iter->first == "BYMONTHDAY") {
692 std::vector<std::string> monthDayList = SplitString(iter->second, ",");
693 for (const auto &monthDay : monthDayList) {
694 out.daysOfMonth.value().push_back(std::stoi(monthDay));
695 }
696 }
697 if (iter->first == "BYYEARDAY") {
698 std::vector<std::string> yearDayList = SplitString(iter->second, ",");
699 for (const auto &yearDay : yearDayList) {
700 out.daysOfYear.value().push_back(std::stoi(yearDay));
701 }
702 }
703 if (iter->first == "BYMONTH") {
704 std::vector<std::string> monthList = SplitString(iter->second, ",");
705 for (const auto &month : monthList) {
706 out.monthsOfYear.value().push_back(std::stoi(month));
707 }
708 }
709 }
710 }
711
SetByDayOfRRule(const std::vector<std::string> & weekDayList,RecurrenceRule & out)712 void SetByDayOfRRule(const std::vector<std::string> &weekDayList, RecurrenceRule &out)
713 {
714 const int weekStrLen = 2;
715 const std::vector<string> dayOfWeekList = {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
716 for (const auto &weekday : weekDayList) {
717 if (weekday.length() >= weekStrLen) {
718 std::string weekDayStr = weekday.substr(weekday.length() - weekStrLen, weekStrLen);
719 std::string WeekNumStr = weekday.substr(0, weekday.length() - weekStrLen);
720 auto it = std::find(dayOfWeekList.begin(), dayOfWeekList.end(), weekDayStr);
721 if (it != dayOfWeekList.end()) {
722 int dayNum = it - dayOfWeekList.begin();
723 out.daysOfWeek.value().push_back(dayNum + 1);
724 out.weeksOfMonth.value().push_back(std::stoi(WeekNumStr));
725 }
726 }
727 }
728 }
729
ResultSetToEvent(Event & event,DataShareResultSetPtr & resultSet,const std::set<std::string> & columns)730 void ResultSetToEvent(Event &event, DataShareResultSetPtr &resultSet, const std::set<std::string>& columns)
731 {
732 GetValueOptional(resultSet, "_id", event.id);
733 if (columns.count("type")) {
734 int type = 0;
735 GetValue(resultSet, "important_event_type", type);
736 event.type = static_cast<EventType>(type);
737 }
738 if (columns.count("title")) {
739 GetValueOptional(resultSet, "title", event.title);
740 }
741 if (columns.count("startTime")) {
742 LOG_DEBUG("TLQ get startTime");
743 GetValue(resultSet, "dtstart", event.startTime);
744 }
745 if (columns.count("endTime")) {
746 LOG_DEBUG("TLQ get endTime");
747 GetValue(resultSet, "dtend", event.endTime);
748 }
749 if (columns.count("isAllDay")) {
750 int isAllDay = 0;
751 GetValue(resultSet, "allDay", isAllDay);
752 event.isAllDay = static_cast<bool>(isAllDay);
753 }
754 if (columns.count("description")) {
755 GetValueOptional(resultSet, "description", event.description);
756 }
757 if (columns.count("timeZone")) {
758 GetValueOptional(resultSet, "eventTimezone", event.timeZone);
759 }
760 if (columns.count("location")) {
761 event.location = ResultSetToLocation(resultSet);
762 }
763 if (columns.count("service")) {
764 event.service = ResultSetToEventService(resultSet);
765 }
766 if (columns.count("recurrenceRule")) {
767 event.recurrenceRule = ResultSetToRecurrenceRule(resultSet);
768 }
769
770 if (columns.count("identifier")) {
771 GetValueOptional(resultSet, "identifier", event.identifier);
772 }
773
774 if (columns.count("isLunar")) {
775 int isLunar = 0;
776 GetValue(resultSet, "event_calendar_type", isLunar);
777 event.isLunar = static_cast<bool>(isLunar);
778 }
779 }
780
ResultSetToEvents(std::vector<Event> & events,DataShareResultSetPtr & resultSet,const std::set<std::string> & columns)781 int ResultSetToEvents(std::vector<Event> &events, DataShareResultSetPtr &resultSet,
782 const std::set<std::string>& columns)
783 {
784 int rowCount = 0;
785 resultSet->GetRowCount(rowCount);
786 LOG_INFO("GetRowCount is %{public}d", rowCount);
787 if (rowCount <= 0) {
788 return -1;
789 }
790 auto err = resultSet->GoToFirstRow();
791 if (err != DataShare::E_OK) {
792 LOG_ERROR("Failed GoToFirstRow %{public}d", err);
793 return -1;
794 }
795 do {
796 Event event;
797 ResultSetToEvent(event, resultSet, columns);
798 events.emplace_back(event);
799 } while (resultSet->GoToNextRow() == DataShare::E_OK);
800 return 0;
801 }
802
ResultSetToAttendees(std::vector<Attendee> & attendees,DataShareResultSetPtr & resultSet)803 int ResultSetToAttendees(std::vector<Attendee> &attendees, DataShareResultSetPtr &resultSet)
804 {
805 int rowCount = 0;
806 resultSet->GetRowCount(rowCount);
807 LOG_INFO("GetRowCount is %{public}d", rowCount);
808 if (rowCount <= 0) {
809 return -1;
810 }
811 auto err = resultSet->GoToFirstRow();
812 if (err != DataShare::E_OK) {
813 LOG_ERROR("Failed GoToFirstRow %{public}d", err);
814 return -1;
815 }
816 int roleValue = 0;
817 do {
818 Attendee attendee;
819 GetValue(resultSet, "attendeeName", attendee.name);
820 GetValue(resultSet, "attendeeEmail", attendee.email);
821 GetValue(resultSet, "attendeeRelationship", roleValue);
822 if (roleValue == PARTICIPANT) {
823 attendee.role = std::make_optional<RoleType>(PARTICIPANT);
824 } else if (roleValue == ORGANIZER) {
825 attendee.role = std::make_optional<RoleType>(ORGANIZER);
826 }
827
828 attendees.emplace_back(attendee);
829 } while (resultSet->GoToNextRow() == DataShare::E_OK);
830 return 0;
831 }
832
ResultSetToReminders(std::vector<int> & reminders,DataShareResultSetPtr & resultSet)833 int ResultSetToReminders(std::vector<int> &reminders, DataShareResultSetPtr &resultSet)
834 {
835 int rowCount = 0;
836 resultSet->GetRowCount(rowCount);
837 LOG_INFO("GetRowCount is %{public}d", rowCount);
838 if (rowCount <= 0) {
839 return -1;
840 }
841 auto err = resultSet->GoToFirstRow();
842 if (err != DataShare::E_OK) {
843 LOG_ERROR("Failed GoToFirstRow %{public}d", err);
844 return -1;
845 }
846 do {
847 int minutes;
848 GetValue(resultSet, "minutes", minutes);
849 reminders.emplace_back(minutes);
850 } while (resultSet->GoToNextRow() == DataShare::E_OK);
851 return 0;
852 }
853
IsValidHexString(const std::string & colorStr)854 bool IsValidHexString(const std::string& colorStr)
855 {
856 if (colorStr.empty()) {
857 return false;
858 }
859 for (char ch : colorStr) {
860 if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
861 continue;
862 }
863 return false;
864 }
865 return true;
866 }
867
ColorParse(const std::string & colorStr,variant<string,int64_t> & colorValue)868 bool ColorParse(const std::string& colorStr, variant<string, int64_t>& colorValue)
869 {
870 if (colorStr.empty()) {
871 LOG_ERROR("color string is empty");
872 return false;
873 }
874
875 if (colorStr[0] != '#') { // start with '#'
876 LOG_ERROR("color string not start with #");
877 return false;
878 }
879
880 const int rgbLen = 7;
881 const int argbLen = 9;
882 if (colorStr.size() != rgbLen && colorStr.size() != argbLen) {
883 LOG_ERROR("color string length is not 7 or 9");
884 return false;
885 }
886
887 std::string colorStrSub = colorStr.substr(1);
888 if (!IsValidHexString(colorStrSub)) {
889 LOG_DEBUG("color string is not valid hex string");
890 return false;
891 }
892
893 LOG_DEBUG("color string size is 7 or 9");
894 colorValue.emplace<1>(std::stoll(colorStrSub, NULL, 16)); // 16 is convert hex string to number
895 if (std::get_if<1>(&colorValue)) {
896 LOG_DEBUG("colorStrSub -> colorValue colorValue:%{public}s", std::to_string(std::get<1>(colorValue)).c_str());
897 return true;
898 }
899 LOG_DEBUG("color is null");
900 return false;
901 }
902
SetFieldInfo(const std::vector<string> & eventKey,std::vector<string> & queryField,std::set<string> & resultSetField,const std::map<string,string> eventField)903 void SetFieldInfo(const std::vector<string>& eventKey, std::vector<string>& queryField,
904 std::set<string>& resultSetField, const std::map<string, string> eventField)
905 {
906 for (const auto& field : eventKey) {
907 if (field == "location") {
908 queryField.emplace_back("eventLocation");
909 queryField.emplace_back("location_longitude");
910 queryField.emplace_back("location_latitude");
911 resultSetField.insert(field);
912 continue;
913 }
914 if (field == "service") {
915 queryField.emplace_back("service_type");
916 queryField.emplace_back("service_cp_bz_uri");
917 queryField.emplace_back("service_description");
918 resultSetField.insert(field);
919 continue;
920 }
921 if (field == "attendee") {
922 resultSetField.insert(field);
923 continue;
924 }
925 if (field == "reminderTime") {
926 resultSetField.insert(field);
927 continue;
928 }
929 if (field == "identifier") {
930 queryField.emplace_back("identifier");
931 resultSetField.insert(field);
932 continue;
933 }
934 if (field == "recurrenceRule") {
935 queryField.emplace_back("rrule");
936 queryField.emplace_back("exdate");
937 resultSetField.insert(field);
938 continue;
939 }
940 if (field == "isLunar") {
941 queryField.emplace_back("event_calendar_type");
942 resultSetField.insert(field);
943 continue;
944 }
945 if (field == "id") {
946 continue;
947 }
948 queryField.emplace_back(eventField.at(field));
949 resultSetField.insert(field);
950 }
951 }
952
SetField(const std::vector<string> & eventKey,std::vector<string> & queryField,std::set<string> & resultSetField)953 void SetField(const std::vector<string>& eventKey, std::vector<string>& queryField, std::set<string>& resultSetField)
954 {
955 const std::map<string, string> eventField = { { "id", "_id" },
956 { "type", "important_event_type" },
957 { "title", "title" },
958 { "startTime", "dtstart" },
959 { "endTime", "dtend" },
960 { "isAllDay", "allDay" },
961 { "timeZone", "eventTimezone" },
962 { "description", "description" }};
963 SetFieldInfo(eventKey, queryField, resultSetField, eventField);
964 }
965 }
966