diff --git a/productMods/WEB-INF/visualization/visualizations-beans-injection.xml b/productMods/WEB-INF/visualization/visualizations-beans-injection.xml index a6b6d471..f7c64b38 100644 --- a/productMods/WEB-INF/visualization/visualizations-beans-injection.xml +++ b/productMods/WEB-INF/visualization/visualizations-beans-injection.xml @@ -21,6 +21,9 @@ class="edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison.EntityPublicationCountRequestHandler" /> + + @@ -44,6 +47,9 @@ + + + diff --git a/productMods/WEB-INF/web.xml b/productMods/WEB-INF/web.xml index 04a6636c..14243702 100644 --- a/productMods/WEB-INF/web.xml +++ b/productMods/WEB-INF/web.xml @@ -172,11 +172,7 @@ org.apache.commons.fileupload.servlet.FileCleanerCleanup - - - edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache - - + - + edu.cornell.mannlib.vitro.webapp.servlet.setup.VivoMergedListFilteringSetup @@ -351,16 +347,6 @@ /N3EditForm - - MenuN3EditController - edu.cornell.mannlib.vitro.webapp.controller.freemarker.MenuN3EditController - - - MenuN3EditController - /MenuN3EditController - - - - - ajaxSparqlQuery - edu.cornell.mannlib.vitro.webapp.controller.ajax.SparqlQueryAjaxController - - - ajaxSparqlQuery - /ajax/sparqlQuery - - fetch diff --git a/productMods/images/visualization/coauthorship/EgoCentric-old-tabbed.swf b/productMods/images/visualization/coauthorship/EgoCentric-old-tabbed.swf deleted file mode 100644 index 5e88a4da..00000000 Binary files a/productMods/images/visualization/coauthorship/EgoCentric-old-tabbed.swf and /dev/null differ diff --git a/productMods/images/visualization/coauthorship/EgoCentric-working.swf b/productMods/images/visualization/coauthorship/EgoCentric-working.swf deleted file mode 100755 index 05c20a01..00000000 Binary files a/productMods/images/visualization/coauthorship/EgoCentric-working.swf and /dev/null differ diff --git a/productMods/images/visualization/coauthorship/EgoCentric.swf b/productMods/images/visualization/coauthorship/EgoCentric.swf index 05c20a01..b13d9352 100644 Binary files a/productMods/images/visualization/coauthorship/EgoCentric.swf and b/productMods/images/visualization/coauthorship/EgoCentric.swf differ diff --git a/productMods/images/visualization/coauthorship/EgoCentric_Old.swf b/productMods/images/visualization/coauthorship/EgoCentric_Old.swf deleted file mode 100644 index 5e88a4da..00000000 Binary files a/productMods/images/visualization/coauthorship/EgoCentric_Old.swf and /dev/null differ diff --git a/productMods/images/visualization/coauthorship/EgoCentric_Old2.swf b/productMods/images/visualization/coauthorship/EgoCentric_Old2.swf deleted file mode 100755 index 694f22d9..00000000 Binary files a/productMods/images/visualization/coauthorship/EgoCentric_Old2.swf and /dev/null differ diff --git a/productMods/js/visualization/personlevel/person_level.js b/productMods/js/visualization/personlevel/person_level.js index ea99cb43..ccb736d4 100644 --- a/productMods/js/visualization/personlevel/person_level.js +++ b/productMods/js/visualization/personlevel/person_level.js @@ -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
"; + }else{ + tableCaption = "Co-pis "; + tableColumnTitle1 = "Principal Investigator"; + tableColumnTitle2 = "Grants with
"; + } + var table = $(''); table.attr('id', tableID); - table.append($(''); var row = $(''); var authorTH = $(''); row.append($('
').html("Co-authors (.CSV File)")); + table.append($('').html(tableCaption + "(.CSV File)")); var header = $('
'); - authorTH.html("Author"); + authorTH.html(tableColumnTitle1); row.append(authorTH); - row.append($('').html("Publications with
" + $('#ego_label').text())); + row.append($('
').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 = $('
').html(item.label)); - row.append($('').html(item.number_of_authored_works)); + row.append($('').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", diff --git a/productMods/templates/visualization/grant_count.jsp b/productMods/templates/visualization/grant_count.jsp new file mode 100644 index 00000000..b807683f --- /dev/null +++ b/productMods/templates/visualization/grant_count.jsp @@ -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"%> + + + +
+ + +
+${sparkline.sparklineContent} +
+${sparkline.sparklineContext} +
\ No newline at end of file diff --git a/productMods/templates/visualization/person_level.jsp b/productMods/templates/visualization/person_level.jsp index 3a87922e..13ee17d8 100644 --- a/productMods/templates/visualization/person_level.jsp +++ b/productMods/templates/visualization/person_level.jsp @@ -10,7 +10,10 @@ + + + @@ -18,6 +21,10 @@ + + + + @@ -34,10 +41,18 @@ - - + + + + + + + + + + - -
- -
-
-
- -
 
- -
- -
-
  Publication(s)
-
  Co-author(s)
- - - - -
- - - - - - - -
- -

Tables

- -
-

- ${egoPubSparkline.table} -

+ + +
+ +
+
+
+ +
 
+ +
+ +
+
  Publication(s)
+
  Co-author(s)
+ + + +
- - - -
-

-
- -
- -
- -
+ + +
+ +
+
+
+ +
 
+ +
+ +
+
  Grant(s)
+
  Co-PI(s)
+ + + + +
+
+ +
+
+ + + + + + + + + + + + + +
+ +

Tables

+ +
+

+ ${egoPubSparkline.table} +

+
+ + + +
+

+
+ +
+ +
+ +
+
+
+ + + +
+ +

Tables

+ +
+

+ ${egoGrantSparkline.table} +

+
+ + + +
+

+
+ +
+ +
+ +
+
+ +
+
\ No newline at end of file diff --git a/productMods/templates/visualization/person_level_inject_head.jsp b/productMods/templates/visualization/person_level_inject_head.jsp index 8211fa1d..1652b9b5 100644 --- a/productMods/templates/visualization/person_level_inject_head.jsp +++ b/productMods/templates/visualization/person_level_inject_head.jsp @@ -59,6 +59,7 @@ var egoCoAuthorsListDataFileURL = "${egoCoAuthorsListDataFileURL}"; var egoCoPIDataFeederURL = "${egoCoPIDataFeederURL}"; var contextPath = "${contextPath}"; var domainParam = "${requestScope.completeURL}"; +var visMode = "${requestScope.visMode}"; // --> diff --git a/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationFrameworkConstants.java b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationFrameworkConstants.java index 8f9db84c..4d065348 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationFrameworkConstants.java +++ b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationFrameworkConstants.java @@ -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"; + } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryRunner.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryRunner.java index 1f73985a..e72c8ab5 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryRunner.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryRunner.java @@ -455,7 +455,7 @@ public class CoAuthorshipQueryRunner implements QueryRunner { + "} " + "ORDER BY ?document ?coAuthorPerson"; -// System.out.println("COAUTHORSHIP QUERY - " + sparqlQuery); + System.out.println("COAUTHORSHIP QUERY - " + sparqlQuery); return sparqlQuery; } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coprincipalinvestigator/CoPIVisCodeGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coprincipalinvestigator/CoPIVisCodeGenerator.java new file mode 100644 index 00000000..be931fd7 --- /dev/null +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coprincipalinvestigator/CoPIVisCodeGenerator.java @@ -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 VIS_DIV_NAMES = new HashMap() { { + + 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> yearToUniqueCoPIs; + + private Log log; + + private SparklineData sparklineData; + + private String contextPath; + + private String individualURI; + + public CoPIVisCodeGenerator(String contextPath, + String individualURI, + String visMode, + String visContainer, + Map> 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 investigatedYears = new HashSet(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("\n"); + + visualizationCode + .append("\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 .csv file.
"; + sparklineData.setDownloadDataLink(getCSVDownloadURL()); + + } else { + csvDownloadURLHref = ""; + } + + } catch (UnsupportedEncodingException e) { + csvDownloadURLHref = ""; + } + + } else { + csvDownloadURLHref = "No data available to export.
"; + } + + String tableCode = generateDataTable(); + + divContextCode.append("

" + tableCode + csvDownloadURLHref + "

"); + + 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 = "View full timeline and co-pi network."; + + sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL); + + } else { + fullTimelineLink = "No data available to render full timeline.
"; + } + + divContextCode.append("

" + fullTimelineLink + "

"); + + } catch (UnsupportedEncodingException e) { + log.error(e); + } + + return divContextCode.toString(); + } + + private String generateDataTable() { + + StringBuilder dataTable = new StringBuilder(); + + dataTable.append("" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""); + + for (Entry> currentEntry : yearToUniqueCoPIs.entrySet()) { + dataTable.append("" + + "" + + "" + + ""); + } + + dataTable.append("\n
Unique Co-PIs per year
YearCount
" + currentEntry.getKey() + "" + currentEntry.getValue().size() + "
\n"); + + return dataTable.toString(); + } + + public SparklineData getValueObjectContainer() { + return sparklineData; + } +} diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountQueryRunner.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountQueryRunner.java index 215df69d..15f0e910 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountQueryRunner.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountQueryRunner.java @@ -49,7 +49,7 @@ public class PersonGrantCountQueryRunner implements QueryRunner>{ 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>{ 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 ." diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountRequestHandler.java index df22681f..b9a33575 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountRequestHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountRequestHandler.java @@ -80,27 +80,27 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl QueryRunner> queryManager = new PersonGrantCountQueryRunner(personURI, dataSource, log); -// try { -// Set authorDocuments = queryManager.getQueryResult(); + try { + Set 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 yearToPublicationCount = -// UtilityFunctions.getYearToPublicationCount(authorDocuments); -// -// Individual author = ((PersonGrantCountQueryRunner) queryManager).getAuthor(); -// -// if (VisualizationFrameworkConstants.DATA_RENDER_MODE -// .equalsIgnoreCase(renderMode)) { -// -// prepareDataResponse(author, -// authorDocuments, -// yearToPublicationCount, -// response); -// return; -// } + Map 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 yearToPublicationCount, + private void writeGrantsOverTimeCSV( + Map yearToGrantCount, PrintWriter responseWriter) { CSVWriter csvWriter = new SimpleWriter(responseWriter); try { - csvWriter.append(new String[] { "Year", "Publications" }); - for (Entry currentEntry : yearToPublicationCount + csvWriter.append(new String[] { "Year", "Grants" }); + for (Entry 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 authorDocuments, - Map yearToPublicationCount, + Individual investigator, + Set piGrants, + Map 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 yearToPublicationCount) { + Map 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 authorDocuments, - Map yearToPublicationCount, + private void preparePDFResponse(Individual investigator, + Set piGrants, + Map 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(); diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountVisCodeGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountVisCodeGenerator.java index 949c16e1..23d35a0f 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountVisCodeGenerator.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/persongrantcount/PersonGrantCountVisCodeGenerator.java @@ -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 VIS_DIV_NAMES = new HashMap() { { + + 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 yearToGrantCount; + + private Log log; + + private SparklineData sparklineData; + + private String contextPath; + + private String individualURI; + + public PersonGrantCountVisCodeGenerator(String contextPath, + String individualURIParam, String visMode, String visContainer, + Set piGrants, + Map 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 piGrants) { + + sparklineData.setSparklineContent(getMainVisualizationCode(piGrants, + visMode, + visContainer)); + + + sparklineData.setSparklineContext(getVisualizationContextCode(visMode)); + + } + + private String getMainVisualizationCode(Set 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 investigatedYears = new HashSet(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("\n"); + + visualizationCode.append("\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 .csv file.
"; + sparklineData.setDownloadDataLink(getCSVDownloadURL()); + + } else { + csvDownloadURLHref = ""; + } + + } catch (UnsupportedEncodingException e) { + csvDownloadURLHref = ""; + } + } else { + csvDownloadURLHref = "No data available to export.
"; + } + + String tableCode = generateDataTable(); + + divContextCode.append("

" + tableCode + csvDownloadURLHref + "

"); + + 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 = "View all VIVO " + + "grants and corresponding co-pi network."; + + 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 = "View all " + + "grants and corresponding co-pi network."; + + sparklineData.setFullTimelineCoPINetworkLink(fullTimelineCoPINetworkURL); + + } else { + fullTimelineLink = "No data available to render full timeline.
"; + fullTimelineCoPILink = "No data available to render full timeline.
"; + + } + + divContextCode.append("" + fullTimelineLink + ""); + divContextCode.append("

" + fullTimelineCoPILink + ""); + + } catch (UnsupportedEncodingException e) { + log.error(e); + } + return divContextCode.toString(); + } + + private String generateDataTable() { + + String csvDownloadURLHref = ""; + + try { + if (getCSVDownloadURL() != null) { + csvDownloadURLHref = "(.CSV File)"; + } else { + csvDownloadURLHref = ""; + } + } catch (UnsupportedEncodingException e) { + csvDownloadURLHref = ""; + } + + StringBuilder dataTable = new StringBuilder(); + + dataTable.append("" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""); + + for (Entry currentEntry : yearToGrantCount.entrySet()) { + dataTable.append("" + + "" + + "" + + ""); + } + + dataTable.append("\n
Grants per year " + csvDownloadURLHref + "
YearGrants
" + currentEntry.getKey() + "" + currentEntry.getValue() + "
\n"); + + return dataTable.toString(); + } + + public SparklineData getValueObjectContainer() { + return sparklineData; + } + } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/personlevel/PersonLevelRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/personlevel/PersonLevelRequestHandler.java index 4e752374..49f9c7d2 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/personlevel/PersonLevelRequestHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personlevel/PersonLevelRequestHandler.java @@ -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> publicationQueryManager = new PersonPublicationCountQueryRunner(egoURI, dataSource, log); + QueryRunner coPIQueryManager = new CoPIGrantCountQueryRunner(egoURI, dataSource, log); + + + QueryRunner> 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 piGrants = grantQueryManager.getQueryResult(); + + /* + * Create a map from the year to number of grants. Use the Grant's + * parsedGrantYear to populate the data. + * */ + Map 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", diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryRunner.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryRunner.java index 45e2e482..3c978559 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryRunner.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryRunner.java @@ -186,7 +186,7 @@ public class PersonPublicationCountQueryRunner implements QueryRunner \n" + sparqlQuery); + System.out.println("SPARQL query for person pub count -> \n" + sparqlQuery); return sparqlQuery; } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountVisCodeGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountVisCodeGenerator.java index 8beb333d..f4aa9ae1 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountVisCodeGenerator.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountVisCodeGenerator.java @@ -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 = "View all " + + "grants and corresponding co-pi network."; + + sparklineData.setFullTimelineCoPINetworkLink(fullTimelineCoPINetworkURL); + } else { fullTimelineLink = "No data available to render full timeline.
"; + fullTimelineCoPILink = "No data available to render full timeline.
"; + } divContextCode.append("" + fullTimelineLink + ""); + divContextCode.append("

" + fullTimelineCoPILink + ""); } catch (UnsupportedEncodingException e) { log.error(e); diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/utilities/UtilitiesRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/utilities/UtilitiesRequestHandler.java index 3e77e0e3..5f169db2 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/utilities/UtilitiesRequestHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/utilities/UtilitiesRequestHandler.java @@ -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; diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineData.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineData.java index 884d3084..d5b6baad 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineData.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineData.java @@ -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; + } + + } diff --git a/themes/wilma/site_icons/visualization/coauthorship/EgoCentric.swf b/themes/wilma/site_icons/visualization/coauthorship/EgoCentric.swf new file mode 100644 index 00000000..b13d9352 Binary files /dev/null and b/themes/wilma/site_icons/visualization/coauthorship/EgoCentric.swf differ