001/* 002 * Copyright 2014 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 */ 016package org.ametys.plugins.explorer.calendars.generators; 017 018import java.io.IOException; 019import java.time.ZonedDateTime; 020import java.time.format.DateTimeFormatter; 021import java.util.Date; 022import java.util.GregorianCalendar; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.ProcessingException; 030import org.apache.cocoon.environment.ObjectModelHelper; 031import org.apache.cocoon.environment.Request; 032import org.apache.cocoon.generation.ServiceableGenerator; 033import org.apache.cocoon.xml.AttributesImpl; 034import org.apache.cocoon.xml.XMLUtils; 035import org.apache.commons.lang.StringUtils; 036import org.xml.sax.SAXException; 037 038import org.ametys.core.user.User; 039import org.ametys.core.user.UserIdentity; 040import org.ametys.core.user.UserManager; 041import org.ametys.core.util.DateUtils; 042import org.ametys.plugins.explorer.calendars.Calendar; 043import org.ametys.plugins.explorer.calendars.CalendarEvent; 044import org.ametys.plugins.explorer.workflow.AbstractExplorerNodeWorkflowComponent; 045import org.ametys.plugins.repository.AmetysObject; 046import org.ametys.plugins.repository.AmetysObjectResolver; 047import org.ametys.plugins.repository.ModifiableAmetysObject; 048import org.ametys.plugins.repository.RemovableAmetysObject; 049import org.ametys.plugins.workflow.support.WorkflowHelper; 050import org.ametys.plugins.workflow.support.WorkflowProvider; 051import org.ametys.runtime.i18n.I18nizableText; 052 053import com.opensymphony.workflow.Workflow; 054import com.opensymphony.workflow.spi.Step; 055 056/** 057 * Generate all the needed calendar's informations 058 */ 059public class CalendarEventInfoGenerator extends ServiceableGenerator 060{ 061 /** The object resolver */ 062 protected AmetysObjectResolver _resolver; 063 /** The ametys users manager */ 064 protected UserManager _userManager; 065 /** The workflow provider */ 066 protected WorkflowProvider _workflowProvider; 067 /** The workflow helper */ 068 protected WorkflowHelper _workflowHelper; 069 070 @Override 071 public void service(ServiceManager serviceManager) throws ServiceException 072 { 073 super.service(serviceManager); 074 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 075 _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE); 076 _workflowProvider = (WorkflowProvider) serviceManager.lookup(WorkflowProvider.ROLE); 077 _workflowHelper = (WorkflowHelper) serviceManager.lookup(WorkflowHelper.ROLE); 078 } 079 080 public void generate() throws IOException, SAXException, ProcessingException 081 { 082 Request request = ObjectModelHelper.getRequest(objectModel); 083 084 String startDateString = request.getParameter("start"); 085 Date startDate = DateUtils.parse(startDateString); 086 087 String endDateString = request.getParameter("end"); 088 Date endDate = DateUtils.parse(endDateString); 089 090 String handleWorkflowInit = request.getParameter("handleWorkflowInit"); 091 092 contentHandler.startDocument(); 093 XMLUtils.startElement(contentHandler, "infos"); 094 095 String ids = request.getParameter("ids"); 096 String occurrencesDate = request.getParameter("occurrencesDate"); 097 098 if (StringUtils.isNotBlank(ids) && StringUtils.isNotBlank(occurrencesDate)) 099 { 100 String[] eventsIds = StringUtils.split(ids, ","); 101 String[] eventOccurrencesDate = StringUtils.split(occurrencesDate, ","); 102 103 XMLUtils.startElement(contentHandler, "events"); 104 for (int i = 0; i < eventsIds.length; i++) 105 { 106 String id = eventsIds[i]; 107 String occurrenceDate = eventOccurrencesDate[i]; 108 109 long date = ZonedDateTime.parse(occurrenceDate, DateTimeFormatter.ISO_DATE_TIME).toInstant().toEpochMilli(); 110 CalendarEvent event = _resolver.resolveById(id); 111 _saxEvent(event, new Date(date)); 112 } 113 XMLUtils.endElement(contentHandler, "events"); 114 } 115 else 116 { 117 String calendarId = request.getParameter("calendarId"); 118 if (calendarId != null) 119 { 120 Calendar calendar = _resolver.resolveById(calendarId); 121 122 if ("true".equals(request.getParameter("fromRootCalendar"))) 123 { 124 AmetysObject parent = calendar; 125 126 while (parent instanceof Calendar) 127 { 128 calendar = (Calendar) parent; 129 parent = parent.getParent(); 130 } 131 } 132 133 _saxCalendar(calendar, "true".equals(request.getParameter("recursive")), "true".equals(request.getParameter("sax-events")), startDate, endDate, handleWorkflowInit); 134 } 135 } 136 137 XMLUtils.endElement(contentHandler, "infos"); 138 contentHandler.endDocument(); 139 } 140 141 private void _saxCalendar(Calendar calendar, boolean recursive, boolean saxEvents, Date startDate, Date endDate, String handleWorkflowInit) throws SAXException 142 { 143 AttributesImpl attr = new AttributesImpl(); 144 attr.addCDATAAttribute("id", calendar.getId()); 145 attr.addCDATAAttribute("title", calendar.getName()); 146 attr.addCDATAAttribute("desc", calendar.getDescription()); 147 attr.addCDATAAttribute("templateDesc", calendar.getTemplateDescription()); 148 attr.addCDATAAttribute("color", calendar.getColor()); 149 attr.addCDATAAttribute("workflowName", calendar.getWorkflowName()); 150 attr.addCDATAAttribute("modifiable", calendar instanceof ModifiableAmetysObject ? "true" : "false"); 151 attr.addCDATAAttribute("hasRight", "true"); 152 attr.addCDATAAttribute("removable", calendar instanceof RemovableAmetysObject ? "true" : "false"); 153 154 HashMap<String, Object> inputs = new HashMap<>(); 155 inputs.put(AbstractExplorerNodeWorkflowComponent.EXPLORERNODE_KEY, calendar); 156 if (handleWorkflowInit == null) 157 { 158 Workflow workflow = _workflowProvider.getAmetysObjectWorkflow(); 159 attr.addCDATAAttribute("canInitWorkflow", workflow.canInitialize(calendar.getWorkflowName(), 1, inputs) ? "true" : "false"); 160 } 161 else 162 { 163 attr.addCDATAAttribute("canInitWorkflow", "true"); 164 } 165 XMLUtils.startElement(contentHandler, "calendar", attr); 166 167 if (recursive) 168 { 169 XMLUtils.startElement(contentHandler, "calendars"); 170 for (AmetysObject object : calendar.getChildren()) 171 { 172 if (object instanceof Calendar) 173 { 174 Calendar subCalendar = (Calendar) object; 175 _saxCalendar(subCalendar, recursive, saxEvents, startDate, endDate, handleWorkflowInit); 176 } 177 } 178 XMLUtils.endElement(contentHandler, "calendars"); 179 } 180 181 if (saxEvents) 182 { 183 XMLUtils.startElement(contentHandler, "events"); 184 185 for (Map.Entry<CalendarEvent, List<Date>> entry : calendar.getEvents(startDate, endDate).entrySet()) 186 { 187 CalendarEvent event = entry.getKey(); 188 List<Date> occurences = entry.getValue(); 189 for (Date date : occurences) 190 { 191 _saxEvent(event, date); 192 } 193 } 194 XMLUtils.endElement(contentHandler, "events"); 195 } 196 197 XMLUtils.endElement(contentHandler, "calendar"); 198 } 199 200 private void _saxEvent(CalendarEvent event, Date date) throws SAXException 201 { 202 AttributesImpl attr = new AttributesImpl(); 203 String id = event.getId() + "$" + DateUtils.dateToString(date); 204 attr.addCDATAAttribute("id", id); 205 attr.addCDATAAttribute("calendarId", event.getParent().getId()); 206 attr.addCDATAAttribute("workflowId", event.getWorkflowId() + ""); 207 attr.addCDATAAttribute("color", ((Calendar) event.getParent()).getColor()); 208 attr.addCDATAAttribute("modifiable", "true"); 209 210 XMLUtils.startElement(contentHandler, "event", attr); 211 212 Workflow workflow = _workflowProvider.getAmetysObjectWorkflow(event); 213 List<Step> listSteps = workflow.getCurrentSteps(event.getWorkflowId()); 214 if (!listSteps.isEmpty()) 215 { 216 // We select the first current step 217 Step step = listSteps.get(0); 218 String stepDesc = _workflowHelper.getStepName(((Calendar) event.getParent()).getWorkflowName(), step.getStepId()); 219 I18nizableText workflowStepName = new I18nizableText("application", stepDesc); 220 221 if ("application".equals(workflowStepName.getCatalogue())) 222 { 223 XMLUtils.createElement(contentHandler, "icon-small-workflow", "/plugins/explorer/resources_workflow/" + workflowStepName.getKey() + "-small.png"); 224 } 225 else 226 { 227 String pluginName = workflowStepName.getCatalogue().substring("plugin.".length()); 228 XMLUtils.createElement(contentHandler, "icon-small-workflow", "/plugins/" + pluginName + "/resources/img/workflow/" + workflowStepName.getKey() + "-small.png"); 229 } 230 } 231 232 XMLUtils.createElement(contentHandler, "title", event.getTitle()); 233 XMLUtils.createElement(contentHandler, "desc", event.getDescription()); 234 XMLUtils.createElement(contentHandler, "fullDay", event.getFullDay() ? "true" : "false"); 235 236 XMLUtils.createElement(contentHandler, "recurrenceType", event.getRecurrenceType().toString()); 237 238 String untilDateAsString = ""; 239 Date untilDate = event.getRepeatUntil(); 240 if (untilDate != null) 241 { 242 untilDateAsString = DateUtils.dateToString(untilDate); 243 } 244 XMLUtils.createElement(contentHandler, "untilDate", untilDateAsString); 245 246 Date firstStartDateEvent = event.getStartDate(); 247 Date firstEndDateEvent = event.getEndDate(); 248 249 long diff = firstEndDateEvent.getTime() - firstStartDateEvent.getTime(); 250 Date startDateEvent = date; 251 Date endDateEvent = new Date(date.getTime() + diff); 252 253 if (event.getFullDay()) 254 { 255 GregorianCalendar gcStart = new GregorianCalendar(); 256 gcStart.setTime(startDateEvent); 257 gcStart.set(java.util.Calendar.HOUR_OF_DAY, 0); 258 gcStart.set(java.util.Calendar.MINUTE, 0); 259 gcStart.set(java.util.Calendar.SECOND, 0); 260 gcStart.set(java.util.Calendar.MILLISECOND, 0); 261 262 startDateEvent = gcStart.getTime(); 263 264 GregorianCalendar gcEnd = new GregorianCalendar(); 265 gcEnd.setTime(endDateEvent); 266 gcEnd.set(java.util.Calendar.HOUR_OF_DAY, 23); 267 gcEnd.set(java.util.Calendar.MINUTE, 59); 268 gcEnd.set(java.util.Calendar.SECOND, 59); 269 gcEnd.set(java.util.Calendar.MILLISECOND, 999); 270 271 endDateEvent = gcEnd.getTime(); 272 } 273 274 XMLUtils.createElement(contentHandler, "startDate", DateUtils.dateToString(startDateEvent)); 275 XMLUtils.createElement(contentHandler, "endDate", DateUtils.dateToString(endDateEvent)); 276 _saxUser(event.getCreator(), "creator"); 277 XMLUtils.createElement(contentHandler, "creationDate", DateUtils.dateToString(event.getCreationDate())); 278 _saxUser(event.getLastContributor(), "contributor"); 279 XMLUtils.createElement(contentHandler, "lastModified", DateUtils.dateToString(event.getLastModified())); 280 281 UserIdentity validator = event.getLastValidator(); 282 if (validator != null) 283 { 284 _saxUser(validator, "validator"); 285 } 286 287 Date lastValidated = event.getLastValidated(); 288 if (lastValidated != null) 289 { 290 XMLUtils.createElement(contentHandler, "lastValidated", DateUtils.dateToString(lastValidated)); 291 } 292 293 XMLUtils.endElement(contentHandler, "event"); 294 } 295 296 private void _saxUser(UserIdentity userIdentity, String tagName) throws SAXException 297 { 298 AttributesImpl attr = new AttributesImpl(); 299 attr.addCDATAAttribute("login", userIdentity.getLogin()); 300 attr.addCDATAAttribute("population", userIdentity.getPopulationId()); 301 302 User user = _userManager.getUser(userIdentity.getPopulationId(), userIdentity.getLogin()); 303 if (user != null) 304 { 305 attr.addCDATAAttribute("fullName", user.getFullName()); 306 } 307 308 XMLUtils.createElement(contentHandler, tagName, attr); 309 } 310}