package in.partake.controller.api.account; import in.partake.base.DateTime; import in.partake.base.Pair; 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.DBAccess; import in.partake.model.dao.DAOException; import in.partake.model.dao.PartakeConnection; import in.partake.model.dao.access.IUserTicketAccess; import in.partake.model.daofacade.EnrollmentDAOFacade; import in.partake.model.dto.Event; import in.partake.model.dto.EventTicket; import in.partake.model.dto.UserTicket; import in.partake.model.dto.auxiliary.CalculatedEnrollmentStatus; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.codehaus.jackson.node.ArrayNode; import org.codehaus.jackson.node.JsonNodeFactory; import org.codehaus.jackson.node.ObjectNode; import play.mvc.Result; class TicketAndStatus { public EventTicket ticket; public Event event; public CalculatedEnrollmentStatus status; public TicketAndStatus(EventTicket ticket, Event event, CalculatedEnrollmentStatus status) { this.ticket = ticket; this.event = event; this.status = status; } } public class GetTicketsAPI extends AbstractPartakeAPI { public static Result get() throws DAOException, PartakeException { return new GetTicketsAPI().execute(); } @Override public Result doExecute() throws DAOException, PartakeException { UserEx user = ensureLogin(); String queryType = getParameter("queryType"); if (queryType == null) queryType = "all"; int offset = optIntegerParameter("offset", 0); offset = Util.ensureRange(offset, 0, Integer.MAX_VALUE); int limit = optIntegerParameter("limit", 10); limit = Util.ensureRange(limit, 0, 100); GetEnrollmentsTransaction transaction = new GetEnrollmentsTransaction(user.getId(), queryType, offset, limit); transaction.execute(); ArrayNode statuses = new ArrayNode(JsonNodeFactory.instance); for (TicketAndStatus ticketAndStatus : transaction.getStatuses()) { ObjectNode obj = new ObjectNode(JsonNodeFactory.instance); obj.put("ticket", ticketAndStatus.ticket.toSafeJSON()); obj.put("event", ticketAndStatus.event.toSafeJSON()); obj.put("status", ticketAndStatus.status.toString()); statuses.add(obj); } ObjectNode obj = new ObjectNode(JsonNodeFactory.instance); obj.put("totalTicketCount", transaction.getTotalTicketCount()); obj.put("ticketStatuses", statuses); return renderOK(obj); } } class GetEnrollmentsTransaction extends DBAccess<Void> { private String userId; private String queryType; private int offset; private int limit; private int numTotalTickets; private List<TicketAndStatus> statuses; public GetEnrollmentsTransaction(String userId, String queryType, int offset, int limit) { this.userId = userId; this.queryType = queryType; this.offset = offset; this.limit = limit; this.statuses = new ArrayList<TicketAndStatus>(); } @Override protected Void doExecute(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException { if ("upcoming".equalsIgnoreCase(queryType)) return doUpcomingQuery(con, daos); else return doAllQuery(con, daos); } private Void doAllQuery(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException { IUserTicketAccess enrollmentAccess = daos.getEnrollmentAccess(); List<UserTicket> enrollments = enrollmentAccess.findByUserId(con, userId, offset, limit); this.numTotalTickets = enrollmentAccess.countByUserId(con, userId); for (UserTicket enrollment : enrollments) { if (enrollment == null) continue; Event event = daos.getEventAccess().find(con, enrollment.getEventId()); if (event == null) continue; EventTicket ticket = daos.getEventTicketAccess().find(con, enrollment.getTicketId()); if (ticket == null) continue; CalculatedEnrollmentStatus calculatedEnrollmentStatus = EnrollmentDAOFacade.calculateEnrollmentStatus(con, daos, userId, ticket, event); TicketAndStatus status = new TicketAndStatus(ticket, event, calculatedEnrollmentStatus); statuses.add(status); } return null; } // TODO(mayah): too slow. Actually this should be done in DB. private Void doUpcomingQuery(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException { IUserTicketAccess dao = daos.getEnrollmentAccess(); DateTime now = TimeUtil.getCurrentDateTime(); List<UserTicket> rawTickets = dao.findByUserId(con, userId, 0, Integer.MAX_VALUE); List<Pair<UserTicket, Event>> filtered = new ArrayList<Pair<UserTicket, Event>>(); for (UserTicket userTicket : rawTickets) { if (userTicket == null) continue; Event event = daos.getEventAccess().find(con, userTicket.getEventId()); if (event == null) continue; if (now.isBefore(event.getBeginDate())) filtered.add(new Pair<UserTicket, Event>(userTicket, event)); } // filtered を開始時刻順にソート Collections.sort(filtered, new Comparator<Pair<UserTicket, Event>>() { @Override public int compare(Pair<UserTicket, Event> o1, Pair<UserTicket, Event> o2) { long t1 = o1.getSecond().getBeginDate().getTime(); long t2 = o2.getSecond().getBeginDate().getTime(); if (t1 < t2) return -1; if (t1 == t2) return 0; return 1; } }); for (int i = 0; i < limit && i + offset < filtered.size(); ++i) { UserTicket userTicket = filtered.get(i + offset).getFirst(); Event event = filtered.get(i + offset).getSecond(); EventTicket ticket = daos.getEventTicketAccess().find(con, userTicket.getTicketId()); if (ticket == null) continue; CalculatedEnrollmentStatus calculatedEnrollmentStatus = EnrollmentDAOFacade.calculateEnrollmentStatus(con, daos, userId, ticket, event); TicketAndStatus status = new TicketAndStatus(ticket, event, calculatedEnrollmentStatus); statuses.add(status); } return null; } public int getTotalTicketCount() { return numTotalTickets; } public List<TicketAndStatus> getStatuses() { return this.statuses; } }