package service.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import model.Appointment;
import model.User;
import persistence.PersistenceContext;
import service.AppointmentService;
import service.exception.AlreadyRegisteredException;
import service.exception.AppointmentNotFoundException;
import service.exception.MaximumMemberCountExceededException;
import service.exception.NotRegisteredException;
import service.exception.RegisterPeriodOverException;
import service.exception.UnregisterPeriodOverException;
import service.exception.NotAllowedException;
/**
* This is the base implementation of the LvaService. It holds appointment objects
* and appointment-user associations within the object state.
*
* @author Christian Beikov
*/
public final class AppointmentServiceImpl<T extends Appointment<T> & Serializable> implements AppointmentService<T> {
private Map<T, List<User>> registrations;
@SuppressWarnings("unchecked")
public AppointmentServiceImpl(Class<T> clazz) {
this.registrations = PersistenceContext.getInstance("oop").getPersistentMap(clazz.getSimpleName() + ".registrations");
}
@Override
public void saveAppointment(T appointment, User responsibleUser) throws NotAllowedException {
List<User> users = registrations.get(appointment);
registrations.remove(appointment);
registrations.put(appointment, users);
}
@Override
public void removeAppointment(T appointment, User responsibleUser) throws AppointmentNotFoundException, NotAllowedException {
appointment = getRealAppointment1(appointment);
registrations.remove(appointment);
}
@Override
public List<T> getAppointments() {
return getAppointments(User.GUEST);
}
@Override
public List<T> getAppointments(User user) {
return new ArrayList<T>(registrations.keySet());
}
@Override
public int getRegisteredUserCount(T appointment, User requester) throws AppointmentNotFoundException {
return getRegisteredUsers(appointment, requester).size();
}
@Override
public void register(User user, T appointment, User responsibleUser) throws RegisterPeriodOverException, AlreadyRegisteredException, MaximumMemberCountExceededException, NotAllowedException, AppointmentNotFoundException {
List<User> st = getRegisteredUsers(appointment, user);
appointment = getRealAppointment1(appointment);
if (st.contains(user)) {
throw new AlreadyRegisteredException();
}
if (appointment.getRegisterStart().after(new Date()) || appointment.getRegisterEnd().before(new Date())) { //nach dem heutigen Tag -> Anmeldung noch nicht begonnen
throw new RegisterPeriodOverException();
}
if (st.isEmpty()) {
st = new ArrayList<User>();
}
if (st.size() + 1 > appointment.getMaximumMemberCount()) {
throw new MaximumMemberCountExceededException();
}
st.add(user);
registrations.put(appointment, st);
}
@Override
public void unregister(User user, T appointment) throws UnregisterPeriodOverException, NotRegisteredException, AppointmentNotFoundException {
List<User> users = getRegisteredUsers(appointment, user);
if (!users.contains(user)) {
throw new NotRegisteredException();
}
appointment = getRealAppointment1(appointment);
if (appointment.getRegisterStart().after(new Date()) || appointment.getUnregisterEnd().before(new Date())) { //nach dem heutigen Tag -> Anmeldung noch nicht begonnen
throw new UnregisterPeriodOverException();
}
users.remove(user);
registrations.put(appointment, users);
}
@Override
public List<User> getRegisteredUsers(T appointment, User requester) throws AppointmentNotFoundException {
if (!registrations.containsKey(appointment)) {
throw new AppointmentNotFoundException();
}
List<User> users = registrations.get(appointment);
if (users == null) {
return Collections.emptyList();
}
return new ArrayList<User>(users);
}
public void cancelAppointment(T appointment, User responsibleUser) throws AppointmentNotFoundException, NotAllowedException {
T real = getRealAppointment1(appointment);
if (real.isCanceled()) {
return;
}
saveAppointment(real.cancel(), responsibleUser);
}
public void rescheduleAppointment(T appointment, User responsibleUser) throws AppointmentNotFoundException, NotAllowedException {
T real = getRealAppointment1(appointment);
if (!real.isCanceled()) {
return;
}
saveAppointment(real.reschedule(), responsibleUser);
}
private T getRealAppointment0(T appointment) {
for (T l : registrations.keySet()) {
if (l.equals(appointment)) {
return l;
}
}
return null;
}
private T getRealAppointment1(T appointment) throws AppointmentNotFoundException {
T real = getRealAppointment0(appointment);
if (real == null) {
throw new AppointmentNotFoundException();
}
return real;
}
}