/** * $URL: https://source.sakaiproject.org/svn/sitestats/trunk/sitestats-impl/src/java/org/sakaiproject/sitestats/impl/chart/ChartServiceImpl.java $ * $Id: ChartServiceImpl.java 105078 2012-02-24 23:00:38Z ottenhoff@longsight.com $ * * 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.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.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_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; } }