mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-13 04:53:16 +00:00
integrated from branch 1.5
Statistics viewer for XMLUI, based on existing DStat. Note that this generates the view from the analysis files (.dat), does not require HTML report generation. git-svn-id: http://scm.dspace.org/svn/repo/trunk@3102 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
@@ -44,6 +44,7 @@ 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;
|
||||
|
||||
@@ -54,13 +55,14 @@ 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 extends Report
|
||||
public class HTMLReport implements Report
|
||||
{
|
||||
// FIXME: all of these methods should do some content escaping before
|
||||
// outputting anything
|
||||
@@ -80,6 +82,10 @@ public class HTMLReport extends Report
|
||||
/** 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
|
||||
*/
|
||||
@@ -88,6 +94,14 @@ public class HTMLReport extends Report
|
||||
// empty constructor
|
||||
}
|
||||
|
||||
public void setOutput(String newOutput)
|
||||
{
|
||||
if (newOutput != null)
|
||||
{
|
||||
output = newOutput;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return a string containing the report as generated by this class
|
||||
*
|
||||
@@ -120,6 +134,23 @@ public class HTMLReport extends Report
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
@@ -48,30 +48,18 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstract class to define an interface to a generic report generating
|
||||
* Sn interface to a generic report generating
|
||||
* class, and to provide the polymorphism necessary to allow the report
|
||||
* generator to generate any number of different formats of report
|
||||
*
|
||||
* Note: This used to be an abstract class, but has been made an interface as there wasn't
|
||||
* any logic contained within it. It's also been made public, so that you can create a Report
|
||||
* type without monkeying about in the statistics package.
|
||||
*
|
||||
* @author Richard Jones
|
||||
*/
|
||||
abstract class Report
|
||||
public interface Report
|
||||
{
|
||||
|
||||
/** a list of the statistics 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;
|
||||
|
||||
/**
|
||||
* output any top headers that this page needs
|
||||
*
|
||||
|
@@ -70,6 +70,7 @@ import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* This class performs the action of coordinating a usage report being
|
||||
@@ -172,16 +173,9 @@ public class ReportGenerator
|
||||
// report generator config data
|
||||
////////////////
|
||||
|
||||
/** the format of the report to be output */
|
||||
private static String format = null;
|
||||
|
||||
/** the input file to build the report from */
|
||||
private static String input = null;
|
||||
|
||||
/** the output file to which to write aggregation data */
|
||||
private static String output = ConfigurationManager.getProperty("dspace.dir") +
|
||||
File.separator + "log" + File.separator + "report";
|
||||
|
||||
/** the log file action to human readable action map */
|
||||
private static String map = ConfigurationManager.getProperty("dspace.dir") +
|
||||
File.separator + "config" + File.separator + "dstat.map";
|
||||
@@ -240,6 +234,9 @@ public class ReportGenerator
|
||||
* aggregation data and output a file containing the report in the
|
||||
* requested format
|
||||
*
|
||||
* this method is retained for backwards compatibility, but delegates the actual
|
||||
* wprk to a new method
|
||||
*
|
||||
* @param context the DSpace context in which this action is performed
|
||||
* @param myFormat the desired output format (currently on HTML supported)
|
||||
* @param myInput the aggregation file to be turned into a report
|
||||
@@ -249,6 +246,32 @@ public class ReportGenerator
|
||||
String myInput, String myOutput,
|
||||
String myMap)
|
||||
throws Exception
|
||||
{
|
||||
// create the relevant report type
|
||||
// FIXME: at the moment we only support HTML report generation
|
||||
Report report = null;
|
||||
if (myFormat.equals("html"))
|
||||
{
|
||||
report = new HTMLReport();
|
||||
((HTMLReport)report).setOutput(myOutput);
|
||||
}
|
||||
|
||||
if (myMap != null)
|
||||
{
|
||||
map = myMap;
|
||||
}
|
||||
|
||||
ReportGenerator.processReport(context, report, myInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* using the pre-configuration information passed here, read in the
|
||||
* aggregation data and output a file containing the report in the
|
||||
* requested format
|
||||
*/
|
||||
public static void processReport(Context context, Report report,
|
||||
String myInput)
|
||||
throws Exception, SQLException
|
||||
{
|
||||
startTime = new GregorianCalendar();
|
||||
|
||||
@@ -264,7 +287,7 @@ public class ReportGenerator
|
||||
generalSummary = new ArrayList();
|
||||
|
||||
// set the parameters for this analysis
|
||||
setParameters(myFormat, myInput, myOutput, myMap);
|
||||
setParameters(myInput);
|
||||
|
||||
// pre prepare our standard file readers and buffered readers
|
||||
FileReader fr = null;
|
||||
@@ -276,14 +299,6 @@ public class ReportGenerator
|
||||
// load the log file action to human readable action map
|
||||
readMap(map);
|
||||
|
||||
// create the relevant report type
|
||||
// FIXME: at the moment we only support HTML report generation
|
||||
Report report = null;
|
||||
if (format.equals("html"))
|
||||
{
|
||||
report = new HTMLReport();
|
||||
}
|
||||
|
||||
report.setStartDate(startDate);
|
||||
report.setEndDate(endDate);
|
||||
report.setMainTitle(name, serverName);
|
||||
@@ -352,7 +367,8 @@ public class ReportGenerator
|
||||
String info = null;
|
||||
for (i = 0; i < items.length; i++)
|
||||
{
|
||||
if (i < itemLookup)
|
||||
// Allow negative value to say that all items should be looked up
|
||||
if (itemLookup < 0 || i < itemLookup)
|
||||
{
|
||||
info = getItemInfo(context, items[i].getKey());
|
||||
}
|
||||
@@ -460,20 +476,7 @@ public class ReportGenerator
|
||||
|
||||
report.addBlock(process);
|
||||
|
||||
// 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(report.render());
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.out.println("Unable to write to output file " + output);
|
||||
System.exit(0);
|
||||
}
|
||||
report.render();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -595,34 +598,15 @@ public class ReportGenerator
|
||||
* the command line with args or calling the processReport method statically
|
||||
* from elsewhere
|
||||
*
|
||||
* @param myFormat the log file directory to be analysed
|
||||
* @param myInput regex for log file names
|
||||
* @param myOutput config file to use for dstat
|
||||
* @param myMap the action map file to use for translations
|
||||
*/
|
||||
public static void setParameters(String myFormat, String myInput,
|
||||
String myOutput, String myMap)
|
||||
public static void setParameters(String myInput)
|
||||
{
|
||||
if (myFormat != null)
|
||||
{
|
||||
format = myFormat;
|
||||
}
|
||||
|
||||
if (myInput != null)
|
||||
{
|
||||
input = myInput;
|
||||
}
|
||||
|
||||
if (myOutput != null)
|
||||
{
|
||||
output = myOutput;
|
||||
}
|
||||
|
||||
if (myMap != null)
|
||||
{
|
||||
map = myMap;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -650,9 +634,13 @@ public class ReportGenerator
|
||||
catch (IOException e)
|
||||
{
|
||||
System.out.println("Failed to read input file: " + input);
|
||||
System.exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// first initialise a date format object to do our date processing
|
||||
// if necessary
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd'/'MM'/'yyyy");
|
||||
|
||||
// FIXME: although this works, it is not very elegant
|
||||
// loop through the aggregator file and read in the values
|
||||
while ((record = br.readLine()) != null)
|
||||
@@ -699,64 +687,48 @@ public class ReportGenerator
|
||||
}
|
||||
|
||||
// if the line is real, then we carry on
|
||||
|
||||
// first initialise a date format object to do our date processing
|
||||
// if necessary
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd'/'MM'/'yyyy");
|
||||
|
||||
// read the analysis contents in
|
||||
if (section.equals("archive"))
|
||||
{
|
||||
archiveStats.put(key, value);
|
||||
}
|
||||
|
||||
if (section.equals("action"))
|
||||
else if (section.equals("action"))
|
||||
{
|
||||
actionAggregator.put(key, value);
|
||||
}
|
||||
|
||||
if (section.equals("user"))
|
||||
else if (section.equals("user"))
|
||||
{
|
||||
userAggregator.put(key, value);
|
||||
}
|
||||
|
||||
if (section.equals("search"))
|
||||
else if (section.equals("search"))
|
||||
{
|
||||
searchAggregator.put(key, value);
|
||||
}
|
||||
|
||||
if (section.equals("item"))
|
||||
else if (section.equals("item"))
|
||||
{
|
||||
itemAggregator.put(key, value);
|
||||
}
|
||||
|
||||
// read the config details used to make this report in
|
||||
if (section.equals("user_email"))
|
||||
else if (section.equals("user_email"))
|
||||
{
|
||||
userEmail = value;
|
||||
}
|
||||
|
||||
if (section.equals("item_floor"))
|
||||
else if (section.equals("item_floor"))
|
||||
{
|
||||
itemFloor = Integer.parseInt(value);
|
||||
}
|
||||
|
||||
if (section.equals("search_floor"))
|
||||
else if (section.equals("search_floor"))
|
||||
{
|
||||
searchFloor = Integer.parseInt(value);
|
||||
}
|
||||
|
||||
if (section.equals("host_url"))
|
||||
else if (section.equals("host_url"))
|
||||
{
|
||||
url = value;
|
||||
}
|
||||
|
||||
if (section.equals("item_lookup"))
|
||||
else if (section.equals("item_lookup"))
|
||||
{
|
||||
itemLookup = Integer.parseInt(value);
|
||||
}
|
||||
|
||||
if (section.equals("avg_item_views"))
|
||||
else if (section.equals("avg_item_views"))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -767,43 +739,35 @@ public class ReportGenerator
|
||||
avgItemViews = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (section.equals("server_name"))
|
||||
else if (section.equals("server_name"))
|
||||
{
|
||||
serverName = value;
|
||||
}
|
||||
|
||||
if (section.equals("service_name"))
|
||||
else if (section.equals("service_name"))
|
||||
{
|
||||
name = value;
|
||||
}
|
||||
|
||||
if (section.equals("start_date"))
|
||||
else if (section.equals("start_date"))
|
||||
{
|
||||
startDate = sdf.parse(value);
|
||||
}
|
||||
|
||||
if (section.equals("end_date"))
|
||||
else if (section.equals("end_date"))
|
||||
{
|
||||
endDate = sdf.parse(value);
|
||||
}
|
||||
|
||||
if (section.equals("analysis_process_time"))
|
||||
else if (section.equals("analysis_process_time"))
|
||||
{
|
||||
processTime = Integer.parseInt(value);
|
||||
}
|
||||
|
||||
if (section.equals("general_summary"))
|
||||
else if (section.equals("general_summary"))
|
||||
{
|
||||
generalSummary.add(value);
|
||||
}
|
||||
|
||||
if (section.equals("log_lines"))
|
||||
else if (section.equals("log_lines"))
|
||||
{
|
||||
logLines = Integer.parseInt(value);
|
||||
}
|
||||
|
||||
if (section.equals("warnings"))
|
||||
else if (section.equals("warnings"))
|
||||
{
|
||||
warnings = Integer.parseInt(value);
|
||||
}
|
||||
|
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* StatisticsLoader.java
|
||||
*
|
||||
* Version: $Revision: 1.0 $
|
||||
*
|
||||
* Date: $Date: 2007/08/28 10:00:00 $
|
||||
*
|
||||
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
|
||||
* Institute of Technology. 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 Hewlett-Packard Company nor the name of the
|
||||
* Massachusetts Institute of Technology nor the names of their
|
||||
* 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.apache.commons.lang.time.DateUtils;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* Helper class for loading the analysis / report files from the reports directory
|
||||
*/
|
||||
public class StatisticsLoader
|
||||
{
|
||||
private static Map<String, StatsFile> monthlyAnalysis = null;
|
||||
private static Map<String, StatsFile> monthlyReports = null;
|
||||
|
||||
private static StatsFile generalAnalysis = null;
|
||||
private static StatsFile generalReport = null;
|
||||
|
||||
private static Date lastLoaded = null;
|
||||
private static int fileCount = 0;
|
||||
|
||||
private static Pattern analysisMonthlyPattern;
|
||||
private static Pattern analysisGeneralPattern;
|
||||
private static Pattern reportMonthlyPattern;
|
||||
private static Pattern reportGeneralPattern;
|
||||
|
||||
private static SimpleDateFormat monthlySDF;
|
||||
private static SimpleDateFormat generalSDF;
|
||||
|
||||
// one time initialisation of the regex patterns and formatters we will use
|
||||
static
|
||||
{
|
||||
analysisMonthlyPattern = Pattern.compile("dspace-log-monthly-([0-9][0-9][0-9][0-9]-[0-9]+)\\.dat");
|
||||
analysisGeneralPattern = Pattern.compile("dspace-log-general-([0-9]+-[0-9]+-[0-9]+)\\.dat");
|
||||
reportMonthlyPattern = Pattern.compile("report-([0-9][0-9][0-9][0-9]-[0-9]+)\\.html");
|
||||
reportGeneralPattern = Pattern.compile("report-general-([0-9]+-[0-9]+-[0-9]+)\\.html");
|
||||
|
||||
monthlySDF = new SimpleDateFormat("yyyy'-'M");
|
||||
generalSDF = new SimpleDateFormat("yyyy'-'M'-'dd");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of the dates of the report files
|
||||
* @return
|
||||
*/
|
||||
public static Date[] getMonthlyReportDates()
|
||||
{
|
||||
return sortDatesDescending(getDatesFromMap(monthlyReports));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of the dates of the analysis files
|
||||
* @return
|
||||
*/
|
||||
public static Date[] getMonthlyAnalysisDates()
|
||||
{
|
||||
return sortDatesDescending(getDatesFromMap(monthlyAnalysis));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the formatted dates that are the keys of the map into a date array
|
||||
* @param monthlyMap
|
||||
* @return
|
||||
*/
|
||||
protected static Date[] getDatesFromMap(Map<String, StatsFile> monthlyMap)
|
||||
{
|
||||
Set<String> keys = monthlyMap.keySet();
|
||||
Date[] dates = new Date[keys.size()];
|
||||
int i = 0;
|
||||
for (String date : keys)
|
||||
{
|
||||
try
|
||||
{
|
||||
dates[i] = monthlySDF.parse(date);
|
||||
}
|
||||
catch (ParseException pe)
|
||||
{
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return dates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the date array in descending (reverse chronological) order
|
||||
* @param dates
|
||||
* @return
|
||||
*/
|
||||
protected static Date[] sortDatesDescending(Date[] dates)
|
||||
{
|
||||
Arrays.sort(dates, new Comparator<Date>() {
|
||||
SimpleDateFormat sdf = monthlySDF;
|
||||
public int compare(Date d1, Date d2)
|
||||
{
|
||||
if (d1 == null && d2 == null)
|
||||
return 0;
|
||||
else if (d1 == null)
|
||||
return -1;
|
||||
else if (d2 == null)
|
||||
return 1;
|
||||
else if (d1.before(d2))
|
||||
return 1;
|
||||
else if (d2.before(d1))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
return dates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the analysis file for a given date
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static File getAnalysisFor(String date)
|
||||
{
|
||||
StatisticsLoader.syncFileList();
|
||||
StatsFile sf = (monthlyAnalysis == null ? null : monthlyAnalysis.get(date));
|
||||
return sf == null ? null : sf.file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the report file for a given date
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static File getReportFor(String date)
|
||||
{
|
||||
StatisticsLoader.syncFileList();
|
||||
StatsFile sf = (monthlyReports == null ? null : monthlyReports.get(date));
|
||||
return sf == null ? null : sf.file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current general analysis file
|
||||
* @return
|
||||
*/
|
||||
public static File getGeneralAnalysis()
|
||||
{
|
||||
StatisticsLoader.syncFileList();
|
||||
return generalAnalysis == null ? null : generalAnalysis.file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current general report file
|
||||
* @return
|
||||
*/
|
||||
public static File getGeneralReport()
|
||||
{
|
||||
StatisticsLoader.syncFileList();
|
||||
return generalReport == null ? null : generalReport.file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncronize the cached list of analysis / report files with the reports directory
|
||||
*
|
||||
* We synchronize if:
|
||||
*
|
||||
* 1) The number of files is different (ie. files have been added or removed)
|
||||
* 2) We haven't cached anything yet
|
||||
* 3) The cache was last generate over an hour ago
|
||||
*/
|
||||
private static void syncFileList()
|
||||
{
|
||||
// Get an array of all the analysis and report files present
|
||||
File[] fileList = StatisticsLoader.getAnalysisAndReportFileList();
|
||||
|
||||
if (fileList != null && fileList.length != fileCount)
|
||||
StatisticsLoader.loadFileList(fileList);
|
||||
else if (lastLoaded == null)
|
||||
StatisticsLoader.loadFileList(fileList);
|
||||
else if (DateUtils.addHours(lastLoaded, 1).before(new Date()))
|
||||
StatisticsLoader.loadFileList(fileList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the cached file list from the array of files
|
||||
* @param fileList
|
||||
*/
|
||||
private static synchronized void loadFileList(File[] fileList)
|
||||
{
|
||||
// If we haven't been passed an array of files, get one now
|
||||
if (fileList == null || fileList.length == 0)
|
||||
{
|
||||
fileList = StatisticsLoader.getAnalysisAndReportFileList();
|
||||
}
|
||||
|
||||
// Create new maps for the monthly analyis / reports
|
||||
Map<String, StatsFile> newMonthlyAnalysis = new HashMap<String, StatsFile>();
|
||||
Map<String, StatsFile> newMonthlyReports = new HashMap<String, StatsFile>();
|
||||
|
||||
StatsFile newGeneralAnalysis = null;
|
||||
StatsFile newGeneralReport = null;
|
||||
|
||||
if (fileList != null)
|
||||
{
|
||||
for (File thisFile : fileList)
|
||||
{
|
||||
StatsFile statsFile = null;
|
||||
|
||||
// If we haven't identified this file yet
|
||||
if (statsFile == null)
|
||||
{
|
||||
// See if it is a monthly analysis file
|
||||
statsFile = makeStatsFile(thisFile, analysisMonthlyPattern, monthlySDF);
|
||||
if (statsFile != null)
|
||||
{
|
||||
// If it is, add it to the map
|
||||
newMonthlyAnalysis.put(statsFile.dateStr, statsFile);
|
||||
}
|
||||
}
|
||||
|
||||
// If we haven't identified this file yet
|
||||
if (statsFile == null)
|
||||
{
|
||||
// See if it is a monthly report file
|
||||
statsFile = makeStatsFile(thisFile, reportMonthlyPattern, monthlySDF);
|
||||
if (statsFile != null)
|
||||
{
|
||||
// If it is, add it to the map
|
||||
newMonthlyReports.put(statsFile.dateStr, statsFile);
|
||||
}
|
||||
}
|
||||
|
||||
// If we haven't identified this file yet
|
||||
if (statsFile == null)
|
||||
{
|
||||
// See if it is a general analysis file
|
||||
statsFile = makeStatsFile(thisFile, analysisGeneralPattern, generalSDF);
|
||||
if (statsFile != null)
|
||||
{
|
||||
// If it is, ensure that we are pointing to the most recent file
|
||||
if (newGeneralAnalysis == null || statsFile.date.after(newGeneralAnalysis.date))
|
||||
{
|
||||
newGeneralAnalysis = statsFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we haven't identified this file yet
|
||||
if (statsFile == null)
|
||||
{
|
||||
// See if it is a general report file
|
||||
statsFile = makeStatsFile(thisFile, reportGeneralPattern, generalSDF);
|
||||
if (statsFile != null)
|
||||
{
|
||||
// If it is, ensure that we are pointing to the most recent file
|
||||
if (newGeneralReport == null || statsFile.date.after(newGeneralReport.date))
|
||||
{
|
||||
newGeneralReport = statsFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the newly discovered values in the member cache
|
||||
monthlyAnalysis = newMonthlyAnalysis;
|
||||
monthlyReports = newMonthlyReports;
|
||||
generalAnalysis = newGeneralAnalysis;
|
||||
generalReport = newGeneralReport;
|
||||
lastLoaded = new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a StatsFile entry for this file. The pattern and date formatters are used to
|
||||
* identify the file as a particular type, and extract the relevant information.
|
||||
* If the file is not identified by the formatter provided, then we return null
|
||||
* @param thisFile
|
||||
* @param thisPattern
|
||||
* @param sdf
|
||||
* @return
|
||||
*/
|
||||
private static StatsFile makeStatsFile(File thisFile, Pattern thisPattern, SimpleDateFormat sdf)
|
||||
{
|
||||
Matcher matcher = thisPattern.matcher(thisFile.getName());
|
||||
if (matcher.matches())
|
||||
{
|
||||
StatsFile sf = new StatsFile();
|
||||
sf.file = thisFile;
|
||||
sf.path = thisFile.getPath();
|
||||
sf.dateStr = matcher.group(1).trim();
|
||||
|
||||
try
|
||||
{
|
||||
sf.date = sdf.parse(sf.dateStr);
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return sf;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all the analysis and report files
|
||||
* @return
|
||||
*/
|
||||
private static File[] getAnalysisAndReportFileList()
|
||||
{
|
||||
File reportDir = new File(ConfigurationManager.getProperty("report.dir"));
|
||||
if (reportDir != null)
|
||||
{
|
||||
return reportDir.listFiles(new AnalysisAndReportFilter());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple class for holding information about an analysis/report file
|
||||
*/
|
||||
private static class StatsFile
|
||||
{
|
||||
File file;
|
||||
String path;
|
||||
Date date;
|
||||
String dateStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter used to restrict files in the reports directory to just analysis or report types
|
||||
*/
|
||||
private static class AnalysisAndReportFilter implements FilenameFilter
|
||||
{
|
||||
public boolean accept(File dir, String name)
|
||||
{
|
||||
if (analysisMonthlyPattern.matcher(name).matches())
|
||||
return true;
|
||||
|
||||
if (analysisGeneralPattern.matcher(name).matches())
|
||||
return true;
|
||||
|
||||
if (reportMonthlyPattern.matcher(name).matches())
|
||||
return true;
|
||||
|
||||
if (reportGeneralPattern.matcher(name).matches())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -109,6 +109,8 @@ public class Navigation extends AbstractDSpaceTransformer implements CacheablePr
|
||||
private static final Message T_context_export_community = message("xmlui.administrative.Navigation.context_export_community");
|
||||
private static final Message T_account_export = message("xmlui.administrative.Navigation.account_export");
|
||||
|
||||
private static final Message T_statistics = message("xmlui.administrative.Navigation.statistics");
|
||||
|
||||
|
||||
/** exports available for download */
|
||||
java.util.List<String> availableExports = null;
|
||||
@@ -303,6 +305,7 @@ public class Navigation extends AbstractDSpaceTransformer implements CacheablePr
|
||||
admin.addItemXref(contextPath+"/admin/item", T_administrative_items);
|
||||
admin.addItemXref(contextPath+"/admin/withdrawn", T_administrative_withdrawn);
|
||||
admin.addItemXref(contextPath+"/admin/panel", T_administrative_control_panel);
|
||||
admin.addItemXref(contextPath+"/statistics", T_statistics);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -88,18 +88,6 @@ public class Navigation extends AbstractDSpaceTransformer implements CacheablePr
|
||||
private static final Message T_communities_and_collections =
|
||||
message("xmlui.ArtifactBrowser.Navigation.communities_and_collections");
|
||||
|
||||
private static final Message T_browse_titles =
|
||||
message("xmlui.ArtifactBrowser.Navigation.browse_titles");
|
||||
|
||||
private static final Message T_browse_authors =
|
||||
message("xmlui.ArtifactBrowser.Navigation.browse_authors");
|
||||
|
||||
private static final Message T_browse_subjects =
|
||||
message("xmlui.ArtifactBrowser.Navigation.browse_subjects");
|
||||
|
||||
private static final Message T_browse_dates =
|
||||
message("xmlui.ArtifactBrowser.Navigation.browse_dates");
|
||||
|
||||
private static final Message T_head_this_collection =
|
||||
message("xmlui.ArtifactBrowser.Navigation.head_this_collection");
|
||||
|
||||
|
@@ -0,0 +1,640 @@
|
||||
/*
|
||||
* Statistics.java
|
||||
*
|
||||
* Version: $Revision: 1.0 $
|
||||
*
|
||||
* Date: $Date: 2007/08/28 10:00:00 $
|
||||
*
|
||||
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
|
||||
* Institute of Technology. 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 Hewlett-Packard Company nor the name of the
|
||||
* Massachusetts Institute of Technology nor the names of their
|
||||
* 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.xmlui.aspect.artifactbrowser;
|
||||
|
||||
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
|
||||
import org.dspace.app.xmlui.wing.element.*;
|
||||
import org.dspace.app.xmlui.wing.element.List;
|
||||
import org.dspace.app.xmlui.wing.WingException;
|
||||
import org.dspace.app.xmlui.wing.Message;
|
||||
import org.dspace.app.xmlui.utils.UIException;
|
||||
import org.dspace.app.xmlui.utils.DSpaceValidity;
|
||||
import org.dspace.app.statistics.*;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.apache.cocoon.caching.CacheableProcessingComponent;
|
||||
import org.apache.cocoon.environment.Request;
|
||||
import org.apache.cocoon.environment.ObjectModelHelper;
|
||||
import org.apache.excalibur.source.SourceValidity;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* Transformer to display statistics data in XML UI.
|
||||
*
|
||||
* Unlike the JSP interface that pre-generates HTML and stores in the reports folder,
|
||||
* this class transforms the raw analysis data into a Wing representation
|
||||
*/
|
||||
public class StatisticsViewer extends AbstractDSpaceTransformer implements CacheableProcessingComponent
|
||||
{
|
||||
private final static Logger log = Logger.getLogger(StatisticsViewer.class);
|
||||
|
||||
private final static Message T_dspace_home = message("xmlui.general.dspace_home");
|
||||
|
||||
private final static Message T_choose_report = message("xmlui.ArtifactBrowser.StatisticsViewer.choose_month");
|
||||
private final static Message T_page_title = message("xmlui.ArtifactBrowser.StatisticsViewer.report.title");
|
||||
|
||||
private final static Message T_empty_title = message("xmlui.ArtifactBrowser.StatisticsViewer.no_report.title");
|
||||
private final static Message T_empty_text = message("xmlui.ArtifactBrowser.StatisticsViewer.no_report.text");
|
||||
|
||||
private final static SimpleDateFormat sdfDisplay = new SimpleDateFormat("MM'/'yyyy");
|
||||
private final static SimpleDateFormat sdfLink = new SimpleDateFormat("yyyy'-'M");
|
||||
|
||||
private boolean initialised = false;
|
||||
private String reportDate = null;
|
||||
private SourceValidity validity;
|
||||
|
||||
/**
|
||||
* Get the caching key for this report
|
||||
* @return
|
||||
*/
|
||||
public Serializable getKey()
|
||||
{
|
||||
initialise();
|
||||
|
||||
if (reportDate != null)
|
||||
return reportDate;
|
||||
|
||||
return "general";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the validity for this cached entry
|
||||
* @return
|
||||
*/
|
||||
public SourceValidity getValidity()
|
||||
{
|
||||
if (validity == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
initialise();
|
||||
boolean showReport = ConfigurationManager.getBooleanProperty("report.public");
|
||||
|
||||
// If the report isn't public
|
||||
if (!showReport)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Administrators can always view reports
|
||||
showReport = AuthorizeManager.isAdmin(context);
|
||||
}
|
||||
catch (SQLException sqle)
|
||||
{
|
||||
log.error("Unable to check for administrator", sqle);
|
||||
}
|
||||
}
|
||||
|
||||
// Only generate a validity if the report is visible
|
||||
if (showReport)
|
||||
{
|
||||
File analysisFile = null;
|
||||
|
||||
// Get a file for the report data
|
||||
if (reportDate != null)
|
||||
analysisFile = StatisticsLoader.getAnalysisFor(reportDate);
|
||||
else
|
||||
analysisFile = StatisticsLoader.getGeneralAnalysis();
|
||||
|
||||
if (analysisFile != null)
|
||||
{
|
||||
// Generate the validity based on the properties of the report data file
|
||||
DSpaceValidity newValidity = new DSpaceValidity();
|
||||
newValidity.add(Long.toString(analysisFile.lastModified()));
|
||||
newValidity.add("-");
|
||||
newValidity.add(Long.toString(analysisFile.length()));
|
||||
validity = newValidity.complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return validity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional navigation options. This is to allow selection of a monthly report
|
||||
*
|
||||
* @param options
|
||||
* @throws SAXException
|
||||
* @throws WingException
|
||||
* @throws UIException
|
||||
* @throws SQLException
|
||||
* @throws IOException
|
||||
* @throws AuthorizeException
|
||||
*/
|
||||
public void addOptions(Options options) throws SAXException, WingException,
|
||||
UIException, SQLException, IOException, AuthorizeException
|
||||
{
|
||||
Date[] monthlyDates = StatisticsLoader.getMonthlyAnalysisDates();
|
||||
|
||||
if (monthlyDates != null && monthlyDates.length > 0)
|
||||
{
|
||||
List statList = options.addList("statsreports");
|
||||
statList.setHead(T_choose_report);
|
||||
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
for (Date date : monthlyDates)
|
||||
{
|
||||
params.put("date", sdfLink.format(date));
|
||||
statList.addItemXref(super.generateURL("statistics", params), sdfDisplay.format(date));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add title, etc. metadata
|
||||
*
|
||||
* @param pageMeta
|
||||
* @throws SAXException
|
||||
* @throws WingException
|
||||
* @throws UIException
|
||||
* @throws SQLException
|
||||
* @throws IOException
|
||||
* @throws AuthorizeException
|
||||
*/
|
||||
public void addPageMeta(PageMeta pageMeta) throws SAXException, WingException, UIException,
|
||||
SQLException, IOException, AuthorizeException
|
||||
{
|
||||
initialise();
|
||||
|
||||
pageMeta.addMetadata("title").addContent(T_page_title);
|
||||
pageMeta.addTrailLink(contextPath + "/", T_dspace_home);
|
||||
pageMeta.addTrail().addContent(T_page_title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the body of the report
|
||||
*
|
||||
* @param body
|
||||
* @throws SAXException
|
||||
* @throws WingException
|
||||
* @throws UIException
|
||||
* @throws SQLException
|
||||
* @throws IOException
|
||||
* @throws AuthorizeException
|
||||
*/
|
||||
public void addBody(Body body) throws SAXException, WingException, UIException, SQLException,
|
||||
IOException, AuthorizeException
|
||||
{
|
||||
initialise();
|
||||
boolean publicise = ConfigurationManager.getBooleanProperty("report.public");
|
||||
|
||||
// Check that the reports are either public, or user is an administrator
|
||||
if (!publicise && !AuthorizeManager.isAdmin(context))
|
||||
throw new AuthorizeException();
|
||||
|
||||
// Retrieve the report data to display
|
||||
File analysisFile;
|
||||
if (reportDate != null)
|
||||
analysisFile = StatisticsLoader.getAnalysisFor(reportDate);
|
||||
else
|
||||
analysisFile = StatisticsLoader.getGeneralAnalysis();
|
||||
|
||||
// Create the renderer for the results
|
||||
Division div = body.addDivision("statistics", "primary");
|
||||
|
||||
if (analysisFile != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Generate the XML stream
|
||||
Report myRep = new XMLUIReport(div);
|
||||
ReportGenerator.processReport(context, myRep, analysisFile.getCanonicalPath());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new UIException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
div.setHead(T_empty_title);
|
||||
div.addPara(T_empty_text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the member variables from the request
|
||||
*/
|
||||
private void initialise()
|
||||
{
|
||||
if (!initialised)
|
||||
{
|
||||
Request request = ObjectModelHelper.getRequest(objectModel);
|
||||
reportDate = (String) request.getParameter("date");
|
||||
|
||||
initialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the member variables so that the instance can be reused
|
||||
*/
|
||||
public void recycle()
|
||||
{
|
||||
initialised = false;
|
||||
reportDate = null;
|
||||
validity = null;
|
||||
super.recycle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the Report interface, to output the statistics data for xmlui
|
||||
* Note that all methods that return Strings return 'null' in this implementation, as
|
||||
* all the outputting is done directly using the Wing framework.
|
||||
*/
|
||||
class XMLUIReport implements Report
|
||||
{
|
||||
private ArrayList<Statistics> blocks = new ArrayList<Statistics>();
|
||||
|
||||
private String mainTitle = null;
|
||||
private String pageTitle = null;
|
||||
|
||||
/** start date for report */
|
||||
private Date start = null;
|
||||
|
||||
/** end date for report */
|
||||
private Date end = null;
|
||||
|
||||
private Division rootDiv;
|
||||
private Division currDiv;
|
||||
|
||||
/**
|
||||
* Hide the default constructor, so that you have to pass in a Division
|
||||
*/
|
||||
private XMLUIReport() {}
|
||||
|
||||
/**
|
||||
* Create instance, providing the Wing element that we will be adding to
|
||||
*
|
||||
* @param myDiv
|
||||
*/
|
||||
public XMLUIReport(Division myDiv)
|
||||
{
|
||||
rootDiv = myDiv;
|
||||
currDiv = myDiv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the header for the report - currently not supported
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String header()
|
||||
{
|
||||
return header("");
|
||||
}
|
||||
|
||||
// Currently not supported
|
||||
public String header(String title)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the main title to the report
|
||||
* @return
|
||||
*/
|
||||
public String mainTitle()
|
||||
{
|
||||
try
|
||||
{
|
||||
rootDiv.setHead(mainTitle);
|
||||
}
|
||||
catch (WingException we)
|
||||
{
|
||||
log.error("Error creating XML for report", we);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the date range for this report
|
||||
* @return
|
||||
*/
|
||||
public String dateRange()
|
||||
{
|
||||
StringBuilder content = new StringBuilder();
|
||||
DateFormat df = DateFormat.getDateInstance();
|
||||
if (start != null)
|
||||
{
|
||||
content.append(df.format(start));
|
||||
}
|
||||
else
|
||||
{
|
||||
content.append("from start of records ");
|
||||
}
|
||||
|
||||
content.append(" to ");
|
||||
|
||||
if (end != null)
|
||||
{
|
||||
content.append(df.format(end));
|
||||
}
|
||||
else
|
||||
{
|
||||
content.append(" end of records");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
rootDiv.addDivision("reportDate").addPara(content.toString());
|
||||
}
|
||||
catch (WingException we)
|
||||
{
|
||||
log.error("Error creating XML for report", we);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the section header
|
||||
* @param title
|
||||
* @return
|
||||
*/
|
||||
public String sectionHeader(String title)
|
||||
{
|
||||
try
|
||||
{
|
||||
currDiv.setHead(title);
|
||||
}
|
||||
catch (WingException we)
|
||||
{
|
||||
log.error("Error creating XML for report", we);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the current statistics block
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
public String statBlock(Statistics content)
|
||||
{
|
||||
Stat[] stats = content.getStats();
|
||||
try
|
||||
{
|
||||
int rows = stats.length;
|
||||
if (content.getStatName() != null || content.getResultName() != null)
|
||||
rows++;
|
||||
|
||||
Table block = currDiv.addTable("reportBlock", rows, 2);
|
||||
|
||||
// prepare the table headers
|
||||
if (content.getStatName() != null || content.getResultName() != null)
|
||||
{
|
||||
Row row = block.addRow();
|
||||
if (content.getStatName() != null)
|
||||
{
|
||||
row.addCellContent(content.getStatName());
|
||||
}
|
||||
else
|
||||
{
|
||||
row.addCellContent(" ");
|
||||
}
|
||||
|
||||
if (content.getResultName() != null)
|
||||
{
|
||||
row.addCellContent(content.getResultName());
|
||||
}
|
||||
else
|
||||
{
|
||||
row.addCellContent(" ");
|
||||
}
|
||||
}
|
||||
|
||||
// output the statistics in the table
|
||||
for (int i = 0; i < stats.length; i++)
|
||||
{
|
||||
Row row = block.addRow();
|
||||
if (stats[i].getReference() != null)
|
||||
{
|
||||
row.addCell().addXref(stats[i].getReference()).addContent(stats[i].getKey());
|
||||
}
|
||||
else
|
||||
{
|
||||
row.addCell().addContent(stats[i].getKey());
|
||||
}
|
||||
|
||||
if (stats[i].getUnits() != null)
|
||||
{
|
||||
row.addCell(null, null, "right").addContent(stats[i].getValue() + " " + stats[i].getUnits());
|
||||
}
|
||||
else
|
||||
{
|
||||
row.addCell(null, null, "right").addContent(ReportTools.numberFormat(stats[i].getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (WingException we)
|
||||
{
|
||||
log.error("Error creating XML for report", we);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output any information about the lower boundary restriction for this section
|
||||
* @param floor
|
||||
* @return
|
||||
*/
|
||||
public String floorInfo(int floor)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (floor > 0)
|
||||
{
|
||||
currDiv.addDivision("reportFloor").addPara("(more than " + ReportTools.numberFormat(floor) + " times)");
|
||||
}
|
||||
}
|
||||
catch (WingException we)
|
||||
{
|
||||
log.error("Error creating XML for report", we);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output an explanation for this section
|
||||
*
|
||||
* @param explanation
|
||||
* @return
|
||||
*/
|
||||
public String blockExplanation(String explanation)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (explanation != null)
|
||||
{
|
||||
currDiv.addDivision("reportExplanation").addPara(explanation);
|
||||
}
|
||||
}
|
||||
catch (WingException we)
|
||||
{
|
||||
log.error("Error creating XML for report", we);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the footer
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String footer()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the main title for this report
|
||||
*
|
||||
* @param name
|
||||
* @param serverName
|
||||
*/
|
||||
public void setMainTitle(String name, String serverName)
|
||||
{
|
||||
mainTitle = "Statistics for " + name;
|
||||
|
||||
if (ConfigurationManager.getBooleanProperty("report.show.server", true))
|
||||
mainTitle += " on " + serverName;
|
||||
|
||||
if (pageTitle == null)
|
||||
{
|
||||
pageTitle = mainTitle;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a block to report on
|
||||
*
|
||||
* @param stat
|
||||
*/
|
||||
public void addBlock(Statistics stat)
|
||||
{
|
||||
blocks.add(stat);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the statistics into an XML stream
|
||||
* @return
|
||||
*/
|
||||
public String render()
|
||||
{
|
||||
Pattern space = Pattern.compile(" ");
|
||||
|
||||
// Output the heading information
|
||||
header(pageTitle);
|
||||
mainTitle();
|
||||
dateRange();
|
||||
|
||||
// Loop through all the sections
|
||||
for (Statistics stats : blocks)
|
||||
{
|
||||
// navigation();
|
||||
try
|
||||
{
|
||||
String title = stats.getSectionHeader();
|
||||
String aName = title.toLowerCase();
|
||||
Matcher matchSpace = space.matcher(aName);
|
||||
aName = matchSpace.replaceAll("_");
|
||||
|
||||
// Create a new division for each section
|
||||
currDiv = rootDiv.addDivision(aName);
|
||||
sectionHeader(title);
|
||||
// topLink();
|
||||
blockExplanation(stats.getExplanation());
|
||||
floorInfo(stats.getFloor());
|
||||
statBlock(stats);
|
||||
currDiv = rootDiv;
|
||||
}
|
||||
catch (WingException we)
|
||||
{
|
||||
log.error("Error creating XML for report", we);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the start date for this report
|
||||
* @param start
|
||||
*/
|
||||
public void setStartDate(Date start)
|
||||
{
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the end date for this report
|
||||
* @param end
|
||||
*/
|
||||
public void setEndDate(Date end)
|
||||
{
|
||||
this.end = end;
|
||||
}
|
||||
}
|
||||
}
|
@@ -64,9 +64,9 @@ and searching the repository.
|
||||
<map:transformer name="Contact" src="org.dspace.app.xmlui.aspect.artifactbrowser.Contact"/>
|
||||
<map:transformer name="RestrictedItem" src="org.dspace.app.xmlui.aspect.artifactbrowser.RestrictedItem"/>
|
||||
<map:transformer name="FrontPageSearch" src="org.dspace.app.xmlui.aspect.artifactbrowser.FrontPageSearch"/>
|
||||
<map:transformer name="Statistics" src="org.dspace.app.xmlui.aspect.artifactbrowser.StatisticsViewer"/>
|
||||
</map:transformers>
|
||||
|
||||
|
||||
<map:matchers default="wildcard">
|
||||
<map:matcher name="HandleTypeMatcher" src="org.dspace.app.xmlui.aspect.general.HandleTypeMatcher"/>
|
||||
<map:matcher name="HandleAuthorizedMatcher" src="org.dspace.app.xmlui.aspect.general.HandleAuthorizedMatcher"/>
|
||||
@@ -244,6 +244,12 @@ and searching the repository.
|
||||
<!-- Handle specific features (legacy) -->
|
||||
<map:match pattern="handle/*/**">
|
||||
|
||||
<!-- Display statistics -->
|
||||
<map:match pattern="statistics">
|
||||
<map:transform type="Statistics"/>
|
||||
<map:serialize type="xml"/>
|
||||
</map:match>
|
||||
|
||||
<!-- Inform the user that the item they are viewing is a restricted resource -->
|
||||
<map:match pattern="handle/*/*/restricted-resource">
|
||||
<map:transform type="RestrictedItem"/>
|
||||
|
@@ -490,6 +490,10 @@ td {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
td.ds-table-cell.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
*.first-cell {
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
|
Reference in New Issue
Block a user