001/* 002 * Copyright 2022 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.ametys.plugins.workspaces.calendars.events; 018 019import java.time.ZonedDateTime; 020import java.util.ArrayList; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024import java.util.Optional; 025import java.util.Set; 026import java.util.stream.Collectors; 027import java.util.stream.Stream; 028 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.commons.lang3.StringUtils; 032 033import org.ametys.core.right.RightManager.RightResult; 034import org.ametys.core.user.User; 035import org.ametys.core.user.UserIdentity; 036import org.ametys.core.util.DateUtils; 037import org.ametys.plugins.explorer.ExplorerNode; 038import org.ametys.plugins.workspaces.calendars.AbstractCalendarDAO; 039import org.ametys.plugins.workspaces.calendars.Calendar; 040import org.ametys.plugins.workspaces.calendars.CalendarDAO; 041 042/** 043 * Helper to convert events to JSON 044 */ 045public class CalendarEventJSONHelper extends AbstractCalendarDAO 046{ 047 048 /** Avalon Role */ 049 public static final String ROLE = CalendarEventJSONHelper.class.getName(); 050 051 /** Calendar DAO */ 052 protected CalendarDAO _calendarDAO; 053 054 @Override 055 public void service(ServiceManager manager) throws ServiceException 056 { 057 super.service(manager); 058 _calendarDAO = (CalendarDAO) manager.lookup(CalendarDAO.ROLE); 059 } 060 061 /** 062 * Get event info for a specific occurrence 063 * @param event The event 064 * @param occurrenceDate the occurrence 065 * @param fullInfo true to include full info (rights, parent id, etc...) 066 * @return the event data in a map 067 */ 068 public Map<String, Object> eventAsJsonWithOccurrence(CalendarEvent event, ZonedDateTime occurrenceDate, boolean fullInfo) 069 { 070 Map<String, Object> eventData = eventAsJson(event, fullInfo); 071 072 Optional<CalendarEventOccurrence> optionalEvent = event.getFirstOccurrence(occurrenceDate); 073 if (optionalEvent.isPresent()) 074 { 075 eventData.putAll(optionalEvent.get().toJSON()); 076 } 077 078 return eventData; 079 } 080 081 /** 082 * Get event info 083 * @param event The event 084 * @param fullInfo true to include full info (rights, parent id, etc...) 085 * @param startDate The start date. 086 * @param endDate The end date. 087 * @return the event data in a map 088 */ 089 public Map<String, Object> eventAsJsonWithOccurrences(CalendarEvent event, boolean fullInfo, ZonedDateTime startDate, ZonedDateTime endDate) 090 { 091 Map<String, Object> eventData = eventAsJson(event, false); 092 093 List<CalendarEventOccurrence> occurences = event.getOccurrences(startDate, endDate); 094 095 List<Object> occurrencesDataList = new ArrayList<>(); 096 eventData.put("occurrences", occurrencesDataList); 097 098 for (CalendarEventOccurrence occurence : occurences) 099 { 100 occurrencesDataList.add(occurence.toJSON()); 101 } 102 return eventData; 103 } 104 105 /** 106 * Get event info 107 * @param event The event 108 * @param fullInfo true to include full info (rights, parent id, etc...) 109 * @return the event data in a map 110 */ 111 public Map<String, Object> eventAsJson(CalendarEvent event, boolean fullInfo) 112 { 113 Calendar calendar = event.getParent(); 114 Map<String, Object> result = new HashMap<>(); 115 116 result.put("id", event.getId()); 117 result.put("calendarId", event.getParent().getId()); 118 result.put("color", calendar.getColor()); 119 120 result.put("title", event.getTitle()); 121 result.put("description", event.getDescription()); 122 result.put("fullDay", event.getFullDay()); 123 result.put("recurrenceType", event.getRecurrenceType().toString()); 124 125 result.put("location", event.getLocation()); 126 result.put("keywords", event.getTags()); 127 128 ZonedDateTime untilDate = event.getRepeatUntil(); 129 if (untilDate != null) 130 { 131 result.put("untilDate", DateUtils.zonedDateTimeToString(untilDate)); 132 } 133 134 ZonedDateTime startDateEvent = event.getStartDate(); 135 ZonedDateTime endDateEvent = event.getEndDate(); 136 137 if (event.getFullDay()) 138 { 139 result.put("endDateNextDay", DateUtils.zonedDateTimeToString(endDateEvent.plusDays(1))); 140 } 141 142 result.put("startDate", DateUtils.zonedDateTimeToString(startDateEvent)); 143 result.put("endDate", DateUtils.zonedDateTimeToString(endDateEvent)); 144 145 //excluded occurences 146 List<ZonedDateTime> excludedOccurences = event.getExcludedOccurences(); 147 if (excludedOccurences != null && !excludedOccurences.isEmpty()) 148 { 149 List<String> excludedOccurencesStrings = new ArrayList<>(); 150 for (ZonedDateTime excludedOccurence : excludedOccurences) 151 { 152 excludedOccurencesStrings.add(DateUtils.zonedDateTimeToString(excludedOccurence)); 153 } 154 result.put("excludedDates", excludedOccurencesStrings); 155 } 156 157 // creator 158 UserIdentity creatorIdentity = event.getCreator(); 159 User creator = _userManager.getUser(creatorIdentity); 160 161 result.put("creator", creatorIdentity); 162 result.put("creatorFullName", creator != null ? creator.getFullName() : creatorIdentity.getLogin()); 163 164 UserIdentity user = _currentUserProvider.getUser(); 165 result.put("isCreator", creatorIdentity.equals(user)); 166 result.put("creationDate", DateUtils.zonedDateTimeToString(event.getCreationDate())); 167 168 // last modification 169 UserIdentity contributorIdentity = event.getLastContributor(); 170 User contributor = _userManager.getUser(contributorIdentity); 171 172 result.put("contributor", contributorIdentity); 173 result.put("contributorFullName", contributor != null ? contributor.getFullName() : contributorIdentity.getLogin()); 174 result.put("lastModified", DateUtils.zonedDateTimeToString(event.getLastModified())); 175 176 if (fullInfo) 177 { 178 result.putAll(_eventAsJsonFullInfo(event)); 179 } 180 181 result.put("calendar", _calendarDAO.getCalendarData(calendar, false, false)); 182 183 result.put("isStillSynchronized", _messagingConnectorCalendarManager.isEventStillSynchronized(event.getId())); 184 185 // tags and places are expected by the client (respectively keywords and location on the server side) 186 result.put("tags", event.getTags()); 187 188 String location = StringUtils.defaultString(event.getLocation()); 189 result.put("location", location); 190 result.put("places", Stream.of(location.split(",")).filter(StringUtils::isNotEmpty).collect(Collectors.toList())); 191 192 // add event rights 193 result.put("rights", _extractEventRightData(event)); 194 195 result.put("resourceIds", event.getResources()); 196 197 return result; 198 } 199 200 /** 201 * Retrieves the event additional info (rights, parent id, etc...) 202 * @param event The event 203 * @return the event additional info (rights, parent id, etc...) in a map 204 */ 205 protected Map<String, Object> _eventAsJsonFullInfo(CalendarEvent event) 206 { 207 Map<String, Object> result = new HashMap<>(); 208 209 ExplorerNode explorerNode = event.getParent(); 210 ExplorerNode root = explorerNode; 211 while (true) 212 { 213 if (root.getParent() instanceof ExplorerNode) 214 { 215 root = root.getParent(); 216 } 217 else 218 { 219 break; 220 } 221 } 222 result.put("rootId", root.getId()); 223 result.put("parentId", explorerNode.getId()); 224 result.put("name", event.getName()); 225 result.put("path", explorerNode.getExplorerPath()); 226 result.put("isModifiable", true); 227 228 result.put("rights", _getUserRights(explorerNode)); 229 230 return result; 231 } 232 233 /** 234 * Internal method to extract the data concerning the right of the current user for an event 235 * @param event The event 236 * @return The map of right data. Keys are the rights id, and values indicates whether the current user has the right or not. 237 */ 238 protected Map<String, Object> _extractEventRightData(CalendarEvent event) 239 { 240 Map<String, Object> rightsData = new HashMap<>(); 241 UserIdentity user = _currentUserProvider.getUser(); 242 Calendar calendar = event.getParent(); 243 244 rightsData.put("edit", _rightManager.hasRight(user, AbstractCalendarDAO.RIGHTS_EVENT_EDIT, calendar) == RightResult.RIGHT_ALLOW); 245 rightsData.put("delete", _rightManager.hasRight(user, AbstractCalendarDAO.RIGHTS_EVENT_DELETE, calendar) == RightResult.RIGHT_ALLOW); 246 rightsData.put("delete-own", _rightManager.hasRight(user, AbstractCalendarDAO.RIGHTS_EVENT_DELETE_OWN, calendar) == RightResult.RIGHT_ALLOW); 247 248 return rightsData; 249 } 250 251 /** 252 * Get the user rights on the resource collection 253 * @param node The explorer node 254 * @return The user's rights 255 */ 256 protected Set<String> _getUserRights(ExplorerNode node) 257 { 258 return _rightManager.getUserRights(_currentUserProvider.getUser(), node); 259 } 260 261}