PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/com/atlassian/confluence/extra/calendar/ical/action/ModifyICalEventAction.java

https://bitbucket.org/soudmaijer/confluence-calendar
Java | 357 lines | 264 code | 42 blank | 51 comment | 85 complexity | 9b3c7a9e22d3bda67bdbc50a15881f71 MD5 | raw file
  1. /*
  2. * Copyright (c) 2006, Atlassian Software Systems Pty Ltd
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * * Neither the name of "Atlassian" nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. * POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. package com.atlassian.confluence.extra.calendar.ical.action;
  30. import java.net.URI;
  31. import java.net.URISyntaxException;
  32. import java.util.List;
  33. import java.util.Iterator;
  34. import org.joda.time.DateTimeZone;
  35. import org.joda.time.Interval;
  36. import org.joda.time.LocalDateTime;
  37. import org.joda.time.Period;
  38. import com.atlassian.confluence.core.ContentEntityObject;
  39. import com.atlassian.confluence.extra.calendar.ical.model.BaseEventDetails;
  40. import com.atlassian.confluence.extra.calendar.ical.model.OverrideEventDetails;
  41. import com.atlassian.confluence.extra.calendar.ical.model.EventDetails;
  42. import com.atlassian.confluence.extra.calendar.ical.model.EventId;
  43. import com.atlassian.confluence.extra.calendar.ical.model.ICalCalendar;
  44. import com.atlassian.confluence.extra.calendar.ical.model.ICalEvent;
  45. import com.atlassian.confluence.extra.calendar.ical.model.ICalOrganizer;
  46. import com.atlassian.confluence.extra.calendar.model.CalendarException;
  47. import com.atlassian.confluence.links.linktypes.PageCreateLink;
  48. import com.atlassian.confluence.renderer.PageContext;
  49. import com.atlassian.renderer.links.Link;
  50. import com.atlassian.renderer.links.UnresolvedLink;
  51. import com.atlassian.user.User;
  52. /**
  53. * Handles ICalendar event actions.
  54. */
  55. public class ModifyICalEventAction extends AbstractICalEventAction {
  56. public ModifyICalEventAction() {
  57. super( true );
  58. }
  59. public String doAdd() {
  60. ICalCalendar calendar = ( ICalCalendar ) getSubCalendar();
  61. if ( calendar == null ) {
  62. addActionError( "Unable to find the calendar to add the event to." );
  63. return ERROR;
  64. }
  65. BaseEventDetails eventDetails = new BaseEventDetails();
  66. String result = updateEventDetails( eventDetails );
  67. if ( result != null )
  68. return result;
  69. try {
  70. calendar.addBaseDetails( eventDetails );
  71. } catch ( CalendarException e ) {
  72. e.printStackTrace();
  73. addActionError( "An error occurred while adding the event: " + e.getMessage() );
  74. return ERROR;
  75. }
  76. setEventId( new EventId( eventDetails, eventDetails.getStartDate(), eventDetails.getTimeZone() ) );
  77. return saveCalendar();
  78. }
  79. /**
  80. * saves user form changes to VEVENT
  81. * @return
  82. */
  83. public String doEdit() {
  84. ICalEvent event = ( ICalEvent ) getEvent();
  85. if ( event == null ) {
  86. addActionError( "Unable to find the event to edit." );
  87. return ERROR;
  88. }
  89. EventDetails details = event.getDetails();
  90. ICalCalendar calendar = ( ICalCalendar ) event.getCalendar();
  91. OverrideEventDetails overrideDetails = null;
  92. EventId eventId = new EventId(getEventId());
  93. if (!isAllOccurrences() && details instanceof BaseEventDetails) {//create a new override event
  94. BaseEventDetails baseDetails = ( BaseEventDetails ) details;
  95. //Create an overrideeventdetail record
  96. overrideDetails = new OverrideEventDetails(calendar, baseDetails, eventId);
  97. String result = updateEventDetails( overrideDetails );
  98. if ( result != null ) {
  99. return result;
  100. }
  101. baseDetails.addOverride(overrideDetails);
  102. try {
  103. calendar.addOverrideDetails( overrideDetails );
  104. } catch ( CalendarException e ) {
  105. e.printStackTrace();
  106. addActionError( "An error occurred while adding override event to calendar: " + e.getMessage() );
  107. return ERROR;
  108. }
  109. setEventId( new EventId( overrideDetails.getUid(), overrideDetails.getOverrideDate(),
  110. eventId.getInstanceDate(), eventId.getTimeZone()));
  111. return saveCalendar();
  112. } else {//Non recurring event or old override event or all occurrences of reccurrence event
  113. String result = updateEventDetails( details );
  114. if ( result != null )
  115. return result;
  116. result = saveCalendar();
  117. if (result == ERROR) {
  118. return result;
  119. }
  120. //When an all occurrence of recurrence event is edited the event details show the
  121. //first occurrence of the recurring event, so we may need to adjust the eventId
  122. //to the new instance eventId or else it will go back to the first occurrence
  123. //rather than the instance that the user mouse clicked
  124. if (!(details instanceof OverrideEventDetails) &&
  125. !getRepeat().equals(BaseEventDetails.NO_REPEAT) &&
  126. !getRepeat().equals(BaseEventDetails.NOT_IMPLEMENTED)) {
  127. LocalDateTime oldInstanceDate = eventId.getInstanceDate();
  128. LocalDateTime newStartDate = getStartDate();
  129. LocalDateTime newInstanceDate = new LocalDateTime(oldInstanceDate.getYear(),oldInstanceDate.getMonthOfYear(),
  130. oldInstanceDate.getDayOfMonth(),newStartDate.getHourOfDay(),
  131. newStartDate.getMinuteOfHour(),newStartDate.getSecondOfMinute());
  132. EventId newEventId = new EventId( details, newInstanceDate, details.getTimeZone() );
  133. List events = null;
  134. //Check if the recurring event dates has changed
  135. try {
  136. events = calendar.findEvents(new Interval(newEventId.getInstanceDate().toLocalDate().toInterval(details.getTimeZone())),
  137. details.getTimeZone());
  138. } catch ( CalendarException e ) {//no problem if you can't find it
  139. }
  140. boolean found = false;
  141. if (events != null) {
  142. Iterator i = events.iterator();
  143. while (i.hasNext()) {
  144. ICalEvent tmpEvent = (ICalEvent) i.next();
  145. if (tmpEvent.getDetails().getUid().equals(newEventId.getUid())) {
  146. found = true;
  147. break;
  148. }
  149. }
  150. }
  151. if (found) {//show event details of the specific event that was mouse clicked
  152. setEventId( new EventId( details, newEventId.getInstanceDate(), newEventId.getTimeZone() ) );
  153. } else {//show event details of first occurrence of recurring event
  154. setEventId( new EventId( details, details.getStartDate(), details.getTimeZone() ) );
  155. }
  156. }
  157. return result;
  158. }
  159. }
  160. /*
  161. * Saves event details form values to ICAL's VEVENT
  162. */
  163. private String updateEventDetails( EventDetails eventDetails ) {
  164. if ( eventSummary == null || eventSummary.trim().length() == 0 ) {
  165. addActionError( "Please provide a summary for the event." );
  166. return ERROR;
  167. }
  168. eventDetails.setSummary( eventSummary );
  169. if ( eventLocation != null && eventLocation.trim().length() > 0 )
  170. eventDetails.setLocation( eventLocation );
  171. else
  172. eventDetails.setLocation( null );
  173. if ( eventDescription != null && eventDescription.trim().length() > 0 )
  174. eventDetails.setDescription( eventDescription );
  175. else
  176. eventDetails.setDescription( null );
  177. LocalDateTime startDate = getStartDate();
  178. if ( startDate == null ) {
  179. addActionError( "Please provide a start date for the event." );
  180. return ERROR;
  181. }
  182. LocalDateTime endDate = getEndDate();
  183. if ( endDate == null ) {
  184. addActionError( "Please provide an end date for the event." );
  185. return ERROR;
  186. } else if ( endDate.isBefore( startDate ) ) {
  187. addActionError( "The event currently ends before it starts." );
  188. return ERROR;
  189. }
  190. DateTimeZone dateTimeZone = getEventDateTimeZone();
  191. //set RRULE
  192. if (eventDetails instanceof BaseEventDetails) {
  193. if ( repeat != null && repeat.trim().length() > 0 )
  194. ((BaseEventDetails)eventDetails).setRepeat( repeat );
  195. else
  196. ((BaseEventDetails)eventDetails).setRepeat( null );
  197. }
  198. if ( isAllDay() ) {
  199. // we add a day to the end date because it seems more logical in the
  200. // UI
  201. // to have the end date being the day the event ends on, whereas
  202. // iCalendar
  203. // specifies it to be midnight of the next day.
  204. eventDetails.setDates( startDate.toLocalDate(), endDate.toLocalDate().plus( Period.days( 1 ) ) );
  205. } else {
  206. eventDetails.setDates( startDate, endDate, dateTimeZone );
  207. }
  208. User user = null;
  209. if ( organizerName != null && organizerName.trim().length() > 0 )
  210. user = userAccessor.getUser( organizerName );
  211. if ( user != null ) {
  212. ICalOrganizer org = eventDetails.getOrganizer();
  213. if ( org == null ) {
  214. org = new ICalOrganizer();
  215. eventDetails.setOrganizer( org );
  216. }
  217. org.setUsername( user.getName() );
  218. org.setName( user.getFullName() != null ? user.getFullName() : user.getName() );
  219. try {
  220. String email = user.getEmail();
  221. if ( email != null ) {
  222. email = email.trim();
  223. if ( email.length() == 0 )
  224. email = null;
  225. }
  226. org.setEmail( email );
  227. } catch ( URISyntaxException e ) {
  228. log.info( e );
  229. addActionError( e.getMessage() );
  230. return ERROR;
  231. }
  232. } else {
  233. eventDetails.setOrganizer( null );
  234. }
  235. // Set the link.
  236. if ( link != null && link.trim().length() > 0 ) {
  237. ContentEntityObject content = getContent();
  238. if ( content != null ) {
  239. PageContext ctx = content.toPageContext();
  240. String url = null;
  241. Link rlink = linkResolver.createLink( ctx, link );
  242. if ( rlink instanceof UnresolvedLink || rlink instanceof PageCreateLink ) {
  243. addActionError( "The content linked to could not be found: " + link );
  244. return ERROR;
  245. }
  246. if ( rlink != null ) {
  247. url = rlink.getUrl();
  248. if ( url != null && rlink.isRelativeUrl() )
  249. url = getFullContextPath() + url;
  250. eventDetails.setStringProperty( CONF_LINK, link );
  251. }
  252. if ( url != null )
  253. link = url;
  254. }
  255. try {
  256. eventDetails.setUrl( new URI( link ) );
  257. } catch ( URISyntaxException e ) {
  258. e.printStackTrace();
  259. addActionError( "Invalid URL: " + link );
  260. return ERROR;
  261. }
  262. } else {
  263. eventDetails.setUrl( null );
  264. }
  265. return null;
  266. }
  267. public String deleteEvent() {
  268. ICalEvent evt = ( ICalEvent ) getEvent();
  269. if ( evt == null ) {
  270. addActionError( "No event was selected to delete." );
  271. return ERROR;
  272. }
  273. EventDetails details = evt.getDetails();
  274. BaseEventDetails baseDetails = null;
  275. OverrideEventDetails overrideDetails = null;
  276. if ( details instanceof BaseEventDetails ) {
  277. baseDetails = ( BaseEventDetails ) details;
  278. }
  279. else {
  280. overrideDetails = (OverrideEventDetails) details;
  281. baseDetails = overrideDetails.getBaseEvent();
  282. }
  283. ICalCalendar cal = ( ICalCalendar ) evt.getCalendar();
  284. if ( cal != null ) {
  285. if (overrideDetails != null) {//remove override details this occurrence event becomes normal recurrence
  286. try {
  287. if ( cal.removeOverrideDetails( overrideDetails ) ) {
  288. return saveCalendar();
  289. }
  290. } catch ( CalendarException e ) {
  291. e.printStackTrace();
  292. addActionError( "An error occurred while deleting override details: " + e.getMessage() );
  293. return ERROR;
  294. }
  295. }
  296. else if (!isAllOccurrences()) {//delete only one occurrence of reccurrence event
  297. EventId eventId = new EventId(getEventId());
  298. baseDetails.addExcludedDate(eventId.getInstanceDate(),eventId.getTimeZone());
  299. return saveCalendar();
  300. } else {//delete nonrecurrence event or all occurrences of recurrence event
  301. try {
  302. if ( cal.removeBaseDetails( baseDetails ) ) {
  303. return saveCalendar();
  304. }
  305. } catch ( CalendarException e ) {
  306. e.printStackTrace();
  307. addActionError( "An error occurred while deleting: " + e.getMessage() );
  308. return ERROR;
  309. }
  310. }
  311. }
  312. addActionError( "The event could not be deleted." );
  313. return ERROR;
  314. }
  315. }