PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/src/main/java/com/atlassian/jira/ext/calendar/model/CalendarFactory.java

https://bitbucket.org/atlassian/jira-calendar-plugin
Java | 327 lines | 225 code | 34 blank | 68 comment | 15 complexity | 19a48623f5aad8c9730093a6875a423a MD5 | raw file
Possible License(s): Apache-2.0
  1. package com.atlassian.jira.ext.calendar.model;
  2. import com.atlassian.jira.component.ComponentAccessor;
  3. import com.atlassian.jira.config.properties.APKeys;
  4. import com.atlassian.jira.issue.Issue;
  5. import com.atlassian.jira.project.version.Version;
  6. import com.google.common.base.MoreObjects;
  7. import net.fortuna.ical4j.model.Calendar;
  8. import net.fortuna.ical4j.model.CategoryList;
  9. import net.fortuna.ical4j.model.Component;
  10. import net.fortuna.ical4j.model.ComponentList;
  11. import net.fortuna.ical4j.model.Date;
  12. import net.fortuna.ical4j.model.DateTime;
  13. import net.fortuna.ical4j.model.ParameterList;
  14. import net.fortuna.ical4j.model.Property;
  15. import net.fortuna.ical4j.model.PropertyList;
  16. import net.fortuna.ical4j.model.TimeZoneRegistryFactory;
  17. import net.fortuna.ical4j.model.component.VEvent;
  18. import net.fortuna.ical4j.model.parameter.Cn;
  19. import net.fortuna.ical4j.model.parameter.Value;
  20. import net.fortuna.ical4j.model.property.Attendee;
  21. import net.fortuna.ical4j.model.property.CalScale;
  22. import net.fortuna.ical4j.model.property.Categories;
  23. import net.fortuna.ical4j.model.property.Description;
  24. import net.fortuna.ical4j.model.property.Method;
  25. import net.fortuna.ical4j.model.property.ProdId;
  26. import net.fortuna.ical4j.model.property.Status;
  27. import net.fortuna.ical4j.model.property.Uid;
  28. import net.fortuna.ical4j.model.property.Url;
  29. import net.fortuna.ical4j.model.property.XProperty;
  30. import org.apache.commons.lang.time.DateUtils;
  31. import org.apache.log4j.Logger;
  32. import java.net.URI;
  33. import java.net.URISyntaxException;
  34. import java.util.ArrayList;
  35. import java.util.Iterator;
  36. import java.util.List;
  37. import java.util.Set;
  38. import java.util.TimeZone;
  39. /**
  40. * A class for handling the production of Calendars.
  41. */
  42. public class CalendarFactory
  43. {
  44. private static final Logger LOG = Logger.getLogger(CalendarFactory.class);
  45. private final CalendarSearchRequest search;
  46. private final DateFieldProvider dateFieldProvider;
  47. private final TimeZone timezone;
  48. public CalendarFactory(CalendarSearchRequest search, String dateFieldName)
  49. {
  50. this.search = search;
  51. this.dateFieldProvider = new DateFieldProvider(dateFieldName);
  52. this.timezone = MoreObjects.firstNonNull(
  53. TimeZoneRegistryFactory.getInstance().createRegistry().getTimeZone(TimeZone.getDefault().getID()),
  54. TimeZone.getDefault()
  55. );
  56. }
  57. /**
  58. * Creates an ICal calendar from the search request
  59. * @param showReleaseDates - Whether release dates are to be shown in the ICal calendar
  60. * @return An ICal calendar
  61. */
  62. public Calendar createICalendarFromSearch(boolean showReleaseDates)
  63. {
  64. ComponentList calendarComponents = new ComponentList();
  65. calendarComponents.addAll(mapIssuesAsEvents());
  66. if(showReleaseDates)
  67. {
  68. calendarComponents.addAll(mapVersionsAsEvents());
  69. }
  70. return createCalendar(calendarComponents);
  71. }
  72. /**
  73. * Returns a MonthEvents object based on the given SearchRequest object
  74. * @param monthStart The starting day of the month
  75. */
  76. public MonthEvents createMonth(java.util.Calendar monthStart)
  77. {
  78. return new MonthEvents(new ArrayList(getIssues()), new ArrayList(getVersions()), monthStart, dateFieldProvider);
  79. }
  80. /**
  81. * Returns a monthEvents for the current month
  82. */
  83. public MonthEvents createCurrentMonth()
  84. {
  85. java.util.Calendar calendar = GregorianCalendarFactory.constructCalendar();
  86. int dom = calendar.get(java.util.Calendar.DAY_OF_MONTH) - 1;
  87. calendar.add(java.util.Calendar.DAY_OF_MONTH, -dom);
  88. return createMonth(calendar);
  89. }
  90. /**
  91. * Takes the list of issues and makes them into a list of ICal Events
  92. * @return a list of ICal events
  93. */
  94. private List mapIssuesAsEvents()
  95. {
  96. List eventList = new ArrayList();
  97. for (Iterator iterator = getIssues().iterator(); iterator.hasNext();)
  98. {
  99. Issue issue = (Issue) iterator.next();
  100. eventList.add(createCalendarIssue(issue));
  101. }
  102. return eventList;
  103. }
  104. ///CLOVER:OFF
  105. protected Set getIssues()
  106. {
  107. return search.getIssues();
  108. }
  109. protected Set getVersions()
  110. {
  111. return search.getVersions();
  112. }
  113. protected TimeZone getTimeZone()
  114. {
  115. return timezone;
  116. }
  117. ///CLOVER:ON
  118. /**
  119. * Takes the list of Versions for the projects involved in the search
  120. * and converts them into ICal events.
  121. * @return A list of ICal events
  122. */
  123. private List mapVersionsAsEvents()
  124. {
  125. List eventList = new ArrayList();
  126. for (Iterator iterator = getVersions().iterator(); iterator.hasNext();)
  127. {
  128. Version version = (Version) iterator.next();
  129. eventList.add(createCalendarVersion(version));
  130. }
  131. return eventList;
  132. }
  133. /**
  134. * Converts a JIRA Issue into an ICal calendar component
  135. * @param issue the issue to be converted
  136. * @return an ICal calendar component
  137. */
  138. private Component createCalendarIssue(Issue issue)
  139. {
  140. Date beginDate = dateFieldProvider.getDate(issue);
  141. Date endDate = null; // set end date to due date + 24 hours to make clients happy (should not be explicit)
  142. if (beginDate instanceof DateTime) {
  143. endDate = new DateTime(beginDate.getTime() + DateUtils.MILLIS_PER_MINUTE * 30);
  144. }
  145. else {
  146. endDate = new Date(beginDate.getTime() + DateUtils.MILLIS_PER_DAY); // Event lasts for 24 hours - full day event
  147. }
  148. VEvent event = new VEvent(beginDate, endDate, getTitle(issue));
  149. PropertyList eventProperties = event.getProperties();
  150. if(beginDate instanceof DateTime) {
  151. eventProperties.getProperty(Property.DTSTART).getParameters().add(Value.DATE_TIME);
  152. }
  153. else {
  154. eventProperties.getProperty(Property.DTSTART).getParameters().add(Value.DATE);
  155. }
  156. if (endDate instanceof DateTime) {
  157. eventProperties.getProperty(Property.DTEND).getParameters().add(Value.DATE_TIME);
  158. }
  159. else {
  160. eventProperties.getProperty(Property.DTEND).getParameters().add(Value.DATE);
  161. }
  162. eventProperties.add(new Uid("issue-" + issue.getId()+ "@" + getBaseUrl()));
  163. eventProperties.add(getDescription(issue));
  164. eventProperties.add(new Categories(new CategoryList("Issues")));
  165. eventProperties.add(Status.VEVENT_CONFIRMED);
  166. eventProperties.add(getUrl(issue));
  167. try
  168. {
  169. eventProperties.add(getAttendee(issue));
  170. }
  171. catch (Exception e)
  172. {
  173. LOG.error("CalendarFactory.createCalendarIssue(Issue):Component Error creating attendee.", e);
  174. }
  175. return event;
  176. }
  177. /**
  178. * Produces an ICal description for a Jira Issue
  179. * @param issue
  180. * @return an ICal description for the issue
  181. */
  182. private Description getDescription(Issue issue)
  183. {
  184. return new Description(issue.getDescription());
  185. }
  186. /**
  187. * Produces the Title for ICal of a Jira Issue
  188. * @param issue
  189. * @return the Title for the issue
  190. */
  191. private String getTitle(Issue issue)
  192. {
  193. return "[" + issue.getKey() + "] " + issue.getSummary();
  194. }
  195. /**
  196. * Produces a URL for ICal of a Jira Issue
  197. * @param issue
  198. * @return the URL to access the issue
  199. */
  200. private Url getUrl(Issue issue)
  201. {
  202. try
  203. {
  204. String baseUrl = getBaseUrl();
  205. return new Url(new URI(baseUrl + "/browse/" + issue.getKey()));
  206. }
  207. catch (URISyntaxException use)
  208. {
  209. return new Url();
  210. }
  211. }
  212. protected String getBaseUrl()
  213. {
  214. return ComponentAccessor.getApplicationProperties().getString(APKeys.JIRA_BASEURL);
  215. }
  216. /**
  217. * Creates an ICal component from a Jira Version
  218. * @param version The Jira Version to be converted
  219. * @return The Ical componenet based on the Jira Version
  220. */
  221. private Component createCalendarVersion(Version version)
  222. {
  223. /* The null check is almost not needed due to the way VersionDelegator#getVersionsList works */
  224. if (version.getReleaseDate() != null)
  225. {
  226. // set end date to release date + 24 hours to make clients happy (should not be explicit)
  227. Date beginDate = new Date(version.getReleaseDate());
  228. Date endDate = new Date(beginDate.getTime() + DateUtils.MILLIS_PER_DAY);
  229. VEvent event = new VEvent(beginDate, endDate, getTitle(version));
  230. PropertyList eventProperties = event.getProperties();
  231. if(beginDate instanceof DateTime) {
  232. eventProperties.getProperty(Property.DTSTART).getParameters().add(Value.DATE_TIME);
  233. }
  234. else {
  235. eventProperties.getProperty(Property.DTSTART).getParameters().add(Value.DATE);
  236. }
  237. if (endDate instanceof DateTime) {
  238. eventProperties.getProperty(Property.DTEND).getParameters().add(Value.DATE_TIME);
  239. }
  240. else {
  241. eventProperties.getProperty(Property.DTEND).getParameters().add(Value.DATE);
  242. }
  243. eventProperties.add(new Uid("version-" + version.getId()+ "@" + getBaseUrl()));
  244. eventProperties.add(getDescription(version));
  245. eventProperties.add(new Categories(new CategoryList("Issues")));
  246. eventProperties.add(Status.VEVENT_CONFIRMED);
  247. return event;
  248. }
  249. else
  250. {
  251. return null;
  252. }
  253. }
  254. private Attendee getAttendee(Issue issue) throws URISyntaxException
  255. {
  256. ParameterList paramList = new ParameterList();
  257. paramList.add(new Cn(issue.getAssignee().getDisplayName()));
  258. return new Attendee(paramList, "mailto:" + issue.getAssignee().getEmailAddress());
  259. }
  260. /**
  261. * Creates a Title for a Jira Version
  262. * @param version
  263. * @return The title for that version
  264. */
  265. private String getTitle(Version version)
  266. {
  267. return "[" + version.getProjectObject().getName() + "] " + version.getName();
  268. }
  269. /**
  270. * Creates an ICal description for a Jira Version
  271. * @param version
  272. * @return the Ical description for the Jira Version
  273. */
  274. private Description getDescription(Version version)
  275. {
  276. return new Description(version.getDescription());
  277. }
  278. /**
  279. * Creates an ICal Calendar containing the given components
  280. * @param calendarComponents
  281. * @return A new ICal Calendar
  282. */
  283. private Calendar createCalendar(ComponentList calendarComponents)
  284. {
  285. PropertyList calendarProperties = new PropertyList();
  286. calendarProperties.add(new ProdId("-//JIRA//iCal4j 1.0//EN"));
  287. calendarProperties.add(net.fortuna.ical4j.model.property.Version.VERSION_2_0);
  288. calendarProperties.add(CalScale.GREGORIAN);
  289. calendarProperties.add(Method.PUBLISH);
  290. calendarProperties.add(new XProperty("X-WR-TIMEZONE", new ParameterList(), timezone.getID()));
  291. return new Calendar(calendarProperties, calendarComponents);
  292. }
  293. }