package fi.otavanopisto.muikku.plugins.calendar.rest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateful;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import fi.otavanopisto.muikku.calendar.CalendarServiceException;
import fi.otavanopisto.muikku.calendar.DefaultCalendar;
import fi.otavanopisto.muikku.calendar.DefaultCalendarEvent;
import fi.otavanopisto.muikku.calendar.DefaultCalendarEventAttendee;
import fi.otavanopisto.muikku.calendar.DefaultCalendarEventLocation;
import fi.otavanopisto.muikku.calendar.DefaultCalendarEventReminder;
import fi.otavanopisto.muikku.calendar.DefaultCalendarEventTemporalField;
import fi.otavanopisto.muikku.plugin.PluginRESTService;
import fi.otavanopisto.muikku.plugins.calendar.CalendarController;
import fi.otavanopisto.muikku.plugins.calendar.model.UserCalendar;
import fi.otavanopisto.muikku.plugins.calendar.rest.model.Calendar;
import fi.otavanopisto.muikku.plugins.calendar.rest.model.CalendarEvent;
import fi.otavanopisto.muikku.plugins.calendar.rest.model.CalendarEventAttendee;
import fi.otavanopisto.muikku.plugins.calendar.rest.model.CalendarEventReminder;
import fi.otavanopisto.muikku.rest.RESTPermitUnimplemented;
import fi.otavanopisto.muikku.rest.types.DateTimeParameter;
import fi.otavanopisto.muikku.session.SessionController;
@Stateful
@RequestScoped
@Path ("/calendar")
@Produces ("application/json")
public class CalendarRESTService extends PluginRESTService {
private static final long serialVersionUID = 5698069370957155106L;
@Inject
private Logger logger;
@Inject
private CalendarController calendarController;
@Inject
private SessionController sessionController;
@POST
@Path ("/calendars/")
@RESTPermitUnimplemented
public Response createCalendar(Calendar calendar) {
return Response.status(501).build();
}
@GET
@Path ("/calendars/")
@RESTPermitUnimplemented
public Response listCalendars(@QueryParam ("writableOnly") Boolean writableOnly) {
List<Calendar> result = new ArrayList<>();
if (!sessionController.isLoggedIn()) {
return Response.status(Response.Status.FORBIDDEN).build();
}
try {
List<UserCalendar> userCalendars = calendarController.listUserCalendars(sessionController.getLoggedUserEntity());
for (UserCalendar userCalendar : userCalendars) {
fi.otavanopisto.muikku.calendar.Calendar calendar = calendarController.loadCalendar(userCalendar);
if (calendar.isWritable() || !Boolean.TRUE.equals(writableOnly)) {
result.add(new Calendar(
userCalendar.getId(),
calendar.isWritable(),
userCalendar.getVisible(),
calendar.getSummary(),
calendar.getDescription())
);
}
}
} catch (CalendarServiceException e) {
logger.log(Level.SEVERE, "Failed to retrieve calendars", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
return Response.ok(result).build();
}
@PUT
@Path ("/calendars/{CALID}")
@RESTPermitUnimplemented
public Response updateCalendar(@PathParam ("CALID") Long calendarId, Calendar calendar) {
if (!sessionController.isLoggedIn()) {
return Response.status(Response.Status.FORBIDDEN).build();
}
if (calendar == null || calendarId == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (calendar.getId() == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (!calendar.getId().equals(calendarId)) {
return Response.status(Response.Status.BAD_REQUEST).entity("Calendar id is immutable").build();
}
if (StringUtils.isBlank(calendar.getSummary())) {
return Response.status(Response.Status.BAD_REQUEST).entity("Calendar summary is required").build();
}
UserCalendar userCalendar = calendarController.findUserCalendar(calendarId);
if (userCalendar == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (!userCalendar.getUserId().equals(sessionController.getLoggedUserEntity().getId())) {
return Response.status(Response.Status.FORBIDDEN).build();
}
try {
calendarController.updateCalendar(userCalendar, new DefaultCalendar(userCalendar.getCalendarId(), calendar.isWritable(), userCalendar.getCalendarProvider(), calendar.getSummary(), calendar.getDescription()));
} catch (CalendarServiceException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
return Response.noContent().build();
}
@DELETE
@Path ("/calendars/{CALID}")
@RESTPermitUnimplemented
public Response deleteCalendar(@PathParam ("CALID") Long calendarId) {
if (!sessionController.isLoggedIn()) {
return Response.status(Response.Status.FORBIDDEN).build();
}
if (calendarId == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
UserCalendar userCalendar = calendarController.findUserCalendar(calendarId);
if (userCalendar == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (!userCalendar.getUserId().equals(sessionController.getLoggedUserEntity().getId())) {
return Response.status(Response.Status.FORBIDDEN).build();
}
try {
calendarController.deleteCalendar(userCalendar);
} catch (CalendarServiceException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
return Response.noContent().build();
}
@POST
@Path ("/calendars/{CALID:[0-9]*}/events/")
@RESTPermitUnimplemented
public Response createEvent(@PathParam ("CALID") Long calendarId, CalendarEvent event) {
if (!sessionController.isLoggedIn()) {
return Response.status(Response.Status.FORBIDDEN).build();
}
if (event == null) {
return Response.status(Response.Status.BAD_REQUEST).entity("Event payload is missing").build();
}
if (calendarId == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (StringUtils.isBlank(event.getSummary())) {
return Response.status(Response.Status.BAD_REQUEST).entity("Event summarys is required").build();
}
if (event.getStatus() == null) {
return Response.status(Response.Status.BAD_REQUEST).entity("Event status is required").build();
}
UserCalendar userCalendar = calendarController.findUserCalendar(calendarId);
if (userCalendar == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (!userCalendar.getUserId().equals(sessionController.getLoggedUserEntity().getId())) {
return Response.status(Response.Status.FORBIDDEN).build();
}
try {
List<fi.otavanopisto.muikku.calendar.CalendarEventAttendee> attendees = createEventAttendeeListFromRestModel(event.getAttendees());
List<fi.otavanopisto.muikku.calendar.CalendarEventReminder> reminders = createEventReminderListFromRestModel(event.getReminders());
fi.otavanopisto.muikku.calendar.CalendarEvent calendarEvent = calendarController.createCalendarEvent(userCalendar, event.getSummary(), event.getDescription(), event.getStatus(),
event.getStart(), event.getStartTimeZone(), event.getEnd(), event.getEndTimeZone(), attendees, reminders, event.getRecurrence(), event.isAllDay(),
event.getExtendedProperties());
return Response.ok(createEventRestModel(userCalendar, calendarEvent)).build();
} catch (CalendarServiceException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@GET
@Path ("/calendars/{CALID}/events/")
@RESTPermitUnimplemented
public Response getEvents(@PathParam ("CALID") Long calendarId, @QueryParam ("timeMin") DateTimeParameter timeMin, @QueryParam ("timeMax") DateTimeParameter timeMax) {
if (!sessionController.isLoggedIn()) {
return Response.status(Response.Status.FORBIDDEN).build();
}
if (calendarId == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
UserCalendar userCalendar = calendarController.findUserCalendar(calendarId);
if (userCalendar == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (!userCalendar.getUserId().equals(sessionController.getLoggedUserEntity().getId())) {
return Response.status(Response.Status.FORBIDDEN).build();
}
try {
List<CalendarEvent> result = new ArrayList<>();
List<fi.otavanopisto.muikku.calendar.CalendarEvent> calendarEvents = calendarController.listCalendarEvents(userCalendar, timeMin != null ? timeMin.getDateTime() : null, timeMax != null ? timeMax.getDateTime() : null);
for (fi.otavanopisto.muikku.calendar.CalendarEvent calendarEvent : calendarEvents) {
result.add(createEventRestModel(userCalendar, calendarEvent));
}
return Response.ok(result).build();
} catch (CalendarServiceException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@GET
@Path ("/calendars/{CALID}/events/{EVTID}")
@RESTPermitUnimplemented
public Response getEvent(@PathParam ("CALID") Long calendarId, @PathParam ("EVTID") String eventId) {
if (!sessionController.isLoggedIn()) {
return Response.status(Response.Status.FORBIDDEN).build();
}
if (calendarId == null || StringUtils.isBlank(eventId)) {
return Response.status(Response.Status.NOT_FOUND).build();
}
UserCalendar userCalendar = calendarController.findUserCalendar(calendarId);
if (userCalendar == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (!userCalendar.getUserId().equals(sessionController.getLoggedUserEntity().getId())) {
return Response.status(Response.Status.FORBIDDEN).build();
}
try {
fi.otavanopisto.muikku.calendar.CalendarEvent calendarEvent = calendarController.findCalendarEvent(userCalendar, eventId);
if (calendarEvent == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
return Response.ok(createEventRestModel(userCalendar, calendarEvent)).build();
} catch (CalendarServiceException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@PUT
@Path ("/calendars/{CALID}/events/{EVTID}")
@RESTPermitUnimplemented
public Response updateEvent(@PathParam ("CALID") Long calendarId, @PathParam ("EVTID") String eventId, CalendarEvent event) {
if (!sessionController.isLoggedIn()) {
return Response.status(Response.Status.FORBIDDEN).build();
}
if (calendarId == null || StringUtils.isBlank(eventId)) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (event == null) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
if (StringUtils.isBlank(event.getSummary())) {
return Response.status(Response.Status.BAD_REQUEST).entity("Summary is mandatory").build();
}
UserCalendar userCalendar = calendarController.findUserCalendar(calendarId);
if (userCalendar == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (!userCalendar.getUserId().equals(sessionController.getLoggedUserEntity().getId())) {
return Response.status(Response.Status.FORBIDDEN).build();
}
try {
fi.otavanopisto.muikku.calendar.CalendarEvent originalCalendarEvent = calendarController.findCalendarEvent(userCalendar, eventId);
if (originalCalendarEvent == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
List<fi.otavanopisto.muikku.calendar.CalendarEventAttendee> attendees = createEventAttendeeListFromRestModel(event.getAttendees());
List<fi.otavanopisto.muikku.calendar.CalendarEventReminder> reminders = createEventReminderListFromRestModel(event.getReminders());
fi.otavanopisto.muikku.calendar.CalendarEventTemporalField start = new DefaultCalendarEventTemporalField(event.getStart(), event.getStartTimeZone());
fi.otavanopisto.muikku.calendar.CalendarEventTemporalField end = new DefaultCalendarEventTemporalField(event.getEnd(), event.getEndTimeZone());
fi.otavanopisto.muikku.calendar.CalendarEventLocation calendarEventLocation = new DefaultCalendarEventLocation(event.getLocation(), event.getVideoCallLink(), event.getLongitude(), event.getLongitude());
fi.otavanopisto.muikku.calendar.CalendarEvent calendarEvent = new DefaultCalendarEvent(originalCalendarEvent.getId(), originalCalendarEvent.getCalendarId(), originalCalendarEvent.getServiceProvider(),
event.getSummary(), event.getDescription(), event.getUrl(), calendarEventLocation, event.getStatus(), attendees, originalCalendarEvent.getOrganizer(),
start, end, event.isAllDay(), null, null, event.getExtendedProperties(), reminders, event.getRecurrence());
calendarController.updateCalendarEvent(userCalendar, calendarEvent);
return Response.noContent().build();
} catch (CalendarServiceException e) {
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@DELETE
@Path ("/calendars/{CALID}/events/{EVTID}")
@RESTPermitUnimplemented
public Response deleteEvent(@PathParam ("CALID") Long calendarId, @PathParam ("EVTID") String eventId) {
if (!sessionController.isLoggedIn()) {
return Response.status(Response.Status.FORBIDDEN).build();
}
if (calendarId == null || StringUtils.isBlank(eventId)) {
return Response.status(Response.Status.NOT_FOUND).build();
}
UserCalendar userCalendar = calendarController.findUserCalendar(calendarId);
if (userCalendar == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
if (!userCalendar.getUserId().equals(sessionController.getLoggedUserEntity().getId())) {
return Response.status(Response.Status.FORBIDDEN).build();
}
try {
calendarController.deleteCalendarEvent(userCalendar, eventId);
return Response.noContent().build();
} catch (CalendarServiceException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
private CalendarEvent createEventRestModel(UserCalendar userCalendar, fi.otavanopisto.muikku.calendar.CalendarEvent calendarEvent) {
List<CalendarEventAttendee> attendees = new ArrayList<>();
List<CalendarEventReminder> reminders = new ArrayList<>();
if (calendarEvent.getAttendees() != null) {
for (fi.otavanopisto.muikku.calendar.CalendarEventAttendee calendarEventAttendee : calendarEvent.getAttendees()) {
attendees.add(new CalendarEventAttendee(calendarEventAttendee.getEmail(), calendarEventAttendee.getDisplayName(),
calendarEventAttendee.getStatus(), calendarEventAttendee.getComment()));
}
}
if (calendarEvent.getEventReminders() != null) {
for (fi.otavanopisto.muikku.calendar.CalendarEventReminder calendarEventReminder : calendarEvent.getEventReminders()) {
reminders.add(new CalendarEventReminder(calendarEventReminder.getType(), calendarEventReminder.getMinutesBefore()));
}
}
String recurrence = calendarEvent.getRecurrence();
String location = calendarEvent.getLocation() != null ? calendarEvent.getLocation().getLocation() : null;
String videoCallLink = calendarEvent.getLocation() != null ? calendarEvent.getLocation().getVideoCallLink() : null;
BigDecimal longitude = calendarEvent.getLocation() != null ? calendarEvent.getLocation().getLongitude() : null;
BigDecimal latitude = calendarEvent.getLocation() != null ? calendarEvent.getLocation().getLatitude() : null;
return new CalendarEvent(userCalendar.getId(), calendarEvent.getId(), calendarEvent.getSummary(), calendarEvent.getDescription(),
calendarEvent.getUrl(), location, videoCallLink, longitude, latitude, calendarEvent.getStatus(),
calendarEvent.getStart().getDateTime(), calendarEvent.getStart().getTimeZone(),
calendarEvent.getEnd().getDateTime(), calendarEvent.getEnd().getTimeZone(), calendarEvent.isAllDay(),
calendarEvent.getCreated(), calendarEvent.getUpdated(), calendarEvent.getExtendedProperties(), attendees, reminders, recurrence);
}
private List<fi.otavanopisto.muikku.calendar.CalendarEventAttendee> createEventAttendeeListFromRestModel(List<CalendarEventAttendee> attendees) {
List<fi.otavanopisto.muikku.calendar.CalendarEventAttendee> result = new ArrayList<>();
if (attendees != null) {
for (CalendarEventAttendee attendee : attendees) {
result.add(new DefaultCalendarEventAttendee(attendee.getComment(), attendee.getEmail(), attendee.getDisplayName(), attendee.getStatus()));
}
}
return result;
}
private List<fi.otavanopisto.muikku.calendar.CalendarEventReminder> createEventReminderListFromRestModel(List<CalendarEventReminder> reminders) {
List<fi.otavanopisto.muikku.calendar.CalendarEventReminder> result = new ArrayList<>();
if (reminders != null) {
for (CalendarEventReminder reminder : reminders) {
result.add(new DefaultCalendarEventReminder(reminder.getMinutesBefore(), reminder.getType()));
}
}
return result;
}
}