/* * HTMLReport.java * * Version: $Revision: 3734 $ * * Date: $Date: 2009-04-24 04:00:19 +0000 (Fri, 24 Apr 2009) $ * * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the DSpace Foundation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.dspace.app.statistics; import org.dspace.app.statistics.Report; import org.dspace.app.statistics.Stat; import org.dspace.app.statistics.Statistics; import org.dspace.app.statistics.ReportTools; import org.dspace.core.ConfigurationManager; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.io.*; /** * This class provides HTML reports for the ReportGenerator class * * @author Richard Jones */ public class HTMLReport implements Report { // FIXME: all of these methods should do some content escaping before // outputting anything /** a list of the statistic blocks being managed by this class */ private List blocks = new ArrayList(); /** the title for the page */ private String pageTitle = null; /** the main title for the page */ private String mainTitle = null; /** start date for report */ private Date start = null; /** end date for report */ private Date end = null; /** the output file to which to write aggregation data */ private static String output = ConfigurationManager.getProperty("dspace.dir") + File.separator + "log" + File.separator + "report"; /** * constructor for HTML reporting */ public void HTMLReport() { // empty constructor } public void setOutput(String newOutput) { if (newOutput != null) { output = newOutput; } } /** * return a string containing the report as generated by this class * * @return the HTML report */ public String render() { StringBuffer frag = new StringBuffer(); // get the page headings frag.append(header(pageTitle)); frag.append(mainTitle()); frag.append(dateRange()); // output the report blocks // FIXME: perhaps the order of report blocks should be configurable Iterator statSets = blocks.iterator(); while (statSets.hasNext()) { frag.append(navigation()); Statistics stats = (Statistics) statSets.next(); frag.append(sectionHeader(stats.getSectionHeader())); frag.append(topLink()); frag.append(blockExplanation(stats.getExplanation())); frag.append(floorInfo(stats.getFloor())); frag.append(statBlock(stats)); } // output the footer and return frag.append(footer()); // NB: HTMLReport now takes responsibility to write the output file, // so that the Report/ReportGenerator can have more general usage // finally write the string into the output file try { FileOutputStream fos = new FileOutputStream(output); OutputStreamWriter osr = new OutputStreamWriter(fos, "UTF-8"); PrintWriter out = new PrintWriter(osr); out.write(frag.toString()); out.close(); } catch (IOException e) { System.out.println("Unable to write to output file " + output); System.exit(0); } return frag.toString(); } /** * provide a link back to the top of the page * * @return a string containing the link text HTML formatted */ public String topLink() { String frag = "<div class=\"reportNavigation\"><a href=\"#top\">Top</a></div>"; return frag; } /** * build the internal navigation for the report * * @return an HTML string providing internal page navigation */ public String navigation() { StringBuffer frag = new StringBuffer(); frag.append("<div class=\"reportNavigation\">"); frag.append("<a href=\"#general_overview\">General Overview</a>"); frag.append(" | "); frag.append("<a href=\"#archive_information\">Archive Information</a>"); frag.append(" | "); frag.append("<a href=\"#items_viewed\">Items Viewed</a>"); frag.append(" | "); frag.append("<a href=\"#all_actions_performed\">All Actions Performed</a>"); frag.append(" | "); frag.append("<a href=\"#user_logins\">User Logins</a>"); frag.append(" | "); frag.append("<a href=\"#words_searched\">Words Searched</a>"); frag.append(" | "); frag.append("<a href=\"#averaging_information\">Averaging Information</a>"); frag.append(" | "); frag.append("<a href=\"#log_level_information\">Log Level Information</a>"); frag.append(" | "); frag.append("<a href=\"#processing_information\">Processing Information</a>"); frag.append("</div>"); return frag.toString(); } /** * add a statistics block to the report to the class register * * @param stat the statistics object to be added to the report */ public void addBlock(Statistics stat) { blocks.add(stat); return; } /** * set the starting date for the report * * @param start the start date for the report */ public void setStartDate(Date start) { this.start = start; } /** * set the end date for the report * * @param end the end date for the report */ public void setEndDate(Date end) { this.end = end; } /** * output the date range in the relevant format. This requires that the * date ranges have been set using setStartDate() and setEndDate() * * @return a string containing date range information */ public String dateRange() { StringBuffer frag = new StringBuffer(); DateFormat df = DateFormat.getDateInstance(); frag.append("<div class=\"reportDate\">"); if (start != null) { frag.append(df.format(start)); } else { frag.append("from start of records "); } frag.append(" to "); if (end != null) { frag.append(df.format(end)); } else { frag.append(" end of records"); } frag.append("</div>\n\n"); return frag.toString(); } /** * output the title in the relevant format. This requires that the title * has been set with setMainTitle() * * @return a string containing the title of the report */ public String mainTitle() { String frag = "<div class=\"reportTitle\"><a name=\"top\">" + mainTitle + "</a></div>\n\n"; return frag; } /** * set the main title for the report * * @param name the name of the service * @param serverName the name of the server */ public void setMainTitle(String name, String serverName) { mainTitle = "Statistics for " + name + " on " + serverName; if (pageTitle == null) { pageTitle = mainTitle; } return; } /** * output any top headers that this page needs * * @return a string containing the header for the report */ public String header() { return header(""); } /** * output any top headers that this page needs, and include a title * argument (Title support currently not implemented) * * @param title the title of the item being headered */ public String header(String title) { // FIXME: this need to be figured out to integrate nicely into the // whole JSTL thing, but for the moment it's just going to deliver // some styles StringBuffer frag = new StringBuffer(); frag.append("<style type=\"text/css\">\n"); frag.append("body { font-family: Arial, Helvetica, sans-serif }"); frag.append(".reportTitle { width: 100%; clear: both; text-align: center; font-weight: bold; font-size: 200%; margin: 20px; }\n"); frag.append(".reportSection { width: 100%; clear: both; font-weight: bold; font-size: 160%; margin: 10px; text-align: center; margin-top: 30px; }\n"); frag.append(".reportBlock { border: 1px solid #000000; margin: 10px; }\n"); frag.append(".reportOddRow { background: #dddddd; }\n"); frag.append(".reportEvenRow { background: #bbbbbb; }\n"); frag.append(".reportExplanation { font-style: italic; text-align: center; }\n"); frag.append(".reportDate { font-style: italic; text-align: center; font-size: 120% }\n"); frag.append(".reportFloor { text-align: center; }\n"); frag.append(".rightAlign { text-align: right; }\n"); frag.append(".reportNavigation { text-align: center; }\n"); frag.append("</style>\n"); return frag.toString(); } /** * output the section header in HTML format * * @param title the title of the section * * @return a string containing the section title HTML formatted */ public String sectionHeader(String title) { // prepare the title to be an <a name="#title"> style link // FIXME: this should be made more generic and used in a number of locations String aName = title.toLowerCase(); Pattern space = Pattern.compile(" "); Matcher matchSpace = space.matcher(aName); aName = matchSpace.replaceAll("_"); String frag = "<div class=\"reportSection\"><a name=\"" + aName + "\">" + title + "</a></div>\n\n"; return frag; } /** * output the report block based on the passed mapping, where the mapping * sould be "name of report element" => "value", where both sides of the * mapping should be Strings. This class also assumes that the reference * is a linkable URL to the resource * * @param content the statistic object array to be displayed * * @return a string containing the statistics block HTML formatted */ public String statBlock(Statistics content) { StringBuffer frag = new StringBuffer(); Stat[] stats = content.getStats(); // start the table frag.append("<table align=\"center\" class=\"reportBlock\" cellpadding=\"5\">\n"); // prepare the table headers if (content.getStatName() != null || content.getResultName() != null) { frag.append("\t<tr>\n"); frag.append("\t\t<th>\n"); if (content.getStatName() != null) { frag.append("\t\t\t" + content.getStatName() + "\n"); } else { frag.append("\t\t\t \n"); } frag.append("\t\t</th>\n"); frag.append("\t\t<th>\n"); if (content.getResultName() != null) { frag.append("\t\t\t" + content.getResultName() + "\n"); } else { frag.append("\t\t\t \n"); } frag.append("\t\t</th>\n"); frag.append("\t</tr>\n"); } // output the statistics in the table for (int i = 0; i < stats.length; i++) { String style = null; if ((i % 2) == 1) { style = "reportOddRow"; } else { style = "reportEvenRow"; } frag.append("\t<tr class=\"" + style + "\">\n\t\t<td>\n"); frag.append("\t\t\t"); if (stats[i].getReference() != null) { frag.append("<a href=\"" + stats[i].getReference() + "\" "); frag.append("target=\"_blank\">"); } frag.append(this.clean(stats[i].getKey())); if (stats[i].getReference() != null) { frag.append("</a>"); } frag.append("\n"); frag.append("\t\t</td>\n\t\t<td class=\"rightAlign\">\n"); frag.append("\t\t\t" + ReportTools.numberFormat(stats[i].getValue())); if (stats[i].getUnits() != null) { frag.append(" " + stats[i].getUnits()); } frag.append("\n"); frag.append("\t\t</td>\n\t</tr>\n"); } frag.append("</table>\n"); return frag.toString(); } /** * output the floor information in HTML format * * @param floor the floor number for the section being displayed * * @return a string containing floor information HTML formatted */ public String floorInfo(int floor) { if (floor > 0) { StringBuffer frag = new StringBuffer(); frag.append("<div class=\"reportFloor\">"); frag.append("(more than " + ReportTools.numberFormat(floor) + " times)"); frag.append("</div>\n"); return frag.toString(); } else { return ""; } } /** * output the explanation of the report block in HTML format * * @param explanation some text explaining the coming report block * * @return a string containing an explanaton HTML formatted */ public String blockExplanation(String explanation) { if (explanation != null) { StringBuffer frag = new StringBuffer(); frag.append("<div class=\"reportExplanation\">"); frag.append(explanation); frag.append("</div>\n\n"); return frag.toString(); } else { return ""; } } /** * output the final footers for this file * * @return a string containing the report footer */ public String footer() { return ""; } /** * Clean Stirngs for display in HTML * * @param s The String to clean * @return The cleaned String */ private String clean(String s) { // Clean up the statistics keys s = s.replace("<", "<"); s = s.replaceAll(">", ">"); return s; } }