Adding Freemarker versions of PersonGrantCount (QueryRunner, RequestHandler, VisCodeGenerator) and related ftls (grantCount, grantSparklineContent)
This commit is contained in:
parent
4e4da7d08e
commit
809ae7b162
7 changed files with 1517 additions and 0 deletions
|
@ -0,0 +1,7 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#assign googleJSAPI = 'http://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22visualization%22%2C%22version%22%3A%221%22%2C%22packages%22%3A%5B%22areachart%22%2C%22imagesparkline%22%5D%7D%5D%7D'>
|
||||||
|
|
||||||
|
${headScripts.add(googleJSAPI)}
|
||||||
|
|
||||||
|
<#include "/visualization/grantSparklineContent.ftl">
|
|
@ -0,0 +1,243 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
<#assign visContainerID = '${sparklineVO.visContainerDivID}'>
|
||||||
|
|
||||||
|
<#if sparklineVO.shortVisMode>
|
||||||
|
<#assign sparklineContainerID = 'grant_count_short_sparkline_vis'>
|
||||||
|
<#else>
|
||||||
|
<#assign sparklineContainerID = 'grant_count_full_sparkline_vis'>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#-- This is used to prevent collision between sparkline & visualization container div ids. -->
|
||||||
|
<#if visContainerID?upper_case == sparklineContainerID?upper_case>
|
||||||
|
<#assign sparklineContainerID = visContainerID + "_spark">
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<div class="staticPageBackground">
|
||||||
|
|
||||||
|
<div id="${visContainerID}">
|
||||||
|
|
||||||
|
<style type='text/css'>
|
||||||
|
.sparkline_style table {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: auto;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
vertical-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.sparkline_wrapper_table
|
||||||
|
td,th {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vis_link a {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.sparkline_number {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.sparkline_text {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incomplete-data-holder {
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
function drawGrantCountVisualization(providedSparklineImgTD) {
|
||||||
|
|
||||||
|
var data = new google.visualization.DataTable();
|
||||||
|
data.addColumn('string', 'Year');
|
||||||
|
data.addColumn('number', 'Grants');
|
||||||
|
data.addRows(${sparklineVO.numOfYearsToBeRendered});
|
||||||
|
|
||||||
|
<#list sparklineVO.yearToGrantCountDataTable as yearToGrantCountDataElement>
|
||||||
|
data.setValue(${yearToGrantCountDataElement.grantCounter}, 0, '${yearToGrantCountDataElement.investigatedYear}');
|
||||||
|
data.setValue(${yearToGrantCountDataElement.grantCounter}, 1, ${yearToGrantCountDataElement.currentGrants});
|
||||||
|
</#list>
|
||||||
|
|
||||||
|
<#-- Create a view of the data containing only the column pertaining to grant count. -->
|
||||||
|
var sparklineDataView = new google.visualization.DataView(data);
|
||||||
|
sparklineDataView.setColumns([1]);
|
||||||
|
|
||||||
|
<#if sparklineVO.shortVisMode>
|
||||||
|
|
||||||
|
console.log("Yay! Short Vis Mode!");
|
||||||
|
|
||||||
|
<#-- For the short view we only want the last 10 year's view of grant count, hence we filter
|
||||||
|
the data we actually want to use for render. -->
|
||||||
|
|
||||||
|
sparklineDataView.setRows(data.getFilteredRows([{
|
||||||
|
column: 0,
|
||||||
|
minValue: '${sparklineVO.earliestRenderedGrantYear?c}',
|
||||||
|
maxValue: '${sparklineVO.latestRenderedGrantYear?c}'
|
||||||
|
/*minValue: '2001',
|
||||||
|
maxValue: '2011'*/
|
||||||
|
}]));
|
||||||
|
|
||||||
|
<#else>
|
||||||
|
|
||||||
|
console.log("Yay! Full Vis Mode!");
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#-- Create the vis object and draw it in the div pertaining to sparkline. -->
|
||||||
|
var sparkline = new google.visualization.ImageSparkLine(providedSparklineImgTD[0]);
|
||||||
|
sparkline.draw(sparklineDataView, {
|
||||||
|
width: 65,
|
||||||
|
height: 30,
|
||||||
|
showAxisLines: false,
|
||||||
|
showValueLabels: false,
|
||||||
|
labelPosition: 'none'
|
||||||
|
});
|
||||||
|
|
||||||
|
<#if sparklineVO.shortVisMode>
|
||||||
|
|
||||||
|
<#-- We want to display how many grant counts were considered, so this is used to calculate this. -->
|
||||||
|
|
||||||
|
var shortSparkRows = sparklineDataView.getViewRows();
|
||||||
|
var renderedShortSparks = 0;
|
||||||
|
$.each(shortSparkRows, function(index, value) {
|
||||||
|
renderedShortSparks += data.getValue(value, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#${sparklineContainerID} td.sparkline_number').text(parseInt(renderedShortSparks) + parseInt(${sparklineVO.unknownYearGrants}));
|
||||||
|
|
||||||
|
var sparksText = ' grant(s) within the last 10 years <span class="incomplete-data-holder" title="This information'
|
||||||
|
+ ' is based solely on grants which have been loaded into the VIVO system. This may only be a small'
|
||||||
|
+ ' sample of the person\'s total work.">incomplete list</span>';
|
||||||
|
|
||||||
|
<#else>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sparks that will be rendered will always be the one's which has
|
||||||
|
* any year associated with it. Hence.
|
||||||
|
* */
|
||||||
|
var renderedSparks = ${sparklineVO.renderedSparks};
|
||||||
|
$('#${sparklineContainerID} td.sparkline_number').text(parseInt(renderedSparks) + parseInt(${sparklineVO.unknownYearGrants}));
|
||||||
|
|
||||||
|
var sparksText = ' grant(s) from <span class="sparkline_range">${sparklineVO.earliestYearConsidered?c}'
|
||||||
|
+ ' to ${sparklineVO.latestRenderedGrantYear?c}</span> '
|
||||||
|
+ ' <a href="${sparklineVO.downloadDataLink}" class="inline_href">(.CSV File)</a> ';
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
$('#${sparklineContainerID} td.sparkline_text').html(sparksText);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This will activate the visualization. It takes care of creating
|
||||||
|
* div elements to hold the actual sparkline image and then calling the
|
||||||
|
* drawGrantCountVisualization function.
|
||||||
|
* */
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
var sparklineImgTD;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a nuclear option (creating the container in which everything goes)
|
||||||
|
* the only reason this will be ever used is the API user never submitted a
|
||||||
|
* container ID in which everything goes. The alternative was to let the
|
||||||
|
* vis not appear in the calling page at all. So now atleast vis appears but
|
||||||
|
* appended at the bottom of the body.
|
||||||
|
* */
|
||||||
|
|
||||||
|
if ($('#${visContainerID}').length === 0) {
|
||||||
|
$('<div/>', {
|
||||||
|
'id': '${visContainerID}'
|
||||||
|
}).appendTo('body');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($('#${sparklineContainerID}').length === 0) {
|
||||||
|
|
||||||
|
$('<div/>', {
|
||||||
|
'id': '${sparklineContainerID}',
|
||||||
|
'class': 'sparkline_style'
|
||||||
|
}).prependTo('#${visContainerID}');
|
||||||
|
|
||||||
|
var table = $('<table>');
|
||||||
|
table.attr('class', 'sparkline_wrapper_table');
|
||||||
|
var row = $('<tr>');
|
||||||
|
sparklineImgTD = $('<td>');
|
||||||
|
sparklineImgTD.attr('id', '${sparklineContainerID}_img');
|
||||||
|
sparklineImgTD.attr('width', '65');
|
||||||
|
sparklineImgTD.attr('align', 'right');
|
||||||
|
sparklineImgTD.attr('class', 'sparkline_style');
|
||||||
|
|
||||||
|
row.append(sparklineImgTD);
|
||||||
|
|
||||||
|
console.log(sparklineImgTD);
|
||||||
|
|
||||||
|
var sparklineNumberTD = $('<td>');
|
||||||
|
sparklineNumberTD.attr('width', '30');
|
||||||
|
sparklineNumberTD.attr('align', 'right');
|
||||||
|
sparklineNumberTD.attr('class', 'sparkline_number');
|
||||||
|
row.append(sparklineNumberTD);
|
||||||
|
var sparklineTextTD = $('<td>');
|
||||||
|
sparklineTextTD.attr('width', '450');
|
||||||
|
sparklineTextTD.attr('class', 'sparkline_text');
|
||||||
|
row.append(sparklineTextTD);
|
||||||
|
table.append(row);
|
||||||
|
table.prependTo('#${sparklineContainerID}');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(sparklineImgTD);
|
||||||
|
drawGrantCountVisualization(sparklineImgTD);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#if sparklineVO.shortVisMode>
|
||||||
|
|
||||||
|
<span class="vis_link">
|
||||||
|
<a href="${sparklineVO.fullTimelineNetworkLink}">View all grants and corresponding co-pi network.</a>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<#else>
|
||||||
|
|
||||||
|
<!-- For Full Sparkline - Print the Table of Grant Counts per Year -->
|
||||||
|
<p>
|
||||||
|
<table id='sparkline_data_table'>
|
||||||
|
<caption>
|
||||||
|
Grants per year <a href="${sparklineVO.downloadDataLink}">(.CSV File)</a>
|
||||||
|
</caption>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Year
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Grants
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
<#list sparklineVO.yearToActivityCount?keys as year>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
${year}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
${sparklineVO.yearToActivityCount[year]}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</#list>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
Download data as <a href="${sparklineVO.downloadDataLink}">.csv</a> file.
|
||||||
|
<br />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,161 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.persongrantcount;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.iri.IRI;
|
||||||
|
import com.hp.hpl.jena.iri.IRIFactory;
|
||||||
|
import com.hp.hpl.jena.iri.Violation;
|
||||||
|
import com.hp.hpl.jena.query.DataSource;
|
||||||
|
import com.hp.hpl.jena.query.Query;
|
||||||
|
import com.hp.hpl.jena.query.QueryExecution;
|
||||||
|
import com.hp.hpl.jena.query.QueryExecutionFactory;
|
||||||
|
import com.hp.hpl.jena.query.QueryFactory;
|
||||||
|
import com.hp.hpl.jena.query.QuerySolution;
|
||||||
|
import com.hp.hpl.jena.query.ResultSet;
|
||||||
|
import com.hp.hpl.jena.query.Syntax;
|
||||||
|
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryFieldLabels;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Grant;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Individual;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This query runner is used to execute Sparql query that will fetch all the grants for an individual
|
||||||
|
* @author bkoniden
|
||||||
|
* Deepak Konidena
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PersonGrantCountQueryRunner implements QueryRunner<Set<Grant>>{
|
||||||
|
|
||||||
|
protected static final Syntax SYNTAX = Syntax.syntaxARQ;
|
||||||
|
|
||||||
|
private String personURI;
|
||||||
|
private DataSource dataSource;
|
||||||
|
private Individual principalInvestigator;
|
||||||
|
|
||||||
|
public Individual getPrincipalInvestigator(){
|
||||||
|
return principalInvestigator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Log log;
|
||||||
|
|
||||||
|
private static final String SPARQL_QUERY_COMMON_SELECT_CLAUSE = ""
|
||||||
|
+ "SELECT (str(?PILabel) as ?PILabelLit) "
|
||||||
|
+ "(str(?Grant) as ?grantLit)"
|
||||||
|
+ "(str(?GrantLabel) as ?grantLabelLit)"
|
||||||
|
+ "(str(?GrantStartDate) as ?grantStartDateLit)"
|
||||||
|
+ "(str(?GrantEndDate) as ?grantEndDateLit)" ;
|
||||||
|
|
||||||
|
public PersonGrantCountQueryRunner(String personURI, DataSource dataSource, Log log){
|
||||||
|
|
||||||
|
this.personURI = personURI;
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<Grant> createJavaValueObjects(ResultSet resultSet){
|
||||||
|
Set<Grant> PIGrant = new HashSet<Grant>();
|
||||||
|
|
||||||
|
while(resultSet.hasNext()){
|
||||||
|
QuerySolution solution = resultSet.nextSolution();
|
||||||
|
|
||||||
|
Grant grant = new Grant(solution.get(QueryFieldLabels.GRANT_URL).toString());
|
||||||
|
|
||||||
|
RDFNode grantLabelNode = solution.get(QueryFieldLabels.GRANT_LABEL);
|
||||||
|
if(grantLabelNode != null){
|
||||||
|
grant.setIndividualLabel(grantLabelNode.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
RDFNode grantStartDateNode = solution.get(QueryFieldLabels.GRANT_START_DATE);
|
||||||
|
if(grantStartDateNode != null){
|
||||||
|
grant.setGrantStartDate(grantStartDateNode.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
RDFNode grantEndDateNode = solution.get(QueryFieldLabels.GRANT_END_DATE);
|
||||||
|
if(grantEndDateNode != null){
|
||||||
|
grant.setGrantEndDate(grantEndDateNode.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since we are getting grant count for just one PI at a time we need
|
||||||
|
* to create only one "Individual" instance. We test against the null for "PI" to
|
||||||
|
* make sure that it has not already been instantiated.
|
||||||
|
* */
|
||||||
|
RDFNode PIURLNode = solution.get(QueryFieldLabels.PI_URL);
|
||||||
|
if (PIURLNode != null && principalInvestigator == null) {
|
||||||
|
principalInvestigator = new Individual(PIURLNode.toString());
|
||||||
|
RDFNode PILabelNode = solution.get(QueryFieldLabels.PI_LABEL);
|
||||||
|
if (PILabelNode != null) {
|
||||||
|
principalInvestigator.setIndividualLabel(PILabelNode.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PIGrant.add(grant);
|
||||||
|
}
|
||||||
|
return PIGrant;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultSet executeQuery(String queryURI, DataSource dataSource){
|
||||||
|
|
||||||
|
QueryExecution queryExecution = null;
|
||||||
|
|
||||||
|
Query query = QueryFactory.create(getSparqlQuery(queryURI), SYNTAX);
|
||||||
|
queryExecution = QueryExecutionFactory.create(query,dataSource);
|
||||||
|
|
||||||
|
return queryExecution.execSelect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String getSparqlQuery(String queryURI){
|
||||||
|
|
||||||
|
String sparqlQuery = QueryConstants.getSparqlPrefixQuery()
|
||||||
|
+ SPARQL_QUERY_COMMON_SELECT_CLAUSE
|
||||||
|
+ "(str(<" + queryURI + ">) as ?PILit) "
|
||||||
|
+ "WHERE {"
|
||||||
|
+ "<" + queryURI + "> rdfs:label ?PILabel;"
|
||||||
|
+ "core:hasCo-PrincipalInvestigatorRole ?Role ."
|
||||||
|
+ "?Role core:roleIn ?Grant ."
|
||||||
|
+ "?Grant rdfs:label ?GrantLabel ; core:startDate ?GrantStartDate ; core:endDate ?GrantEndDate ."
|
||||||
|
+ "}";
|
||||||
|
|
||||||
|
System.out.println("SPARQL query for person grant count -> \n"+ sparqlQuery);
|
||||||
|
return sparqlQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Grant> getQueryResult() throws MalformedQueryParametersException{
|
||||||
|
|
||||||
|
if(StringUtils.isNotBlank(this.personURI)){
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To test the validity of the URI submitted
|
||||||
|
*/
|
||||||
|
IRIFactory iriFactory = IRIFactory.jenaImplementation();
|
||||||
|
IRI iri = iriFactory.create(this.personURI);
|
||||||
|
|
||||||
|
if(iri.hasViolation(false)){
|
||||||
|
String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage();
|
||||||
|
log.error("Grant Count vis Query " + errorMsg);
|
||||||
|
throw new MalformedQueryParametersException(
|
||||||
|
"URI provided for an individual is malformed.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new MalformedQueryParametersException("URL parameter is either null or empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultSet resultSet = executeQuery(this.personURI, this.dataSource);
|
||||||
|
|
||||||
|
return createJavaValueObjects(resultSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,375 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.persongrantcount;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import javax.servlet.RequestDispatcher;
|
||||||
|
import javax.servlet.ServletOutputStream;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringEscapeUtils;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.query.DataSource;
|
||||||
|
import com.itextpdf.text.Document;
|
||||||
|
import com.itextpdf.text.DocumentException;
|
||||||
|
import com.itextpdf.text.pdf.PdfWriter;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.FileResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Grant;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Individual;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.SparklineData;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.web.ContentType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This request handler is used to serve the content related to an individual's
|
||||||
|
* grants over the years like,
|
||||||
|
* 1. Sparkline representing this
|
||||||
|
* 2. An entire page dedicated to the sparkline vis which will also have links to
|
||||||
|
* download the data using which the sparkline was rendered & its tabular representation etc.
|
||||||
|
* 3. Downloadable CSV file containing number of grants over the years.
|
||||||
|
* 4. Downloadable PDf file containing the grant content, among other things.
|
||||||
|
* Currently this is disabled because the feature is half-baked. We plan to activate this in
|
||||||
|
* the next major release.
|
||||||
|
*
|
||||||
|
* @author bkoniden
|
||||||
|
* Deepak Konidena
|
||||||
|
*/
|
||||||
|
public class PersonGrantCountRequestHandler implements VisualizationRequestHandler {
|
||||||
|
|
||||||
|
public ResponseValues generateVisualization(VitroRequest vitroRequest,
|
||||||
|
Log log, DataSource dataSource) {
|
||||||
|
|
||||||
|
String personURI = vitroRequest
|
||||||
|
.getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
|
||||||
|
|
||||||
|
String renderMode = vitroRequest
|
||||||
|
.getParameter(VisualizationFrameworkConstants.RENDER_MODE_KEY);
|
||||||
|
|
||||||
|
String visMode = vitroRequest
|
||||||
|
.getParameter(VisualizationFrameworkConstants.VIS_MODE_KEY);
|
||||||
|
|
||||||
|
String visContainer = vitroRequest
|
||||||
|
.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_KEY);
|
||||||
|
|
||||||
|
QueryRunner<Set<Grant>> queryManager = new PersonGrantCountQueryRunner(personURI, dataSource, log );
|
||||||
|
|
||||||
|
try{
|
||||||
|
Set<Grant> piGrants = queryManager.getQueryResult();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a map from the year to number of grants. Use the Grant's
|
||||||
|
* parsedGrantYear to populate the data.
|
||||||
|
* */
|
||||||
|
Map<String, Integer> yearToGrantCount =
|
||||||
|
UtilityFunctions.getYearToGrantCount(piGrants);
|
||||||
|
|
||||||
|
Individual investigator = ((PersonGrantCountQueryRunner) queryManager).getPrincipalInvestigator();
|
||||||
|
|
||||||
|
if (VisualizationFrameworkConstants.DATA_RENDER_MODE
|
||||||
|
.equalsIgnoreCase(renderMode)) {
|
||||||
|
|
||||||
|
return prepareDataResponse(investigator,
|
||||||
|
piGrants,
|
||||||
|
yearToGrantCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For now we are disabling the capability to render pdf file.
|
||||||
|
* */
|
||||||
|
/*
|
||||||
|
if (VisualizationFrameworkConstants.PDF_RENDER_MODE
|
||||||
|
.equalsIgnoreCase(renderMode)) {
|
||||||
|
|
||||||
|
preparePDFResponse(investigator,
|
||||||
|
piGrants,
|
||||||
|
yearToGrantCount,
|
||||||
|
response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Computations required to generate HTML for the sparkline & related context.
|
||||||
|
* */
|
||||||
|
PersonGrantCountVisCodeGenerator visualizationCodeGenerator =
|
||||||
|
new PersonGrantCountVisCodeGenerator(vitroRequest.getContextPath(),
|
||||||
|
personURI,
|
||||||
|
visMode,
|
||||||
|
visContainer,
|
||||||
|
piGrants,
|
||||||
|
yearToGrantCount,
|
||||||
|
log);
|
||||||
|
|
||||||
|
SparklineData sparklineData = visualizationCodeGenerator
|
||||||
|
.getValueObjectContainer();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is side-effecting because the response of this method is just to redirect to
|
||||||
|
* a page with visualization on it.
|
||||||
|
* */
|
||||||
|
RequestDispatcher requestDispatcher = null;
|
||||||
|
|
||||||
|
if (VisualizationFrameworkConstants.DYNAMIC_RENDER_MODE
|
||||||
|
.equalsIgnoreCase(renderMode)) {
|
||||||
|
|
||||||
|
return prepareDynamicResponse(vitroRequest,
|
||||||
|
sparklineData,
|
||||||
|
yearToGrantCount);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return prepareStandaloneResponse(vitroRequest,
|
||||||
|
sparklineData);
|
||||||
|
}
|
||||||
|
} catch (MalformedQueryParametersException e) {
|
||||||
|
return UtilityFunctions.handleMalformedParameters(
|
||||||
|
"Visualization Query Error - Individual Grant Count",
|
||||||
|
e.getMessage(),
|
||||||
|
vitroRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getGrantsOverTimeCSVContent(Map<String, Integer> yearToGrantCount) {
|
||||||
|
|
||||||
|
StringBuilder csvFileContent = new StringBuilder();
|
||||||
|
|
||||||
|
csvFileContent.append("Year, Grants\n");
|
||||||
|
|
||||||
|
for (Entry<String, Integer> currentEntry : yearToGrantCount.entrySet()) {
|
||||||
|
csvFileContent.append(StringEscapeUtils.escapeCsv(currentEntry.getKey()));
|
||||||
|
csvFileContent.append(",");
|
||||||
|
csvFileContent.append(currentEntry.getValue());
|
||||||
|
csvFileContent.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return csvFileContent.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides response when csv file containing the grant count over the years
|
||||||
|
* is requested.
|
||||||
|
* @param investigator
|
||||||
|
* @param piGrants
|
||||||
|
* @param yearToGrantCount
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private FileResponseValues prepareDataResponse(
|
||||||
|
Individual investigator,
|
||||||
|
Set<Grant> piGrants,
|
||||||
|
Map<String, Integer> yearToGrantCount) {
|
||||||
|
|
||||||
|
|
||||||
|
String piName = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To protect against cases where there are no PI grants associated with the
|
||||||
|
* individual.
|
||||||
|
* */
|
||||||
|
if (piGrants.size() > 0) {
|
||||||
|
piName = investigator.getIndividualLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To make sure that null/empty records for PI names do not cause any mischief.
|
||||||
|
* */
|
||||||
|
if (StringUtils.isBlank(piName)) {
|
||||||
|
piName = "no-principal-investigator";
|
||||||
|
}
|
||||||
|
|
||||||
|
String outputFileName = UtilityFunctions.slugify(piName)
|
||||||
|
+ "_grants-per-year" + ".csv";
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, Object> fileContents = new HashMap<String, Object>();
|
||||||
|
fileContents.put("fileContent", getGrantsOverTimeCSVContent(yearToGrantCount));
|
||||||
|
|
||||||
|
return new FileResponseValues(new ContentType(), outputFileName, fileContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides response when an entire page dedicated to grant sparkline is requested.
|
||||||
|
* @param vreq
|
||||||
|
* @param valueObjectContainer
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private TemplateResponseValues prepareStandaloneResponse(VitroRequest vreq,
|
||||||
|
SparklineData valueObjectContainer) {
|
||||||
|
|
||||||
|
Portal portal = vreq.getPortal();
|
||||||
|
|
||||||
|
String standaloneTemplate = "/visualization/grantCount.ftl";
|
||||||
|
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
body.put("portalBean", portal);
|
||||||
|
body.put("title", "Individual Grant Count visualization");
|
||||||
|
body.put("sparklineVO", valueObjectContainer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DO NOT DO THIS HERE. Set stylesheets/scripts in the *.ftl instead using $(scripts.add)
|
||||||
|
* */
|
||||||
|
// body.put("scripts", "/templates/visualization/visualization_scripts.jsp");
|
||||||
|
|
||||||
|
return new TemplateResponseValues(standaloneTemplate, body);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides response when the grant sparkline has to be rendered in already existing
|
||||||
|
* page, e.g. profile page.
|
||||||
|
* @param vreq
|
||||||
|
* @param valueObjectContainer
|
||||||
|
* @param yearToGrantCount
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private TemplateResponseValues prepareDynamicResponse(
|
||||||
|
VitroRequest vreq,
|
||||||
|
SparklineData valueObjectContainer,
|
||||||
|
Map<String, Integer> yearToGrantCount) {
|
||||||
|
|
||||||
|
Portal portal = vreq.getPortal();
|
||||||
|
|
||||||
|
|
||||||
|
String dynamicTemplate = "/visualization/sparklineAjaxVisContent.ftl";
|
||||||
|
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
body.put("portalBean", portal);
|
||||||
|
body.put("sparklineVO", valueObjectContainer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DO NOT DO THIS HERE. Set stylesheets/scripts in the *.ftl instead using $(scripts.add)
|
||||||
|
* */
|
||||||
|
// body.put("scripts", "/templates/visualization/visualization_scripts.jsp");
|
||||||
|
|
||||||
|
if (yearToGrantCount.size() > 0) {
|
||||||
|
body.put("shouldVIVOrenderVis", true);
|
||||||
|
} else {
|
||||||
|
body.put("shouldVIVOrenderVis", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TemplateResponseValues(dynamicTemplate, body);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void preparePDFResponse(Individual investigator,
|
||||||
|
Set<Grant> piGrants,
|
||||||
|
Map<String, Integer> yearToGrantCount,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
|
||||||
|
String piName = null;
|
||||||
|
|
||||||
|
// To protect against cases where there are no PI grants
|
||||||
|
// associated with the
|
||||||
|
// / individual.
|
||||||
|
if (piGrants.size() > 0) {
|
||||||
|
piName = investigator.getIndividualLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// To make sure that null/empty records for PI names do not cause
|
||||||
|
// any mischief.
|
||||||
|
if (StringUtils.isBlank(piName)) {
|
||||||
|
piName = "no-principal-investigator";
|
||||||
|
}
|
||||||
|
|
||||||
|
String outputFileName = UtilityFunctions.slugify(piName)
|
||||||
|
+ "_report" + ".pdf";
|
||||||
|
|
||||||
|
response.setContentType("application/pdf");
|
||||||
|
response.setHeader("Content-Disposition", "attachment;filename="
|
||||||
|
+ outputFileName);
|
||||||
|
|
||||||
|
ServletOutputStream responseOutputStream;
|
||||||
|
try {
|
||||||
|
responseOutputStream = response.getOutputStream();
|
||||||
|
|
||||||
|
Document document = new Document();
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
|
||||||
|
document.open();
|
||||||
|
|
||||||
|
PDFDocument pdfDocument = new PDFDocument(piName,
|
||||||
|
yearToGrantCount, document, pdfWriter);
|
||||||
|
|
||||||
|
document.close();
|
||||||
|
|
||||||
|
// setting some response headers & content type
|
||||||
|
response.setHeader("Expires", "0");
|
||||||
|
response.setHeader("Cache-Control",
|
||||||
|
"must-revalidate, post-check=0, pre-check=0");
|
||||||
|
response.setHeader("Pragma", "public");
|
||||||
|
response.setContentLength(baos.size());
|
||||||
|
// write ByteArrayOutputStream to the ServletOutputStream
|
||||||
|
baos.writeTo(responseOutputStream);
|
||||||
|
responseOutputStream.flush();
|
||||||
|
responseOutputStream.close();
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (DocumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,658 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.persongrantcount;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.VisualizationController;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Grant;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.SparklineData;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.YearGrantCountDataElement;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class PersonGrantCountVisCodeGenerator {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are 2 modes of sparkline that are available via this visualization.
|
||||||
|
* 1. Short Sparkline - This sparkline will render all the data points (or sparks),
|
||||||
|
* which in this case are the grants over the years, from the last 10 years.
|
||||||
|
*
|
||||||
|
* 2. Full Sparkline - This sparkline will render all the data points (or sparks)
|
||||||
|
* spanning the career of the person & last 10 years at the minimum, in case if
|
||||||
|
* the person started his career in the last 10 yeras.
|
||||||
|
* */
|
||||||
|
private static final Map<String, String> VIS_DIV_NAMES = new HashMap<String, String>() { {
|
||||||
|
|
||||||
|
put("SHORT_SPARK", "grant_count_short_sparkline_vis");
|
||||||
|
put("FULL_SPARK", "grant_count_full_sparkline_vis");
|
||||||
|
|
||||||
|
} };
|
||||||
|
|
||||||
|
private static final String VISUALIZATION_STYLE_CLASS = "sparkline_style";
|
||||||
|
|
||||||
|
private static final String DEFAULT_VIS_CONTAINER_DIV_ID = "grant_count_vis_container";
|
||||||
|
|
||||||
|
private Map<String, Integer> yearToGrantCount;
|
||||||
|
|
||||||
|
private Log log;
|
||||||
|
|
||||||
|
private SparklineData sparklineData;
|
||||||
|
|
||||||
|
private String contextPath;
|
||||||
|
|
||||||
|
private String individualURI;
|
||||||
|
|
||||||
|
public PersonGrantCountVisCodeGenerator(String contextPath,
|
||||||
|
String individualURIParam, String visMode, String visContainer,
|
||||||
|
Set<Grant> piGrants,
|
||||||
|
Map<String, Integer> yearToGrantCount, Log log) {
|
||||||
|
|
||||||
|
this.contextPath = contextPath;
|
||||||
|
this.individualURI = individualURIParam;
|
||||||
|
|
||||||
|
this.yearToGrantCount = yearToGrantCount;
|
||||||
|
this.sparklineData = new SparklineData();
|
||||||
|
|
||||||
|
sparklineData.setYearToActivityCount(yearToGrantCount);
|
||||||
|
|
||||||
|
this.log = log;
|
||||||
|
|
||||||
|
generateVisualizationCode(visMode, visContainer, piGrants);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to generate the visualization code (HMTL, CSS & JavaScript).
|
||||||
|
* There 2 parts to it - 1. Actual Content Code & 2. Context Code.
|
||||||
|
* 1. Actual Content code in this case is the sparkline image, text related to
|
||||||
|
* data and the wrapping tables. This is generated via call to google vis API through
|
||||||
|
* JavaScript.
|
||||||
|
* 2. Context code is generally optional but contains code pertaining to tabulated
|
||||||
|
* data & links to download files etc.
|
||||||
|
* @param visMode
|
||||||
|
* @param visContainer
|
||||||
|
* @param piGrants
|
||||||
|
*/
|
||||||
|
private void generateVisualizationCode(String visMode,
|
||||||
|
String visContainer,
|
||||||
|
Set<Grant> piGrants) {
|
||||||
|
|
||||||
|
sparklineData.setSparklineContent(getMainVisualizationCode(piGrants,
|
||||||
|
visMode,
|
||||||
|
visContainer));
|
||||||
|
|
||||||
|
|
||||||
|
sparklineData.setSparklineContext(getVisualizationContextCode(visMode));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMainVisualizationCode(Set<Grant> piGrants,
|
||||||
|
String visMode, String providedVisContainerID) {
|
||||||
|
|
||||||
|
int numOfYearsToBeRendered = 0;
|
||||||
|
int currentYear = Calendar.getInstance().get(Calendar.YEAR);
|
||||||
|
int shortSparkMinYear = currentYear
|
||||||
|
- VisConstants.MINIMUM_YEARS_CONSIDERED_FOR_SPARKLINE + 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is required because when deciding the range of years over which
|
||||||
|
* the vis was rendered we dont want to be influenced by the
|
||||||
|
* "DEFAULT_GRANT_YEAR".
|
||||||
|
*/
|
||||||
|
Set<String> grantYears = new HashSet<String>(yearToGrantCount
|
||||||
|
.keySet());
|
||||||
|
grantYears.remove(VOConstants.DEFAULT_GRANT_YEAR);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are setting the default value of minGrantYear to be 10 years
|
||||||
|
* before the current year (which is suitably represented by the
|
||||||
|
* shortSparkMinYear), this in case we run into invalid set of grant
|
||||||
|
* years.
|
||||||
|
*/
|
||||||
|
int minGrantYear = shortSparkMinYear;
|
||||||
|
|
||||||
|
String visContainerID = null;
|
||||||
|
|
||||||
|
StringBuilder visualizationCode = new StringBuilder();
|
||||||
|
|
||||||
|
if (yearToGrantCount.size() > 0) {
|
||||||
|
try {
|
||||||
|
minGrantYear = Integer.parseInt(Collections
|
||||||
|
.min(grantYears));
|
||||||
|
} catch (NoSuchElementException e1) {
|
||||||
|
log.debug("vis: " + e1.getMessage() + " error occurred for "
|
||||||
|
+ yearToGrantCount.toString());
|
||||||
|
} catch (NumberFormatException e2) {
|
||||||
|
log.debug("vis: " + e2.getMessage() + " error occurred for "
|
||||||
|
+ yearToGrantCount.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int minGrantYearConsidered = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There might be a case that the author investigated his first grant
|
||||||
|
* within the last 10 years but we want to make sure that the sparkline
|
||||||
|
* is representative of at least the last 10 years, so we will set the
|
||||||
|
* minGrantYearConsidered to "currentYear - 10" which is also given by
|
||||||
|
* "shortSparkMinYear".
|
||||||
|
*/
|
||||||
|
if (minGrantYear > shortSparkMinYear) {
|
||||||
|
minGrantYearConsidered = shortSparkMinYear;
|
||||||
|
} else {
|
||||||
|
minGrantYearConsidered = minGrantYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
numOfYearsToBeRendered = currentYear - minGrantYearConsidered + 1;
|
||||||
|
|
||||||
|
sparklineData.setNumOfYearsToBeRendered(numOfYearsToBeRendered);
|
||||||
|
|
||||||
|
visualizationCode.append("<style type='text/css'>" + "."
|
||||||
|
+ VISUALIZATION_STYLE_CLASS + " table{" + " margin: 0;"
|
||||||
|
+ " padding: 0;" + " width: auto;"
|
||||||
|
+ " border-collapse: collapse;" + " border-spacing: 0;"
|
||||||
|
+ " vertical-align: inherit;" + "}"
|
||||||
|
+ "table.sparkline_wrapper_table td, th {"
|
||||||
|
+ " vertical-align: bottom;" + "}" + ".vis_link a{"
|
||||||
|
+ " padding-top: 5px;" + "}"
|
||||||
|
+ "td.sparkline_number { text-align:right; "
|
||||||
|
+ "padding-right:5px; }"
|
||||||
|
+ "td.sparkline_text {text-align:left;}"
|
||||||
|
+ ".incomplete-data-holder {" + "" + "}" + "</style>\n");
|
||||||
|
|
||||||
|
visualizationCode.append("<script type=\"text/javascript\">\n"
|
||||||
|
+ "function drawGrantCountVisualization(providedSparklineImgTD) "
|
||||||
|
+ "{\n" + "var data = new google.visualization.DataTable();\n"
|
||||||
|
+ "data.addColumn('string', 'Year');\n"
|
||||||
|
+ "data.addColumn('number', 'Publications');\n"
|
||||||
|
+ "data.addRows(" + numOfYearsToBeRendered + ");\n");
|
||||||
|
|
||||||
|
int grantCounter = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the purpose of this visualization I have come up with a term
|
||||||
|
* "Sparks" which essentially means data points. Sparks that will be
|
||||||
|
* rendered in full mode will always be the one's which have any year
|
||||||
|
* associated with it. Hence.
|
||||||
|
*/
|
||||||
|
int renderedFullSparks = 0;
|
||||||
|
|
||||||
|
List<YearGrantCountDataElement> yearToGrantCountDataTable = new ArrayList<YearGrantCountDataElement>();
|
||||||
|
|
||||||
|
for (int grantYear = minGrantYearConsidered; grantYear <= currentYear; grantYear++) {
|
||||||
|
|
||||||
|
String stringInvestigatedYear = String.valueOf(grantYear);
|
||||||
|
Integer currentGrants = yearToGrantCount
|
||||||
|
.get(stringInvestigatedYear);
|
||||||
|
|
||||||
|
if (currentGrants == null) {
|
||||||
|
currentGrants = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
visualizationCode.append("data.setValue(" + grantCounter
|
||||||
|
+ ", 0, '" + stringInvestigatedYear + "');\n");
|
||||||
|
|
||||||
|
visualizationCode.append("data.setValue(" + grantCounter
|
||||||
|
+ ", 1, " + currentGrants + ");\n");
|
||||||
|
|
||||||
|
yearToGrantCountDataTable
|
||||||
|
.add(new YearGrantCountDataElement(
|
||||||
|
grantCounter, stringInvestigatedYear,
|
||||||
|
currentGrants));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sparks that will be rendered will always be the one's which has
|
||||||
|
* any year associated with it. Hence.
|
||||||
|
*/
|
||||||
|
renderedFullSparks += currentGrants;
|
||||||
|
grantCounter++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sparklineData
|
||||||
|
.setYearToGrantCountDataTable(yearToGrantCountDataTable);
|
||||||
|
|
||||||
|
sparklineData.setRenderedSparks(renderedFullSparks);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Total grants will also consider publications that have no year
|
||||||
|
* associated with it. Hence.
|
||||||
|
*/
|
||||||
|
Integer unknownYearGrants = 0;
|
||||||
|
if (yearToGrantCount.get(VOConstants.DEFAULT_GRANT_YEAR) != null) {
|
||||||
|
unknownYearGrants = yearToGrantCount
|
||||||
|
.get(VOConstants.DEFAULT_GRANT_YEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
sparklineData.setUnknownYearGrants(unknownYearGrants);
|
||||||
|
|
||||||
|
String sparklineDisplayOptions = "{width: 65, height: 30, showAxisLines: false, "
|
||||||
|
+ "showValueLabels: false, labelPosition: 'none'}";
|
||||||
|
|
||||||
|
if (providedVisContainerID != null) {
|
||||||
|
visContainerID = providedVisContainerID;
|
||||||
|
} else {
|
||||||
|
visContainerID = DEFAULT_VIS_CONTAINER_DIV_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
sparklineData.setVisContainerDivID(visContainerID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default these represents the range of the rendered sparks. Only in
|
||||||
|
* case of "short" sparkline mode we will set the Earliest
|
||||||
|
* RenderedGrant year to "currentYear - 10".
|
||||||
|
*/
|
||||||
|
sparklineData.setEarliestYearConsidered(minGrantYearConsidered);
|
||||||
|
sparklineData.setEarliestRenderedGrantYear(minGrantYear);
|
||||||
|
sparklineData.setLatestRenderedGrantYear(currentYear);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Full Sparkline will be rendered by default. Only if the url has
|
||||||
|
* specific mention of SHORT_SPARKLINE_MODE_URL_HANDLE then we render
|
||||||
|
* the short sparkline and not otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since building StringBuilder objects (which is being used to store
|
||||||
|
* the vis code) is essentially a side-effecting process, we have both
|
||||||
|
* the activators method as side- effecting. They both side-effect
|
||||||
|
* "visualizationCode"
|
||||||
|
*/
|
||||||
|
if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE
|
||||||
|
.equalsIgnoreCase(visMode)) {
|
||||||
|
|
||||||
|
sparklineData.setEarliestRenderedGrantYear(shortSparkMinYear);
|
||||||
|
|
||||||
|
sparklineData.setShortVisMode(true);
|
||||||
|
|
||||||
|
generateShortSparklineVisualizationContent(currentYear,
|
||||||
|
shortSparkMinYear, visContainerID, visualizationCode,
|
||||||
|
unknownYearGrants, sparklineDisplayOptions);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
sparklineData.setShortVisMode(false);
|
||||||
|
generateFullSparklineVisualizationContent(currentYear,
|
||||||
|
minGrantYearConsidered, visContainerID, visualizationCode,
|
||||||
|
unknownYearGrants, renderedFullSparks,
|
||||||
|
sparklineDisplayOptions);
|
||||||
|
}
|
||||||
|
log.debug(visualizationCode);
|
||||||
|
return visualizationCode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateShortSparklineVisualizationContent(int currentYear,
|
||||||
|
int shortSparkMinYear, String visContainerID,
|
||||||
|
StringBuilder visualizationCode, int unknownYearGrants,
|
||||||
|
String sparklineDisplayOptions) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a view of the data containing only the column pertaining to
|
||||||
|
* grant count.
|
||||||
|
*/
|
||||||
|
visualizationCode.append("var shortSparklineView = "
|
||||||
|
+ "new google.visualization.DataView(data);\n"
|
||||||
|
+ "shortSparklineView.setColumns([1]);\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the short view we only want the last 10 year's view of
|
||||||
|
* grant count, hence we filter the data we actually want to use
|
||||||
|
* for render.
|
||||||
|
*/
|
||||||
|
visualizationCode.append("shortSparklineView.setRows("
|
||||||
|
+ "data.getFilteredRows([{column: 0, " + "minValue: '"
|
||||||
|
+ shortSparkMinYear + "', " + "maxValue: '" + currentYear
|
||||||
|
+ "'}])" + ");\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the vis object and draw it in the div pertaining to
|
||||||
|
* short-sparkline.
|
||||||
|
*/
|
||||||
|
visualizationCode
|
||||||
|
.append("var short_spark = new google.visualization.ImageSparkLine("
|
||||||
|
+ "providedSparklineImgTD[0]"
|
||||||
|
+ ");\n"
|
||||||
|
+ "short_spark.draw(shortSparklineView, "
|
||||||
|
+ sparklineDisplayOptions + ");\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We want to display how many grant counts were considered, so
|
||||||
|
* this is used to calculate this.
|
||||||
|
*/
|
||||||
|
visualizationCode
|
||||||
|
.append("var shortSparkRows = shortSparklineView.getViewRows();\n"
|
||||||
|
+ "var renderedShortSparks = 0;\n"
|
||||||
|
+ "$.each(shortSparkRows, function(index, value) {"
|
||||||
|
+ "renderedShortSparks += data.getValue(value, 1);"
|
||||||
|
+ "});\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate the text introducing the vis.
|
||||||
|
*/
|
||||||
|
|
||||||
|
String imcompleteDataText = "This information is based solely on grants which "
|
||||||
|
+ "have been loaded into the VIVO system. "
|
||||||
|
+ "This may only be a small sample of the person\\'s "
|
||||||
|
+ "total work.";
|
||||||
|
|
||||||
|
visualizationCode.append("$('#" + VIS_DIV_NAMES.get("SHORT_SPARK")
|
||||||
|
+ " td.sparkline_number').text("
|
||||||
|
+ "parseInt(renderedShortSparks) " + "+ parseInt("
|
||||||
|
+ unknownYearGrants + "));");
|
||||||
|
|
||||||
|
visualizationCode.append("var shortSparksText = ''"
|
||||||
|
+ "+ ' grant(s) within the last 10 years "
|
||||||
|
+ "<span class=\"incomplete-data-holder\" title=\""
|
||||||
|
+ imcompleteDataText + "\">incomplete data</span>'" + "+ '';"
|
||||||
|
+ "$('#" + VIS_DIV_NAMES.get("SHORT_SPARK") + " "
|
||||||
|
+ "td.sparkline_text').html(shortSparksText);");
|
||||||
|
|
||||||
|
visualizationCode.append("}\n ");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate the code that will activate the visualization. It takes care
|
||||||
|
* of creating div elements to hold the actual sparkline image and then
|
||||||
|
* calling the drawGrantCountVisualization function.
|
||||||
|
*/
|
||||||
|
visualizationCode.append(generateVisualizationActivator(VIS_DIV_NAMES
|
||||||
|
.get("SHORT_SPARK"), visContainerID));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateFullSparklineVisualizationContent(
|
||||||
|
int currentYear,
|
||||||
|
int minGrantYearConsidered,
|
||||||
|
String visContainerID,
|
||||||
|
StringBuilder visualizationCode,
|
||||||
|
int unknownYearGrants,
|
||||||
|
int renderedFullSparks,
|
||||||
|
String sparklineDisplayOptions) {
|
||||||
|
|
||||||
|
String csvDownloadURLHref = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (getCSVDownloadURL() != null) {
|
||||||
|
|
||||||
|
csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL()
|
||||||
|
+ "\" class=\"inline_href\">(.CSV File)</a>";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
csvDownloadURLHref = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
csvDownloadURLHref = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
visualizationCode.append("var fullSparklineView = "
|
||||||
|
+ "new google.visualization.DataView(data);\n"
|
||||||
|
+ "fullSparklineView.setColumns([1]);\n");
|
||||||
|
|
||||||
|
visualizationCode.append("var full_spark = new google.visualization.ImageSparkLine("
|
||||||
|
+ "providedSparklineImgTD[0]"
|
||||||
|
+ ");\n"
|
||||||
|
+ "full_spark.draw(fullSparklineView, "
|
||||||
|
+ sparklineDisplayOptions + ");\n");
|
||||||
|
|
||||||
|
visualizationCode.append("$('#" + VIS_DIV_NAMES.get("FULL_SPARK")
|
||||||
|
+ " td.sparkline_number').text('" + (renderedFullSparks
|
||||||
|
+ unknownYearGrants) + "');");
|
||||||
|
|
||||||
|
visualizationCode.append("var allSparksText = ''"
|
||||||
|
+ "+ ' grant(s) '"
|
||||||
|
+ "+ ' from "
|
||||||
|
+ "<span class=\"sparkline_range\">"
|
||||||
|
+ "" + minGrantYearConsidered + " to " + currentYear + ""
|
||||||
|
+ "</span> '"
|
||||||
|
+ "+ ' " + csvDownloadURLHref + " ';"
|
||||||
|
+ "$('#" + VIS_DIV_NAMES.get("FULL_SPARK")
|
||||||
|
+ " td.sparkline_text').html(allSparksText);");
|
||||||
|
|
||||||
|
visualizationCode.append("}\n ");
|
||||||
|
|
||||||
|
visualizationCode.append(generateVisualizationActivator(VIS_DIV_NAMES.get("FULL_SPARK"),
|
||||||
|
visContainerID));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String generateVisualizationActivator(String sparklineID, String visContainerID) {
|
||||||
|
|
||||||
|
String sparklineTableWrapper = "\n"
|
||||||
|
+ "var table = $('<table>');"
|
||||||
|
+ "table.attr('class', 'sparkline_wrapper_table');"
|
||||||
|
+ "var row = $('<tr>');"
|
||||||
|
+ "sparklineImgTD = $('<td>');"
|
||||||
|
+ "sparklineImgTD.attr('id', '" + sparklineID + "_img');"
|
||||||
|
+ "sparklineImgTD.attr('width', '65');"
|
||||||
|
+ "sparklineImgTD.attr('align', 'right');"
|
||||||
|
+ "sparklineImgTD.attr('class', '" + VISUALIZATION_STYLE_CLASS + "');"
|
||||||
|
+ "row.append(sparklineImgTD);"
|
||||||
|
+ "var sparklineNumberTD = $('<td>');"
|
||||||
|
+ "sparklineNumberTD.attr('width', '30');"
|
||||||
|
+ "sparklineNumberTD.attr('align', 'right');"
|
||||||
|
+ "sparklineNumberTD.attr('class', 'sparkline_number');"
|
||||||
|
+ "row.append(sparklineNumberTD);"
|
||||||
|
+ "var sparklineTextTD = $('<td>');"
|
||||||
|
+ "sparklineTextTD.attr('width', '450');"
|
||||||
|
+ "sparklineTextTD.attr('class', 'sparkline_text');"
|
||||||
|
+ "row.append(sparklineTextTD);"
|
||||||
|
+ "table.append(row);"
|
||||||
|
+ "table.prependTo('#" + sparklineID + "');\n";
|
||||||
|
|
||||||
|
return "$(document).ready(function() {"
|
||||||
|
+ "var sparklineImgTD; "
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a nuclear option (creating the container in which everything goes)
|
||||||
|
* the only reason this will be ever used is the API user never submitted a
|
||||||
|
* container ID in which everything goes. The alternative was to let the
|
||||||
|
* vis not appear in the calling page at all. So now atleast vis appears but
|
||||||
|
* appended at the bottom of the body.
|
||||||
|
* */
|
||||||
|
|
||||||
|
+ "if ($('#" + visContainerID + "').length === 0) {"
|
||||||
|
+ " $('<div/>', {'id': '" + visContainerID + "'"
|
||||||
|
+ " }).appendTo('body');"
|
||||||
|
+ "}"
|
||||||
|
+ "if ($('#" + sparklineID + "').length === 0) {"
|
||||||
|
+ "$('<div/>', {'id': '" + sparklineID + "',"
|
||||||
|
+ "'class': '" + VISUALIZATION_STYLE_CLASS + "'"
|
||||||
|
+ "}).prependTo('#" + visContainerID + "');"
|
||||||
|
+ sparklineTableWrapper
|
||||||
|
+ "}"
|
||||||
|
+ "drawPubCountVisualization(sparklineImgTD);"
|
||||||
|
+ "});"
|
||||||
|
+ "</script>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getVisualizationContextCode(String visMode) {
|
||||||
|
|
||||||
|
String visualizationContextCode = "";
|
||||||
|
if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE.equalsIgnoreCase(visMode)) {
|
||||||
|
visualizationContextCode = generateShortVisContext();
|
||||||
|
} else {
|
||||||
|
visualizationContextCode = generateFullVisContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(visualizationContextCode);
|
||||||
|
|
||||||
|
return visualizationContextCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateFullVisContext() {
|
||||||
|
|
||||||
|
StringBuilder divContextCode = new StringBuilder();
|
||||||
|
|
||||||
|
String csvDownloadURLHref = "";
|
||||||
|
|
||||||
|
if (yearToGrantCount.size() > 0) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (getCSVDownloadURL() != null) {
|
||||||
|
|
||||||
|
csvDownloadURLHref = "Download data as <a href='"
|
||||||
|
+ getCSVDownloadURL() + "'>.csv</a> file.<br />";
|
||||||
|
sparklineData.setDownloadDataLink(getCSVDownloadURL());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
csvDownloadURLHref = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
csvDownloadURLHref = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
csvDownloadURLHref = "No data available to export.<br />";
|
||||||
|
}
|
||||||
|
|
||||||
|
String tableCode = generateDataTable();
|
||||||
|
|
||||||
|
divContextCode.append("<p>" + tableCode + csvDownloadURLHref + "</p>");
|
||||||
|
|
||||||
|
sparklineData.setTable(tableCode);
|
||||||
|
|
||||||
|
return divContextCode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getCSVDownloadURL()
|
||||||
|
throws UnsupportedEncodingException {
|
||||||
|
|
||||||
|
if (yearToGrantCount.size() > 0) {
|
||||||
|
|
||||||
|
String secondaryContextPath = "";
|
||||||
|
if (!contextPath.contains(VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX)) {
|
||||||
|
secondaryContextPath = VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
String downloadURL = contextPath
|
||||||
|
+ secondaryContextPath
|
||||||
|
+ "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
|
||||||
|
+ "=" + URLEncoder.encode(individualURI,
|
||||||
|
VisualizationController.URL_ENCODING_SCHEME)
|
||||||
|
.toString()
|
||||||
|
+ "&" + VisualizationFrameworkConstants.VIS_TYPE_KEY
|
||||||
|
+ "=" + URLEncoder.encode(
|
||||||
|
VisualizationFrameworkConstants
|
||||||
|
.PERSON_GRANT_COUNT_VIS,
|
||||||
|
VisualizationController.URL_ENCODING_SCHEME)
|
||||||
|
.toString()
|
||||||
|
+ "&" + VisualizationFrameworkConstants.RENDER_MODE_KEY
|
||||||
|
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
|
||||||
|
.DATA_RENDER_MODE,
|
||||||
|
VisualizationController.URL_ENCODING_SCHEME)
|
||||||
|
.toString();
|
||||||
|
return downloadURL;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String generateShortVisContext() {
|
||||||
|
|
||||||
|
StringBuilder divContextCode = new StringBuilder();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
String fullTimelineLink;
|
||||||
|
if (yearToGrantCount.size() > 0) {
|
||||||
|
|
||||||
|
String secondaryContextPath = "";
|
||||||
|
if (!contextPath.contains(VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX)) {
|
||||||
|
secondaryContextPath = VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
String fullTimelineNetworkURL = contextPath
|
||||||
|
+ secondaryContextPath
|
||||||
|
+ "?"
|
||||||
|
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
|
||||||
|
+ "=" + URLEncoder.encode(individualURI,
|
||||||
|
VisualizationController.URL_ENCODING_SCHEME).toString()
|
||||||
|
+ "&"
|
||||||
|
+ VisualizationFrameworkConstants.VIS_TYPE_KEY
|
||||||
|
+ "=" + URLEncoder.encode("person_level",
|
||||||
|
VisualizationController.URL_ENCODING_SCHEME).toString()
|
||||||
|
+ "&"
|
||||||
|
+ VisualizationFrameworkConstants.RENDER_MODE_KEY
|
||||||
|
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
|
||||||
|
.STANDALONE_RENDER_MODE,
|
||||||
|
VisualizationController.URL_ENCODING_SCHEME).toString();
|
||||||
|
|
||||||
|
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View all VIVO "
|
||||||
|
+ "grants and corresponding co-pi network.</a>";
|
||||||
|
|
||||||
|
sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fullTimelineLink = "No data available to render full timeline.<br />";
|
||||||
|
}
|
||||||
|
|
||||||
|
divContextCode.append("<span class=\"vis_link\">" + fullTimelineLink + "</span>");
|
||||||
|
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
log.error(e);
|
||||||
|
}
|
||||||
|
return divContextCode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateDataTable() {
|
||||||
|
|
||||||
|
String csvDownloadURLHref = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (getCSVDownloadURL() != null) {
|
||||||
|
csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL() + "\">(.CSV File)</a>";
|
||||||
|
} else {
|
||||||
|
csvDownloadURLHref = "";
|
||||||
|
}
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
csvDownloadURLHref = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder dataTable = new StringBuilder();
|
||||||
|
|
||||||
|
dataTable.append("<table id='sparkline_data_table'>"
|
||||||
|
+ "<caption>Grants per year " + csvDownloadURLHref + "</caption>"
|
||||||
|
+ "<thead>"
|
||||||
|
+ "<tr>"
|
||||||
|
+ "<th>Year</th>"
|
||||||
|
+ "<th>Grants</th>"
|
||||||
|
+ "</tr>"
|
||||||
|
+ "</thead>"
|
||||||
|
+ "<tbody>");
|
||||||
|
|
||||||
|
for (Entry<String, Integer> currentEntry : yearToGrantCount.entrySet()) {
|
||||||
|
dataTable.append("<tr>"
|
||||||
|
+ "<td>" + currentEntry.getKey() + "</td>"
|
||||||
|
+ "<td>" + currentEntry.getValue() + "</td>"
|
||||||
|
+ "</tr>");
|
||||||
|
}
|
||||||
|
|
||||||
|
dataTable.append("</tbody>\n </table>\n");
|
||||||
|
|
||||||
|
return dataTable.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SparklineData getValueObjectContainer() {
|
||||||
|
return sparklineData;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,9 +18,13 @@ public class SparklineData {
|
||||||
private Integer earliestYearConsidered;
|
private Integer earliestYearConsidered;
|
||||||
private Integer earliestRenderedPublicationYear;
|
private Integer earliestRenderedPublicationYear;
|
||||||
private Integer latestRenderedPublicationYear;
|
private Integer latestRenderedPublicationYear;
|
||||||
|
private Integer earliestRenderedGrantYear;
|
||||||
|
private Integer latestRenderedGrantYear;
|
||||||
|
|
||||||
private Integer renderedSparks;
|
private Integer renderedSparks;
|
||||||
private Integer unknownYearPublications;
|
private Integer unknownYearPublications;
|
||||||
|
private Integer unknownYearGrants;
|
||||||
|
|
||||||
|
|
||||||
private Map<String, Integer> yearToActivityCount;
|
private Map<String, Integer> yearToActivityCount;
|
||||||
|
|
||||||
|
@ -36,6 +40,7 @@ public class SparklineData {
|
||||||
private boolean isShortVisMode = true;
|
private boolean isShortVisMode = true;
|
||||||
|
|
||||||
private List<YearPublicationCountDataElement> yearToPublicationCountDataTable;
|
private List<YearPublicationCountDataElement> yearToPublicationCountDataTable;
|
||||||
|
private List<YearGrantCountDataElement> yearToGrantCountDataTable;
|
||||||
|
|
||||||
private int numOfYearsToBeRendered;
|
private int numOfYearsToBeRendered;
|
||||||
|
|
||||||
|
@ -56,6 +61,39 @@ public class SparklineData {
|
||||||
this.sparklinePublicationRangeText = sparklinePublicationRangeText;
|
this.sparklinePublicationRangeText = sparklinePublicationRangeText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getEarliestRenderedGrantYear() {
|
||||||
|
return earliestRenderedGrantYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEarliestRenderedGrantYear(Integer earliestRenderedGrantYear) {
|
||||||
|
this.earliestRenderedGrantYear = earliestRenderedGrantYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getLatestRenderedGrantYear() {
|
||||||
|
return latestRenderedGrantYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLatestRenderedGrantYear(Integer latestRenderedGrantYear) {
|
||||||
|
this.latestRenderedGrantYear = latestRenderedGrantYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getUnknownYearGrants() {
|
||||||
|
return unknownYearGrants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUnknownYearGrants(Integer unknownYearGrants) {
|
||||||
|
this.unknownYearGrants = unknownYearGrants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<YearGrantCountDataElement> getYearToGrantCountDataTable() {
|
||||||
|
return yearToGrantCountDataTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYearToGrantCountDataTable(
|
||||||
|
List<YearGrantCountDataElement> yearToGrantCountDataTable) {
|
||||||
|
this.yearToGrantCountDataTable = yearToGrantCountDataTable;
|
||||||
|
}
|
||||||
|
|
||||||
public void setNumOfYearsToBeRendered(int numOfYearsToBeRendered) {
|
public void setNumOfYearsToBeRendered(int numOfYearsToBeRendered) {
|
||||||
this.numOfYearsToBeRendered = numOfYearsToBeRendered;
|
this.numOfYearsToBeRendered = numOfYearsToBeRendered;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object is used to store information about the yearToGrantCount Map in the format
|
||||||
|
* easily expressed to Google Visualization's DataTableAPI.
|
||||||
|
* @author bkoniden
|
||||||
|
* Deepak Konidena
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class YearGrantCountDataElement {
|
||||||
|
|
||||||
|
private int grantCounter;
|
||||||
|
private String investigatedYear;
|
||||||
|
private int currentGrants;
|
||||||
|
|
||||||
|
public YearGrantCountDataElement(int grantCounter,
|
||||||
|
String investigatedYear, int currentGrants) {
|
||||||
|
this.grantCounter = grantCounter;
|
||||||
|
this.investigatedYear = investigatedYear;
|
||||||
|
this.currentGrants = currentGrants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGrantCounter() {
|
||||||
|
return grantCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInvestigatedYear() {
|
||||||
|
return investigatedYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCurrentGrants() {
|
||||||
|
return currentGrants;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue