package in.partake.controller.api.ticket;
import in.partake.base.PartakeException;
import in.partake.base.TimeUtil;
import in.partake.base.Util;
import in.partake.controller.api.AbstractPartakeAPI;
import in.partake.model.IPartakeDAOs;
import in.partake.model.UserEx;
import in.partake.model.access.Transaction;
import in.partake.model.dao.DAOException;
import in.partake.model.dao.PartakeConnection;
import in.partake.model.daofacade.EnrollmentDAOFacade;
import in.partake.model.daofacade.MessageDAOFacade;
import in.partake.model.dto.Event;
import in.partake.model.dto.EventTicket;
import in.partake.model.dto.UserPreference;
import in.partake.model.dto.auxiliary.ParticipationStatus;
import in.partake.resource.UserErrorCode;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.JsonNodeFactory;
import org.codehaus.jackson.node.ObjectNode;
import play.mvc.Result;
public class ApplyAPI extends AbstractPartakeAPI {
public static Result post() throws DAOException, PartakeException {
return new ApplyAPI().execute();
}
@Override
protected Result doExecute() throws PartakeException, DAOException {
UserEx user = ensureLogin();
ensureValidSessionToken();
UUID ticketId = getValidTicketIdParameter();
String status = getParameter("status");
String comment = getParameter("comment");
Map<UUID, List<String>> enqueteAnswers = convertToMap(getParameter("enqueteAnswers"));
// If the comment does not exist, we use empty string instead.
if (comment == null)
comment = "";
if (comment.length() > 1024)
return renderInvalid(UserErrorCode.INVALID_COMMENT_TOOLONG);
ParticipationStatus participationStatus;
if ("enroll".equalsIgnoreCase(status))
participationStatus = ParticipationStatus.ENROLLED;
else if ("reserve".equalsIgnoreCase(status))
participationStatus = ParticipationStatus.RESERVED;
else if ("cancel".equals(status))
participationStatus = ParticipationStatus.CANCELLED;
else
return renderInvalid(UserErrorCode.INVALID_ENROLL_STATUS);
new EnrollTransaction(user, ticketId, participationStatus, comment, enqueteAnswers).execute();
return renderOK();
}
private Map<UUID, List<String>> convertToMap(String jsonStr) throws PartakeException {
try {
ObjectNode map;
if (jsonStr == null) {
map = new ObjectNode(JsonNodeFactory.instance);
} else {
ObjectMapper mapper = new ObjectMapper();
map = mapper.readValue(jsonStr, ObjectNode.class);
}
return Util.parseEnqueteAnswers(map);
} catch (JsonParseException e) {
throw new PartakeException(UserErrorCode.INVALID_ENQUETE_ANSWERS);
} catch (JsonMappingException e) {
throw new PartakeException(UserErrorCode.INVALID_ENQUETE_ANSWERS);
} catch (IOException e) {
// I can not find Exception which suits in this situation,
// so I use RuntimeException. 2012/Dec/16 Kengo TODA
throw new RuntimeException(e);
}
}
}
class EnrollTransaction extends Transaction<Void> {
private UserEx user;
private UUID ticketId;
private ParticipationStatus status;
private String comment;
private Map<UUID, List<String>> enqueteAnswers;
public EnrollTransaction(UserEx user, UUID ticketId, ParticipationStatus status, String comment, Map<UUID, List<String>> enqueteAnswers) {
this.user = user;
this.ticketId = ticketId;
this.status = status;
this.comment = comment;
this.enqueteAnswers = enqueteAnswers;
}
// TODO: We should share a lot of code with ChangeEnrollmentCommentAPI.
@Override
protected Void doExecute(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException {
EventTicket ticket = daos.getEventTicketAccess().find(con, ticketId);
if (ticket == null)
throw new PartakeException(UserErrorCode.INVALID_TICKET_ID);
Event event = daos.getEventAccess().find(con, ticket.getEventId());
if (event == null)
throw new PartakeException(UserErrorCode.INVALID_EVENT_ID);
// もし、締め切りを過ぎている場合、変更が出来なくなる。
if (!ticket.acceptsApplication(event, TimeUtil.getCurrentDateTime()))
throw new PartakeException(UserErrorCode.INVALID_ENROLL_TIMEOVER);
// もし、予約締切を過ぎている場合、reservation にはできない。
if (ticket.isReservationTimeOver(event) && ParticipationStatus.RESERVED.equals(status))
throw new PartakeException(UserErrorCode.INVALID_APPLICATION_RESERVATION_TIMEOVER);
EnrollmentDAOFacade.enrollImpl(con, daos, user, ticketId, event, status, comment, enqueteAnswers, false, ticket.isReservationTimeOver(event));
tweetEnrollment(con, daos, user, event, status);
return null;
}
private void tweetEnrollment(PartakeConnection con, IPartakeDAOs daos, UserEx user, Event event, ParticipationStatus status) throws DAOException {
UserPreference pref = daos.getUserPreferenceAccess().find(con, user.getId());
if (pref == null)
pref = UserPreference.getDefaultPreference(user.getId());
if (!pref.tweetsAttendanceAutomatically())
return;
String left = "[PARTAKE] ";
String right;
switch (status) {
case ENROLLED:
right = " (" + event.getEventURL() + ") へ参加します。";
break;
case RESERVED:
right = " (" + event.getEventURL() + ") へ参加予定です。";
break;
case CANCELLED:
right = " (" + event.getEventURL() + ") への参加を取りやめました。";
break;
default:
right = null;
}
if (right == null)
return;
String message = left + Util.shorten(event.getTitle(), 140 - Util.codePointCount(left) - Util.codePointCount(right)) + right;
MessageDAOFacade.tweetMessageImpl(con, daos, user, message);
}
}