package protocol;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import general.DateOperator;
import general.EventAttributesAccessPolicy;
import javax.servlet.http.HttpServletRequest;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import domain.Event;
import domain.EventType;
import domain.RepetitionType;
import domain.User;
/**
* This class represent a query for generate a list of records for the given type
* @author Yury Michurin
*
*/
public class OverlapEventQuery extends Query {
private static final long serialVersionUID = 5000528582600313550L;
/* Event data */
private String from;
private String to;
/* Old event data if the query is from edit so we'll know to skip it */
private String oldFrom;
private String oldTo;
private Long oldEventType;
private Long oldOwner;
@SuppressWarnings("unchecked")
@Override
protected Response internalExecute(HttpServletRequest request, Session databaseSession) {
Response response = null;
try {
Event oldEvent = null;
Date fromDate = DateOperator.stringToDate(from);
Date toDate = DateOperator.stringToDate(to);
if( null == fromDate || null == toDate ) {
throw new IllegalArgumentException("Dates parsing problem" );
}
if( !DateOperator.date1IsBeforeDate2(fromDate, toDate) ) {
throw new IllegalArgumentException("Start date need to be before end date");
}
if (oldFrom != null && oldTo != null) { // if we need to exclude old event, get it.
EventType oldEventTypeObj = (EventType) databaseSession.get(EventType.class, oldEventType);
User oldOwnerObj = (User) databaseSession.get(User.class, oldOwner);
oldEvent = (Event) databaseSession.createCriteria(Event.class)
.add(Restrictions.eq("id.from", DateOperator.stringToDate(this.oldFrom) ))
.add(Restrictions.eq("id.to", DateOperator.stringToDate(this.oldTo)))
.add(Restrictions.eq("id.type", oldEventTypeObj))
.add(Restrictions.eq("id.owner", oldOwnerObj))
.uniqueResult();
}
RepetitionType noRepeat = (RepetitionType) databaseSession.get(RepetitionType.class, new Long(1));
// Get not repeated event that overlap
Criteria notRepeatedOverlapCriteria = databaseSession.createCriteria(Event.class)
.add(Restrictions.conjunction() // AND
.add(Restrictions.eq("repetition", noRepeat))
.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))
)
)
);
if (oldEvent != null) { // skip old event in overlap check
notRepeatedOverlapCriteria.add(Restrictions.not(Restrictions.idEq(oldEvent.getId())));
}
List<Event> notRepeatedOverlap = notRepeatedOverlapCriteria.list();
List<Event> repeatedEvents = databaseSession.createCriteria(Event.class)
.add(Restrictions.ne("repetition", noRepeat))
.list();
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.YEAR, -1);
Date periodStart = calendar.getTime();
calendar.add(Calendar.YEAR, +2);
Date periodEnd = calendar.getTime();
List<Event> generatedOverlap = new LinkedList<Event>();
for(Event event: repeatedEvents) {
List<Event> generatedEvents = event.generateEvents(periodStart, periodEnd);
for (Event generatedEvent: generatedEvents) {
if (DateOperator.isEventOverlap(generatedEvent, fromDate, toDate)) {
// add only the root event
generatedOverlap.add(generatedEvent.getGeneratedFrom());
// stop check other generated
break;
}
}
}
notRepeatedOverlap.addAll(generatedOverlap);
// remove information that need not to be sent
EventAttributesAccessPolicy.enforce(databaseSession, (User) request.getSession().getAttribute("currentUser"), notRepeatedOverlap);
response = new OverlapEventResponse(ResponseStatus.OK, "", notRepeatedOverlap);
} catch(Exception ex) {
response = new OverlapEventResponse(ResponseStatus.FAIL, ex.toString());
}
return response;
}
}