Java tutorial
/** * $URL$ * $Id$ * * Copyright (c) 2006-2009 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sakaiproject.sitestats.impl.chart; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import javax.imageio.ImageIO; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.PeriodAxis; import org.jfree.chart.axis.PeriodAxisLabelInfo; import org.jfree.chart.labels.StandardCategoryItemLabelGenerator; import org.jfree.chart.labels.XYItemLabelGenerator; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PiePlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.category.BarRenderer; import org.jfree.chart.renderer.category.LineAndShapeRenderer; import org.jfree.chart.renderer.xy.AbstractXYItemRenderer; import org.jfree.chart.renderer.xy.ClusteredXYBarRenderer; import org.jfree.chart.renderer.xy.XYBarRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.UnknownKeyException; import org.jfree.data.category.CategoryDataset; import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.data.general.AbstractDataset; import org.jfree.data.general.DefaultPieDataset; import org.jfree.data.general.PieDataset; import org.jfree.data.time.RegularTimePeriod; import org.jfree.data.time.TimePeriodAnchor; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; import org.jfree.data.xy.IntervalXYDataset; import org.jfree.data.xy.XYDataset; import org.jfree.ui.RectangleInsets; import org.jfree.util.SortOrder; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.site.api.SiteService; import org.sakaiproject.sitestats.api.EventStat; import org.sakaiproject.sitestats.api.LessonBuilderStat; import org.sakaiproject.sitestats.api.ResourceStat; import org.sakaiproject.sitestats.api.SiteActivityByTool; import org.sakaiproject.sitestats.api.SitePresence; import org.sakaiproject.sitestats.api.SiteVisits; import org.sakaiproject.sitestats.api.Stat; import org.sakaiproject.sitestats.api.StatsManager; import org.sakaiproject.sitestats.api.SummaryActivityChartData; import org.sakaiproject.sitestats.api.SummaryVisitsChartData; import org.sakaiproject.sitestats.api.Util; import org.sakaiproject.sitestats.api.chart.ChartService; import org.sakaiproject.sitestats.api.event.EventRegistryService; import org.sakaiproject.sitestats.api.report.Report; import org.sakaiproject.sitestats.api.report.ReportManager; import org.sakaiproject.sitestats.impl.event.EventRegistryServiceImpl; import org.sakaiproject.user.api.PreferencesService; import org.sakaiproject.user.api.UserDirectoryService; import org.sakaiproject.user.api.UserNotDefinedException; import org.sakaiproject.util.ResourceLoader; public class ChartServiceImpl implements ChartService { /** Static fields */ private static Log LOG = LogFactory.getLog(EventRegistryServiceImpl.class); private static ResourceLoader msgs = new ResourceLoader("Messages"); private static final int MIN_CHART_WIDTH_TO_DRAW_ALL_DAYS = 640; /** Utility */ private Map<Integer, String> weekDaysMap = null; private Map<Integer, String> monthNamesMap = null; /** Sakai services */ private StatsManager M_sm; private SiteService M_ss; private UserDirectoryService M_uds; private PreferencesService M_ps; private EventRegistryService M_ers; // ################################################################ // Spring methods // ################################################################ public void setStatsManager(StatsManager statsManager) { this.M_sm = statsManager; } public void setSiteService(SiteService siteService) { this.M_ss = siteService; } public void setUserService(UserDirectoryService userDirectoryService) { this.M_uds = userDirectoryService; } public void setPreferencesService(PreferencesService preferencesService) { this.M_ps = preferencesService; } public void setEventRegistryService(EventRegistryService eventRegistryService) { this.M_ers = eventRegistryService; } // ################################################################ // Chart Service methods // ################################################################ /* (non-Javadoc) * @see org.sakaiproject.sitestats.api.chart.ChartService#generateVisitsChart(java.lang.String, java.lang.String, int, int, boolean, float, boolean) */ public byte[] generateVisitsChart(String siteId, String viewType, int width, int height, boolean render3d, float transparency, boolean itemLabelsVisible) { CategoryDataset dataset = null; boolean smallFontInDomainAxis = false; render3d = false; if (StatsManager.VIEW_WEEK.equals(viewType)) { dataset = getVisitsWeekDataSet(siteId); } else if (StatsManager.VIEW_MONTH.equals(viewType)) { dataset = getVisitsMonthDataSet(siteId, width); smallFontInDomainAxis = true; } else { dataset = getVisitsYearDataSet(siteId); } if (dataset != null) return generateBarChart(siteId, dataset, width, height, render3d, transparency, itemLabelsVisible, smallFontInDomainAxis); else return generateNoDataChart(width, height); } /* (non-Javadoc) * @see org.sakaiproject.sitestats.api.chart.ChartService#generateActivityChart(java.lang.String, java.lang.String, java.lang.String, int, int, boolean, float, boolean) */ public byte[] generateActivityChart(String siteId, String viewType, String chartType, int width, int height, boolean render3d, float transparency, boolean itemLabelsVisible) { boolean smallFontInDomainAxis = false; render3d = false; if (StatsManager.CHARTTYPE_PIE.equals(chartType)) { DefaultPieDataset dataset = null; if (StatsManager.VIEW_WEEK.equals(viewType)) dataset = getActivityWeekPieDataSet(siteId); else if (StatsManager.VIEW_MONTH.equals(viewType)) dataset = getActivityMonthPieDataSet(siteId); else dataset = getActivityYearPieDataSet(siteId); if (dataset != null) return generatePieChart(siteId, dataset, width, height, render3d, transparency, smallFontInDomainAxis); else return generateNoDataChart(width, height); } else { CategoryDataset dataset = null; if (StatsManager.VIEW_WEEK.equals(viewType)) dataset = getActivityWeekBarDataSet(siteId); else if (StatsManager.VIEW_MONTH.equals(viewType)) { dataset = getActivityMonthBarDataSet(siteId, width); smallFontInDomainAxis = true; } else dataset = getActivityYearBarDataSet(siteId); if (dataset != null) return generateBarChart(siteId, dataset, width, height, render3d, transparency, itemLabelsVisible, smallFontInDomainAxis); else return generateNoDataChart(width, height); } } /* (non-Javadoc) * @see org.sakaiproject.sitestats.api.chart.ChartService#generateChart(java.lang.String, java.lang.Object, java.lang.String, int, int, boolean, float, boolean, java.lang.String) */ public byte[] generateChart(String siteId, Object dataset, String chartType, int width, int height, boolean render3d, float transparency, boolean itemLabelsVisible, String timePeriod) { render3d = false; if (StatsManager.CHARTTYPE_BAR.equals(chartType)) { if (dataset instanceof CategoryDataset) { CategoryDataset ds = (CategoryDataset) dataset; return generateBarChart(siteId, ds, width, height, render3d, transparency, itemLabelsVisible, false); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing CategoryDataset are supported."); } } else if (StatsManager.CHARTTYPE_LINE.equals(chartType)) { if (dataset instanceof CategoryDataset) { CategoryDataset ds = (CategoryDataset) dataset; return generateLineChart(siteId, ds, width, height, render3d, transparency, itemLabelsVisible, false); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing CategoryDataset are supported."); } } else if (StatsManager.CHARTTYPE_PIE.equals(chartType)) { if (dataset instanceof PieDataset) { PieDataset ds = (PieDataset) dataset; return generatePieChart(siteId, ds, width, height, render3d, transparency, false); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing PieDataset are supported."); } } else if (StatsManager.CHARTTYPE_TIMESERIES.equals(chartType)) { if (dataset instanceof IntervalXYDataset) { IntervalXYDataset ds = (IntervalXYDataset) dataset; return generateTimeSeriesChart(siteId, ds, width, height, false, transparency, itemLabelsVisible, false, timePeriod); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing XYDataset are supported."); } } else if (StatsManager.CHARTTYPE_TIMESERIESBAR.equals(chartType)) { if (dataset instanceof IntervalXYDataset) { IntervalXYDataset ds = (IntervalXYDataset) dataset; return generateTimeSeriesChart(siteId, ds, width, height, true, transparency, itemLabelsVisible, false, timePeriod); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing XYDataset are supported."); } } LOG.warn("Chart type " + chartType + " not supported: only line, bar, pie, timeseries are supported."); return null; } /* (non-Javadoc) * @see org.sakaiproject.sitestats.api.chart.ChartService#generateChart(org.sakaiproject.sitestats.api.report.ReportDef, int, int, boolean, float, boolean) */ public byte[] generateChart(Report report, int width, int height, boolean render3d, float transparency, boolean itemLabelsVisible) { // Data set AbstractDataset dataset = null; String chartType = report.getReportDefinition().getReportParams().getHowChartType(); render3d = false; if (StatsManager.CHARTTYPE_BAR.equals(chartType) || StatsManager.CHARTTYPE_LINE.equals(chartType)) { dataset = getCategoryDataset(report); } else if (StatsManager.CHARTTYPE_TIMESERIES.equals(chartType) || StatsManager.CHARTTYPE_TIMESERIESBAR.equals(chartType)) { dataset = getTimeSeriesCollectionDataset(report); } else if (StatsManager.CHARTTYPE_PIE.equals(chartType)) { dataset = getPieDataset(report); } // Report if (dataset != null) { /*return generateChart( report.getReportDefinition().getReportParams().getSiteId(), dataset, chartType, width, height, render3d, transparency, true, report.getReportDefinition().getReportParams().getHowChartSeriesPeriod() );*/ String siteId = report.getReportDefinition().getReportParams().getSiteId(); String timePeriod = report.getReportDefinition().getReportParams().getHowChartSeriesPeriod(); Date firstDate = report.getReportDefinition().getReportParams().getWhenFrom(); Date lastDate = report.getReportDefinition().getReportParams().getWhenTo(); if (StatsManager.CHARTTYPE_BAR.equals(chartType)) { if (dataset instanceof CategoryDataset) { CategoryDataset ds = (CategoryDataset) dataset; return generateBarChart(siteId, ds, width, height, render3d, transparency, itemLabelsVisible, false); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing CategoryDataset are supported."); } } else if (StatsManager.CHARTTYPE_LINE.equals(chartType)) { if (dataset instanceof CategoryDataset) { CategoryDataset ds = (CategoryDataset) dataset; return generateLineChart(siteId, ds, width, height, render3d, transparency, itemLabelsVisible, false); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing CategoryDataset are supported."); } } else if (StatsManager.CHARTTYPE_PIE.equals(chartType)) { if (dataset instanceof PieDataset) { PieDataset ds = (PieDataset) dataset; return generatePieChart(siteId, ds, width, height, render3d, transparency, false); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing PieDataset are supported."); } } else if (StatsManager.CHARTTYPE_TIMESERIES.equals(chartType)) { if (dataset instanceof IntervalXYDataset) { IntervalXYDataset ds = (IntervalXYDataset) dataset; return generateTimeSeriesChart(siteId, ds, width, height, false, transparency, itemLabelsVisible, false, timePeriod, firstDate, lastDate); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing XYDataset are supported."); } } else if (StatsManager.CHARTTYPE_TIMESERIESBAR.equals(chartType)) { if (dataset instanceof IntervalXYDataset) { IntervalXYDataset ds = (IntervalXYDataset) dataset; return generateTimeSeriesChart(siteId, ds, width, height, true, transparency, itemLabelsVisible, false, timePeriod, firstDate, lastDate); } else { LOG.warn("Dataset not supported for " + chartType + " chart type: only classes implementing XYDataset are supported."); } } LOG.warn("Chart type " + chartType + " not supported: only line, bar, pie, timeseries are supported."); return null; } else { LOG.warn("Chart type " + chartType + " not supported: only line, bar, pie, timeseries are supported."); return null; } } // ###################################################################################### // Chart Generation methods // ###################################################################################### private byte[] generateBarChart(String siteId, CategoryDataset dataset, int width, int height, boolean render3d, float transparency, boolean itemLabelsVisible, boolean smallFontInDomainAxis) { JFreeChart chart = null; if (render3d) chart = ChartFactory.createBarChart3D(null, null, null, dataset, PlotOrientation.VERTICAL, true, false, false); else chart = ChartFactory.createBarChart(null, null, null, dataset, PlotOrientation.VERTICAL, true, false, false); CategoryPlot plot = (CategoryPlot) chart.getPlot(); // set transparency plot.setForegroundAlpha(transparency); // set background chart.setBackgroundPaint(parseColor(M_sm.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // allow longer legends (prevent truncation) plot.getDomainAxis().setMaximumCategoryLabelLines(50); plot.getDomainAxis().setMaximumCategoryLabelWidthRatio(1.0f); // set antialias chart.setAntiAlias(true); // set domain axis font size if (smallFontInDomainAxis && !canUseNormalFontSize(width)) { plot.getDomainAxis().setTickLabelFont(new Font("SansSerif", Font.PLAIN, 8)); plot.getDomainAxis().setCategoryMargin(0.05); } // set bar outline BarRenderer barrenderer = (BarRenderer) plot.getRenderer(); barrenderer.setDrawBarOutline(true); if (smallFontInDomainAxis && !canUseNormalFontSize(width)) barrenderer.setItemMargin(0.05); else barrenderer.setItemMargin(0.10); // item labels if (itemLabelsVisible) { plot.getRangeAxis().setUpperMargin(0.2); barrenderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator() { private static final long serialVersionUID = 1L; @Override public String generateLabel(CategoryDataset dataset, int row, int column) { Number n = dataset.getValue(row, column); if (n.doubleValue() != 0) { if ((double) n.intValue() == n.doubleValue()) return Integer.toString(n.intValue()); else return Double.toString(Util.round(n.doubleValue(), 1)); } return ""; } }); barrenderer.setItemLabelFont(new Font("SansSerif", Font.PLAIN, 8)); barrenderer.setItemLabelsVisible(true); } BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { LOG.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] generateLineChart(String siteId, CategoryDataset dataset, int width, int height, boolean render3d, float transparency, boolean itemLabelsVisible, boolean smallFontInDomainAxis) { JFreeChart chart = null; if (render3d) chart = ChartFactory.createLineChart3D(null, null, null, dataset, PlotOrientation.VERTICAL, true, false, false); else chart = ChartFactory.createLineChart(null, null, null, dataset, PlotOrientation.VERTICAL, true, false, false); CategoryPlot plot = (CategoryPlot) chart.getPlot(); // set transparency plot.setForegroundAlpha(transparency); // set background chart.setBackgroundPaint(parseColor(M_sm.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set antialias chart.setAntiAlias(true); // set domain axis font size if (smallFontInDomainAxis && !canUseNormalFontSize(width)) { plot.getDomainAxis().setTickLabelFont(new Font("SansSerif", Font.PLAIN, 8)); plot.getDomainAxis().setCategoryMargin(0.05); } // set outline LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer(); renderer.setDrawOutlines(true); // item labels if (itemLabelsVisible) { plot.getRangeAxis().setUpperMargin(0.2); renderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator() { private static final long serialVersionUID = 1L; @Override public String generateLabel(CategoryDataset dataset, int row, int column) { Number n = dataset.getValue(row, column); if (n.intValue() != 0) //return n.intValue()+""; return n.toString(); return ""; } }); renderer.setItemLabelFont(new Font("SansSerif", Font.PLAIN, 8)); renderer.setItemLabelsVisible(true); } BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { LOG.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] generatePieChart(String siteId, PieDataset dataset, int width, int height, boolean render3d, float transparency, boolean smallFontInDomainAxis) { JFreeChart chart = null; if (render3d) chart = ChartFactory.createPieChart3D(null, dataset, false, false, false); else chart = ChartFactory.createPieChart(null, dataset, false, false, false); PiePlot plot = (PiePlot) chart.getPlot(); // set start angle (135 or 150 deg so minor data has more space on the left) plot.setStartAngle(150D); // set transparency plot.setForegroundAlpha(transparency); // set background chart.setBackgroundPaint(parseColor(M_sm.getChartBackgroundColor())); plot.setBackgroundPaint(parseColor(M_sm.getChartBackgroundColor())); // fix border offset chart.setPadding(new RectangleInsets(5, 5, 5, 5)); plot.setInsets(new RectangleInsets(1, 1, 1, 1)); // set chart border plot.setOutlinePaint(null); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set antialias chart.setAntiAlias(true); BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { LOG.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] generateTimeSeriesChart(String siteId, IntervalXYDataset dataset, int width, int height, boolean renderBar, float transparency, boolean itemLabelsVisible, boolean smallFontInDomainAxis, String timePeriod) { return generateTimeSeriesChart(siteId, dataset, width, height, renderBar, transparency, itemLabelsVisible, smallFontInDomainAxis, timePeriod, null, null); } private byte[] generateTimeSeriesChart(String siteId, IntervalXYDataset dataset, int width, int height, boolean renderBar, float transparency, boolean itemLabelsVisible, boolean smallFontInDomainAxis, String timePeriod, Date firstDate, Date lastDate) { JFreeChart chart = null; if (!renderBar) { chart = ChartFactory.createTimeSeriesChart(null, null, null, dataset, true, false, false); } else { chart = ChartFactory.createXYBarChart(null, null, true, null, dataset, PlotOrientation.VERTICAL, true, false, false); } XYPlot plot = (XYPlot) chart.getPlot(); // set transparency plot.setForegroundAlpha(transparency); // set background chart.setBackgroundPaint(parseColor(M_sm.getChartBackgroundColor())); // set chart border chart.setPadding(new RectangleInsets(10, 5, 5, 5)); chart.setBorderVisible(true); chart.setBorderPaint(parseColor("#cccccc")); // set antialias chart.setAntiAlias(true); // set domain axis font size if (smallFontInDomainAxis && !canUseNormalFontSize(width)) { plot.getDomainAxis().setTickLabelFont(new Font("SansSerif", Font.PLAIN, 8)); } // configure date display (localized) in domain axis Locale locale = msgs.getLocale(); PeriodAxis periodaxis = new PeriodAxis(null); Class timePeriodClass = null; if (dataset instanceof TimeSeriesCollection) { TimeSeriesCollection tsc = (TimeSeriesCollection) dataset; if (tsc.getSeriesCount() > 0) { timePeriodClass = tsc.getSeries(0).getTimePeriodClass(); } else { timePeriodClass = org.jfree.data.time.Day.class; } periodaxis.setAutoRangeTimePeriodClass(timePeriodClass); } PeriodAxisLabelInfo aperiodaxislabelinfo[] = null; if (StatsManager.CHARTTIMESERIES_WEEKDAY.equals(timePeriod)) { aperiodaxislabelinfo = new PeriodAxisLabelInfo[2]; aperiodaxislabelinfo[0] = new PeriodAxisLabelInfo(org.jfree.data.time.Day.class, new SimpleDateFormat("E", locale)); aperiodaxislabelinfo[1] = new PeriodAxisLabelInfo(org.jfree.data.time.Day.class, new SimpleDateFormat("d", locale)); } else if (StatsManager.CHARTTIMESERIES_DAY.equals(timePeriod)) { aperiodaxislabelinfo = new PeriodAxisLabelInfo[3]; aperiodaxislabelinfo[0] = new PeriodAxisLabelInfo(org.jfree.data.time.Day.class, new SimpleDateFormat("d", locale)); aperiodaxislabelinfo[1] = new PeriodAxisLabelInfo(org.jfree.data.time.Month.class, new SimpleDateFormat("MMM", locale)); aperiodaxislabelinfo[2] = new PeriodAxisLabelInfo(org.jfree.data.time.Year.class, new SimpleDateFormat("yyyy", locale)); } else if (StatsManager.CHARTTIMESERIES_MONTH.equals(timePeriod)) { aperiodaxislabelinfo = new PeriodAxisLabelInfo[2]; aperiodaxislabelinfo[0] = new PeriodAxisLabelInfo(org.jfree.data.time.Month.class, new SimpleDateFormat("MMM", locale)); aperiodaxislabelinfo[1] = new PeriodAxisLabelInfo(org.jfree.data.time.Year.class, new SimpleDateFormat("yyyy", locale)); } else if (StatsManager.CHARTTIMESERIES_YEAR.equals(timePeriod)) { aperiodaxislabelinfo = new PeriodAxisLabelInfo[1]; aperiodaxislabelinfo[0] = new PeriodAxisLabelInfo(org.jfree.data.time.Year.class, new SimpleDateFormat("yyyy", locale)); } periodaxis.setLabelInfo(aperiodaxislabelinfo); // date range if (firstDate != null || lastDate != null) { periodaxis.setAutoRange(false); if (firstDate != null) { if (StatsManager.CHARTTIMESERIES_MONTH.equals(timePeriod) || StatsManager.CHARTTIMESERIES_YEAR.equals(timePeriod)) { periodaxis.setFirst(new org.jfree.data.time.Month(firstDate)); } else { periodaxis.setFirst(new org.jfree.data.time.Day(firstDate)); } } if (lastDate != null) { if (StatsManager.CHARTTIMESERIES_MONTH.equals(timePeriod) || StatsManager.CHARTTIMESERIES_YEAR.equals(timePeriod)) { periodaxis.setLast(new org.jfree.data.time.Month(lastDate)); } else { periodaxis.setLast(new org.jfree.data.time.Day(lastDate)); } } } periodaxis.setTickMarkOutsideLength(0.0F); plot.setDomainAxis(periodaxis); // set outline AbstractXYItemRenderer renderer = (AbstractXYItemRenderer) plot.getRenderer(); if (renderer instanceof XYLineAndShapeRenderer) { XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) renderer; r.setDrawSeriesLineAsPath(true); r.setShapesVisible(true); r.setShapesFilled(true); } else if (renderer instanceof XYBarRenderer) { //XYBarRenderer r = (XYBarRenderer) renderer; ClusteredXYBarRenderer r = new ClusteredXYBarRenderer(); r.setDrawBarOutline(true); if (smallFontInDomainAxis && !canUseNormalFontSize(width)) r.setMargin(0.05); else r.setMargin(0.10); plot.setRenderer(r); renderer = r; } // item labels if (itemLabelsVisible) { plot.getRangeAxis().setUpperMargin(0.2); renderer.setItemLabelGenerator(new XYItemLabelGenerator() { private static final long serialVersionUID = 1L; public String generateLabel(XYDataset dataset, int series, int item) { Number n = dataset.getY(series, item); if (n.doubleValue() != 0) return n.toString(); return ""; } }); renderer.setItemLabelFont(new Font("SansSerif", Font.PLAIN, 8)); renderer.setItemLabelsVisible(true); } BufferedImage img = chart.createBufferedImage(width, height); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { LOG.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } private byte[] generateNoDataChart(int width, int height) { BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = img.createGraphics(); g2d.setBackground(parseColor(M_sm.getChartBackgroundColor())); g2d.clearRect(0, 0, width - 1, height - 1); g2d.setColor(parseColor("#cccccc")); g2d.drawRect(0, 0, width - 1, height - 1); Font f = new Font("SansSerif", Font.PLAIN, 12); g2d.setFont(f); FontMetrics fm = g2d.getFontMetrics(f); String noData = msgs.getString("no_data"); int noDataWidth = fm.stringWidth(noData); int noDataHeight = fm.getHeight(); g2d.setColor(parseColor("#555555")); g2d.drawString(noData, width / 2 - noDataWidth / 2, height / 2 - noDataHeight / 2 + 2); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(img, "png", out); } catch (IOException e) { LOG.warn("Error occurred while generating SiteStats chart image data", e); } return out.toByteArray(); } // ###################################################################################### // Chart DataSet methods // ###################################################################################### private DefaultCategoryDataset getVisitsWeekDataSet(String siteId) { // LOG.info("Generating visitsWeekDataSet"); SummaryVisitsChartData svc = M_sm.getSummaryVisitsChartData(siteId, StatsManager.VIEW_WEEK); if (svc == null) return null; DefaultCategoryDataset visitsWeekDataSet = new DefaultCategoryDataset(); String visits = msgs.getString("legend_visits"); String uniqueVisits = msgs.getString("legend_unique_visitors"); Calendar cal = Calendar.getInstance(); cal.setTime(svc.getFirstDay()); Calendar currDay = (Calendar) cal.clone(); long visitsData[] = svc.getVisits(); long uniqueVisitsData[] = svc.getUniqueVisits(); for (int i = 0; i < visitsData.length; i++) { visitsWeekDataSet.addValue(visitsData[i], visits, getWeekDaysMap().get(currDay.get(Calendar.DAY_OF_WEEK))); visitsWeekDataSet.addValue(uniqueVisitsData[i], uniqueVisits, getWeekDaysMap().get(currDay.get(Calendar.DAY_OF_WEEK))); currDay.add(Calendar.DAY_OF_YEAR, 1); } return visitsWeekDataSet; } private DefaultCategoryDataset getVisitsMonthDataSet(String siteId, int width) { // LOG.info("Generating visitsMonthDataSet"); SummaryVisitsChartData svc = M_sm.getSummaryVisitsChartData(siteId, StatsManager.VIEW_MONTH); if (svc == null) return null; DefaultCategoryDataset visitsMonthDataSet = new DefaultCategoryDataset(); String visits = msgs.getString("legend_visits"); String uniqueVisits = msgs.getString("legend_unique_visitors"); Day day; Calendar cal = Calendar.getInstance(); cal.setTime(svc.getFirstDay()); Calendar currDay = (Calendar) cal.clone(); long visitsData[] = svc.getVisits(); long uniqueVisitsData[] = svc.getUniqueVisits(); for (int i = 0; i < visitsData.length; i++) { int dayOfMonth = currDay.get(Calendar.DAY_OF_MONTH); if (canUseNormalFontSize(width) || (i == 0 || i == 30 - 1 || i % 2 == 0)) { day = new Day(dayOfMonth, Integer.toString(dayOfMonth)); } else { day = new Day(dayOfMonth, ""); } visitsMonthDataSet.addValue(visitsData[i], visits, day); visitsMonthDataSet.addValue(uniqueVisitsData[i], uniqueVisits, day); currDay.add(Calendar.DAY_OF_MONTH, 1); } return visitsMonthDataSet; } private DefaultCategoryDataset getVisitsYearDataSet(String siteId) { // LOG.info("Generating visitsYearDataSet"); SummaryVisitsChartData svc = M_sm.getSummaryVisitsChartData(siteId, StatsManager.VIEW_YEAR); if (svc == null) return null; DefaultCategoryDataset visitsYearDataSet = new DefaultCategoryDataset(); String visits = msgs.getString("legend_visits"); String uniqueVisits = msgs.getString("legend_unique_visitors"); Calendar cal = Calendar.getInstance(); cal.setTime(svc.getFirstDay()); Calendar currMonth = (Calendar) cal.clone(); long visitsData[] = svc.getVisits(); long uniqueVisitsData[] = svc.getUniqueVisits(); for (int i = 0; i < visitsData.length; i++) { visitsYearDataSet.addValue(visitsData[i], visits, getMonthNamesMap().get(currMonth.get(Calendar.MONTH))); visitsYearDataSet.addValue(uniqueVisitsData[i], uniqueVisits, getMonthNamesMap().get(currMonth.get(Calendar.MONTH))); currMonth.add(Calendar.MONTH, 1); } return visitsYearDataSet; } private DefaultPieDataset getActivityWeekPieDataSet(String siteId) { // LOG.info("Generating activityWeekPieDataSet"); SummaryActivityChartData sac = M_sm.getSummaryActivityChartData(siteId, StatsManager.VIEW_WEEK, StatsManager.CHARTTYPE_PIE); if (sac == null) return null; DefaultPieDataset activityWeekPieDataSet = fillActivityPieDataSet(sac); return activityWeekPieDataSet; } private DefaultPieDataset getActivityMonthPieDataSet(String siteId) { // LOG.info("Generating activityMonthPieDataSet"); SummaryActivityChartData sac = M_sm.getSummaryActivityChartData(siteId, StatsManager.VIEW_MONTH, StatsManager.CHARTTYPE_PIE); if (sac == null) return null; DefaultPieDataset activityMonthPieDataSet = fillActivityPieDataSet(sac); return activityMonthPieDataSet; } private DefaultPieDataset getActivityYearPieDataSet(String siteId) { // LOG.info("Generating activityYearPieDataSet"); SummaryActivityChartData sac = M_sm.getSummaryActivityChartData(siteId, StatsManager.VIEW_YEAR, StatsManager.CHARTTYPE_PIE); if (sac == null) return null; DefaultPieDataset activityYearPieDataSet = fillActivityPieDataSet(sac); return activityYearPieDataSet; } private DefaultPieDataset fillActivityPieDataSet(SummaryActivityChartData sac) { DefaultPieDataset pieDataSet = new DefaultPieDataset(); List<SiteActivityByTool> lsac = sac.getActivityByTool(); int total = sac.getActivityByToolTotal(); int showMax = 5; for (int i = 0; i < lsac.size() && i < showMax; i++) { SiteActivityByTool s = lsac.get(i); double percentage = (double) s.getCount() * 100 / total; int decimalPlaces = 1; if (percentage < 0.1) decimalPlaces = 2; String label = M_ers.getToolName(s.getTool().getToolId()) + " " + Util.round(percentage, decimalPlaces) + "%"; pieDataSet.setValue(label, percentage); } if (lsac.size() > showMax) { int acumulated = 0; String otherTools = msgs.getString("label_activity_other_tools"); for (int i = showMax; i < lsac.size(); i++) { SiteActivityByTool s = lsac.get(i); acumulated += s.getCount(); } double percentage = (double) acumulated * 100 / total; int decimalPlaces = 1; if (percentage < 0.1) decimalPlaces = 2; String label = otherTools + " " + Util.round(percentage, decimalPlaces) + "%"; pieDataSet.setValue(label, percentage); } return pieDataSet; } private DefaultCategoryDataset getActivityWeekBarDataSet(String siteId) { // LOG.info("Generating activityWeekBarDataSet"); SummaryActivityChartData sac = M_sm.getSummaryActivityChartData(siteId, StatsManager.VIEW_WEEK, StatsManager.CHARTTYPE_BAR); if (sac == null) return null; DefaultCategoryDataset activityWeekBarDataSet = new DefaultCategoryDataset(); String activity = msgs.getString("legend_activity"); Calendar cal = Calendar.getInstance(); cal.setTime(sac.getFirstDay()); Calendar currDay = (Calendar) cal.clone(); long activityData[] = sac.getActivity(); for (int i = 0; i < activityData.length; i++) { activityWeekBarDataSet.addValue(activityData[i], activity, getWeekDaysMap().get(currDay.get(Calendar.DAY_OF_WEEK))); currDay.add(Calendar.DAY_OF_YEAR, 1); } return activityWeekBarDataSet; } private DefaultCategoryDataset getActivityMonthBarDataSet(String siteId, int width) { // LOG.info("Generating activityMonthBarDataSet"); SummaryActivityChartData sac = M_sm.getSummaryActivityChartData(siteId, StatsManager.VIEW_MONTH, StatsManager.CHARTTYPE_BAR); if (sac == null) return null; DefaultCategoryDataset activityMonthBarDataSet = new DefaultCategoryDataset(); String activity = msgs.getString("legend_activity"); Day day; Calendar cal = Calendar.getInstance(); cal.setTime(sac.getFirstDay()); Calendar currDay = (Calendar) cal.clone(); long activityData[] = sac.getActivity(); for (int i = 0; i < activityData.length; i++) { int dayOfMonth = currDay.get(Calendar.DAY_OF_MONTH); //if(params.areAllDaysDrawable() || (i == 0 || i == 30 - 1 || i % 2 == 0)){ if (canUseNormalFontSize(width) || (i == 0 || i == 30 - 1 || i % 2 == 0)) { day = new Day(dayOfMonth, Integer.toString(dayOfMonth)); } else { day = new Day(dayOfMonth, ""); } activityMonthBarDataSet.addValue(activityData[i], activity, day); currDay.add(Calendar.DAY_OF_MONTH, 1); } return activityMonthBarDataSet; } private DefaultCategoryDataset getActivityYearBarDataSet(String siteId) { // LOG.info("Generating activityYearBarDataSet"); SummaryActivityChartData sac = M_sm.getSummaryActivityChartData(siteId, StatsManager.VIEW_YEAR, StatsManager.CHARTTYPE_BAR); if (sac == null) return null; DefaultCategoryDataset activityYearBarDataSet = new DefaultCategoryDataset(); String activity = msgs.getString("legend_activity"); Calendar cal = Calendar.getInstance(); cal.setTime(sac.getFirstDay()); Calendar currMonth = (Calendar) cal.clone(); long activityData[] = sac.getActivity(); for (int i = 0; i < activityData.length; i++) { activityYearBarDataSet.addValue(activityData[i], activity, getMonthNamesMap().get(currMonth.get(Calendar.MONTH))); currMonth.add(Calendar.MONTH, 1); } return activityYearBarDataSet; } private AbstractDataset getCategoryDataset(Report report) { List<Stat> reportData = report.getReportData(); // fill dataset DefaultCategoryDataset dataSet = new DefaultCategoryDataset(); String dataSource = report.getReportDefinition().getReportParams().getHowChartSource(); String categorySource = report.getReportDefinition().getReportParams().getHowChartCategorySource(); if (StatsManager.T_NONE.equals(categorySource)) { categorySource = null; } if (categorySource == null) { // without categories Set<Comparable> usedKeys = new HashSet<Comparable>(); for (Stat s : reportData) { Comparable key = getStatValue(s, dataSource); if (key != null) { if (usedKeys.contains(key)) { dataSet.incrementValue(getTotalValue(s, report).doubleValue(), key, key); } else { dataSet.addValue(getTotalValue(s, report), key, key); usedKeys.add(key); } } } } else { // with categories Map<Comparable, Comparable> usedKeys = new HashMap<Comparable, Comparable>(); for (Stat s : reportData) { Comparable key = getStatValue(s, dataSource); Comparable cat = getStatValue(s, categorySource); if (key != null && cat != null) { if (usedKeys.containsKey(cat) && key.equals(usedKeys.get(cat))) { dataSet.incrementValue(getTotalValue(s, report).doubleValue(), key, cat); } else { dataSet.addValue(getTotalValue(s, report), key, cat); usedKeys.put(cat, key); } } } // fill missing values with zeros for (Comparable c : usedKeys.keySet()) { for (Comparable k : usedKeys.values()) { if (dataSet.getValue(k, c) == null) { dataSet.addValue(0, k, c); } } } } return dataSet; } private AbstractDataset getPieDataset(Report report) { List<Stat> reportData = report.getReportData(); // fill dataset DefaultPieDataset dataSet = new DefaultPieDataset(); String dataSource = report.getReportDefinition().getReportParams().getHowChartSource(); //int total = 0; double total = 0; for (Stat s : reportData) { Comparable key = getStatValue(s, dataSource); if (key != null) { try { Number existingValue = dataSet.getValue(key); dataSet.setValue(key, getTotalValue(existingValue, s, report)); total += getTotalValue(s, report).doubleValue(); } catch (UnknownKeyException e) { dataSet.setValue(key, getTotalValue(s, report)); total += getTotalValue(s, report).doubleValue(); } } } // sort dataSet.sortByValues(SortOrder.DESCENDING); // fill in final key values in dataset // show only top values (aggregate remaining in 'others') int maxDisplayedItems = 10; int currItem = 1; Number othersValues = Integer.valueOf(0); List<Comparable> keys = dataSet.getKeys(); for (Comparable key : keys) { Number existingValue = dataSet.getValue(key); if (currItem < maxDisplayedItems) { // re-compute values double percentage = (double) existingValue.doubleValue() * 100 / total; double valuePercentage = Util.round(percentage, (percentage > 0.1) ? 1 : 2); // replace key with updated label StringBuilder keyStr = new StringBuilder(key.toString()); keyStr.append(' '); keyStr.append(valuePercentage); keyStr.append("% ("); if ((double) existingValue.intValue() == existingValue.doubleValue()) keyStr.append(existingValue.intValue()); else keyStr.append(existingValue.doubleValue()); keyStr.append(")"); dataSet.remove(key); dataSet.setValue(keyStr.toString(), existingValue); } else { othersValues = Integer.valueOf(othersValues.intValue() + existingValue.intValue()); dataSet.remove(key); } currItem++; } // compute "Others" value if (othersValues.intValue() > 0) { double percentage = (double) othersValues.doubleValue() * 100 / total; double valuePercentage = Util.round(percentage, (percentage > 0.1) ? 1 : 2); // replace key with updated label StringBuilder keyStr = new StringBuilder(msgs.getString("pie_chart_others")); keyStr.append(' '); keyStr.append(valuePercentage); keyStr.append("% ("); if ((double) othersValues.intValue() == othersValues.doubleValue()) keyStr.append(othersValues.intValue()); else keyStr.append(othersValues.doubleValue()); keyStr.append(")"); dataSet.setValue(keyStr.toString(), othersValues); } return dataSet; } private AbstractDataset getTimeSeriesCollectionDataset(Report report) { List<Stat> reportData = report.getReportData(); // fill dataset TimeSeriesCollection dataSet = new TimeSeriesCollection(); String dataSource = report.getReportDefinition().getReportParams().getHowChartSource(); String seriesFrom = report.getReportDefinition().getReportParams().getHowChartSeriesSource(); if (StatsManager.T_TOTAL.equals(seriesFrom) || StatsManager.T_NONE.equals(seriesFrom)) { seriesFrom = null; } Class periodGrouping = null; if (StatsManager.CHARTTIMESERIES_DAY .equals(report.getReportDefinition().getReportParams().getHowChartSeriesPeriod()) || StatsManager.CHARTTIMESERIES_WEEKDAY .equals(report.getReportDefinition().getReportParams().getHowChartSeriesPeriod())) { periodGrouping = org.jfree.data.time.Day.class; } else if (StatsManager.CHARTTIMESERIES_MONTH .equals(report.getReportDefinition().getReportParams().getHowChartSeriesPeriod())) { periodGrouping = org.jfree.data.time.Month.class; } else if (StatsManager.CHARTTIMESERIES_YEAR .equals(report.getReportDefinition().getReportParams().getHowChartSeriesPeriod())) { periodGrouping = org.jfree.data.time.Year.class; } boolean visitsTotalsChart = ReportManager.WHAT_VISITS_TOTALS .equals(report.getReportDefinition().getReportParams().getWhat()) || report.getReportDefinition().getReportParams().getHowTotalsBy().contains(StatsManager.T_VISITS) || report.getReportDefinition().getReportParams().getHowTotalsBy() .contains(StatsManager.T_UNIQUEVISITS); Set<RegularTimePeriod> keys = new HashSet<RegularTimePeriod>(); if (!visitsTotalsChart && seriesFrom == null) { // without additional series String name = msgs.getString("th_total"); TimeSeries ts = new TimeSeries(name, periodGrouping); for (Stat s : reportData) { RegularTimePeriod key = (RegularTimePeriod) getStatValue(s, dataSource, periodGrouping); if (key != null) { Number existing = null; if ((existing = ts.getValue(key)) == null) { ts.add(key, getTotalValue(s, report)); } else { ts.addOrUpdate(key, getTotalValue(existing, s, report)); } keys.add(key); } } dataSet.addSeries(ts); } else if (!visitsTotalsChart && seriesFrom != null) { // with additional series Map<Comparable, TimeSeries> series = new HashMap<Comparable, TimeSeries>(); //TimeSeries ts = new TimeSeries(dataSource, org.jfree.data.time.Day.class); for (Stat s : reportData) { RegularTimePeriod key = (RegularTimePeriod) getStatValue(s, dataSource, periodGrouping); Comparable serie = (Comparable) getStatValue(s, seriesFrom); if (key != null && serie != null) { // determine appropriate serie TimeSeries ts = null; if (!series.containsKey(serie)) { ts = new TimeSeries(serie.toString(), periodGrouping); series.put(serie, ts); } else { ts = series.get(serie); } Number existing = null; if ((existing = ts.getValue(key)) == null) { ts.add(key, getTotalValue(s, report)); } else { ts.addOrUpdate(key, getTotalValue(existing, s, report)); } keys.add(key); } } // add series for (TimeSeries ts : series.values()) { dataSet.addSeries(ts); } } else if (visitsTotalsChart) { // 2 series: visits & unique visitors TimeSeries tsV = new TimeSeries(msgs.getString("th_visits"), periodGrouping); TimeSeries tsUV = new TimeSeries(msgs.getString("th_uniquevisitors"), periodGrouping); for (Stat _s : reportData) { SiteVisits s = (SiteVisits) _s; RegularTimePeriod key = (RegularTimePeriod) getStatValue(s, dataSource, periodGrouping); if (key != null) { Number existing = null; if ((existing = tsV.getValue(key)) == null) { tsV.add(key, s.getTotalVisits()); tsUV.add(key, s.getTotalUnique()); } else { tsV.addOrUpdate(key, s.getTotalVisits() + existing.longValue()); tsUV.addOrUpdate(key, s.getTotalVisits() + existing.longValue()); } keys.add(key); } } dataSet.addSeries(tsV); dataSet.addSeries(tsUV); } // fill missing values with zeros /*for(TimeSeries ts : (List<TimeSeries>) dataSet.getSeries()) { for(RegularTimePeriod tp : keys) { if(ts.getValue(tp) == null) { ts.add(tp, 0.0); } } }*/ dataSet.setXPosition(TimePeriodAnchor.MIDDLE); return dataSet; } // ################################################################ // Utility Methods // ################################################################ private static class Day implements Comparable<Object> { private String dayLabel; private int day; public Day(int day, String dayLabel) { this.day = day; this.dayLabel = dayLabel; } public int getDay() { return this.day; } public String toString() { return this.dayLabel; } public int compareTo(Object o) { if (!(o instanceof Day)) return -1; int otherDay = ((Day) o).getDay(); if (day < otherDay) return -1; else if (day > otherDay) return 1; else return 0; } public boolean equals(Object o) { if (!(o instanceof Day)) return false; int otherDay = ((Day) o).getDay(); if (day == otherDay) return true; else return false; } public int hashCode() { return getDay(); } } private Map<Integer, String> getWeekDaysMap() { weekDaysMap = new HashMap<Integer, String>(); weekDaysMap.put(Calendar.SUNDAY, msgs.getString("day_sun")); weekDaysMap.put(Calendar.MONDAY, msgs.getString("day_mon")); weekDaysMap.put(Calendar.TUESDAY, msgs.getString("day_tue")); weekDaysMap.put(Calendar.WEDNESDAY, msgs.getString("day_wed")); weekDaysMap.put(Calendar.THURSDAY, msgs.getString("day_thu")); weekDaysMap.put(Calendar.FRIDAY, msgs.getString("day_fri")); weekDaysMap.put(Calendar.SATURDAY, msgs.getString("day_sat")); return weekDaysMap; } private Map<Integer, String> getMonthNamesMap() { monthNamesMap = new HashMap<Integer, String>(); monthNamesMap.put(Calendar.JANUARY, msgs.getString("mo_jan")); monthNamesMap.put(Calendar.FEBRUARY, msgs.getString("mo_feb")); monthNamesMap.put(Calendar.MARCH, msgs.getString("mo_mar")); monthNamesMap.put(Calendar.APRIL, msgs.getString("mo_apr")); monthNamesMap.put(Calendar.MAY, msgs.getString("mo_may")); monthNamesMap.put(Calendar.JUNE, msgs.getString("mo_jun")); monthNamesMap.put(Calendar.JULY, msgs.getString("mo_jul")); monthNamesMap.put(Calendar.AUGUST, msgs.getString("mo_ago")); monthNamesMap.put(Calendar.SEPTEMBER, msgs.getString("mo_sep")); monthNamesMap.put(Calendar.OCTOBER, msgs.getString("mo_oct")); monthNamesMap.put(Calendar.NOVEMBER, msgs.getString("mo_nov")); monthNamesMap.put(Calendar.DECEMBER, msgs.getString("mo_dec")); return monthNamesMap; } private boolean canUseNormalFontSize(int chartWidth) { return chartWidth >= MIN_CHART_WIDTH_TO_DRAW_ALL_DAYS; } private static Color parseColor(String color) { if (color != null) { if (color.trim().startsWith("#")) { // HTML colors (#FFFFFF format) return new Color(Integer.parseInt(color.substring(1), 16)); } else if (color.trim().startsWith("rgb")) { // HTML colors (rgb(255, 255, 255) format) String values = color.substring(color.indexOf("(") + 1, color.indexOf(")")); String rgb[] = values.split(","); return new Color(Integer.parseInt(rgb[0].trim()), Integer.parseInt(rgb[1].trim()), Integer.parseInt(rgb[2].trim())); } else { // Colors by name if (color.equalsIgnoreCase("black")) return Color.black; if (color.equalsIgnoreCase("grey")) return Color.gray; if (color.equalsIgnoreCase("yellow")) return Color.yellow; if (color.equalsIgnoreCase("green")) return Color.green; if (color.equalsIgnoreCase("blue")) return Color.blue; if (color.equalsIgnoreCase("red")) return Color.red; if (color.equalsIgnoreCase("orange")) return Color.orange; if (color.equalsIgnoreCase("cyan")) return Color.cyan; if (color.equalsIgnoreCase("magenta")) return Color.magenta; if (color.equalsIgnoreCase("darkgray")) return Color.darkGray; if (color.equalsIgnoreCase("lightgray")) return Color.lightGray; if (color.equalsIgnoreCase("pink")) return Color.pink; if (color.equalsIgnoreCase("white")) return Color.white; } } LOG.info("Unable to parse body background-color (color:" + color + "). Assuming white."); return Color.white; } //periodGrouping private Comparable getStatValue(Stat s, String fieldCode) { return getStatValue(s, fieldCode, org.jfree.data.time.Day.class); } private Comparable getStatValue(Stat s, String fieldCode, Class periodGrouping) { if (fieldCode == null) { return null; } try { if (fieldCode.equals(StatsManager.T_SITE)) { String siteId = s.getSiteId(); String title = null; try { title = M_ss.getSite(siteId).getTitle(); } catch (IdUnusedException e) { title = siteId; } return title; } else if (fieldCode.equals(StatsManager.T_USER)) { String userId = s.getUserId(); String name = null; if (userId != null) { if (("-").equals(userId)) { name = msgs.getString("user_anonymous"); } else if (("?").equals(userId)) { name = msgs.getString("user_anonymous_access"); } else { name = M_sm.getUserNameForDisplay(userId); } } else { name = msgs.getString("user_unknown"); } return name; } else if (fieldCode.equals(StatsManager.T_EVENT)) { String eventName = ""; if (s instanceof EventStat) { String eventId = ((EventStat) s).getEventId(); if (!"".equals(eventId)) { eventName = M_ers.getEventName(eventId); } } return eventName; } else if (fieldCode.equals(StatsManager.T_TOOL)) { String toolName = ""; if (s instanceof EventStat) { String toolId = ((EventStat) s).getToolId(); if (!"".equals(toolId)) { toolName = M_ers.getToolName(toolId); } } return toolName; } else if (fieldCode.equals(StatsManager.T_RESOURCE)) { if (s instanceof ResourceStat) { String ref = ((ResourceStat) s).getResourceRef(); String resName = M_sm.getResourceName(ref); return resName != null ? resName : msgs.getString("resource_unknown"); } else { return ""; } } else if (fieldCode.equals(StatsManager.T_RESOURCE_ACTION)) { String action = ""; if (s instanceof ResourceStat) { String refAction = ((ResourceStat) s).getResourceAction(); if (refAction == null) { action = ""; } else { if (!"".equals(refAction.trim())) action = msgs.getString("action_" + refAction); } } return action; } else if (fieldCode.equals(StatsManager.T_PAGE)) { if (s instanceof LessonBuilderStat) { return M_sm.getLessonPageTitle(((LessonBuilderStat) s).getPageId()); } else { return ""; } } else if (fieldCode.equals(StatsManager.T_PAGE_ACTION)) { String action = ""; if (s instanceof LessonBuilderStat) { String refAction = ((LessonBuilderStat) s).getPageAction(); if (refAction == null) { action = ""; } else { if (!"".equals(refAction.trim())) action = msgs.getString("action_" + refAction); } } return action; } else if (fieldCode.equals(StatsManager.T_DATE) || fieldCode.equals(StatsManager.T_LASTDATE) || fieldCode.equals(StatsManager.T_DATEMONTH) || fieldCode.equals(StatsManager.T_DATEYEAR)) { Date d = s.getDate(); if (d != null) { Calendar c = Calendar.getInstance(); c.setTime(d); c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); if (org.jfree.data.time.Year.class.equals(periodGrouping)) { return new org.jfree.data.time.Year(c.getTime()); } else if (org.jfree.data.time.Month.class.equals(periodGrouping)) { return new org.jfree.data.time.Month(c.getTime()); } else if (org.jfree.data.time.Week.class.equals(periodGrouping)) { return new org.jfree.data.time.Week(c.getTime()); } else { return new org.jfree.data.time.Day(c.getTime()); } } else { return null; } } else if (fieldCode.equals(StatsManager.T_TOTAL)) { return s.getCount(); } else if (fieldCode.equals(StatsManager.T_VISITS)) { if (s instanceof SiteVisits) { return ((SiteVisits) s).getTotalVisits(); } return s.getCount(); } else if (fieldCode.equals(StatsManager.T_UNIQUEVISITS)) { if (s instanceof SiteVisits) { return ((SiteVisits) s).getTotalUnique(); } return s.getCount(); } else if (fieldCode.equals(StatsManager.T_DURATION)) { if (s instanceof SitePresence) { double duration = (double) ((SitePresence) s).getDuration(); return Util.round(duration / 1000 / 60, 1); // in minutes } } } catch (Exception e) { LOG.warn("Error occurred while getting value for chart", e); } return null; } private Number getTotalValue(Stat s, Report r) { return getTotalValue(null, s, r); } private Number getTotalValue(Number existingValue, Stat s, Report r) { try { String what = r.getReportDefinition().getReportParams().getWhat(); if (ReportManager.WHAT_VISITS_TOTALS.equals(what)) { if (s instanceof SiteVisits) { long totalVisits = ((SiteVisits) s).getTotalVisits(); if (existingValue != null) { totalVisits += existingValue.longValue(); } return totalVisits; } } else if (ReportManager.WHAT_PRESENCES.equals(what)) { if (s instanceof SitePresence) { double duration = (double) ((SitePresence) s).getDuration(); duration = Util.round(duration / 1000 / 60, 1); // in minutes if (existingValue != null) { duration += existingValue.doubleValue(); } return duration; } } long count = s.getCount(); if (existingValue != null) { count += existingValue.longValue(); } return count; } catch (Exception e) { LOG.warn("Error occurred while getting total value for chart", e); } return null; } }