ca.myewb.frame.servlet.GraphServlet.java Source code

Java tutorial

Introduction

Here is the source code for ca.myewb.frame.servlet.GraphServlet.java

Source

/*
    
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.frame.servlet;

import java.awt.BasicStroke;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TreeMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardPieItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.DataUtilities;
import org.jfree.data.DefaultKeyedValues;
import org.jfree.data.KeyedValues;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.MovingAverage;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.util.SortOrder;

import ca.myewb.frame.ErrorMessage;
import ca.myewb.frame.Helpers;
import ca.myewb.frame.HibernateUtil;
import ca.myewb.frame.Permissions;
import ca.myewb.frame.RedirectionException;
import ca.myewb.frame.SafeHibList;
import ca.myewb.model.DailyStatsModel;
import ca.myewb.model.GroupChapterModel;
import ca.myewb.model.GroupModel;
import ca.myewb.model.UserModel;

public class GraphServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        Logger log = Logger.getLogger(this.getClass());

        try {
            Session s = HibernateUtil.currentSession();
            HttpSession httpSession = req.getSession();
            UserModel currentUser = WrapperServlet.getUser(Helpers.getDefaultURL(), log, s, httpSession);

            String url = req.getRequestURI();

            if (!currentUser.isMember(Helpers.getGroup("Exec"))) {
                log.warn(currentUser.getUsername() + "tried to access GraphServlet!");
                httpSession.setAttribute("message", new ErrorMessage("You can't access the graphs!"));
                throw new RedirectionException(Helpers.getDefaultURL());
            }

            JFreeChart chart = null;

            if (url.contains("genderpie")) {
                chart = getGenderPie(s);
            } else if (url.contains("languagepie")) {
                chart = getLanguagePie(s);
            } else if (url.contains("studentpie")) {
                chart = getStudentPie(s);
            } else if (url.contains("chapterrankpie")) {
                chart = getChapterRankPie(s, url);
            } else if (url.contains("rankpie")) {
                chart = getRankPie();
            } else if (url.contains("nochapterpie")) {
                chart = getNoChapterPie();
            } else if (url.contains("chapterpie")) {
                chart = getChapterPie(s);
            } else if (url.contains("postpie")) {
                chart = getPostPie(s);
            } else if (url.contains("post2pie")) {
                chart = getPost2Pie(s);
            } else if (url.contains("post3pie")) {
                chart = getPost3Pie(s);
            } else if (url.contains("provincepie")) {
                chart = getProvincePie(s);
            } else if (url.contains("lastlogin")) {
                chart = getLastLogin(s);
            } else if (url.contains("daily4stats")) {
                chart = getDailyStats(s);
            } else if (url.contains("daily2stats")) {
                chart = getDaily2Stats(s);
            } else if (url.contains("daily3stats")) {
                chart = getDaily3Stats(s);
            } else if (url.contains("dailyintegratedstats")) {
                chart = getDailyIntegratedStats(s);
            } else if (url.contains("logins")) {
                chart = getLogins(s);
            } else if (url.contains("dailynewstats")) {
                chart = getNewDailyStats(s);
            } else if (url.contains("birthyears")) {
                chart = getBirthyears(s);
            } else if (url.contains("listmemberships") || url.contains("chaptermemberships")) {
                chart = getListMemberships(s,
                        Integer.parseInt(url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.'))),
                        currentUser);
            }

            res.setContentType("image/png");

            OutputStream out = res.getOutputStream();

            if (url.contains("listmemberships")) {
                ChartUtilities.writeChartAsPNG(out, chart, 700, 500);
            } else {
                ChartUtilities.writeChartAsPNG(out, chart, 800, 600);
            }
        } catch (RedirectionException re) {
            log.info("Clean redirect: " + re.getTargetURL());
            res.sendRedirect(re.getTargetURL());
        } catch (Exception e) {
            log.error("graph servlet error", e);
            res.sendError(500, e.toString());
        }
    }

    private static Date getStartDate() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -14);
        return cal.getTime();
    }

    private JFreeChart getDailyIntegratedStats(Session s) throws CloneNotSupportedException {
        JFreeChart chart;
        List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
                s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
                        .setDate(0, new Date()).setDate(1, GraphServlet.getStartDate()))).list();
        TimeSeriesCollection theData = new TimeSeriesCollection();
        TimeSeriesCollection theData2 = new TimeSeriesCollection();

        TimeSeries users = new TimeSeries("Total Users", Day.class);
        theData.addSeries(users);

        TimeSeries regulars = new TimeSeries("Regular Members", Day.class);
        theData2.addSeries(regulars);

        int numUsers = Helpers.getGroup("Org").getNumMembers();
        int numReg = Helpers.getGroup("Regular").getNumMembers();

        for (DailyStatsModel ds : stats) {
            Day theDay = new Day(ds.getDay());
            users.add(theDay, numUsers);
            regulars.add(theDay, numReg);
            numUsers -= (ds.getMailinglistsignups() + ds.getSignups() - ds.getDeletions());
            numReg -= (ds.getRegupgrades() - ds.getRegdowngrades());
        }

        chart = ChartFactory.createTimeSeriesChart("Membership", "Day", "Users", theData, true, true, true);

        XYPlot plot = (XYPlot) chart.getPlot();

        NumberAxis axis2 = new NumberAxis("Regular Members");
        plot.setRangeAxis(1, axis2);
        plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_RIGHT);
        plot.setDataset(1, MovingAverage.createMovingAverage(theData2, "", 14, 0));
        plot.mapDatasetToRangeAxis(1, 1);

        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(0);
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        renderer = (XYLineAndShapeRenderer) renderer.clone();
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        plot.setRenderer(1, renderer);
        return chart;
    }

    private JFreeChart getBirthyears(Session s) {
        JFreeChart chart;
        XYSeriesCollection seriesCollection = new XYSeriesCollection();

        List logins = s
                .createQuery("select count(*), birth from UserModel where birth!=0 group by birth order by birth")
                .list();
        XYSeries theData = new XYSeries("Ages");
        seriesCollection.addSeries(theData);

        for (int i = 0; i < logins.size(); i++) {
            Object[] tuple = (Object[]) logins.get(i);
            theData.add(Calendar.getInstance().get(Calendar.YEAR) - (Integer) tuple[1], (Long) tuple[0]);
        }

        logins = s.createQuery(
                "select count(*), birth from UserModel where birth!=0 and gender='f' group by birth order by birth")
                .list();
        XYSeries theData2 = new XYSeries("Female");
        seriesCollection.addSeries(theData2);

        for (int i = 0; i < logins.size(); i++) {
            Object[] tuple = (Object[]) logins.get(i);
            theData2.add(Calendar.getInstance().get(Calendar.YEAR) - (Integer) tuple[1], (Long) tuple[0]);
        }

        logins = s.createQuery(
                "select count(*), birth from UserModel where birth!=0 and gender='m' group by birth order by birth")
                .list();
        XYSeries theData3 = new XYSeries("Male");
        seriesCollection.addSeries(theData3);

        for (int i = 0; i < logins.size(); i++) {
            Object[] tuple = (Object[]) logins.get(i);
            theData3.add(Calendar.getInstance().get(Calendar.YEAR) - (Integer) tuple[1], (Long) tuple[0]);
        }

        chart = ChartFactory.createXYLineChart("Age Distribution", "Age", "Number of Users", seriesCollection,
                PlotOrientation.VERTICAL, true, true, true);

        XYPlot plot = (XYPlot) chart.getPlot();
        plot.getDomainAxis().setUpperBound(80);
        plot.getDomainAxis().setLowerBound(15);

        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        return chart;
    }

    private JFreeChart getLogins(Session s) {
        JFreeChart chart;

        XYSeriesCollection seriesCollection = new XYSeriesCollection();
        XYSeries theData = new XYSeries("Logins");
        seriesCollection.addSeries(theData);
        List logins = s.createQuery(
                "select count(*), logins from UserModel where logins!=0 and logins<=100 group by logins order by logins desc")
                .list();
        Integer numLogins = ((Long) s.createQuery("select count(*) from UserModel where logins>100").uniqueResult())
                .intValue();

        for (int i = 0; i < logins.size(); i++) {
            Object[] tuple = (Object[]) logins.get(i);
            numLogins += ((Long) tuple[0]).intValue();
            theData.add((Integer) tuple[1], numLogins);
        }

        XYSeries theData3 = new XYSeries("Female");
        seriesCollection.addSeries(theData3);
        logins = s.createQuery(
                "select count(*), logins from UserModel where gender='f' and logins!=0 and logins<=100 group by logins order by logins desc")
                .list();
        numLogins = ((Long) s.createQuery("select count(*) from UserModel where gender='f' and logins>100")
                .uniqueResult()).intValue();

        for (int i = 0; i < logins.size(); i++) {
            Object[] tuple = (Object[]) logins.get(i);
            numLogins += ((Long) tuple[0]).intValue();
            theData3.add((Integer) tuple[1], numLogins);
        }

        XYSeries theData2 = new XYSeries("Male");
        seriesCollection.addSeries(theData2);
        logins = s.createQuery(
                "select count(*), logins from UserModel where gender='m' and logins!=0 and logins<=100 group by logins order by logins desc")
                .list();
        numLogins = ((Long) s.createQuery("select count(*) from UserModel where gender='m' and logins>100")
                .uniqueResult()).intValue();

        for (int i = 0; i < logins.size(); i++) {
            Object[] tuple = (Object[]) logins.get(i);
            numLogins += ((Long) tuple[0]).intValue();
            theData2.add((Integer) tuple[1], numLogins);
        }

        chart = ChartFactory.createXYLineChart("Logins Distribution", "Number of Logins", "Number of Users",
                seriesCollection, PlotOrientation.VERTICAL, true, true, true);

        XYPlot plot = (XYPlot) chart.getPlot();
        plot.getDomainAxis().setUpperBound(100);

        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        return chart;
    }

    private JFreeChart getLastLogin(Session s) throws CloneNotSupportedException {

        Integer numCurrentLogins = ((Long) s
                .createQuery("select count(*) from UserModel "
                        + "where currentLogin is not null and currentLogin >= :date")
                .setDate("date", getStartDate()).uniqueResult()).intValue();

        List currentStats = s
                .createSQLQuery("SELECT DATE(currentLogin) as date, count( * ) as lastLogins "
                        + "FROM users where currentLogin is not null  and currentLogin >= :date "
                        + "GROUP BY DATE( currentLogin )")
                .addScalar("date", Hibernate.DATE).addScalar("lastLogins", Hibernate.INTEGER)
                .setDate("date", getStartDate()).list();

        TimeSeriesCollection theData = new TimeSeriesCollection();
        TimeSeriesCollection theData2 = new TimeSeriesCollection();

        TimeSeries current = new TimeSeries("Num Latest Sign-ins", Day.class);
        theData.addSeries(current);
        TimeSeries current2 = new TimeSeries("Signed-in Users Since", Day.class);
        theData2.addSeries(current2);

        for (Object ds : currentStats) {
            Date date = (Date) ((Object[]) ds)[0];
            Day day = new Day(date);
            Integer integer = (Integer) ((Object[]) ds)[1];
            current.add(day, integer);
            numCurrentLogins -= integer.intValue();
            current2.add(day, numCurrentLogins);

        }

        JFreeChart chart = ChartFactory.createTimeSeriesChart("Sign-in Recency", "Day", "Sign-ins", theData, true,
                true, true);

        XYPlot plot = (XYPlot) chart.getPlot();

        NumberAxis axis2 = new NumberAxis("Users");
        plot.setRangeAxis(1, axis2);
        plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_RIGHT);
        plot.setDataset(1, theData2);
        plot.mapDatasetToRangeAxis(1, 1);

        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(0);
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        renderer.setSeriesStroke(1, new BasicStroke(2.0f));
        renderer = (XYLineAndShapeRenderer) renderer.clone();
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        renderer.setSeriesStroke(1, new BasicStroke(2.0f));
        plot.setRenderer(1, renderer);
        return chart;
    }

    private JFreeChart getDaily3Stats(Session s) {
        JFreeChart chart;
        List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
                s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
                        .setDate(0, new Date()).setDate(1, GraphServlet.getStartDate()))).list();
        TimeSeriesCollection theData = new TimeSeriesCollection();

        TimeSeries regUpgrades = new TimeSeries("Regular Upgrades", Day.class);
        theData.addSeries(regUpgrades);

        TimeSeries renewals = new TimeSeries("Regular Renewals", Day.class);
        theData.addSeries(renewals);

        TimeSeries regDowngrades = new TimeSeries("Regular Downgrades", Day.class);
        theData.addSeries(regDowngrades);

        for (DailyStatsModel ds : stats) {
            Day theDay = new Day(ds.getDay());
            regUpgrades.add(theDay, ds.getRegupgrades());
            renewals.add(theDay, ds.getRenewals());
            regDowngrades.add(theDay, ds.getRegdowngrades());
        }

        chart = ChartFactory.createTimeSeriesChart("Regular membership changes (14-day moving avg)", "Day",
                "Occurrences", MovingAverage.createMovingAverage(theData, "", 14, 0), true, true, true);

        XYPlot plot = (XYPlot) chart.getPlot();
        plot.getRangeAxis().setUpperBound(10);

        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        renderer.setSeriesStroke(1, new BasicStroke(2.0f));
        renderer.setSeriesStroke(2, new BasicStroke(2.0f));
        return chart;
    }

    private JFreeChart getDaily2Stats(Session s) {
        JFreeChart chart;
        List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
                s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
                        .setDate(0, new Date()).setDate(1, GraphServlet.getStartDate()))).list();
        TimeSeriesCollection theData = new TimeSeriesCollection();

        TimeSeries signups = new TimeSeries("signups", Day.class);
        theData.addSeries(signups);

        TimeSeries mlSignups = new TimeSeries("Mailing list signups", Day.class);
        theData.addSeries(mlSignups);

        TimeSeries mlUpgrades = new TimeSeries("Mailing list upgrades", Day.class);
        theData.addSeries(mlUpgrades);

        TimeSeries deletions = new TimeSeries("Deletions", Day.class);
        theData.addSeries(deletions);

        for (DailyStatsModel ds : stats) {
            Day theDay = new Day(ds.getDay());
            signups.add(theDay, ds.getSignups());
            deletions.add(theDay, ds.getDeletions());
            mlSignups.add(theDay, ds.getMailinglistsignups());
            mlUpgrades.add(theDay, ds.getMailinglistupgrades());
        }

        chart = ChartFactory.createTimeSeriesChart("Account changes (14-day moving avg)", "Day", "Occurrences",
                MovingAverage.createMovingAverage(theData, "", 14, 0), true, true, true);

        XYPlot plot = (XYPlot) chart.getPlot();
        plot.getRangeAxis().setUpperBound(25);

        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        renderer.setSeriesStroke(1, new BasicStroke(2.0f));
        renderer.setSeriesStroke(2, new BasicStroke(2.0f));
        renderer.setSeriesStroke(3, new BasicStroke(2.0f));
        return chart;
    }

    private JFreeChart getDailyStats(Session s) {
        JFreeChart chart;
        List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
                s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
                        .setDate(0, new Date()).setDate(1, GraphServlet.getStartDate()))).list();
        TimeSeriesCollection theData = new TimeSeriesCollection();

        TimeSeries signins = new TimeSeries("Raw Signins", Day.class);
        TimeSeries posts = new TimeSeries("Posts", Day.class);
        TimeSeries replies = new TimeSeries("Replies", Day.class);
        TimeSeries whiteboards = new TimeSeries("Whiteboards", Day.class);
        TimeSeries files = new TimeSeries("Files", Day.class);

        for (DailyStatsModel ds : stats) {
            Day theDay = new Day(ds.getDay());
            signins.add(theDay, ds.getSignins());
            posts.add(theDay, ds.getPosts());
            replies.add(theDay, ds.getReplies());
            whiteboards.add(theDay, ds.getWhiteboardEdits());
            files.add(theDay, ds.getFilesadded());
        }

        String title = "Usage (14-day moving avg)";
        theData.addSeries(MovingAverage.createMovingAverage(signins, "Signins", 14, 0));
        theData.addSeries(MovingAverage.createMovingAverage(posts, "Posts", 14, 0));
        theData.addSeries(MovingAverage.createMovingAverage(replies, "Replies", 14, 0));
        theData.addSeries(signins);
        theData.addSeries(MovingAverage.createMovingAverage(whiteboards, "Whiteboard Edits", 14, 0));
        theData.addSeries(MovingAverage.createMovingAverage(files, "Files Uploaded", 14, 0));

        chart = ChartFactory.createTimeSeriesChart(title, "Day", "Occurrences", theData, true, true, true);

        XYPlot plot = (XYPlot) chart.getPlot();
        plot.getRangeAxis().setUpperBound(400);
        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        renderer.setSeriesStroke(1, new BasicStroke(2.0f));
        renderer.setSeriesStroke(2, new BasicStroke(2.0f));
        renderer.setSeriesStroke(3, new BasicStroke(2.0f));
        renderer.setSeriesStroke(4, new BasicStroke(2.0f));
        renderer.setSeriesStroke(5, new BasicStroke(2.0f));
        return chart;
    }

    private JFreeChart getNewDailyStats(Session s) {
        JFreeChart chart;
        List<DailyStatsModel> stats = (new SafeHibList<DailyStatsModel>(
                s.createQuery("select ds from DailyStatsModel as ds where day<? and day>=? order by day desc")
                        .setDate(0, new Date()).setDate(1, GraphServlet.getStartDate()))).list();
        TimeSeriesCollection theData = new TimeSeriesCollection();

        TimeSeries events = new TimeSeries("Events Created", Day.class);
        TimeSeries mailings = new TimeSeries("Event Mailings", Day.class);

        for (DailyStatsModel ds : stats) {
            Day theDay = new Day(ds.getDay());
            events.add(theDay, ds.getEvents());
            mailings.add(theDay, ds.getEventMailings());
        }

        String title = "Usage";
        theData.addSeries(MovingAverage.createMovingAverage(events, "Events Created", 14, 0));
        theData.addSeries(MovingAverage.createMovingAverage(mailings, "Event Mailings", 14, 0));

        chart = ChartFactory.createTimeSeriesChart(title, "Day", "Occurrences", theData, true, true, true);

        XYPlot plot = (XYPlot) chart.getPlot();
        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        renderer.setSeriesStroke(1, new BasicStroke(2.0f));
        return chart;
    }

    private JFreeChart getProvincePie(Session s) {
        JFreeChart chart;
        String[] provinces = { "PE", "YT", "NT", "NU", "ON", "QC", "AB", "BC", "NL", "MB", "NB", "NS", "SK" };
        DefaultPieDataset ds = new DefaultPieDataset();
        String query = "select count(*) from UserModel as u where u.province=?";

        int total = 0;
        for (String province : provinces) {
            Integer integer = ((Long) s.createQuery(query).setString(0, province).list().get(0)).intValue();
            total += integer;
            ds.setValue(province, integer);
        }

        chart = ChartFactory.createPieChart("Province Breakdown (for " + total + " known addresses)", ds, false,
                false, false);

        PiePlot plot = ((PiePlot) chart.getPlot());
        StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
                new DecimalFormat("0"), new DecimalFormat("0.0%"));
        plot.setLabelGenerator(n);
        return chart;
    }

    private JFreeChart getPostPie(Session s) {
        JFreeChart chart;
        DefaultPieDataset ds = new DefaultPieDataset();

        int numPosts = 0;
        int numTypePosts = 0;

        String query;

        query = "select count(*) from PostModel as p where p.poster.gender='m' and p.emailed=true and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ;
        ds.setValue("Emails by Males", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.poster.gender='m' and "
                + "p.parent is null and p.emailed=false and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ;
        ds.setValue("Posts by Males", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.poster.gender='m' and "
                + "p.parent is not null and p.emailed=false and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ;
        ds.setValue("Replies by Males", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.poster.gender!='f' and p.poster.gender!='m' and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ;
        ds.setValue("All Posts by Unknown Gender", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.poster.gender='f' and "
                + "p.parent is not null and p.emailed=false and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ;
        ds.setValue("Replies by Females", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.poster.gender='f' and "
                + "p.parent is null and p.emailed=false and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ;
        ds.setValue("Posts by Females", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.poster.gender='f' and p.emailed=true and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ;
        ds.setValue("Emails by Females", numTypePosts);
        numPosts += numTypePosts;

        chart = ChartFactory.createPieChart("Post Type/Author Gender Breakdown (for " + numPosts + " posts)", ds,
                false, false, false);

        PiePlot plot = ((PiePlot) chart.getPlot());
        StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
                new DecimalFormat("0"), new DecimalFormat("0.0%"));
        plot.setLabelGenerator(n);
        return chart;
    }

    private JFreeChart getPost2Pie(Session s) {
        JFreeChart chart;
        DefaultPieDataset ds = new DefaultPieDataset();

        int numPosts = 0;
        int numTypePosts = 0;

        String query = "select count(*) from PostModel as p where p.group.id=1 and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ds.setValue("Org List", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.group.admin=false and p.group.postName not like 'anyone in the%' and "
                + "p.group.public=true and p.group.parent is null and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ds.setValue("General Public Lists", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.group.admin=false and "
                + "p.group.public=false and p.group.parent is null and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ds.setValue("General Private Lists", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.group.admin=true and p.group.visible=true"
                + " and p.group.id != 1 and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ds.setValue("All-exec Lists", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.group.id = 14 and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ds.setValue("Deleted Posts", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.group.postName like 'anyone in the%' and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ds.setValue("Chapter Lists", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.group.parent!=null and "
                + "p.group.shortname='exec' and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ds.setValue("Chapter-exec Lists", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.group.parent!=null and "
                + "p.group.shortname!='exec' and p.group.public=true and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ds.setValue("Chapter Public Lists", numTypePosts);
        numPosts += numTypePosts;

        query = "select count(*) from PostModel as p where p.group.parent!=null and "
                + "p.group.shortname!='exec' and p.group.public=false and p.date>?";
        numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate()).list().get(0))
                .intValue();
        ds.setValue("Chapter Private Lists", numTypePosts);
        numPosts += numTypePosts;

        chart = ChartFactory.createPieChart("Post Group Breakdown (for " + numPosts + " posts)", ds, false, false,
                false);

        PiePlot plot = ((PiePlot) chart.getPlot());
        StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
                new DecimalFormat("0"), new DecimalFormat("0.0%"));
        plot.setLabelGenerator(n);
        return chart;
    }

    private JFreeChart getPost3Pie(Session s) {
        DefaultKeyedValues data = new DefaultKeyedValues();

        int numPosts = 0;
        int numTypePosts = 0;
        String query = "select count(*) from PostModel as p where p.date > ? and "
                + "(p.group=? or p.group.parent=?)";

        for (GroupChapterModel chapter : GroupChapterModel.getChapters()) {
            numTypePosts = ((Long) s.createQuery(query).setDate(0, GraphServlet.getStartDate())
                    .setEntity(1, chapter).setEntity(2, chapter).list().get(0)).intValue();
            numPosts += numTypePosts;
            data.addValue(chapter.getShortname(), numTypePosts);
        }

        return getChapterPareto(data, "Posts by Chapter (for " + numPosts + " posts)", "Posts", "Number of Posts");

    }

    private JFreeChart getChapterPie(Session s) {
        DefaultKeyedValues data = new DefaultKeyedValues();

        for (GroupChapterModel chapter : GroupChapterModel.getChapters()) {
            data.addValue(chapter.getShortname(), chapter.getNumMembers());
        }

        return getChapterPareto(data, "Chapter Membership Breakdown By Chapter", "Membership", "Number of Members");
    }

    private JFreeChart getChapterPareto(DefaultKeyedValues data, String title, String quantity, String range) {

        JFreeChart chart;

        data.sortByValues(SortOrder.DESCENDING);
        KeyedValues cummulative = DataUtilities.getCumulativePercentages(data);
        CategoryDataset dataset = DatasetUtilities.createCategoryDataset(quantity, data);

        // create the chart...
        chart = ChartFactory.createBarChart(title, // chart title
                "Chapter", // domain axis label
                range, // range axis label
                dataset, // data
                PlotOrientation.VERTICAL, true, // include legend
                true, false);

        CategoryPlot plot = chart.getCategoryPlot();

        CategoryAxis domainAxis = plot.getDomainAxis();
        domainAxis.setLowerMargin(0.02);
        domainAxis.setUpperMargin(0.02);
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);

        // set the range axis to display integers only...
        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        LineAndShapeRenderer renderer2 = new LineAndShapeRenderer();

        CategoryDataset dataset2 = DatasetUtilities.createCategoryDataset("Cummulative", cummulative);
        NumberAxis axis2 = new NumberAxis("Percent");
        axis2.setNumberFormatOverride(NumberFormat.getPercentInstance());
        axis2.setUpperBound(1);
        axis2.setLowerBound(0);
        plot.setRangeAxis(1, axis2);
        plot.setDataset(1, dataset2);
        plot.setRenderer(1, renderer2);
        plot.mapDatasetToRangeAxis(1, 1);
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);

        return chart;
    }

    private JFreeChart getNoChapterPie() {
        JFreeChart chart;
        DefaultPieDataset ds = new DefaultPieDataset();

        Integer numChapter = Helpers.getGroup("Chapter").getNumMembers();
        ds.setValue("in a chapter", numChapter);

        ds.setValue("not in a chapter", Helpers.getGroup("Org").getNumMembers() - numChapter);

        chart = ChartFactory.createPieChart("Chapter Membership Breakdown", ds, false, false, false);

        PiePlot plot = ((PiePlot) chart.getPlot());
        StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
                new DecimalFormat("0"), new DecimalFormat("0.0%"));
        plot.setLabelGenerator(n);
        return chart;
    }

    private JFreeChart getRankPie() {
        JFreeChart chart;
        DefaultPieDataset ds = new DefaultPieDataset();

        int numRegular = Helpers.getGroup("Regular").getNumMembers();
        int numAssociate = Helpers.getGroup("Associate").getNumMembers();
        int numUsers = Helpers.getGroup("Org").getNumMembers();

        ds.setValue("Regular Members", numRegular);
        ds.setValue("Associate Members", numAssociate);
        ds.setValue("Mailing list Members", numUsers - numAssociate - numRegular);

        chart = ChartFactory.createPieChart("Status breakdown for " + numUsers + " members", ds, false, false,
                false);

        PiePlot plot = ((PiePlot) chart.getPlot());
        StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
                new DecimalFormat("0"), new DecimalFormat("0.0%"));
        plot.setLabelGenerator(n);
        return chart;
    }

    private JFreeChart getChapterRankPie(Session s, String url) {
        String[] path = url.split("/");
        String lastPiece = path[path.length - 1];
        Integer chapterId = new Integer(lastPiece.substring(0, lastPiece.length() - 4));
        GroupChapterModel chapter = (GroupChapterModel) s.get(GroupChapterModel.class, chapterId);

        JFreeChart chart;
        DefaultPieDataset ds = new DefaultPieDataset();

        String query = "select count(*) as num from roles r1, roles r2 "
                + "where r1.userid=r2.userid and r1.groupid=? and r1.level='m' and r2.level='m' "
                + "and r1.end is null and r2.end is null and r2.groupid=?";
        int numRegular = ((Integer) s.createSQLQuery(query).addScalar("num", Hibernate.INTEGER)
                .setInteger(0, chapter.getId()).setInteger(1, Helpers.getGroup("Regular").getId()).list().get(0))
                        .intValue();

        int numAssociate = ((Integer) s.createSQLQuery(query).addScalar("num", Hibernate.INTEGER)
                .setInteger(0, chapter.getId()).setInteger(1, Helpers.getGroup("Associate").getId()).list().get(0))
                        .intValue();
        int numUsers = chapter.getNumMembers();

        ds.setValue("Regular Members", numRegular);
        ds.setValue("Associate Members", numAssociate);
        ds.setValue("Mailing list Members", numUsers - numAssociate - numRegular);

        chart = ChartFactory.createPieChart("Status breakdown for " + numUsers + " chapter members", ds, false,
                false, false);

        PiePlot plot = ((PiePlot) chart.getPlot());
        StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
                new DecimalFormat("0"), new DecimalFormat("0.0%"));
        plot.setLabelGenerator(n);
        return chart;
    }

    private JFreeChart getStudentPie(Session s) {
        JFreeChart chart;
        DefaultPieDataset ds = new DefaultPieDataset();

        String query = "select count(*) from UserModel as u where u.student='y'";
        int numStudent = ((Long) s.createQuery(query).list().get(0)).intValue();

        query = "select count(*) from UserModel as u where u.student='n'";

        int numNonStudent = ((Long) s.createQuery(query).list().get(0)).intValue();

        int numRegular = Helpers.getGroup("Regular").getNumMembers();
        int numAssociate = Helpers.getGroup("Associate").getNumMembers();

        ds.setValue("Student users", numStudent);
        ds.setValue("Unspecified", numAssociate + numRegular - numStudent - numNonStudent);
        ds.setValue("Non-Student users", numNonStudent);

        chart = ChartFactory.createPieChart("Student Status Breakdown for Associate/Regular members", ds, false,
                false, false);

        PiePlot plot = ((PiePlot) chart.getPlot());
        StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
                new DecimalFormat("0"), new DecimalFormat("0.0%"));
        plot.setLabelGenerator(n);
        return chart;
    }

    private JFreeChart getLanguagePie(Session s) {
        JFreeChart chart;
        DefaultPieDataset ds = new DefaultPieDataset();

        String query = "select count(*) from UserModel as u where u.language='en'";
        int numEn = ((Long) s.createQuery(query).list().get(0)).intValue();

        query = "select count(*) from UserModel as u where u.language='fr'";
        int numFr = ((Long) s.createQuery(query).list().get(0)).intValue();

        int numRegular = Helpers.getGroup("Regular").getNumMembers();
        int numAssociate = Helpers.getGroup("Associate").getNumMembers();
        ds.setValue("English", numEn);
        ds.setValue("Unspecified", numAssociate + numRegular - numEn - numFr);
        ds.setValue("French", numFr);

        chart = ChartFactory.createPieChart("Preferred Language Breakdown for Associate/Regular members", ds, false,
                false, false);

        PiePlot plot = ((PiePlot) chart.getPlot());
        StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
                new DecimalFormat("0"), new DecimalFormat("0.0%"));
        plot.setLabelGenerator(n);
        return chart;
    }

    private JFreeChart getGenderPie(Session s) {
        JFreeChart chart;
        DefaultPieDataset ds = new DefaultPieDataset();

        String query = "select count(*) from UserModel as u where u.gender='f'";
        int numFemale = ((Long) s.createQuery(query).list().get(0)).intValue();

        query = "select count(*) from UserModel as u where u.gender='m'";

        int numMale = ((Long) s.createQuery(query).list().get(0)).intValue();

        int numRegular = Helpers.getGroup("Regular").getNumMembers();
        int numAssociate = Helpers.getGroup("Associate").getNumMembers();
        ds.setValue("Female users", numFemale);
        ds.setValue("Unspecified", numAssociate + numRegular - numFemale - numMale);
        ds.setValue("Male users", numMale);

        chart = ChartFactory.createPieChart("Gender Breakdown for Associate/Regular members", ds, false, false,
                false);

        PiePlot plot = ((PiePlot) chart.getPlot());
        StandardPieItemLabelGenerator n = new StandardPieItemLabelGenerator("{0} = {1} ({2})",
                new DecimalFormat("0"), new DecimalFormat("0.0%"));
        plot.setLabelGenerator(n);
        return chart;
    }

    private JFreeChart getListMemberships(Session s, int groupId, UserModel currentUser) {
        final int NUM_MONTHS = 6;
        Logger log = Logger.getLogger(this.getClass());
        JFreeChart chart;
        Date startDate;
        TreeMap<Day, Integer> memberChange = new TreeMap<Day, Integer>();
        GroupModel g = (GroupModel) s.get(GroupModel.class, groupId);

        if (g == null) {
            log.warn("Someone requested chapter stats with a bad group id");
        } else if (!Permissions.canAdministerGroupMembership(currentUser, g)) {
            log.warn(currentUser.getUsername() + "tried to access list memberships graph!");
        }

        Calendar cal = GregorianCalendar.getInstance();
        Date now = cal.getTime();
        cal.set(Calendar.HOUR, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 1);
        cal.add(Calendar.MONTH, -NUM_MONTHS);
        startDate = cal.getTime();

        //Set Initial Number of Members      
        int initMembers = g.getNumMembers() + g.getNumRecipients();

        //Pull a list of all of the membership start dates
        List starts = s.createQuery("SELECT rm.start, count(*) " + "FROM RoleModel as rm "
                + "WHERE rm.group = :group " + "AND (rm.level = 'r' OR rm.level = 'm') "
                + "AND rm.start > :startDate " + "GROUP BY rm.start ").setEntity("group", g)
                .setDate("startDate", startDate).list();

        for (Object o : starts) {
            Day date = new Day((Date) (((Object[]) o)[0]));
            int change = ((Long) (((Object[]) o)[1])).intValue();
            memberChange.put(date, change);
            initMembers -= change;
        }

        //Pull a list of all of the membership end dates
        List ends = s.createQuery("SELECT rm.end, count(*) " + "FROM RoleModel as rm " + "WHERE rm.group = :group "
                + "AND (rm.level = 'r' OR rm.level = 'm') " + "AND rm.end > :startDate " + "GROUP BY rm.end ")
                .setEntity("group", g).setDate("startDate", startDate).list();

        for (Object o : ends) {
            Day date = new Day((Date) (((Object[]) o)[0]));
            int change = ((Long) (((Object[]) o)[1])).intValue();
            if (memberChange.containsKey(date)) {
                memberChange.put(date, memberChange.get(date) - change);
            } else {
                memberChange.put(date, -change);
            }
            initMembers += change;
        }

        TimeSeriesCollection theData = new TimeSeriesCollection();

        TimeSeries signups = new TimeSeries("List Membership", Day.class);
        theData.addSeries(signups);
        while (startDate.before(now)) {
            Day d = new Day(startDate);
            if (memberChange.containsKey(d)) {
                initMembers += memberChange.get(d);
            }
            signups.add(d, initMembers);
            cal.add(Calendar.DATE, 1);
            startDate = cal.getTime();
        }

        chart = ChartFactory.createTimeSeriesChart("List Members", "Day", "Number of Members", theData, true, true,
                true);

        XYPlot plot = (XYPlot) chart.getPlot();

        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        return chart;
    }

}