/*
This file is part of OpenMyEWB.
OpenMyEWB is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenMyEWB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMyEWB. If not, see <http://www.gnu.org/licenses/>.
OpenMyEWB is Copyright 2005-2009 Nicolas Kruchten (nicolas@kruchten.com), Francis Kung, Engineers Without Borders Canada, Michael Trauttmansdorff, Jon Fishbein, David Kadish
*/
package ca.myewb.controllers.common;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import org.apache.velocity.context.Context;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.LogicalExpression;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import ca.myewb.frame.GetParamWrapper;
import ca.myewb.frame.Helpers;
import ca.myewb.frame.Controller;
import ca.myewb.frame.Permissions;
import ca.myewb.frame.PostParamWrapper;
import ca.myewb.frame.SafeHibList;
import ca.myewb.model.EventModel;
import ca.myewb.model.GroupChapterModel;
import ca.myewb.model.GroupModel;
import ca.myewb.model.TagModel;
import ca.myewb.model.UserModel;
public class EventList extends Controller
{
Logger log = Logger.getLogger(this.getClass());
public EventList(HttpSession httpSession, Session hibernate,
PostParamWrapper requestParams, GetParamWrapper urlParams,
UserModel currentUser)
{
super();
this.httpSession = httpSession;
this.hibernateSession = hibernate;
this.requestParams = requestParams;
this.currentUser = currentUser;
this.urlParams = urlParams;
}
public void list(Context ctx, String mode, int pagesize) throws Exception
{
urlParams.processParams(new String[]{"filter", "pagenum"},
new String[]{"Any", "0"});
log.info("EventList started with params " + urlParams.get("filter") + ", " + urlParams.get("pagenum"));
String filterToUse = urlParams.get("filter");
ctx.put("filterParam", filterToUse);
if (filterToUse.equals("Any"))
{
filterToUse = null;
}
int pageNo = 1;
int firstEvent = 0;
int numTotalEvents = 0;
List<EventModel> events = null;
log.info("EventList mode: events");
try{
pageNo = new Integer(urlParams.get("pagenum")).intValue();
}
catch( NullPointerException npe )
{
log.debug("EventList NPE: pageNo");
pageNo = 0;
}
Date now = new Date();
if (mode.equals("events"))
{
if (pageNo < 1)
{
pageNo = (visiblePreviousEventCount(filterToUse, now) / pagesize) + 1;
}
firstEvent = (pageNo - 1) * pagesize;
log.info("EventList first event: " + firstEvent);
events = listPaginatedVisibleEvents(filterToUse, firstEvent, pagesize, null);
numTotalEvents = visibleEventCount(filterToUse, null);
}
else if (mode.equals("upcoming"))
{
if (pageNo < 1)
{
pageNo = 1;
}
firstEvent = (pageNo - 1) * pagesize;
log.info("EventList first event: " + firstEvent);
events = listPaginatedVisibleEvents(filterToUse, firstEvent, pagesize, now);
numTotalEvents = visibleEventCount(filterToUse, now);
}
ctx.put("thetag", filterToUse);
ctx.put("pageNum", new Integer(pageNo));
ctx.put("pageSize", new Integer(pagesize));
int numPages = (numTotalEvents / pagesize);
if ((numTotalEvents % pagesize) != 0)
{
numPages++;
}
ctx.put("numPages", new Integer(numPages));
ctx.put("events", events);
}
public void handle(Context ctx) throws Exception
{
// You should never come here directly!
throw getSecurityException("Someone accessed common/PostList directly!",
path + "/home/Home");
}
public Collection<EventModel> listVisibleEventsBetweenDates(Date start, Date end, GroupChapterModel chapter) throws HibernateException
{
Criteria criteria = hibernateSession.createCriteria(EventModel.class);
LogicalExpression singleDayEvents = Restrictions.and(Restrictions.ge(
"startDate", start), Restrictions.le("endDate", end));
LogicalExpression endsToday = Restrictions.and(Restrictions.lt("startDate",
start), Restrictions.and(Restrictions.ge("endDate", start),
Restrictions.le("endDate", end)));
LogicalExpression startsToday = Restrictions.and(Restrictions.and(
Restrictions.ge("startDate", start), Restrictions.le("startDate",
end)), Restrictions.gt("endDate", end));
LogicalExpression ongoing = Restrictions.and(Restrictions.lt("startDate",
start), Restrictions.gt("endDate", end));
criteria.add(Restrictions.or(singleDayEvents, Restrictions.or(endsToday,
Restrictions.or(startsToday, ongoing))));
if (chapter == null)
{
if(!currentUser.isAdmin())
{
criteria.add(Restrictions.in("group", Permissions.visibleGroups(currentUser, true)));
}
else
{
List<GroupModel> adminGroups = Helpers.getNationalRepLists(true, true);
adminGroups.add(Helpers.getGroup("Exec"));
adminGroups.add(Helpers.getGroup("ProChaptersExec"));
criteria.add(Restrictions.in("group", adminGroups));
}
}
else
{
criteria.add(Restrictions.in("group", Permissions.visibleGroupsInChapter(currentUser, chapter)));
}
criteria.addOrder(Order.asc("startDate"));
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
return new SafeHibList<EventModel>(criteria).list();
}
public Collection<EventModel> listVisibleEventsForDay(Date time, GroupChapterModel chapter)
{
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(time);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.AM_PM, Calendar.AM);
Date dayStart = cal.getTime();
cal.add(Calendar.DATE, 1);
cal.add(Calendar.SECOND, -1);
Date dayEnd = cal.getTime();
return listVisibleEventsBetweenDates(dayStart, dayEnd, chapter);
}
public Collection<EventModel> listVisibleEventsForQuarter(Date date, GroupChapterModel chapter) throws HibernateException
{
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(date);
cal.set(Calendar.DATE, 1);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.AM_PM, Calendar.AM);
cal.add(Calendar.MONTH, -1);
Date monthStart = cal.getTime(); //the first of the previous month
cal.add(Calendar.MONTH, 5);
cal.add(Calendar.SECOND, -1);
Date monthEnd = cal.getTime(); //the last of the next month
return listVisibleEventsBetweenDates(monthStart, monthEnd, chapter);
}
public Map<Date, Set<EventModel>> mapToDateVisibleEventsForMonth(Date d, GroupChapterModel chapter)
{
//Get List of Events
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(d);
cal.set(Calendar.DATE, 1);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 1);
cal.set(Calendar.AM_PM, Calendar.AM);
cal.add(Calendar.DATE, -cal.get(Calendar.DAY_OF_WEEK) + 1);
Date monthStart = cal.getTime();
cal.setTime(d);
cal.set(Calendar.DATE, 1);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 1);
cal.set(Calendar.AM_PM, Calendar.AM);
cal.add(Calendar.MONTH, 1);
cal.add(Calendar.DATE, 7);
cal.add(Calendar.DATE, -cal.get(Calendar.DAY_OF_WEEK) + 1);
cal.add(Calendar.SECOND, -1);
Date monthEnd = cal.getTime();
return mapToDateVisibleEventsBetweenDates(monthStart, monthEnd, chapter);
}
public Map<Date, Set<EventModel>> mapToDateVisibleEventsForNextNWeeks(Date d, GroupChapterModel chapter, int n)
{
// Get List of Events
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(d);
cal.add(Calendar.DATE, -cal.get(Calendar.DAY_OF_WEEK) + 1);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 1);
cal.set(Calendar.AM_PM, Calendar.AM);
Date start = cal.getTime();
cal.add(Calendar.WEEK_OF_YEAR, n);
cal.add(Calendar.DATE, 7);
cal.add(Calendar.DATE, -cal.get(Calendar.DAY_OF_WEEK) + 1);
cal.add(Calendar.SECOND, -1);
Date end = cal.getTime();
return mapToDateVisibleEventsBetweenDates(start, end, chapter);
}
private Map<Date, Set<EventModel>> mapToDateVisibleEventsBetweenDates(Date start, Date end, GroupChapterModel chapter)
{
Hashtable<Date, Set<EventModel>> month = new Hashtable<Date, Set<EventModel>>();
//Get List of Events
Calendar cal = GregorianCalendar.getInstance();
LinkedList<EventModel> events = new LinkedList<EventModel>(listVisibleEventsBetweenDates(start, end, chapter));
//Sort Events into Dates
for( EventModel e : events )
{
cal.setTime(e.getStartDate());
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 1);
cal.set(Calendar.AM_PM, Calendar.AM);
do
{
if( !month.containsKey(cal.getTime()) )
{
month.put(cal.getTime(), new HashSet<EventModel>());
}
month.get(cal.getTime()).add(e);
cal.add(Calendar.DATE, 1);
}
while(cal.getTime().before(e.getEndDate()));
}
return month;
}
public List<EventModel> listPaginatedVisibleEvents(String filter, int startPage, int eventsPerPage, Date endAfter)
throws HibernateException
{
Criteria criteria = hibernateSession.createCriteria(EventModel.class);
if(!currentUser.isAdmin())
{
log.info("EventList visible groups added to criteria");
criteria.add(Restrictions.in("group", Permissions.visibleGroups(currentUser, true)));
}
criteria.addOrder(Order.asc("startDate"));
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
addBooleanFilters(endAfter, criteria);
addFilter(filter, criteria);
addPagination(startPage, eventsPerPage, criteria);
return getUniqueEventList(criteria);
}
private void addPagination(int startPage, int eventsPerPage, Criteria criteria)
{
if (eventsPerPage > 0)
{
criteria.setMaxResults(eventsPerPage);
}
if (startPage > 0)
{
criteria.setFirstResult(startPage);
}
}
private List<EventModel> getUniqueEventList(Criteria criteria)
{
criteria.setProjection(Projections.groupProperty("id"));
Iterator it = criteria.list().iterator();
List<EventModel> list = new ArrayList<EventModel>();
while (it.hasNext())
{
list.add((EventModel) hibernateSession.load(EventModel.class, (Integer) it
.next()));
}
return list;
}
public int visibleEventCount(String filter, Date endAfter)
throws HibernateException
{
Criteria criteria = hibernateSession.createCriteria(EventModel.class);
if(!currentUser.isAdmin())
{
criteria.add(Restrictions.in("group", Permissions.visibleGroups(currentUser, true)));
}
addBooleanFilters(endAfter, criteria);
addFilter(filter, criteria);
criteria.addOrder(Order.asc("startDate"));
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
return getUniqueEventCount(criteria);
}
public int visiblePreviousEventCount(String filter, Date fromDate)
throws HibernateException
{
Criteria criteria = hibernateSession.createCriteria(EventModel.class);
if(!currentUser.isAdmin())
{
criteria.add(Restrictions.in("group", Permissions.visibleGroups(currentUser, true)));
}
criteria.add(Restrictions.lt("startDate", fromDate));
addFilter(filter, criteria);
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
return getUniqueEventCount(criteria);
}
private int getUniqueEventCount(Criteria criteria)
{
criteria.setProjection(Projections.groupProperty("id"));
return criteria.list().size();
}
private void addBooleanFilters(Date endAfter, Criteria criteria)
{
if(endAfter != null)
{
log.info("Events that ended after endDate set");
criteria.add(Restrictions.ge("endDate", endAfter));
}
}
private void addFilter(String filter, Criteria criteria)
{
if (filter == null)
{
return; // just in case
}
log.debug("Filtering events: " + filter);
TagModel t = TagModel.getTag(filter);
criteria.createAlias("tags", "t");
if(t==null) //won't find anything
{
criteria.add(Restrictions.like("t.name", "%" + filter + "%"));
}
else //broaden the search
{
criteria.add(Restrictions.like("t.name", "%" + t.getName() + "%"));
}
}
public List<List<Date>> getDatesInMonth(Date d)
{
ArrayList<List<Date>> dates = new ArrayList<List<Date>>();
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(d);
int monthNo = cal.get(Calendar.MONTH);
cal.set(Calendar.DATE, 1);
cal.add(Calendar.DATE, -cal.get(Calendar.DAY_OF_WEEK) + 1);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 1);
cal.set(Calendar.AM_PM, Calendar.AM);
do
{
dates.add(new LinkedList<Date>());
for(int i = 0; i < 7; i++)
{
dates.get(dates.size() - 1).add(cal.getTime());
cal.add(Calendar.DATE, 1);
}
}
while(!((cal.get(Calendar.DAY_OF_WEEK) == 1) && (cal.get(Calendar.MONTH) != monthNo)));
return dates;
}
public List<List<Date>> getDatesInNextNWeeks(Date d, int n)
{
ArrayList<List<Date>> dates = new ArrayList<List<Date>>();
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(d);
cal.add(Calendar.DATE, -cal.get(Calendar.DAY_OF_WEEK) + 1);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 1);
cal.set(Calendar.AM_PM, Calendar.AM);
cal.add(Calendar.WEEK_OF_YEAR, n);
Date endDate = cal.getTime();
cal.add(Calendar.WEEK_OF_YEAR, -n);
do
{
dates.add(new LinkedList<Date>());
for(int i = 0; ( i < 7 ) && (!cal.getTime().equals(endDate)); i++)
{
dates.get(dates.size() - 1).add(cal.getTime());
cal.add(Calendar.DATE, 1);
}
}
while(!cal.getTime().equals(endDate) && !cal.getTime().after(endDate));
return dates;
}
}