committing persongrantcount related files,new Egocentric swf file, CoPIVisCodeGenerator, person_level.js (to include co-author and co-pi vis).

This commit is contained in:
bkoniden 2010-12-15 17:20:57 +00:00
parent 31dbc619a4
commit 313a2da5da
23 changed files with 1900 additions and 240 deletions

View file

@ -21,6 +21,9 @@
class="edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison.EntityPublicationCountRequestHandler" />
<bean id="coprincipalinvestigator"
class="edu.cornell.mannlib.vitro.webapp.visualization.coprincipalinvestigator.CoPIGrantCountRequestHandler" />
<bean id="person_grant_count"
class="edu.cornell.mannlib.vitro.webapp.visualization.persongrantcount.PersonGrantCountRequestHandler" />
<bean id="visualizationInjector"
class="edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationInjector">
@ -44,6 +47,9 @@
<entry key="coprincipalinvestigator">
<ref bean="coprincipalinvestigator"></ref>
</entry>
<entry key="person_grant_count">
<ref bean="person_grant_count"></ref>
</entry>
</map>
</property>

View file

@ -172,11 +172,7 @@
org.apache.commons.fileupload.servlet.FileCleanerCleanup
</listener-class>
</listener>
<listener>
<listener-class>edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache</listener-class>
</listener>
<!--
<listener>
<listener-class>
@ -193,7 +189,7 @@
</listener>
-->
<!-- vivo specific -->
<!-- vivo specific -->
<listener>
<listener-class>edu.cornell.mannlib.vitro.webapp.servlet.setup.VivoMergedListFilteringSetup</listener-class>
</listener>
@ -351,16 +347,6 @@
<url-pattern>/N3EditForm</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>MenuN3EditController</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.MenuN3EditController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MenuN3EditController</servlet-name>
<url-pattern>/MenuN3EditController</url-pattern>
</servlet-mapping>
<!-- This is the new navigation controller. It is not ready for the 1.1 release
see http://issues.library.cornell.edu/browse/NIHVIVO-597
<servlet>
@ -509,7 +495,6 @@
<url-pattern>/csv2rdf</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>JenaExportController</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.jena.JenaExportController</servlet-class>
@ -1264,16 +1249,24 @@
</servlet-mapping>
<servlet>
<servlet-name>DummyVisClient</servlet-name>
<servlet-name>DummyVisClientFM</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.DummyVisClientController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DummyVisClientFM</servlet-name>
<url-pattern>/admin/dummyVisClientfm</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DummyVisClient</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.DummyVisClientController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DummyVisClient</servlet-name>
<url-pattern>/admin/dummyVisClient</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>VisualizationController</servlet-name>
@ -1334,15 +1327,6 @@
</servlet-mapping>
-->
<servlet>
<servlet-name>ajaxSparqlQuery</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.ajax.SparqlQueryAjaxController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ajaxSparqlQuery</servlet-name>
<url-pattern>/ajax/sparqlQuery</url-pattern>
</servlet-mapping>
<!-- ============================== servlet-mappings ======================== -->
<servlet-mapping>
<servlet-name>fetch</servlet-name>

View file

@ -29,7 +29,21 @@ function getWellFormedURLs(given_uri, type) {
return finalURL;
} else if (type == "profile") {
} else if (type == "copi") {
finalURL = $.ajax({
url: contextPath + "/visualization",
data: ({vis: "utilities", vis_mode: "COPI_URL", uri: given_uri}),
dataType: "text",
async: false,
success:function(data){
}
}).responseText;
return finalURL;
}else if (type == "profile") {
finalURL = $.ajax({
url: contextPath + "/visualization",
@ -213,40 +227,70 @@ function processProfileInformation(nameContainerID,
function visLoaded(nodes){
var jsonedNodes = jQuery.parseJSON(nodes);
var tableID = "";
var tableContainer = "";
if(visMode == "coauthorship"){
tableID = "coauthorships_table";
tableContainer = "coauth_table_container";
} else{
tableID = "copis_table";
tableContainer = "copi_table_container";
}
$(document).ready(function() {
createTable("coauthorships_table", "coauth_table_container", jsonedNodes.slice(1));
createTable("coauthorships_table" , "coauth_table_container" , jsonedNodes.slice(1));
});
}
function createTable(tableID, tableContainer, tableData) {
var number_of_works = "";
var tableCaption = "";
var tableColumnTitle1 = "";
var tableColumnTitle2 = "";
if(visMode == "coauthorship"){
tableCaption = "Co-authors ";
tableColumnTitle1 = "Author";
tableColumnTitle2 = "Publications with <br />";
}else{
tableCaption = "Co-pis ";
tableColumnTitle1 = "Principal Investigator";
tableColumnTitle2 = "Grants with <br />";
}
var table = $('<table>');
table.attr('id', tableID);
table.append($('<caption>').html("Co-authors <a href=\"" + egoCoAuthorsListDataFileURL + "\">(.CSV File)</a>"));
table.append($('<caption>').html(tableCaption + "<a href=\"" + egoCoAuthorsListDataFileURL + "\">(.CSV File)</a>"));
var header = $('<thead>');
var row = $('<tr>');
var authorTH = $('<th>');
authorTH.html("Author");
authorTH.html(tableColumnTitle1);
row.append(authorTH);
row.append($('<th>').html("Publications with <br />" + $('#ego_label').text()));
row.append($('<th>').html(tableColumnTitle2 + "" + $('#ego_label').text()));
header.append(row);
table.append(header);
$.each(tableData, function(i, item){
if(visMode == "coauthorship"){
number_of_works = item.number_of_authored_works;
}else{
number_of_works = item.number_of_investigated_grants;
}
var row = $('<tr>');
row.append($('<td>').html(item.label));
row.append($('<td>').html(item.number_of_authored_works));
row.append($('<td>').html(number_of_works));
table.append(row);
@ -259,10 +303,38 @@ function createTable(tableID, tableContainer, tableData) {
//renderStatsOnNodeClicked, CoRelations, noOfCoRelations
//function nodeClickedJS(json){
function renderStatsOnNodeClicked(json){
//console.log(json);
var obj = jQuery.parseJSON(json);
var works = "";
var persons = "";
var relation = "";
var earliest_work = "";
var latest_work = "";
var number_of_works = "";
if(visMode == "coauthorship"){
works = "Publication(s)";
persons = "Co-author(s)";
relation = "coauthorship"
earliest_work = obj.earliest_publication;
latest_work = obj.latest_publication;
number_of_works = obj.number_of_authored_works;
}else{
works = "Grant(s)";
persons = "Co-PI(s)";
relation = "copi";
earliest_work = obj.earliest_grant;
latest_work = obj.latest_grant;
number_of_works = obj.number_of_investigated_grants;
}
$("#dataPanel").attr("style","visibility:visible");
$("#works").empty().append(obj.number_of_authored_works);
$("#works").empty().append(number_of_works);
/*
* Here obj.url points to the uri of that individual
@ -272,19 +344,19 @@ function renderStatsOnNodeClicked(json){
if (obj.url == egoURI) {
$("#authorName").addClass('author_name').removeClass('neutral_author_name');
$('#num_works > .author_stats_text').text('Publication(s)');
$('#num_authors > .author_stats_text').text('Co-author(s)');
$('#num_works > .author_stats_text').text(works);
$('#num_authors > .author_stats_text').text(persons);
} else {
$("#authorName").addClass('neutral_author_name').removeClass('author_name');
$('#num_works > .author_stats_text').text('Joint Publication(s)');
$('#num_authors > .author_stats_text').text('Joint Co-author(s)');
$('#num_works > .author_stats_text').text('Joint ' + works);
$('#num_authors > .author_stats_text').text('Joint ' + persons);
}
$("#profileUrl").attr("href", getWellFormedURLs(obj.url, "profile"));
$("#coAuthorshipVisUrl").attr("href", getWellFormedURLs(obj.url, "coauthorship"));
$("#coAuthorshipVisUrl").attr("href", getWellFormedURLs(obj.url, relation));
processProfileInformation("authorName",
"profileMoniker",
"profileImage",
@ -299,12 +371,12 @@ function renderStatsOnNodeClicked(json){
$("#coAuthorshipVisUrl").attr("href","#");
}
$("#coAuthors").empty().append(obj.num_coauthors);
$("#coAuthors").empty().append(obj.noOfCorelations);
$("#firstPublication").empty().append(obj.earliest_publication);
(obj.earliest_publication)?$("#fPub").attr("style","visibility:visible"):$("#fPub").attr("style","visibility:hidden");
$("#lastPublication").empty().append(obj.latest_publication);
(obj.latest_publication)?$("#lPub").attr("style","visibility:visible"):$("#lPub").attr("style","visibility:hidden");
$("#firstPublication").empty().append(earliest_work);
(earliest_work)?$("#fPub").attr("style","visibility:visible"):$("#fPub").attr("style","visibility:hidden");
$("#lastPublication").empty().append(latest_work);
(latest_work)?$("#lPub").attr("style","visibility:visible"):$("#lPub").attr("style","visibility:hidden");
// obj.url:the url parameter for node
@ -332,7 +404,19 @@ function getEncodedCoPIURL(){
}
function renderCoAuthorshipVisualization() {
var visualization = "";
var encodedURL = "";
if(visMode == "coauthorship"){
visualization = "CoAuthor";
encodedURL = getEncodedCoAuthorURL();
} else {
visualization = "CoPI";
encodedURL = getEncodedCoPIURL();
}
// console.log('visualization is ' + visualization + ' and encodedURL is '+ encodedURL);
// Version check for the Flash Player that has the ability to start Player
// Product Install (6.0r65)
var hasProductInstall = DetectFlashVer(6, 0, 65);
@ -371,7 +455,8 @@ function renderCoAuthorshipVisualization() {
"src", swfLink,
// "flashVars", 'coAuthorUrl='+ encodeURL(egoCoAuthorshipDataFeederURL) + '&coPIUrl=' + encodeURL(egoCoPIDataFeederURL) ,
// "flashVars", 'coAuthorUrl='+ getEncodedCoAuthorURL() + '&coPIUrl=' + getEncodedCoPIURL() ,
"flashVars", 'graphmlUrl=' + getEncodedCoAuthorURL() + '&labelField=label&visType=CoAuthor',
// "flashVars", 'graphmlUrl=' + getEncodedCoAuthorURL() + '&labelField=label&visType=CoAuthor',
"flashVars", 'graphmlUrl=' + encodedURL + '&labelField=label&visType='+visualization,
"width", "800",
"height", "850",
"align", "top",

View file

@ -0,0 +1,17 @@
<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
<%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<c:set var='sparkline' value='${requestScope.sparklineVO}'/>
<div class="staticPageBackground">
<div id="pub_count_vis_container">
${sparkline.sparklineContent}
</div>
${sparkline.sparklineContext}
</div>

View file

@ -10,7 +10,10 @@
<c:url var="loadingImageLink" value="/${themeDir}site_icons/visualization/ajax-loader.gif"></c:url>
<c:set var='egoPubSparkline' value='${requestScope.egoPubSparklineVO}' />
<c:set var='egoGrantSparkline' value='${requestScope.egoGrantSparklineVO}' />
<c:set var='uniqueCoauthorsSparkline' value='${requestScope.uniqueCoauthorsSparklineVO}' />
<c:set var='uniqueCopisSparkline' value='${requestScope.uniqueCopisSparklineVO}' />
<c:set var='egoPubSparklineContainerID' value='${requestScope.egoPubSparklineContainerID}' />
<c:set var='uniqueCoauthorsSparklineVisContainerID' value='${requestScope.uniqueCoauthorsSparklineVisContainerID}' />
@ -18,6 +21,10 @@
<c:set var='numOfAuthors' value='${requestScope.numOfAuthors}' />
<c:set var='numOfCoAuthorShips' value='${requestScope.numOfCoAuthorShips}' />
<c:set var='numOfInvestigators' value='${requestScope.numOfInvestigators}' />
<c:set var='numOfCoPIs' value='${requestScope.numOfCoPIs}' />
<c:url var="egoVivoProfileURL" value="/individual">
<c:param name="uri" value="${requestScope.egoURIParam}" />
</c:url>
@ -34,10 +41,18 @@
<c:param name="uri" value="${requestScope.egoURIParam}" />
</c:url>
<c:url var="coprincipalinvestigator" value="/visualization">
<c:param name="vis" value="coprincipalinvestigator"/>
<c:url var="coprincipalinvestigatorURL" value="/visualization">
<c:param name="vis" value="person_level"/>
<c:param name="render_mode" value="standalone"/>
<c:param name="uri" value="${requestScope.egoURIParam}"/>
<c:param name = "vis_mode" value = "copi"/>
</c:url>
<c:url var="coauthorshipURL" value="/visualization">
<c:param name="vis" value="person_level"/>
<c:param name="render_mode" value="standalone"/>
<c:param name="uri" value="${requestScope.egoURIParam}"/>
<c:param name = "vis_mode" value = "coauthorship"/>
</c:url>
<script language="JavaScript" type="text/javascript">
@ -103,22 +118,41 @@ $(document).ready(function(){
<%-- Sparkline --%>
<h2 class="sub_headings">General Statistics</h2>
<div id="${egoPubSparklineContainerID}">
${egoPubSparkline.sparklineContent}
</div>
<c:choose>
<c:when test='${visMode == "coauthorship"}'>
<div id="${egoPubSparklineContainerID}">
${egoPubSparkline.sparklineContent}
</div>
<div id="${uniqueCoauthorsSparklineVisContainerID}">
${uniqueCoauthorsSparkline.sparklineContent}
</div>
</c:when>
<c:otherwise>
<div id="${egoPubSparklineContainerID}">
${egoGrantSparkline.sparklineContent}
</div>
<div id="${uniqueCoauthorsSparklineVisContainerID}">
${uniqueCopisSparkline.sparklineContent}
</div>
</c:otherwise>
</c:choose>
<div id="${uniqueCoauthorsSparklineVisContainerID}">
${uniqueCoauthorsSparkline.sparklineContent}
</div>
<h2 class="sub_headings">Co-Author Network
<c:choose>
<c:when test='${visMode == "coauthorship"}'>
<h2 class="sub_headings">Co-Author Network </h2>
</c:when>
<c:otherwise>
<h2 class="sub_headings">Co-PI Network </h2>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${numOfCoAuthorShips > 0 || numOfAuthors > 0}">
<a href="${coAuthorshipDownloadFile}">(GraphML File)</a></h2>
<a href="${coAuthorshipDownloadFile}">(GraphML File)</a>
</c:when>
<c:otherwise>
</h2>
<c:if test='${numOfAuthors > 0}'>
<c:set var='authorsText' value='multi-author' />
</c:if>
@ -149,55 +183,118 @@ $(document).ready(function(){
//-->
</script>
</div>
<div id="dataPanel">
<br />
<br />
<div id="profileImage" class="thumbnail"></div>
<div class="bold"><strong><span id="authorName" class="neutral_author_name">&nbsp;</span></strong></div>
<div class="italicize"><span id="profileMoniker" class="author_moniker"></span></div>
<div><a href="#" id="profileUrl">VIVO profile</a> | <a href="#" id="coAuthorshipVisUrl">Co-author network</a></div>
<br />
<div class="author_stats" id="num_works"><span class="numbers" style="width: 40px;" id="works"></span>&nbsp;&nbsp;<span class="author_stats_text">Publication(s)</span></div>
<div class="author_stats" id="num_authors"><span class="numbers" style="width: 40px;" id="coAuthors"></span>&nbsp;&nbsp;<span class="author_stats_text">Co-author(s)</span></div>
<div class="author_stats" id="fPub" style="visibility:hidden"><span class="numbers" style="width:40px;" id="firstPublication"></span>&nbsp;&nbsp;<span>First Publication</span></div>
<div class="author_stats" id="lPub" style="visibility:hidden"><span class="numbers" style="width:40px;" id="lastPublication"></span>&nbsp;&nbsp;<span>Last Publication</span></div>
</div>
</div>
</c:if>
<div style="text-align:center; clear: left;">
<a href='<c:out value="${coprincipalinvestigator}"/>'> View all grants and corresponding co-pi network for this author</a>
</div>
<c:if test='${numOfAuthors > 0}'>
<div class="vis_stats">
<h2 class="sub_headings">Tables</h2>
<div class="vis-tables">
<p id="publications_table_container" class="datatable">
${egoPubSparkline.table}
</p>
<c:choose>
<c:when test='${visMode == "coauthorship"}'>
<div id="dataPanel">
<br />
<br />
<div id="profileImage" class="thumbnail"></div>
<div class="bold"><strong><span id="authorName" class="neutral_author_name">&nbsp;</span></strong></div>
<div class="italicize"><span id="profileMoniker" class="author_moniker"></span></div>
<div><a href="#" id="profileUrl">VIVO profile</a> | <a href="#" id="coAuthorshipVisUrl">Co-author network</a></div>
<br />
<div class="author_stats" id="num_works"><span class="numbers" style="width: 40px;" id="works"></span>&nbsp;&nbsp;<span class="author_stats_text">Publication(s)</span></div>
<div class="author_stats" id="num_authors"><span class="numbers" style="width: 40px;" id="coAuthors"></span>&nbsp;&nbsp;<span class="author_stats_text">Co-author(s)</span></div>
<div class="author_stats" id="fPub" style="visibility:hidden"><span class="numbers" style="width:40px;" id="firstPublication"></span>&nbsp;&nbsp;<span>First Publication</span></div>
<div class="author_stats" id="lPub" style="visibility:hidden"><span class="numbers" style="width:40px;" id="lastPublication"></span>&nbsp;&nbsp;<span>Last Publication</span></div>
</div>
<c:if test='${numOfCoAuthorShips > 0}'>
<div class="vis-tables">
<p id="coauth_table_container" class="datatable"></p>
</div>
</c:if>
<div style="clear:both;"></div>
</div>
</c:when>
<c:otherwise>
<div id="dataPanel">
<br />
<br />
<div id="profileImage" class="thumbnail"></div>
<div class="bold"><strong><span id="authorName" class="neutral_author_name">&nbsp;</span></strong></div>
<div class="italicize"><span id="profileMoniker" class="author_moniker"></span></div>
<div><a href="#" id="profileUrl">VIVO profile</a> | <a href="#" id="coAuthorshipVisUrl">Co-PI network</a></div>
<br />
<div class="author_stats" id="num_works"><span class="numbers" style="width: 40px;" id="works"></span>&nbsp;&nbsp;<span class="author_stats_text">Grant(s)</span></div>
<div class="author_stats" id="num_authors"><span class="numbers" style="width: 40px;" id="coAuthors"></span>&nbsp;&nbsp;<span class="author_stats_text">Co-PI(s)</span></div>
<div class="author_stats" id="fPub" style="visibility:hidden"><span class="numbers" style="width:40px;" id="firstPublication"></span>&nbsp;&nbsp;<span>First Grant</span></div>
<div class="author_stats" id="lPub" style="visibility:hidden"><span class="numbers" style="width:40px;" id="lastPublication"></span>&nbsp;&nbsp;<span>Last Grant</span></div>
</div>
</c:otherwise>
</c:choose>
</div>
</c:if>
<c:choose>
<c:when test='${visMode == "coauthorship"}'>
<div style="text-align:center; clear: left;">
<a href='<c:out value="${coprincipalinvestigatorURL}"/>'> View all grants and corresponding co-pi network for this person</a>
</div>
</c:when>
<c:otherwise>
<div style="text-align:center; clear: left;">
<a href='<c:out value="${coauthorshipURL}"/>'> View all publications and corresponding co-author network for this person</a>
</div>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test='${visMode == "coauthorship"}'>
<c:if test='${numOfAuthors > 0}'>
<div class="vis_stats">
<h2 class="sub_headings">Tables</h2>
<div class="vis-tables">
<p id="publications_table_container" class="datatable">
${egoPubSparkline.table}
</p>
</div>
<c:if test='${numOfCoAuthorShips > 0}'>
<div class="vis-tables">
<p id="coauth_table_container" class="datatable"></p>
</div>
</c:if>
<div style="clear:both;"></div>
</div>
</c:if>
</c:when>
<c:otherwise>
<c:if test='${numOfInvestigators > 0}'>
<div class="vis_stats">
<h2 class="sub_headings">Tables</h2>
<div class="vis-tables">
<p id="publications_table_container" class="datatable">
${egoGrantSparkline.table}
</p>
</div>
<c:if test='${numOfCoPIs > 0}'>
<div class="vis-tables">
<p id="coauth_table_container" class="datatable"></p>
</div>
</c:if>
<div style="clear:both;"></div>
</div>
</c:if>
</c:otherwise>
</c:choose>
</div>

View file

@ -59,6 +59,7 @@ var egoCoAuthorsListDataFileURL = "${egoCoAuthorsListDataFileURL}";
var egoCoPIDataFeederURL = "${egoCoPIDataFeederURL}";
var contextPath = "${contextPath}";
var domainParam = "${requestScope.completeURL}";
var visMode = "${requestScope.visMode}";
// -->
</script>

View file

@ -65,6 +65,7 @@ public class VisualizationFrameworkConstants {
public static final String PROFILE_UTILS_VIS_MODE = "PROFILE_URL";
public static final String COAUTHOR_UTILS_VIS_MODE = "COAUTHORSHIP_URL";
public static final String PERSON_LEVEL_UTILS_VIS_MODE = "PERSON_LEVEL_URL";
public static final String COPI_UTILS_VIS_MODE = "COPI_URL";
public static final String IMAGE_UTILS_VIS_MODE = "IMAGE_URL";
public static final String UNIVERSITY_COMPARISON_VIS_MODE = "UNIVERSITY";
public static final String SCHOOL_COMPARISON_VIS_MODE = "SCHOOL";
@ -75,6 +76,7 @@ public class VisualizationFrameworkConstants {
* These values represent possible visualizations provided as values to the "vis" url key.
* */
public static final String PERSON_PUBLICATION_COUNT_VIS = "person_pub_count";
public static final String PERSON_GRANT_COUNT_VIS = "person_grant_count";
public static final String PDF_REPORT_VIS = "pdf_report";
public static final String COLLEGE_PUBLICATION_COUNT_VIS = "college_pub_count";
public static final String COAUTHORSHIP_VIS = "coauthorship";
@ -83,5 +85,6 @@ public class VisualizationFrameworkConstants {
public static final String ENTITY_COMPARISON_VIS = "entity_comparison";
public static final String CO_PI_VIS = "coprincipalinvestigator";
}

View file

@ -455,7 +455,7 @@ public class CoAuthorshipQueryRunner implements QueryRunner<CoAuthorshipData> {
+ "} "
+ "ORDER BY ?document ?coAuthorPerson";
// System.out.println("COAUTHORSHIP QUERY - " + sparqlQuery);
System.out.println("COAUTHORSHIP QUERY - " + sparqlQuery);
return sparqlQuery;
}

View file

@ -0,0 +1,623 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.visualization.coprincipalinvestigator;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
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.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.valueobjects.CoPINode;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
/**
* This class contains code for rendering sparklines and displaying tables for
* Co-PI visualization.
* @author bkoniden
* Deepak Konidena
*/
@SuppressWarnings("serial")
public class CoPIVisCodeGenerator {
/*
* 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 copi(s) 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 years.
* */
private static final Map<String, String> VIS_DIV_NAMES = new HashMap<String, String>() { {
put("SHORT_SPARK", "unique_copis_short_sparkline_vis");
put("FULL_SPARK", "unique_copis_full_sparkline_vis");
} };
private static final String VISUALIZATION_STYLE_CLASS = "sparkline_style";
private static final String DEFAULT_VISCONTAINER_DIV_ID = "unique_copis_vis_container";
private Map<String, Set<CoPINode>> yearToUniqueCoPIs;
private Log log;
private SparklineData sparklineData;
private String contextPath;
private String individualURI;
public CoPIVisCodeGenerator(String contextPath,
String individualURI,
String visMode,
String visContainer,
Map<String, Set<CoPINode>> yearToUniqueCoPIs,
Log log){
this.contextPath = contextPath;
this.individualURI = individualURI;
this.yearToUniqueCoPIs = yearToUniqueCoPIs;
this.sparklineData = new SparklineData();
this.log = log;
generateVisualizationCode(visMode, visContainer);
}
/**
* 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
*/
private void generateVisualizationCode(String visMode, String visContainer) {
sparklineData.setSparklineContent(getMainVisualizationCode(visMode,
visContainer));
sparklineData.setSparklineContext(getVisualizationContextCode(visMode));
}
private String getMainVisualizationCode(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> investigatedYears = new HashSet<String>(yearToUniqueCoPIs
.keySet());
investigatedYears.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 investigated
* years.
*/
int minGrantYear = shortSparkMinYear;
String visContainerID = null;
StringBuilder visualizationCode = new StringBuilder();
if (yearToUniqueCoPIs.size() > 0) {
try {
minGrantYear = Integer.parseInt(Collections
.min(investigatedYears));
} catch (NoSuchElementException e1) {
log.debug("vis: " + e1.getMessage() + " error occurred for "
+ yearToUniqueCoPIs.toString());
} catch (NumberFormatException e2) {
log.debug("vis: " + e2.getMessage() + " error occurred for "
+ yearToUniqueCoPIs.toString());
}
}
int minGrantYearConsidered = 0;
/*
* There might be a case that the person 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;
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;" + "}"
+ ".incomplete-data-holder {" + "" + "}"
+ "td.sparkline_number { text-align:right; "
+ "padding-right:5px; }"
+ "td.sparkline_text {text-align:left;}" + "</style>\n");
visualizationCode
.append("<script type=\"text/javascript\">\n"
+ "function drawUniqueCoPICountVisualization(providedSparklineImgTD) {\n"
+ "var data = new google.visualization.DataTable();\n"
+ "data.addColumn('string', 'Year');\n"
+ "data.addColumn('number', 'Unique Co-PI(s)');\n"
+ "data.addRows(" + numOfYearsToBeRendered + ");\n");
int uniqueCoPICounter = 0;
int renderedFullSparks = 0;
Set<CoPINode> allCoPIsWithKnownGrantShipYears = new HashSet<CoPINode>();
for (int grantYear = minGrantYearConsidered; grantYear <= currentYear; grantYear++) {
String grantYearAsString = String.valueOf(grantYear);
Set<CoPINode> currentCoPIs = yearToUniqueCoPIs
.get(grantYearAsString);
Integer currentUniqueCoPIs = null;
if (currentCoPIs != null) {
currentUniqueCoPIs = currentCoPIs.size();
allCoPIsWithKnownGrantShipYears.addAll(currentCoPIs);
} else {
currentUniqueCoPIs = 0;
}
visualizationCode.append("data.setValue(" + uniqueCoPICounter
+ ", 0, '" + grantYearAsString + "');\n");
visualizationCode.append("data.setValue(" + uniqueCoPICounter
+ ", 1, " + currentUniqueCoPIs + ");\n");
uniqueCoPICounter++;
}
/*
* 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.
*/
renderedFullSparks = allCoPIsWithKnownGrantShipYears.size();
/*
* Total grants will also consider publications that have no year
* associated with them. Hence.
*/
Integer unknownYearCoPIs = 0;
if (yearToUniqueCoPIs.get(VOConstants.DEFAULT_GRANT_YEAR) != null) {
unknownYearCoPIs = yearToUniqueCoPIs.get(
VOConstants.DEFAULT_GRANT_YEAR).size();
}
String sparklineDisplayOptions = "{width: 65, height: 30, showAxisLines: false, "
+ "showValueLabels: false, labelPosition: 'none'}";
if (providedVisContainerID != null) {
visContainerID = providedVisContainerID;
} else {
visContainerID = DEFAULT_VISCONTAINER_DIV_ID;
}
/*
* 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.setEarliestRenderedGrantYear(minGrantYear);
sparklineData.setLatestRenderedGrantYear(currentYear);
/*
* The Full Sparkline will be rendered by default. Only if the url has
* specific mention of SHORT_SPARKLINE_MODE_KEY 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);
generateShortSparklineVisualizationContent(currentYear,
shortSparkMinYear, visContainerID, visualizationCode,
unknownYearCoPIs, sparklineDisplayOptions);
} else {
generateFullSparklineVisualizationContent(currentYear,
minGrantYearConsidered, visContainerID, visualizationCode,
unknownYearCoPIs, 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 drawUniqueCoPICountVisualization 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 = ''"
+ "+ ' Co-Principal Investigator(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
+ "}"
+ "drawUniqueCoPICountVisualization(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 (yearToUniqueCoPIs.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 (yearToUniqueCoPIs.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
.CO_PI_VIS,
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + VisualizationFrameworkConstants.VIS_MODE_KEY
+ "=" + URLEncoder.encode("sparkline",
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 (yearToUniqueCoPIs.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.VIS_CONTAINER_KEY
+ "=" + URLEncoder.encode("ego_sparkline",
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 full timeline and co-pi network.</a>";
sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL);
} else {
fullTimelineLink = "No data available to render full timeline.<br />";
}
divContextCode.append("<p>" + fullTimelineLink + "</p>");
} catch (UnsupportedEncodingException e) {
log.error(e);
}
return divContextCode.toString();
}
private String generateDataTable() {
StringBuilder dataTable = new StringBuilder();
dataTable.append("<table id='sparkline_data_table'>"
+ "<caption>Unique Co-PIs per year</caption>"
+ "<thead>"
+ "<tr>"
+ "<th>Year</th>"
+ "<th>Count</th>"
+ "</tr>"
+ "</thead>"
+ "<tbody>");
for (Entry<String, Set<CoPINode>> currentEntry : yearToUniqueCoPIs.entrySet()) {
dataTable.append("<tr>"
+ "<td>" + currentEntry.getKey() + "</td>"
+ "<td>" + currentEntry.getValue().size() + "</td>"
+ "</tr>");
}
dataTable.append("</tbody>\n </table>\n");
return dataTable.toString();
}
public SparklineData getValueObjectContainer() {
return sparklineData;
}
}

View file

@ -49,7 +49,7 @@ public class PersonGrantCountQueryRunner implements QueryRunner<Set<Grant>>{
private Log log;
private static final String SPARQL_QUERY_COMMON_SELECT_CLAUSE = ""
+ "SELECT (str(?PILabel)) as ?PILabelLit) "
+ "SELECT (str(?PILabel) as ?PILabelLit) "
+ "(str(?Grant) as ?grantLit)"
+ "(str(?GrantLabel) as ?grantLabelLit)"
+ "(str(?GrantStartDate) as ?grantStartDateLit)"
@ -120,7 +120,7 @@ public class PersonGrantCountQueryRunner implements QueryRunner<Set<Grant>>{
String sparqlQuery = QueryConstants.getSparqlPrefixQuery()
+ SPARQL_QUERY_COMMON_SELECT_CLAUSE
+ "(str(<" + queryURI + ">) as ?PILit "
+ "(str(<" + queryURI + ">) as ?PILit) "
+ "WHERE {"
+ "<" + queryURI + "> rdfs:label ?PILabel;"
+ "core:hasCo-PrincipalInvestigatorRole ?Role ."

View file

@ -80,27 +80,27 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
QueryRunner<Set<Grant>> queryManager =
new PersonGrantCountQueryRunner(personURI, dataSource, log);
// try {
// Set<Grant> authorDocuments = queryManager.getQueryResult();
try {
Set<Grant> PIGrants = queryManager.getQueryResult();
/*
* Create a map from the year to number of publications. Use the BiboDocument's
* Create a map from the year to number of grants. Use the Grant's
* parsedPublicationYear to populate the data.
* */
// Map<String, Integer> yearToPublicationCount =
// UtilityFunctions.getYearToPublicationCount(authorDocuments);
//
// Individual author = ((PersonGrantCountQueryRunner) queryManager).getAuthor();
//
// if (VisualizationFrameworkConstants.DATA_RENDER_MODE
// .equalsIgnoreCase(renderMode)) {
//
// prepareDataResponse(author,
// authorDocuments,
// yearToPublicationCount,
// response);
// return;
// }
Map<String, Integer> yearToGrantCount =
UtilityFunctions.getYearToGrantCount(PIGrants);
Individual investigator = ((PersonGrantCountQueryRunner) queryManager).getPrincipalInvestigator();
if (VisualizationFrameworkConstants.DATA_RENDER_MODE
.equalsIgnoreCase(renderMode)) {
prepareDataResponse(investigator,
PIGrants,
yearToGrantCount,
response);
return;
}
/*
@ -121,77 +121,77 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
/*
* Computations required to generate HTML for the sparkline & related context.
* */
// PersonGrantCountVisCodeGenerator visualizationCodeGenerator =
// new PersonGrantCountVisCodeGenerator(vitroRequest.getContextPath(),
// personURI,
// visMode,
// visContainer,
// authorDocuments,
// yearToPublicationCount,
// 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)) {
//
// prepareDynamicResponse(request,
// response,
// vitroRequest,
// sparklineData,
// yearToPublicationCount);
// requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp");
//
// } else {
// prepareStandaloneResponse(request,
// response,
// vitroRequest,
// sparklineData);
// requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
// }
//
// try {
// requestDispatcher.forward(request, response);
// } catch (Exception e) {
// log.error("EntityEditController could not forward to view.");
// log.error(e.getMessage());
// log.error(e.getStackTrace());
// }
//
// } catch (MalformedQueryParametersException e) {
// try {
// UtilityFunctions.handleMalformedParameters(
// e.getMessage(),
// "Visualization Query Error - Individual Publication Count",
// vitroRequest,
// request,
// response,
// log);
// } catch (ServletException e1) {
// log.error(e1.getStackTrace());
// } catch (IOException e1) {
// log.error(e1.getStackTrace());
// }
// return;
// }
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)) {
prepareDynamicResponse(request,
response,
vitroRequest,
sparklineData,
yearToGrantCount);
requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp");
} else {
prepareStandaloneResponse(request,
response,
vitroRequest,
sparklineData);
requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
}
try {
requestDispatcher.forward(request, response);
} catch (Exception e) {
log.error("EntityEditController could not forward to view.");
log.error(e.getMessage());
log.error(e.getStackTrace());
}
} catch (MalformedQueryParametersException e) {
try {
UtilityFunctions.handleMalformedParameters(
e.getMessage(),
"Visualization Query Error - Individual Publication Count",
vitroRequest,
request,
response,
log);
} catch (ServletException e1) {
log.error(e1.getStackTrace());
} catch (IOException e1) {
log.error(e1.getStackTrace());
}
return;
}
}
private void writePublicationsOverTimeCSV(
Map<String, Integer> yearToPublicationCount,
private void writeGrantsOverTimeCSV(
Map<String, Integer> yearToGrantCount,
PrintWriter responseWriter) {
CSVWriter csvWriter = new SimpleWriter(responseWriter);
try {
csvWriter.append(new String[] { "Year", "Publications" });
for (Entry<String, Integer> currentEntry : yearToPublicationCount
csvWriter.append(new String[] { "Year", "Grants" });
for (Entry<String, Integer> currentEntry : yearToGrantCount
.entrySet()) {
csvWriter.append(new Object[] { currentEntry.getKey(),
currentEntry.getValue() });
@ -205,38 +205,38 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
}
/**
* Provides response when csv file containing the publication count over the years
* Provides response when csv file containing the grant count over the years
* is requested.
* @param author
* @param authorDocuments
* @param yearToPublicationCount
* @param investigator
* @param piGrants
* @param yearToGrantCount
* @param response
*/
private void prepareDataResponse(
Individual author,
Set<Grant> authorDocuments,
Map<String, Integer> yearToPublicationCount,
Individual investigator,
Set<Grant> piGrants,
Map<String, Integer> yearToGrantCount,
HttpServletResponse response) {
String authorName = null;
String investigatorName = null;
/*
* To protect against cases where there are no author documents associated with the
* To protect against cases where there are no grants associated with the
* individual.
* */
if (authorDocuments.size() > 0) {
authorName = author.getIndividualLabel();
if (piGrants.size() > 0) {
investigatorName = investigator.getIndividualLabel();
}
/*
* To make sure that null/empty records for author names do not cause any mischief.
* To make sure that null/empty records for investigator names do not cause any mischief.
* */
if (StringUtils.isBlank(authorName)) {
authorName = "no-author";
if (StringUtils.isBlank(investigatorName)) {
investigatorName = "no-investigator";
}
String outputFileName = UtilityFunctions.slugify(authorName)
+ "_publications-per-year" + ".csv";
String outputFileName = UtilityFunctions.slugify(investigatorName)
+ "_grants-per-year" + ".csv";
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName);
@ -249,7 +249,7 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
* We are side-effecting responseWriter since we are directly manipulating the response
* object of the servlet.
* */
writePublicationsOverTimeCSV(yearToPublicationCount, responseWriter);
writeGrantsOverTimeCSV(yearToGrantCount, responseWriter);
responseWriter.close();
@ -273,34 +273,34 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
request.setAttribute("sparklineVO", valueObjectContainer);
request.setAttribute("bodyJsp", "/templates/visualization/publication_count.jsp");
request.setAttribute("bodyJsp", "/templates/visualization/grant_count.jsp");
request.setAttribute("portalBean", portal);
request.setAttribute("title", "Individual Publication Count visualization");
request.setAttribute("title", "Individual Grant Count visualization");
request.setAttribute("scripts", "/templates/visualization/visualization_scripts.jsp");
}
/**
* Provides response when the publication sparkline has to be rendered in already existing
* Provides response when the grant sparkline has to be rendered in already existing
* page, e.g. profile page.
* @param request
* @param response
* @param vreq
* @param valueObjectContainer
* @param yearToPublicationCount
* @param yearToGrantCount
*/
private void prepareDynamicResponse(
HttpServletRequest request,
HttpServletResponse response,
VitroRequest vreq,
SparklineData valueObjectContainer,
Map<String, Integer> yearToPublicationCount) {
Map<String, Integer> yearToGrantCount) {
Portal portal = vreq.getPortal();
request.setAttribute("sparklineVO", valueObjectContainer);
if (yearToPublicationCount.size() > 0) {
if (yearToGrantCount.size() > 0) {
request.setAttribute("shouldVIVOrenderVis", true);
} else {
request.setAttribute("shouldVIVOrenderVis", false);
@ -310,30 +310,30 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
request.setAttribute("bodyJsp", "/templates/visualization/ajax_vis_content.jsp");
}
private void preparePDFResponse(Individual author,
Set<Grant> authorDocuments,
Map<String, Integer> yearToPublicationCount,
private void preparePDFResponse(Individual investigator,
Set<Grant> piGrants,
Map<String, Integer> yearToGrantCount,
HttpServletResponse response) {
String authorName = null;
String investigatorName = null;
/*
* To protect against cases where there are no author documents
* To protect against cases where there are no PI Grants
* associated with the individual.
*/
if (authorDocuments.size() > 0) {
authorName = author.getIndividualLabel();
if (piGrants.size() > 0) {
investigatorName = investigator.getIndividualLabel();
}
/*
* To make sure that null/empty records for author names do not cause
* To make sure that null/empty records for PI names do not cause
* any mischief.
*/
if (StringUtils.isBlank(authorName)) {
authorName = "no-author";
if (StringUtils.isBlank(investigatorName)) {
investigatorName = "no-investigator";
}
String outputFileName = UtilityFunctions.slugify(authorName)
String outputFileName = UtilityFunctions.slugify(investigatorName)
+ "_report" + ".pdf";
response.setContentType("application/pdf");
@ -349,8 +349,8 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
document.open();
PDFDocument pdfDocument = new PDFDocument(authorName,
yearToPublicationCount, document, pdfWriter);
PDFDocument pdfDocument = new PDFDocument(investigatorName,
yearToGrantCount, document, pdfWriter);
document.close();

View file

@ -2,6 +2,674 @@
package edu.cornell.mannlib.vitro.webapp.visualization.persongrantcount;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
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.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.valueobjects.Grant;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
/**
* Class for rendering sparklines of grants over time for a person
* @author bkoniden
* Deepak Konidena
*/
@SuppressWarnings("serial")
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 years.
* */
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();
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> investigatedYears = new HashSet<String>(yearToGrantCount
.keySet());
investigatedYears.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 investigated
* years.
*/
int minInvestigatedYear = shortSparkMinYear;
String visContainerID = null;
StringBuilder visualizationCode = new StringBuilder();
if (yearToGrantCount.size() > 0) {
try {
minInvestigatedYear = Integer.parseInt(Collections
.min(investigatedYears));
} 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 minInvestigatedYearConsidered = 0;
/*
* There might be a case that the author has 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
* minInvestigatedYearConsidered to "currentYear - 10" which is also given by
* "shortSparkMinYear".
*/
if (minInvestigatedYear > shortSparkMinYear) {
minInvestigatedYearConsidered = shortSparkMinYear;
} else {
minInvestigatedYearConsidered = minInvestigatedYear;
}
numOfYearsToBeRendered = currentYear - minInvestigatedYearConsidered + 1;
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;
for (int grantYear = minInvestigatedYearConsidered; 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");
/*
* Sparks that will be rendered in full mode will always be the
* one's which has any year associated with it. Hence.
*/
renderedFullSparks += currentGrants;
grantCounter++;
}
/*
* Total grants will also consider grants 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);
}
String sparklineDisplayOptions = "{width: 65, height: 30, showAxisLines: false, "
+ "showValueLabels: false, labelPosition: 'none'}";
if (providedVisContainerID != null) {
visContainerID = providedVisContainerID;
} else {
visContainerID = DEFAULT_VIS_CONTAINER_DIV_ID;
}
/*
* 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.setEarliestRenderedGrantYear(minInvestigatedYear);
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);
generateShortSparklineVisualizationContent(currentYear,
shortSparkMinYear, visContainerID, visualizationCode,
unknownYearGrants, sparklineDisplayOptions);
} else {
generateFullSparklineVisualizationContent(currentYear,
minInvestigatedYearConsidered, 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
+ "}"
+ "drawGrantCountVisualization(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()
+ "&"
+ VisualizationFrameworkConstants.VIS_MODE_KEY
+ "="
+ URLEncoder.encode("copi",
VisualizationController.URL_ENCODING_SCHEME)
.toString();
return downloadURL;
} else {
return null;
}
}
private String generateShortVisContext() {
StringBuilder divContextCode = new StringBuilder();
try {
String fullTimelineLink, fullTimelineCoPILink;
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()
+ "&"
+ VisualizationFrameworkConstants.VIS_MODE_KEY
+ "=" + URLEncoder.encode("copi",
VisualizationController.URL_ENCODING_SCHEME).toString();
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View all VIVO "
+ "grants and corresponding co-pi network.</a>";
sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL);
String fullTimelineCoPINetworkURL = 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()
+ "&"
+ VisualizationFrameworkConstants.VIS_MODE_KEY
+ "=" + URLEncoder.encode("copi",
VisualizationController.URL_ENCODING_SCHEME).toString();
fullTimelineCoPILink = "<a href='" + fullTimelineCoPINetworkURL + "'>View all "
+ "grants and corresponding co-pi network.</a>";
sparklineData.setFullTimelineCoPINetworkLink(fullTimelineCoPINetworkURL);
} else {
fullTimelineLink = "No data available to render full timeline.<br />";
fullTimelineCoPILink = "No data available to render full timeline.<br />";
}
divContextCode.append("<span class=\"vis_link\">" + fullTimelineLink + "</span>");
divContextCode.append("<br/><br/><span class=\"vis_link_copi\">" + fullTimelineCoPILink + "</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;
}
}

View file

@ -28,10 +28,16 @@ import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipG
import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipQueryRunner;
import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipVisCodeGenerator;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.persongrantcount.PersonGrantCountQueryRunner;
import edu.cornell.mannlib.vitro.webapp.visualization.persongrantcount.PersonGrantCountVisCodeGenerator;
import edu.cornell.mannlib.vitro.webapp.visualization.coprincipalinvestigator.CoPIGrantCountQueryRunner;
import edu.cornell.mannlib.vitro.webapp.visualization.coprincipalinvestigator.CoPIVisCodeGenerator;
import edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.PersonPublicationCountQueryRunner;
import edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.PersonPublicationCountVisCodeGenerator;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.CoAuthorshipData;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.CoPIData;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Grant;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
@ -53,6 +59,10 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
private static final String EGO_PUB_SPARKLINE_VIS_CONTAINER_ID = "ego_pub_sparkline";
private static final String UNIQUE_COAUTHORS_SPARKLINE_VIS_CONTAINER_ID =
"unique_coauthors_sparkline";
private static final String EGO_GRANT_SPARKLINE_VIS_CONTAINER_ID = "ego_grant_sparkline";
private static final String UNIQUE_COPIS_SPARKLINE_VIS_CONTAINER_ID =
"unique_copis_sparkline";
public void generateVisualization(VitroRequest vitroRequest,
HttpServletRequest request,
@ -75,10 +85,18 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
QueryRunner<Set<BiboDocument>> publicationQueryManager =
new PersonPublicationCountQueryRunner(egoURI, dataSource, log);
QueryRunner<CoPIData> coPIQueryManager = new CoPIGrantCountQueryRunner(egoURI, dataSource, log);
QueryRunner<Set<Grant>> grantQueryManager =
new PersonGrantCountQueryRunner(egoURI, dataSource, log);
try {
CoAuthorshipData coAuthorshipData = coAuthorshipQueryManager.getQueryResult();
CoPIData coPIData = coPIQueryManager.getQueryResult();
if (VisualizationFrameworkConstants.DATA_RENDER_MODE
.equalsIgnoreCase(renderMode)) {
@ -154,18 +172,63 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
SparklineData uniqueCoauthorsSparklineVO = uniqueCoauthorsVisCodeGenerator
.getValueObjectContainer();
/*
* grants over time sparkline
*/
Set<Grant> piGrants = grantQueryManager.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);
PersonGrantCountVisCodeGenerator personGrantCountVisCodeGenerator =
new PersonGrantCountVisCodeGenerator(
vitroRequest.getRequestURI(),
egoURI,
VisualizationFrameworkConstants.FULL_SPARKLINE_VIS_MODE,
EGO_PUB_SPARKLINE_VIS_CONTAINER_ID,
piGrants,
yearToGrantCount,
log);
SparklineData grantSparklineVO = personGrantCountVisCodeGenerator
.getValueObjectContainer();
/*
* Co-PI's over time sparkline
*/
CoPIVisCodeGenerator uniqueCopisVisCodeGenerator =
new CoPIVisCodeGenerator(
vitroRequest.getRequestURI(),
egoURI,
VisualizationFrameworkConstants.FULL_SPARKLINE_VIS_MODE,
UNIQUE_COAUTHORS_SPARKLINE_VIS_CONTAINER_ID,
UtilityFunctions.getGrantYearToCoPI(coPIData),
log);
SparklineData uniqueCopisSparklineVO = uniqueCopisVisCodeGenerator
.getValueObjectContainer();
RequestDispatcher requestDispatcher = null;
prepareStandaloneResponse(
egoURI,
publicationSparklineVO,
uniqueCoauthorsSparklineVO,
grantSparklineVO,
uniqueCopisSparklineVO,
coAuthorshipData,
coPIData,
EGO_PUB_SPARKLINE_VIS_CONTAINER_ID,
UNIQUE_COAUTHORS_SPARKLINE_VIS_CONTAINER_ID,
vitroRequest,
request);
request, visMode);
requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
@ -319,21 +382,25 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
* @param egoURI
* @param egoPubSparklineVO
* @param uniqueCoauthorsSparklineVO
* @param uniqueCopisSparklineVO
* @param grantSparklineVO
* @param coAuthorshipVO
* @param coPIVO
* @param egoPubSparklineVisContainer
* @param uniqueCoauthorsSparklineVisContainer
* @param vitroRequest
* @param request
* @param visMode
*/
private void prepareStandaloneResponse (
String egoURI,
SparklineData egoPubSparklineVO,
SparklineData uniqueCoauthorsSparklineVO,
CoAuthorshipData coAuthorshipVO,
String egoPubSparklineVisContainer,
SparklineData egoGrantSparklineVO, SparklineData uniqueCopisSparklineVO, CoAuthorshipData coAuthorshipVO,
CoPIData coPIVO, String egoPubSparklineVisContainer,
String uniqueCoauthorsSparklineVisContainer,
VitroRequest vitroRequest,
HttpServletRequest request) {
HttpServletRequest request, String visMode) {
String completeURL = "";
Portal portal = vitroRequest.getPortal();
@ -350,16 +417,28 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
request.setAttribute("numOfCoAuthorShips", coAuthorshipVO.getEdges().size());
}
if (coPIVO.getNodes() != null && coPIVO.getNodes().size() > 0) {
request.setAttribute("numOfInvestigators", coPIVO.getNodes().size());
//title = coPIVO.getEgoNode().getNodeName() + " - ";
}
if (coPIVO.getEdges() != null && coPIVO.getEdges().size() > 0) {
request.setAttribute("numOfCoPIs", coPIVO.getEdges().size());
}
try {
completeURL = getCompleteURL(request);
} catch (MalformedURLException e) {
e.printStackTrace();
}
request.setAttribute("visMode", visMode);
request.setAttribute("completeURL", completeURL);
request.setAttribute("egoPubSparklineVO", egoPubSparklineVO);
request.setAttribute("egoGrantSparklineVO", egoGrantSparklineVO);
request.setAttribute("uniqueCoauthorsSparklineVO", uniqueCoauthorsSparklineVO);
request.setAttribute("uniqueCopisSparklineVO", uniqueCopisSparklineVO);
request.setAttribute("egoPubSparklineContainerID", egoPubSparklineVisContainer);
request.setAttribute("uniqueCoauthorsSparklineVisContainerID",

View file

@ -186,7 +186,7 @@ public class PersonPublicationCountQueryRunner implements QueryRunner<Set<BiboDo
+ SPARQL_QUERY_COMMON_WHERE_CLAUSE
+ "}";
// System.out.println("SPARQL query for person pub count -> \n" + sparqlQuery);
System.out.println("SPARQL query for person pub count -> \n" + sparqlQuery);
return sparqlQuery;
}

View file

@ -567,7 +567,7 @@ public class PersonPublicationCountVisCodeGenerator {
try {
String fullTimelineLink;
String fullTimelineLink, fullTimelineCoPILink;
if (yearToPublicationCount.size() > 0) {
String secondaryContextPath = "";
@ -600,11 +600,39 @@ public class PersonPublicationCountVisCodeGenerator {
sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL);
String fullTimelineCoPINetworkURL = 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()
+ "&"
+ VisualizationFrameworkConstants.VIS_MODE_KEY
+ "=" + URLEncoder.encode("copi",
VisualizationController.URL_ENCODING_SCHEME).toString();
fullTimelineCoPILink = "<a href='" + fullTimelineCoPINetworkURL + "'>View all "
+ "grants and corresponding co-pi network.</a>";
sparklineData.setFullTimelineCoPINetworkLink(fullTimelineCoPINetworkURL);
} else {
fullTimelineLink = "No data available to render full timeline.<br />";
fullTimelineCoPILink = "No data available to render full timeline.<br />";
}
divContextCode.append("<span class=\"vis_link\">" + fullTimelineLink + "</span>");
divContextCode.append("<br/><br/><span class=\"vis_link_copi\">" + fullTimelineCoPILink + "</span>");
} catch (UnsupportedEncodingException e) {
log.error(e);

View file

@ -213,7 +213,36 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
+ VisualizationFrameworkConstants.RENDER_MODE_KEY
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
.STANDALONE_RENDER_MODE,
VisualizationController.URL_ENCODING_SCHEME).toString();
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&"
+ VisualizationFrameworkConstants.VIS_MODE_KEY
+ "=" + URLEncoder.encode("coauthorship",
VisualizationController.URL_ENCODING_SCHEME).toString();
prepareUtilitiesResponse(preparedURL, response);
return;
} else if (VisualizationFrameworkConstants.COPI_UTILS_VIS_MODE
.equalsIgnoreCase(visMode)) {
preparedURL += request.getContextPath()
+ VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX
+ "?"
+ 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()
+ "&"
+ VisualizationFrameworkConstants.VIS_MODE_KEY
+ "=" + URLEncoder.encode("copi",
VisualizationController.URL_ENCODING_SCHEME).toString();
prepareUtilitiesResponse(preparedURL, response);
return;

View file

@ -15,11 +15,17 @@ public class SparklineData {
private Integer earliestRenderedPublicationYear;
private Integer latestRenderedPublicationYear;
private Integer earliestRenderedGrantYear;
private Integer latestRenderedGrantYear;
private String table = "";
private String downloadDataLink = "";
private String fullTimelineNetworkLink = "";
private String downloadCoPIDataLink = "";
private String fullTimelineCoPINetworkLink = "";
private String sparklineContent;
private String sparklineContext;
@ -97,4 +103,38 @@ public class SparklineData {
public void setSparklineContext(String shortSparklineContext) {
this.sparklineContext = shortSparklineContext;
}
public String getDownloadCoPIDataLink() {
return downloadCoPIDataLink;
}
public void setDownloadCoPIDataLink(String downloadCoPIDataLink) {
this.downloadCoPIDataLink = downloadCoPIDataLink;
}
public String getFullTimelineCoPINetworkLink() {
return fullTimelineCoPINetworkLink;
}
public void setFullTimelineCoPINetworkLink(String fullTimelineCoPINetworkLink) {
this.fullTimelineCoPINetworkLink = fullTimelineCoPINetworkLink;
}
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;
}
}