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 "calendar_log.h"
17 #include "native_util.h"
18
19 namespace OHOS::CalendarApi::Native {
DumpCalendarAccount(const CalendarAccount & account)20 void DumpCalendarAccount(const CalendarAccount &account)
21 {
22 LOG_DEBUG("account.name:%{public}s", account.name.c_str());
23 LOG_DEBUG("account.type:%{public}s", account.type.c_str());
24 LOG_DEBUG("account.displayName:%{public}s", account.displayName.value_or("").c_str());
25 }
26
DumpEvent(const Event & event)27 void DumpEvent(const Event &event)
28 {
29 LOG_DEBUG("id :%{public}d", event.id.value_or(-1));
30 LOG_DEBUG("type :%{public}d", event.type);
31 LOG_DEBUG("title :%{public}s", event.title.value_or("[null]").c_str());
32 if (event.location) {
33 auto location = event.location.value();
34 LOG_DEBUG("location.location :%{public}s", location.location.value_or("[null]").c_str());
35 LOG_DEBUG("location.longitude :%{public}d", location.longitude.value_or(-1));
36 LOG_DEBUG("location.latitude :%{public}d", location.latitude.value_or(-1));
37 } else {
38 LOG_DEBUG("location [null]");
39 }
40 if (event.service) {
41 auto service = event.service.value();
42 LOG_DEBUG("service.type :%{public}s", service.type.c_str());
43 LOG_DEBUG("service.description :%{public}s", service.description.value_or("[null]").c_str());
44 LOG_DEBUG("service.uri :%{public}s", service.uri.c_str());
45 } else {
46 LOG_DEBUG("service [null]");
47 }
48 LOG_DEBUG("title :%{public}s", event.title.value_or("").c_str());
49 LOG_DEBUG("startTime :%{public}s", std::to_string(event.startTime).c_str());
50 LOG_DEBUG("endTime :%{public}s", std::to_string(event.endTime).c_str());
51 LOG_DEBUG("isAllDay :%{public}d", event.isAllDay.value_or(0));
52
53 for (const auto &attendee : event.attendees) {
54 LOG_DEBUG("attendee.name :%{public}s", attendee.name.c_str());
55 LOG_DEBUG("attendee.email :%{public}s", attendee.email.c_str());
56 }
57
58 LOG_DEBUG("timeZone :%{public}s", event.timeZone.value_or("[null]").c_str());
59 LOG_DEBUG("description :%{public}s", event.description.value_or("[null]").c_str());
60 }
61
BuildEventLocation(DataShare::DataShareValuesBucket & valuesBucket,const Event & event)62 void BuildEventLocation(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
63 {
64 if (!event.location) {
65 return;
66 }
67 auto location = event.location.value();
68 if (location.location) {
69 valuesBucket.Put("eventLocation", location.location.value());
70 }
71 if (location.longitude) {
72 // longitude is string in db
73 valuesBucket.Put("location_longitude", std::to_string(location.longitude.value()));
74 }
75 if (location.latitude) {
76 // latitude is string in db
77 valuesBucket.Put("location_latitude", std::to_string(location.latitude.value()));
78 }
79 }
80
BuildEventService(DataShare::DataShareValuesBucket & valuesBucket,const Event & event)81 void BuildEventService(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
82 {
83 if (!event.service) {
84 return;
85 }
86 const auto service = event.service.value();
87 if (service.description) {
88 valuesBucket.Put("service_description", service.description.value());
89 }
90 valuesBucket.Put("service_type", service.type);
91 valuesBucket.Put("service_cp_bz_uri", service.uri);
92 }
93
BuildValueEvent(const Event & event,int calendarId)94 DataShare::DataShareValuesBucket BuildValueEvent(const Event &event, int calendarId)
95 {
96 DataShare::DataShareValuesBucket valuesBucket;
97 valuesBucket.Put("calendar_id", calendarId);
98
99 LOG_DEBUG("title %{public}s", event.title.value_or("").c_str());
100 valuesBucket.Put("title", event.title.value_or(""));
101 valuesBucket.Put("event_calendar_type", event.type);
102 valuesBucket.Put("dtstart", event.startTime);
103 valuesBucket.Put("dtend", event.endTime);
104
105 BuildEventLocation(valuesBucket, event);
106 BuildEventService(valuesBucket, event);
107
108 LOG_DEBUG("description %{public}s", event.description.value_or("").c_str());
109
110 if (event.description.has_value()) {
111 valuesBucket.Put("description", event.description.value());
112 }
113 if (event.timeZone.has_value()) {
114 valuesBucket.Put("eventTimezone", event.timeZone.value());
115 }
116 if (event.isAllDay.has_value()) {
117 valuesBucket.Put("allDay", event.isAllDay.value());
118 }
119 return valuesBucket;
120 }
121
BuildAttendeeValue(const Attendee & attendee,int eventId)122 DataShare::DataShareValuesBucket BuildAttendeeValue(const Attendee &attendee, int eventId)
123 {
124 DataShare::DataShareValuesBucket valuesBucket;
125 valuesBucket.Put("event_id", eventId);
126 valuesBucket.Put("attendeeName", attendee.name);
127 LOG_DEBUG("attendeeName %{public}s", attendee.name.c_str());
128 valuesBucket.Put("attendeeEmail", attendee.email);
129 LOG_DEBUG("attendeeEmail %{public}s", attendee.email.c_str());
130 return valuesBucket;
131 }
132
GetValue(DataShareResultSetPtr & resultSet,string_view fieldName,int & out)133 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, int& out)
134 {
135 int index = 0;
136 auto ret = resultSet->GetColumnIndex(string(fieldName), index);
137 if (ret != DataShare::E_OK) {
138 return ret;
139 }
140 return resultSet->GetInt(index, out);
141 }
142
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,std::string & out)143 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, std::string& out)
144 {
145 return resultSet->GetString(index, out);
146 }
147
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,int & out)148 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int& out)
149 {
150 return resultSet->GetInt(index, out);
151 }
152
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,int64_t & out)153 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int64_t& out)
154 {
155 return resultSet->GetLong(index, out);
156 }
157
GetValue(DataShareResultSetPtr & resultSet,string_view fieldName,std::string & out)158 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, std::string& out)
159 {
160 int index = 0;
161 auto fieldNameStr = string(fieldName);
162 auto ret = resultSet->GetColumnIndex(fieldNameStr, index);
163 if (ret != DataShare::E_OK) {
164 LOG_WARN("GetValue [%{public}s] failed [%{public}d]", fieldNameStr.c_str(), ret);
165 return ret;
166 }
167 return resultSet->GetString(index, out);
168 }
169
170
ResultSetToCalendars(DataShareResultSetPtr & resultSet)171 std::vector<std::shared_ptr<Calendar>> ResultSetToCalendars(DataShareResultSetPtr &resultSet)
172 {
173 std::vector<std::shared_ptr<Calendar>> result;
174 int rowCount = 0;
175 resultSet->GetRowCount(rowCount);
176 LOG_INFO("GetRowCount is %{public}d", rowCount);
177 if (rowCount == 0) {
178 return result;
179 }
180 auto err = resultSet->GoToFirstRow();
181 if (err != DataShare::E_OK) {
182 LOG_INFO("Failed GoToFirstRow %{public}d", err);
183 return result;
184 }
185 do {
186 int idValue = -1;
187 if (GetValue(resultSet, "_id", idValue) != DataShare::E_OK) {
188 break;
189 }
190 LOG_DEBUG("id: %{public}d", idValue);
191 std::string nameValue;
192 if (GetValue(resultSet, "account_name", nameValue) != DataShare::E_OK) {
193 break;
194 }
195 LOG_DEBUG("account_name: %{public}s", nameValue.c_str());
196 std::string typeValue;
197 if (GetValue(resultSet, "account_type", typeValue) != DataShare::E_OK) {
198 break;
199 }
200 LOG_DEBUG("account_type: %{public}s", typeValue.c_str());
201
202 std::string displayNameValue;
203 GetValue(resultSet, "calendar_displayName", displayNameValue);
204 LOG_DEBUG("calendar_displayName: %{public}s", displayNameValue.c_str());
205
206 int canReminder = -1;
207 GetValue(resultSet, "canReminder", canReminder);
208 LOG_DEBUG("canReminder: %{public}d", canReminder);
209
210 int colorValue = 0;
211 GetValue(resultSet, "calendar_color", colorValue);
212 CalendarAccount curAccount {nameValue, typeValue, displayNameValue};
213 result.emplace_back(std::make_shared<Calendar>(curAccount, idValue));
214 } while (resultSet->GoToNextRow() == DataShare::E_OK);
215 return result;
216 }
217
218
ResultSetToLocation(DataShareResultSetPtr & resultSet)219 std::optional<Location> ResultSetToLocation(DataShareResultSetPtr &resultSet)
220 {
221 Location out;
222 string value;
223 auto ret = GetValue(resultSet, "eventLocation", value);
224 out.location = std::make_optional<string>(value);
225 ret = GetValue(resultSet, "location_longitude", value);
226 int longitudeValue = -1;
227 std::stringstream str2digit;
228 str2digit << value;
229 str2digit >> longitudeValue;
230 if (longitudeValue != -1) {
231 out.longitude = std::make_optional<int>(longitudeValue);
232 }
233 ret = GetValue(resultSet, "location_latitude", value);
234 int latitudeValue = -1;
235 str2digit.clear();
236 str2digit << value;
237 str2digit >> latitudeValue;
238 if (latitudeValue != -1) {
239 out.latitude = std::make_optional<int>(latitudeValue);
240 }
241
242 if (ret != DataShare::E_OK) {
243 return std::nullopt;
244 }
245 return std::make_optional<Location>(out);
246 }
247
ResultSetToEventService(DataShareResultSetPtr & resultSet)248 std::optional<EventService> ResultSetToEventService(DataShareResultSetPtr &resultSet)
249 {
250 EventService out;
251 string value;
252 auto ret = GetValue(resultSet, "service_type", value);
253 if (ret != DataShare::E_OK) {
254 return std::nullopt;
255 }
256 const std::set<std::string> serviceType = {"Meeting", "Watching", "Repayment", "Live", "Shopping",
257 "Trip", "Class", "SportsEvents", "SportsExercise"};
258 if (serviceType.count(value)) {
259 out.type = value;
260 } else {
261 return std::nullopt;
262 }
263 ret = GetValue(resultSet, "service_cp_bz_uri", value);
264 if (ret != DataShare::E_OK) {
265 return std::nullopt;
266 }
267 out.uri = value;
268 ret = GetValue(resultSet, "service_description", value);
269 if (ret == DataShare::E_OK) {
270 out.description = std::make_optional<string>(value);
271 }
272 return std::make_optional<EventService>(out);
273 }
274
ResultSetToEvent(Event & event,DataShareResultSetPtr & resultSet,const std::set<std::string> & columns)275 void ResultSetToEvent(Event &event, DataShareResultSetPtr &resultSet, const std::set<std::string>& columns)
276 {
277 GetValueOptional(resultSet, "_id", event.id);
278 if (columns.count("type")) {
279 int type = 0;
280 GetValue(resultSet, "event_calendar_type", type);
281 event.type = static_cast<EventType>(type);
282 }
283 if (columns.count("title")) {
284 GetValueOptional(resultSet, "title", event.title);
285 }
286 if (columns.count("startTime")) {
287 LOG_DEBUG("TLQ get startTime");
288 GetValue(resultSet, "dtstart", event.startTime);
289 }
290 if (columns.count("endTime")) {
291 LOG_DEBUG("TLQ get endTime");
292 GetValue(resultSet, "dtend", event.endTime);
293 }
294 if (columns.count("isAllDay")) {
295 int isAllDay = 0;
296 GetValue(resultSet, "allDay", isAllDay);
297 event.isAllDay = static_cast<bool>(isAllDay);
298 }
299 if (columns.count("description")) {
300 GetValueOptional(resultSet, "description", event.description);
301 }
302 if (columns.count("timeZone")) {
303 GetValueOptional(resultSet, "eventTimezone", event.timeZone);
304 }
305 if (columns.count("location")) {
306 event.location = ResultSetToLocation(resultSet);
307 }
308 if (columns.count("service")) {
309 event.service = ResultSetToEventService(resultSet);
310 }
311 }
312
ResultSetToEvents(std::vector<Event> & events,DataShareResultSetPtr & resultSet,const std::set<std::string> & columns)313 int ResultSetToEvents(std::vector<Event> &events, DataShareResultSetPtr &resultSet,
314 const std::set<std::string>& columns)
315 {
316 int rowCount = 0;
317 resultSet->GetRowCount(rowCount);
318 LOG_INFO("GetRowCount is %{public}d", rowCount);
319 if (rowCount <= 0) {
320 return -1;
321 }
322 auto err = resultSet->GoToFirstRow();
323 if (err != DataShare::E_OK) {
324 LOG_ERROR("Failed GoToFirstRow %{public}d", err);
325 return -1;
326 }
327 do {
328 Event event;
329 ResultSetToEvent(event, resultSet, columns);
330 events.emplace_back(event);
331 } while (resultSet->GoToNextRow() == DataShare::E_OK);
332 return 0;
333 }
334
ResultSetToAttendees(std::vector<Attendee> & attendees,DataShareResultSetPtr & resultSet)335 int ResultSetToAttendees(std::vector<Attendee> &attendees, DataShareResultSetPtr &resultSet)
336 {
337 int rowCount = 0;
338 resultSet->GetRowCount(rowCount);
339 LOG_INFO("GetRowCount is %{public}d", rowCount);
340 if (rowCount <= 0) {
341 return -1;
342 }
343 auto err = resultSet->GoToFirstRow();
344 if (err != DataShare::E_OK) {
345 LOG_ERROR("Failed GoToFirstRow %{public}d", err);
346 return -1;
347 }
348 do {
349 Attendee attendee;
350 GetValue(resultSet, "attendeeName", attendee.name);
351 GetValue(resultSet, "attendeeEmail", attendee.email);
352 attendees.emplace_back(attendee);
353 } while (resultSet->GoToNextRow() == DataShare::E_OK);
354 return 0;
355 }
356
ResultSetToReminders(std::vector<int> & reminders,DataShareResultSetPtr & resultSet)357 int ResultSetToReminders(std::vector<int> &reminders, DataShareResultSetPtr &resultSet)
358 {
359 int rowCount = 0;
360 resultSet->GetRowCount(rowCount);
361 LOG_INFO("GetRowCount is %{public}d", rowCount);
362 if (rowCount <= 0) {
363 return -1;
364 }
365 auto err = resultSet->GoToFirstRow();
366 if (err != DataShare::E_OK) {
367 LOG_ERROR("Failed GoToFirstRow %{public}d", err);
368 return -1;
369 }
370 do {
371 int minutes;
372 GetValue(resultSet, "minutes", minutes);
373 reminders.emplace_back(minutes);
374 } while (resultSet->GoToNextRow() == DataShare::E_OK);
375 return 0;
376 }
377
IsValidHexString(const std::string & colorStr)378 bool IsValidHexString(const std::string& colorStr)
379 {
380 if (colorStr.empty()) {
381 return false;
382 }
383 for (char ch : colorStr) {
384 if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
385 continue;
386 }
387 return false;
388 }
389 return true;
390 }
391
ColorParse(const std::string & colorStr,variant<string,int64_t> & colorValue)392 bool ColorParse(const std::string& colorStr, variant<string, int64_t>& colorValue)
393 {
394 if (colorStr.empty()) {
395 LOG_ERROR("color string is empty");
396 return false;
397 }
398
399 if (colorStr[0] != '#') { // start with '#'
400 LOG_ERROR("color string not start with #");
401 return false;
402 }
403
404 const int rgbLen = 7;
405 const int argbLen = 9;
406 if (colorStr.size() != rgbLen && colorStr.size() != argbLen) {
407 LOG_ERROR("color string length is not 7 or 9");
408 return false;
409 }
410
411 std::string colorStrSub = colorStr.substr(1);
412 if (!IsValidHexString(colorStrSub)) {
413 LOG_DEBUG("color string is not valid hex string");
414 return false;
415 }
416
417 LOG_DEBUG("color string size is 7 or 9");
418 colorValue.emplace<1>(std::stoll(colorStrSub, NULL, 16)); // 16 is convert hex string to number
419 if (std::get_if<1>(&colorValue)) {
420 LOG_DEBUG("colorStrSub -> colorValue colorValue:%{public}s", std::to_string(std::get<1>(colorValue)).c_str());
421 return true;
422 }
423 LOG_DEBUG("color is null");
424 return false;
425 }
426
setField(const std::vector<string> & eventKey,std::vector<string> & queryField,std::set<string> & resultSetField)427 void setField(const std::vector<string>& eventKey, std::vector<string>& queryField, std::set<string>& resultSetField)
428 {
429 const std::map<string, string> eventField = { { "id", "_id" },
430 { "type", "event_calendar_type" },
431 { "title", "title" },
432 { "startTime", "dtstart" },
433 { "endTime", "dtend" },
434 { "isAllDay", "allDay" },
435 { "timeZone", "eventTimezone" },
436 { "description", "description" } };
437 for (const auto& field : eventKey) {
438 if (field == "location") {
439 queryField.emplace_back("eventLocation");
440 queryField.emplace_back("location_longitude");
441 queryField.emplace_back("location_latitude");
442 resultSetField.insert(field);
443 continue;
444 }
445 if (field == "service") {
446 queryField.emplace_back("service_type");
447 queryField.emplace_back("service_cp_bz_uri");
448 queryField.emplace_back("service_description");
449 resultSetField.insert(field);
450 continue;
451 }
452 if (field == "attendee") {
453 resultSetField.insert(field);
454 continue;
455 }
456 if (field == "reminderTime") {
457 resultSetField.insert(field);
458 continue;
459 }
460 if (field == "id") {
461 continue;
462 }
463 queryField.emplace_back(eventField.at(field));
464 resultSetField.insert(field);
465 }
466 }
467 }