/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.aspect.statisticsElasticSearch;
import au.com.bytecode.opencsv.CSVWriter;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Response;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.reading.AbstractReader;
import org.apache.log4j.Logger;
import org.dspace.app.xmlui.aspect.statistics.StatisticsTransformer;
import org.dspace.app.xmlui.utils.ContextUtil;
import org.dspace.app.xmlui.utils.HandleUtil;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.content.Bitstream;
import org.dspace.content.Metadatum;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.facet.datehistogram.DateHistogramFacet;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.xml.sax.SAXException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Provides the usage statistics in CSV form
* @author Peter Dietz (pdietz84@gmail.com)
*/
public class CSVOutputter extends AbstractReader implements Recyclable
{
protected static final Logger log = Logger.getLogger(CSVOutputter.class);
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
protected Response response;
protected Request request;
protected Context context;
protected CSVWriter writer = null;
public void setup(SourceResolver sourceResolver, Map objectModel, String src, Parameters parameters) throws IOException, SAXException, ProcessingException {
log.info("CSV Writer for stats");
super.setup(sourceResolver, objectModel, src, parameters);
try {
//super.setup(sourceResolver, objectModel, src, parameters);
this.request = ObjectModelHelper.getRequest(objectModel);
this.response = ObjectModelHelper.getResponse(objectModel);
context = ContextUtil.obtainContext(objectModel);
String requestURI = request.getRequestURI();
String[] uriSegments = requestURI.split("/");
String requestedReport = uriSegments[uriSegments.length-1];
if(requestedReport == null || requestedReport.length() < 1) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
response.setContentType("text/csv; encoding='UTF-8'");
response.setStatus(HttpServletResponse.SC_OK);
writer = new CSVWriter(response.getWriter());
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
response.setHeader("Content-Disposition", "attachment; filename=KBStats-" + dso.getHandle() + "-" + requestedReport +".csv");
Map<String, String> params = new HashMap<String, String>();
for (Enumeration<String> paramNames = (Enumeration<String>) request.getParameterNames(); paramNames.hasMoreElements(); ) {
String param = paramNames.nextElement();
params.put(param, request.getParameter(param));
}
String fromValue = "";
if(params.containsKey("from")) {
fromValue = params.get("from");
}
String toValue = "";
if(params.containsKey("to")) {
toValue = params.get("to");
}
Date fromDate;
ReportGenerator reportGeneratorInstance = new ReportGenerator();
if(fromValue.length() > 0) {
fromDate = reportGeneratorInstance.tryParse(fromValue);
} else {
fromDate = null;
}
Date toDate;
if(toValue.length() > 0) {
toDate = reportGeneratorInstance.tryParse(toValue);
} else {
toDate = null;
}
ElasticSearchStatsViewer esStatsViewer = new ElasticSearchStatsViewer(dso, fromDate, toDate);
StatisticsTransformer statisticsTransformerInstance = new StatisticsTransformer(fromDate, toDate);
if(requestedReport.equalsIgnoreCase("topCountries"))
{
SearchRequestBuilder requestBuilder = esStatsViewer.facetedQueryBuilder(esStatsViewer.facetTopCountries);
SearchResponse searchResponse = requestBuilder.execute().actionGet();
TermsFacet topCountriesFacet = searchResponse.getFacets().facet(TermsFacet.class, "top_countries");
addTermFacetToWriter(topCountriesFacet, "");
}
else if (requestedReport.equalsIgnoreCase("fileDownloads"))
{
SearchRequestBuilder requestBuilder = esStatsViewer.facetedQueryBuilder(esStatsViewer.facetMonthlyDownloads);
SearchResponse searchResponse = requestBuilder.execute().actionGet();
DateHistogramFacet monthlyDownloadsFacet = searchResponse.getFacets().facet(DateHistogramFacet.class, "monthly_downloads");
addDateHistogramFacetToWriter(monthlyDownloadsFacet);
}
else if(requestedReport.equalsIgnoreCase("topDownloads"))
{
SearchRequestBuilder requestBuilder = esStatsViewer.facetedQueryBuilder(esStatsViewer.facetTopBitstreamsAllTime);
SearchResponse searchResponse = requestBuilder.execute().actionGet();
log.info(searchResponse.toString());
TermsFacet topBitstreams = searchResponse.getFacets().facet(TermsFacet.class, "top_bitstreams_alltime");
addTermFacetToWriter(topBitstreams, "bitstream");
}
else {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
} catch (SQLException e) {
log.error("Some Error:" + e.getMessage());
} catch (WingException e) {
log.error("Some Error:" + e.getMessage());
} catch (IOException e) {
log.error("Some Error:" + e.getMessage());
} finally {
try {
if(writer != null) {
writer.close();
} else {
log.error("CSV Writer was null!!");
}
} catch (IOException e) {
log.error("Hilarity Ensues... IO Exception while closing the csv writer.");
}
}
}
private void addTermFacetToWriter(TermsFacet termsFacet, String termType) throws SQLException {
List<? extends TermsFacet.Entry> termsFacetEntries = termsFacet.getEntries();
if(termType.equalsIgnoreCase("bitstream")) {
writer.writeNext(new String[]{"BitstreamID", "Bitstream Name", "Bitstream Bundle", "Item Title", "Item Handle", "Item Creator", "Item Publisher", "Item Issue Date", "Count"});
} else {
writer.writeNext(new String[]{"term", "count"});
}
if(termsFacetEntries.size() == 0) {
return;
}
for(TermsFacet.Entry facetEntry : termsFacetEntries)
{
if(termType.equalsIgnoreCase("bitstream"))
{
Bitstream bitstream = Bitstream.find(context, Integer.parseInt(facetEntry.getTerm().string()));
Item item = (Item) bitstream.getParentObject();
String[] entryValues = new String[9];
entryValues[0] = bitstream.getID() + "";
entryValues[1] = bitstream.getName();
entryValues[2] = bitstream.getBundles()[0].getName();
entryValues[3] = item.getName();
entryValues[4] = "http://hdl.handle.net/" + item.getHandle();
entryValues[5] = wrapInDelimitedString(item.getMetadataByMetadataString("dc.creator"));
entryValues[6] = wrapInDelimitedString(item.getMetadataByMetadataString("dc.publisher"));
entryValues[7] = wrapInDelimitedString(item.getMetadataByMetadataString("dc.date.issued"));
entryValues[8] = facetEntry.getCount() + "";
writer.writeNext(entryValues);
} else {
writer.writeNext(new String[]{facetEntry.getTerm().string(), String.valueOf(facetEntry.getCount())});
}
}
}
public String wrapInDelimitedString(Metadatum[] metadataEntries) {
StringBuilder metadataString = new StringBuilder();
for(Metadatum metadataEntry : metadataEntries) {
if(metadataString.length() > 0) {
// Delimit entries with the || double pipe character sequence.
metadataString.append("\\|\\|");
}
metadataString.append(metadataEntry.value);
}
return metadataString.toString();
}
private void addDateHistogramFacetToWriter(DateHistogramFacet dateHistogramFacet) {
List<? extends DateHistogramFacet.Entry> monthlyFacetEntries = dateHistogramFacet.getEntries();
if(monthlyFacetEntries.size() == 0) {
return;
}
writer.writeNext(new String[]{"Month", "Count"});
for(DateHistogramFacet.Entry histogramEntry : monthlyFacetEntries) {
Date facetDate = new Date(histogramEntry.getTime());
writer.writeNext(new String[]{dateFormat.format(facetDate), String.valueOf(histogramEntry.getCount())});
}
}
public void generate() throws IOException {
log.info("CSV Writer generator for stats");
out.flush();
out.close();
}
public void recycle() {
this.request = null;
this.response = null;
}
}