1 /*
2 * Copyright (c) 2025 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
16 #include "cj_native_calendar.h"
17 #include "cj_data_share_helper_manager.h"
18 #include "calendar_log.h"
19 #include "calendar_env.h"
20 #include "data_ability_helper.h"
21 #include "cj_native_util.h"
22
23 namespace {
24 const string eventUrl = "datashare:///calendardata/Events";
25 const string attendeeUrl = "datashare:///calendardata/Attendees";
26 const string calendarUrl = "datashare:///calendardata/Calendars";
27 const string reminderUrl = "datashare:///calendardata/Reminders";
28 const string instanceUrl = "datashare:///calendardata/Instances";
29 }
30 namespace OHOS::CalendarApi::Native {
CJNativeCalendar(int id)31 CJNativeCalendar::CJNativeCalendar(int id)
32 : m_id(id)
33 {
34 uint64_t tokenId = CalendarEnv::GetInstance().GetTokenId();
35 auto bundleName = CalendarEnv::GetInstance().GetBundleName();
36 auto bundleName_tokeId = "?bundleName=" + bundleName + "&tokenId=" + std::to_string(tokenId);
37 m_eventUri = std::make_unique<Uri>(eventUrl + bundleName_tokeId);
38 m_calendarUri = std::make_unique<Uri>(calendarUrl + bundleName_tokeId);
39 }
40
CJNativeCalendar(CalendarAccount account,int id)41 CJNativeCalendar::CJNativeCalendar(CalendarAccount account, int id)
42 :m_account(std::move(account)), m_id(id)
43 {
44 uint64_t tokenId = CalendarEnv::GetInstance().GetTokenId();
45 auto bundleName = CalendarEnv::GetInstance().GetBundleName();
46 auto bundleName_tokeId = "?bundleName=" + bundleName + "&tokenId=" + std::to_string(tokenId);
47 m_eventUri = std::make_unique<Uri>(eventUrl + bundleName_tokeId);
48 m_attendeeUri = std::make_unique<Uri>(attendeeUrl + bundleName_tokeId);
49 m_calendarUri = std::make_unique<Uri>(calendarUrl + bundleName_tokeId);
50 m_reminderUrl = std::make_unique<Uri>(reminderUrl + bundleName_tokeId);
51 m_instanceUrl = std::make_unique<Uri>(instanceUrl + bundleName_tokeId);
52 }
InsertReminders(int eventId,vector<int> reminders)53 void CJNativeCalendar::InsertReminders(int eventId, vector<int> reminders)
54 {
55 std::sort(reminders.begin(), reminders.end());
56 reminders.erase(std::unique(reminders.begin(), reminders.end()), reminders.end());
57 for (const auto &reminder : reminders) {
58 DataShare::DataShareValuesBucket valuesBucket;
59 valuesBucket.Put("event_id", eventId);
60 valuesBucket.Put("minutes", reminder);
61 auto index = CJDataShareHelperManager::GetInstance().Insert(*(m_reminderUrl.get()), valuesBucket);
62 LOG_INFO("Insert reminder index %{private}d", index);
63 }
64 }
65
AddEventInfo(const Event & event,int channelId)66 int CJNativeCalendar::AddEventInfo(const Event& event, int channelId)
67 {
68 const auto valueEvent = BuildValueEvent(event, m_id, channelId, false);
69 uint64_t tokenId = CalendarEnv::GetInstance().GetTokenId();
70 auto bundleName = CalendarEnv::GetInstance().GetBundleName();
71 auto bundleName_tokeId = "?bundleName=" + bundleName + "&tokenId=" + std::to_string(tokenId);
72 Uri eventUri(eventUrl + bundleName_tokeId);
73 auto eventId = CJDataShareHelperManager::GetInstance().Insert(eventUri, valueEvent);
74 LOG_INFO("Insert Event eventId %{private}d", eventId);
75 if (eventId <= 0) {
76 return eventId;
77 }
78 // insert attendee
79 auto valueAttendees = std::vector<DataShare::DataShareValuesBucket>();
80 for (const auto &attendee : event.attendees) {
81 auto valueAttendee = BuildAttendeeValue(attendee, eventId);
82 valueAttendees.emplace_back(valueAttendee);
83 }
84 if (valueAttendees.size() > 0) {
85 auto count = CJDataShareHelperManager::GetInstance().BatchInsert(*(m_attendeeUri.get()), valueAttendees);
86 LOG_INFO("batchInsert attendees count %{private}d", count);
87 }
88
89 // insert reminder
90 if (event.reminderTime.has_value()) {
91 InsertReminders(eventId, event.reminderTime.value());
92 }
93
94 return eventId;
95 }
96
AddEvent(const Event & event)97 int CJNativeCalendar::AddEvent(const Event& event)
98 {
99 return CJNativeCalendar::AddEventInfo(event, 0);
100 }
101 #define SUPPORT_BATCH_INSERT 0
102
103 #if SUPPORT_BATCH_INSERT
AddEvents(const std::vector<Event> & events)104 int CJNativeCalendar::AddEvents(const std::vector<Event>& events)
105 {
106 std::vector<DataShare::DataShareValuesBucket> valueEvents;
107 for (const auto &event : events) {
108 valueEvents.emplace_back(BuildValueEvent(event));
109 }
110 auto count = CJDataShareHelperManager::GetInstance().BatchInsert(*(m_eventUri.get()), valueEvents);
111 LOG_INFO("BatchInsert count %{private}d", count);
112 return count;
113 }
114 #else
AddEvents(const std::vector<Event> & events)115 int CJNativeCalendar::AddEvents(const std::vector<Event>& events)
116 {
117 int count = 0;
118 int channelId = 0;
119 for (const auto &event : events) {
120 auto index = CJNativeCalendar::AddEventInfo(event, channelId);
121 if (index > 0) {
122 count++;
123 }
124 channelId++;
125 }
126 LOG_INFO("AddEvents count %{private}d", count);
127 return count;
128 }
129 #endif
130
131
DeleteEvent(int id)132 bool CJNativeCalendar::DeleteEvent(int id)
133 {
134 DataShare::DataSharePredicates predicates;
135 predicates.EqualTo("_id", id);
136 predicates.EqualTo("calendar_id", GetId());
137 auto ret = CJDataShareHelperManager::GetInstance().Delete(*(m_eventUri.get()), predicates);
138 return ret == 1;
139 }
140
DeleteAllEvents()141 void CJNativeCalendar::DeleteAllEvents()
142 {
143 DataShare::DataSharePredicates predicates;
144 predicates.EqualTo("_id", GetId());
145 auto ret = CJDataShareHelperManager::GetInstance().Delete(*(m_eventUri.get()), predicates);
146 LOG_INFO("DeleteEvent number %{public}d", ret);
147 return;
148 }
149
DeleteEvents(const std::vector<int> & ids)150 int CJNativeCalendar::DeleteEvents(const std::vector<int>& ids)
151 {
152 int count = 0;
153 for (const auto &id : ids) {
154 if (DeleteEvent(id)) {
155 count += 1;
156 }
157 }
158 LOG_INFO("DeleteEvents %{public}d", count);
159 return count;
160 }
161
UpdateEvent(const Event & event)162 bool CJNativeCalendar::UpdateEvent(const Event& event)
163 {
164 if (!event.id) {
165 LOG_ERROR("event id not exist");
166 return false;
167 }
168 const auto eventId = event.id.value();
169 DataShare::DataSharePredicates m_predicates;
170 m_predicates.EqualTo("_id", eventId);
171 const auto valueEvent = BuildValueEvent(event, m_id, 0, true);
172 auto ret = CJDataShareHelperManager::GetInstance().Update(*(m_eventUri.get()), m_predicates, valueEvent);
173 LOG_INFO(" Update code %{public}d", ret);
174 {
175 // delete attendee
176 DataShare::DataSharePredicates predicates;
177 predicates.EqualTo("event_id", eventId);
178 auto ret = CJDataShareHelperManager::GetInstance().Delete(*(m_attendeeUri.get()), predicates);
179 LOG_INFO("Delete attendee num %{public}d", ret);
180 }
181 auto valueAttendees = std::vector<DataShare::DataShareValuesBucket>();
182 for (const auto &attendee : event.attendees) {
183 auto valueAttendee = BuildAttendeeValue(attendee, eventId);
184 valueAttendees.emplace_back(valueAttendee);
185 }
186 if (valueAttendees.size() > 0) {
187 auto count = CJDataShareHelperManager::GetInstance().BatchInsert(*(m_attendeeUri.get()), valueAttendees);
188 LOG_INFO("batchInsert attendees count %{public}d", count);
189 }
190
191 {
192 // delete reminder
193 DataShare::DataSharePredicates predicates;
194 predicates.EqualTo("event_id", eventId);
195 auto ret = CJDataShareHelperManager::GetInstance().Delete(*(m_reminderUrl.get()), predicates);
196 LOG_INFO("Delete reminder num %{public}d", ret);
197 }
198 if (event.reminderTime.has_value()) {
199 InsertReminders(eventId, event.reminderTime.value());
200 }
201
202 return ret == 1;
203 }
204
UpdateEvents(const std::vector<Event> & events)205 int CJNativeCalendar::UpdateEvents(const std::vector<Event>& events)
206 {
207 int count = 0;
208 for (const auto &event : events) {
209 if (UpdateEvent(event)) {
210 count +=1;
211 }
212 }
213 LOG_INFO("UpdateEvents %{public}d", count);
214 return count;
215 }
216
GetAttendeesByEventId(int id)217 std::vector<Attendee> CJNativeCalendar::GetAttendeesByEventId(int id)
218 {
219 DataShare::DataSharePredicates predicates;
220 predicates.EqualTo("event_id", id);
221 std::vector<std::string> columns = {"attendeeName", "attendeeEmail",
222 "attendeeRelationship", "attendeeStatus", "attendeeType"};
223 DataShare::DatashareBusinessError error;
224 auto result = CJDataShareHelperManager::GetInstance().Query(*(m_attendeeUri.get()), predicates, columns, &error);
225 std::vector<Attendee> attendees;
226 if (result != nullptr) {
227 ResultSetToAttendees(attendees, result);
228 }
229 LOG_INFO(" query attendee finished");
230 return attendees;
231 }
232
GetRemindersByEventId(int id)233 std::optional<std::vector<int>> CJNativeCalendar::GetRemindersByEventId(int id)
234 {
235 DataShare::DataSharePredicates predicates;
236 predicates.EqualTo("event_id", id);
237 std::vector<std::string> columns = {"event_id", "minutes"};
238 DataShare::DatashareBusinessError error;
239 auto result = CJDataShareHelperManager::GetInstance().Query(*(m_reminderUrl.get()), predicates, columns, &error);
240 if (result == nullptr) {
241 return std::nullopt;
242 }
243 std::vector<int> reminders;
244 auto ret = ResultSetToReminders(reminders, result);
245 if (ret != DataShare::E_OK) {
246 return std::nullopt;
247 }
248 LOG_INFO("query reminder finished");
249 return reminders;
250 }
251
GetEvents(std::shared_ptr<EventFilter> filter,const std::vector<string> & eventKey)252 std::vector<Event> CJNativeCalendar::GetEvents(std::shared_ptr<EventFilter> filter, const std::vector<string>& eventKey)
253 {
254 std::vector<Event> events;
255 std::shared_ptr<DataShare::DataSharePredicates> predicates = nullptr;
256 if (filter) {
257 predicates = filter->GetFilterPrediacates();
258 if (!predicates) {
259 LOG_ERROR("predicates null");
260 return events;
261 }
262 } else {
263 predicates = std::make_shared<DataShare::DataSharePredicates>();
264 }
265 predicates->EqualTo("calendar_id", GetId());
266 std::vector<string> queryField = {};
267 std::set<string> resultSetField;
268 if (eventKey.size() > 0) {
269 queryField.emplace_back("_id");
270 SetField(eventKey, queryField, resultSetField);
271 } else {
272 resultSetField = {"type", "title", "startTime", "endTime", "isAllDay", "description",
273 "timeZone", "location", "service", "attendee", "reminderTime"};
274 }
275 DataShare::DatashareBusinessError error;
276 auto result = CJDataShareHelperManager::GetInstance().Query(*(m_eventUri.get()),
277 *(predicates.get()), queryField, &error);
278 if (!result) {
279 LOG_ERROR("query failed");
280 return events;
281 }
282 ResultSetToEvents(events, result, resultSetField);
283 for (auto &event : events) {
284 if (!event.id.has_value()) {
285 continue;
286 }
287 const auto eventId = event.id.value();
288 if (resultSetField.count("attendee")) {
289 event.attendees = GetAttendeesByEventId(eventId);
290 }
291 if (resultSetField.count("reminderTime")) {
292 event.reminderTime = GetRemindersByEventId(eventId);
293 }
294 DumpEvent(event);
295 }
296 LOG_INFO("query finished");
297 return events;
298 }
299
FillEventsInfo(std::vector<Event> & events,const std::set<std::string> & resultSetField)300 void CJNativeCalendar::FillEventsInfo(std::vector<Event> &events, const std::set<std::string>& resultSetField)
301 {
302 std::vector<Attendee> attendees;
303 std::optional<std::vector<int>> reminders;
304 int previousEventId = 0;
305 for (size_t i = 0; i < events.size(); i++) {
306 if (!events[i].id.has_value()) {
307 continue;
308 }
309 const auto eventId = events[i].id.value();
310 if (resultSetField.count("attendee")) {
311 if (eventId != previousEventId) {
312 attendees = GetAttendeesByEventId(eventId);
313 }
314 events[i].attendees = attendees;
315 }
316 if (resultSetField.count("reminderTime")) {
317 if (eventId != previousEventId) {
318 reminders = GetRemindersByEventId(eventId);
319 }
320 events[i].reminderTime = reminders;
321 }
322 previousEventId = eventId;
323 }
324 }
325
QueryEventInstances(int64_t start,int64_t end,const std::vector<int> & ids,const std::vector<string> & eventKey)326 std::vector<Event> CJNativeCalendar::QueryEventInstances(int64_t start, int64_t end, const std::vector<int> &ids,
327 const std::vector<string>& eventKey)
328 {
329 LOG_INFO("query instance start");
330 std::vector<Event> events;
331 std::shared_ptr<DataShare::DataSharePredicates> predicates = std::make_shared<DataShare::DataSharePredicates>();
332 predicates->EqualTo("calendar_id", GetId());
333 std::vector<string> queryField = {};
334 std::set<string> resultSetField;
335 if (eventKey.size() > 0) {
336 queryField.emplace_back("Events._id");
337 SetField(eventKey, queryField, resultSetField);
338 } else {
339 resultSetField = {"id", "title", "startTime", "endTime", "instanceStartTime", "instanceEndTime",
340 "isAllDay", "description", "timeZone", "location", "service"};
341 queryField = {"Events._id", "title", "dtstart", "dtend", "service_type", "service_cp_bz_uri",
342 "service_description", "allDay", "eventTimezone", "description", "eventLocation",
343 "location_longitude", "location_latitude", "begin", "end"};
344 }
345 auto url = "&begin=" + std::to_string(start) + "&end=" + std::to_string(end) +
346 "&calendarId=" + std::to_string(GetId()) +"&orderByAsc=startDay";
347 std::string idsString = EventIdsToString(ids);
348 if (!idsString.empty()) {
349 url = url + "&eventIds=" + idsString;
350 }
351 m_instanceUrl = std::make_unique<Uri>(m_instanceUrl->ToString() + url);
352 DataShare::DatashareBusinessError error;
353 auto result = CJDataShareHelperManager::GetInstance().Query(*(m_instanceUrl.get()),
354 *(predicates.get()), queryField, &error);
355 if (!result) {
356 LOG_ERROR("query failed");
357 return events;
358 }
359 ResultSetToEvents(events, result, resultSetField);
360 FillEventsInfo(events, resultSetField);
361 LOG_INFO("query instance finished");
362 return events;
363 }
364
GetConfig()365 CalendarConfig CJNativeCalendar::GetConfig()
366 {
367 DataShare::DataSharePredicates predicates;
368 predicates.EqualTo("_id", m_id);
369 std::vector<std::string> columns = {"calendar_color", "canReminder"};
370 DataShare::DatashareBusinessError error;
371 auto result = CJDataShareHelperManager::GetInstance().Query(*(m_calendarUri.get()), predicates, columns, &error);
372 if (result != nullptr) {
373 ResultSetToConfig(m_config, result);
374 };
375 LOG_INFO(" query config finished");
376 return m_config;
377 }
378
SetConfig(const CalendarConfig & config)379 bool CJNativeCalendar::SetConfig(const CalendarConfig& config)
380 {
381 DataShare::DataSharePredicates m_predicates;
382 m_predicates.EqualTo("_id", m_id);
383 DataShare::DataShareValuesBucket valuesBucket;
384 if (std::get_if<1>(&config.color)) {
385 valuesBucket.Put("calendar_color", std::get<1>(config.color));
386 }
387 if (config.enableReminder) {
388 valuesBucket.Put("canReminder", config.enableReminder.value());
389 }
390 if (valuesBucket.IsEmpty()) {
391 LOG_INFO("no need update");
392 return true;
393 }
394
395 // dataShareHelper 需要提到event_handler基类里面去
396 auto ret = CJDataShareHelperManager::GetInstance().Update(*(m_calendarUri.get()), m_predicates, valuesBucket) == 1;
397 LOG_INFO("SetConfig %{public}d", ret);
398 if (ret) {
399 m_config = config;
400 }
401 return ret;
402 }
403 }