package protocol;
import general.DateOperator;
import general.EventAttributesAccessPolicy;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import domain.Event;
import domain.RepetitionType;
import domain.User;
/**
* This class represent a query for get a list of events by dates
* @author Yury Michurin
*
*/
public class EventListQuery extends Query {
private static final long serialVersionUID = -750123916445874194L;
private String from;
private String to;
private int offset = 0;
private int limit = 10;
/**
* Checks if a user is logged-in,
* Checks if the given dates are valid,
* and then pull the required events from the database
*/
@SuppressWarnings("unchecked")
@Override
protected Response internalExecute(HttpServletRequest request, Session databaseSession) {
Response response = null;
Date fromDate = DateOperator.stringToDate(from);
Date toDate = DateOperator.stringToDate(to);
if (fromDate != null && toDate != null && !DateOperator.date1IsBeforeDate2(fromDate, toDate)) {
return new EventListResponse(ResponseStatus.FAIL, "From date should be before To date!", null);
}
HttpSession httpSession = request.getSession();
try {
User currentUser = (User) httpSession.getAttribute("currentUser");
if (currentUser == null) {
throw new Exception("You are not logged in!");
}
RepetitionType noRepeat = (RepetitionType) databaseSession.get(RepetitionType.class, new Long(1));
Conjunction notRepeatableEventConjunction = Restrictions.conjunction();
notRepeatableEventConjunction.add( Restrictions.eq("repetition", noRepeat) );
if (fromDate != null && toDate != null) {
notRepeatableEventConjunction.add(Restrictions.disjunction() // OR
.add(Restrictions.conjunction()
.add(Restrictions.between("id.from", fromDate, toDate))
.add(Restrictions.between("id.to", fromDate, toDate))
)
.add(Restrictions.conjunction() // AND
.add(Restrictions.le("id.from", fromDate))
.add(Restrictions.ge("id.to", toDate))
)
.add(Restrictions.conjunction() // AND
.add(Restrictions.ge("id.from", fromDate))
.add(Restrictions.le("id.to", toDate))
)
);
}
Criteria notRepeatableEventCriteria = databaseSession.createCriteria(Event.class)
.add( notRepeatableEventConjunction )
.addOrder( Order.desc("id.from") );
if (fromDate != null && toDate == null) {
notRepeatableEventCriteria.add(Restrictions.ge("id.from", fromDate));
}
if (toDate != null && fromDate == null) {
notRepeatableEventCriteria.add(Restrictions.le("id.to", toDate));
}
if (this.offset > 0) {
notRepeatableEventCriteria.setFirstResult(offset);
}
if (this.limit > 0) {
notRepeatableEventCriteria.setMaxResults(limit);
}
if ( (fromDate == null && toDate == null)
// && (this.offset <= 0) // intentionaly left out
&& (this.limit <= 0) ) {
throw new IllegalArgumentException("At least something need to be set");
}
List<Event> events = notRepeatableEventCriteria.list();
List<Event> generatedEvents = new LinkedList<Event>();
Criteria repeatableEventCriteria = databaseSession.createCriteria(Event.class)
.add( Restrictions.not( Restrictions.eq("repetition", noRepeat) ) )
.addOrder( Order.desc("id.from") );
List<Event> repeatableEvents = repeatableEventCriteria.list();
// generate events if applied
if (fromDate != null && toDate != null) {
for(Event event : repeatableEvents) {
generatedEvents.addAll(event.generateEvents(fromDate, toDate));
}
// add generated events to regular events
events.addAll(generatedEvents);
} else { // add just the root event
events.addAll(repeatableEvents);
}
// remove information that need not to be sent
EventAttributesAccessPolicy.enforce(databaseSession, currentUser, events);
response = new EventListResponse(ResponseStatus.OK, "", events);
} catch (Exception ex) {
response = new EventListResponse(ResponseStatus.FAIL, ex.toString(), null);
}
return response;
}
}