/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.modules.vitero.restapi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import javax.ws.rs.Consumes;
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.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.SearchIdentityParams;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.UserConstants;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.Util;
import org.olat.modules.vitero.ViteroModule;
import org.olat.modules.vitero.manager.ViteroManager;
import org.olat.modules.vitero.manager.VmsNotAvailableException;
import org.olat.modules.vitero.model.ErrorCode;
import org.olat.modules.vitero.model.GroupRole;
import org.olat.modules.vitero.model.ViteroBooking;
import org.olat.modules.vitero.model.ViteroGroupRoles;
import org.olat.modules.vitero.model.ViteroStatus;
import org.olat.modules.vitero.ui.ViteroBookingsController;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 14.07.2015<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class ViteroBookingWebService {
private static final OLog log = Tracing.createLoggerFor(ViteroBookingWebService.class);
private final String subIdentifier;
private final OLATResourceable ores;
@Autowired
private ViteroModule viteroModule;
@Autowired
private ViteroManager viteroManager;
@Autowired
private BaseSecurity securityManager;
public ViteroBookingWebService(OLATResourceable ores, String subIdentifier) {
this.ores = ores;
this.subIdentifier = subIdentifier;
}
/**
* returns the list of booking of the resource.
*
* @response.representation.200.qname {http://www.example.com}viteroBookingVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc This is the list of all bookings of a resource
* @response.representation.200.example {@link org.olat.modules.vitero.restapi.Examples#SAMPLE_ViteroBookingVO}
* @return The list of vitero booking
*/
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getRooms() {
try {
List<ViteroBooking> bookings = viteroManager.getBookings(null, ores, subIdentifier);
ViteroBookingVO[] bookingVos = new ViteroBookingVO[bookings.size()];
int count = 0;
for(ViteroBooking booking:bookings) {
bookingVos[count++] = new ViteroBookingVO(booking);
}
return Response.ok(bookingVos).build();
} catch (VmsNotAvailableException e) {
log.error("", e);
return handleNotAvailableException();
}
}
/**
* Return the created or updated booking
*
* @response.representation.200.qname {http://www.example.com}viteroBookingVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The created booking
* @response.representation.200.example {@link org.olat.modules.vitero.restapi.Examples#SAMPLE_ViteroBookingVO}
* @return The list of vitero booking
*/
@PUT
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response createRoom(ViteroBookingVO booking) {
return saveRoom(booking);
}
/**
* Return the created or updated booking
*
* @response.representation.200.qname {http://www.example.com}viteroBookingVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The created booking
* @response.representation.200.example {@link org.olat.modules.vitero.restapi.Examples#SAMPLE_ViteroBookingVO}
* @return The list of vitero booking
*/
@POST
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response updateRoom(ViteroBookingVO booking) {
return saveRoom(booking);
}
private Response saveRoom(ViteroBookingVO booking) {
try {
ViteroBooking vBooking = new ViteroBooking();
vBooking.setBookingId(booking.getBookingId());
vBooking.setExternalId(booking.getExternalId());
vBooking.setGroupId(booking.getGroupId());
vBooking.setGroupName(booking.getGroupName());
vBooking.setEventName(booking.getEventName());
vBooking.setStart(booking.getStart());
vBooking.setStartBuffer(booking.getStartBuffer());
vBooking.setEnd(booking.getEnd());
vBooking.setEndBuffer(booking.getEndBuffer());
vBooking.setRoomSize(booking.getRoomSize());
vBooking.setAutoSignIn(booking.isAutoSignIn());
vBooking.setTimeZoneId(viteroModule.getTimeZoneId());
ViteroStatus status;
if(booking.getBookingId() > 0) {
status = viteroManager.updateVmsBooking(vBooking);
} else {
status = viteroManager.createBooking(null, ores, subIdentifier, vBooking);
}
Response response;
if(status.isOk()) {
response = Response.ok(new ViteroBookingVO(vBooking)).build();
} else {
response = handleViteroError(status);
}
return response;
} catch (VmsNotAvailableException e) {
log.error("", e);
return handleNotAvailableException();
}
}
/**
* Delete the booking
*
* @response.representation.200.doc The booking is deleted
* @return Nothing
*/
@DELETE
@Path("{bookingId}")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response deleteRoom(@PathParam("bookingId") int bookingId) {
try {
ViteroBooking vBooking = viteroManager.getBookingById(null, ores, subIdentifier, bookingId);
if(vBooking == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
} else if(viteroManager.deleteBooking(vBooking)) {
return Response.ok().build();
} else {
return Response.serverError().status(500).build();
}
} catch (VmsNotAvailableException e) {
log.error("", e);
return handleNotAvailableException();
}
}
/**
* Returns the list of members of the booking.
*
* @response.representation.200.qname {http://www.example.com}viteroGroupMemberVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc This is the list of all bookings of a resource
* @response.representation.200.example {@link org.olat.modules.vitero.restapi.Examples#SAMPLE_ViteroGroupMemberVO}
* @param bookingId The id of the booking
* @return The list of members in the specified booking
*/
@GET
@Path("{bookingId}/members")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getMembers(@PathParam("bookingId") int bookingId) {
try {
ViteroBooking booking = viteroManager.getBookingById(null, ores, subIdentifier, bookingId);
if(booking == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
ViteroGroupRoles roles = viteroManager.getGroupRoles(booking.getGroupId());
if(roles == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
List<String> currentEmails = new ArrayList<>(roles.getEmailsOfParticipants());
List<ViteroGroupMemberVO> memberList = new ArrayList<>(currentEmails.size());
for(String email:currentEmails) {
SearchIdentityParams params = new SearchIdentityParams();
params.setUserProperties(Collections.singletonMap(UserConstants.EMAIL, email));
List<Identity> identities = securityManager.getIdentitiesByPowerSearch(params, 0, 1);
for(Identity identity:identities) {
GroupRole role = roles.getEmailsToRole().get(email);
memberList.add(new ViteroGroupMemberVO(identity.getKey(), role.name()));
}
}
ViteroGroupMemberVO[] members = memberList.toArray(new ViteroGroupMemberVO[memberList.size()]);
return Response.ok(members).build();
} catch (VmsNotAvailableException e) {
log.error("", e);
return handleNotAvailableException();
}
}
/**
* Update the list of members of the booking, it add and mutates the
* members and delete the missing members.
*
* @response.representation.200.qname {http://www.example.com}viteroGroupMemberVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc This is the list of all bookings of a resource
* @response.representation.200.example {@link org.olat.modules.vitero.restapi.Examples#SAMPLE_ViteroGroupMemberVO}
* @param bookingId The id of the booking
* @param members The array of members
* @return Nothing
*/
@POST
@Path("{bookingId}/members")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response addMembers(@PathParam("bookingId") int bookingId, ViteroGroupMemberVO[] members) {
try {
ViteroBooking booking = viteroManager.getBookingById(null, ores, subIdentifier, bookingId);
if(booking == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
ViteroGroupRoles roles = viteroManager.getGroupRoles(booking.getGroupId());
if(roles == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
List<ViteroErrorVO> errors = new ArrayList<>();
List<String> currentEmails = new ArrayList<>(roles.getEmailsOfParticipants());
for(ViteroGroupMemberVO member:members) {
GroupRole role = GroupRole.valueOf(member.getGroupRole());
Identity identity = securityManager.loadIdentityByKey(member.getIdentityKey());
String currentEmail = identity.getUser().getProperty(UserConstants.EMAIL, null);
GroupRole currentRole = roles.getEmailsToRole().get(currentEmail);
if(currentRole == null) {
ViteroStatus status = viteroManager.addToRoom(booking, identity, role);
if(!status.isOk()) {
errors.add(viteroErrorVO(status));
}
} else if(!currentRole.equals(role)) {
Integer vmsUserId = roles.getEmailsToVmsUserId().get(currentEmail);
ViteroStatus status = viteroManager.changeGroupRole(booking.getGroupId(), vmsUserId.intValue(), role.getVmsValue());
if(!status.isOk()) {
errors.add(viteroErrorVO(status));
}
}
currentEmails.remove(currentEmail);
}
for(String email:currentEmails) {
SearchIdentityParams params = new SearchIdentityParams();
params.setUserProperties(Collections.singletonMap(UserConstants.EMAIL, email));
List<Identity> identities = securityManager.getIdentitiesByPowerSearch(params, 0, 1);
for(Identity identity:identities) {
ViteroStatus status = viteroManager.removeFromRoom(booking, identity);
if(!status.isOk()) {
errors.add(viteroErrorVO(status));
}
}
}
return Response.ok().build();
} catch (VmsNotAvailableException e) {
log.error("", e);
return handleNotAvailableException();
}
}
private Response handleViteroError(ViteroStatus status) {
return Response.serverError().entity(viteroErrorVO(status)).status(500).build();
}
private ViteroErrorVO viteroErrorVO(ViteroStatus status) {
String msg = "";
if(status.getError() != null) {
msg = Util.createPackageTranslator(ViteroBookingsController.class, Locale.ENGLISH)
.translate(status.getError().i18nKey());
}
return new ViteroErrorVO(status, msg);
}
private Response handleNotAvailableException() {
ViteroStatus status = new ViteroStatus(ErrorCode.unkown);
ViteroErrorVO error = new ViteroErrorVO(status, "vitero server is probable not avalailable at this time");
return Response.serverError().entity(error).status(Status.SERVICE_UNAVAILABLE).build();
}
}