1) Added link for Co-PI network on the Co-Author visualization.

2) created entityComparison folder under themes/wilma/css/visualization and added layout.css there to make Temporal Vis working with wilma.
3) Created new classes for PersonGrantCount(sparkline for grants over time) and EntityGrantCount(grants for institutional level entities)
This commit is contained in:
bkoniden 2010-12-03 15:53:50 +00:00
parent 46a3b9a7bf
commit 72662f38bf
7 changed files with 865 additions and 3 deletions

View file

@ -34,6 +34,12 @@
<c:param name="uri" value="${requestScope.egoURIParam}" />
</c:url>
<c:url var="coprincipalinvestigator" value="/visualization">
<c:param name="vis" value="coprincipalinvestigator"/>
<c:param name="render_mode" value="standalone"/>
<c:param name="uri" value="${requestScope.egoURIParam}"/>
</c:url>
<script language="JavaScript" type="text/javascript">
$(document).ready(function(){
@ -166,7 +172,9 @@ $(document).ready(function(){
</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">

View file

@ -0,0 +1,7 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.visualization.entitygrantcount;
public class EntityGrantCountQueryRunner {
}

View file

@ -0,0 +1,260 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.visualization.persongrantcount;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import com.hp.hpl.jena.iri.IRI;
import com.hp.hpl.jena.iri.IRIFactory;
import com.hp.hpl.jena.iri.Violation;
import com.hp.hpl.jena.query.DataSource;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.Syntax;
import com.hp.hpl.jena.rdf.model.RDFNode;
import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryFieldLabels;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Grant;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
/**
* This query runner is used to execute Sparql query that will fetch all the grants for an individual
* @author bkoniden
* Deepak Konidena
*
*/
public class PersonGrantCountQueryRunner implements QueryRunner<Set<Grant>>{
protected static final Syntax SYNTAX = Syntax.syntaxARQ;
private String personURI;
private DataSource dataSource;
private Individual principalInvestigator;
public Individual getPrincipalInvestigator(){
return principalInvestigator;
}
private Log log;
private static final String SPARQL_QUERY_COMMON_SELECT_CLAUSE = ""
+ "SELECT (str(?PILabel)) as ?PILabelLit) "
+ "(str(?Grant) as ?grantLit)"
+ "(str(?GrantLabel) as ?grantLabelLit)"
+ "(str(?GrantStartDate) as ?grantStartDateLit)"
+ "(str(?GrantEndDate) as ?grantEndDateLit)" ;
public PersonGrantCountQueryRunner(String personURI, DataSource dataSource, Log log){
this.personURI = personURI;
this.dataSource = dataSource;
this.log = log;
}
private Set<Grant> createJavaValueObjects(ResultSet resultSet){
Set<Grant> PIGrant = new HashSet<Grant>();
while(resultSet.hasNext()){
QuerySolution solution = resultSet.nextSolution();
Grant grant = new Grant(solution.get(QueryFieldLabels.GRANT_URL).toString());
RDFNode grantLabelNode = solution.get(QueryFieldLabels.GRANT_LABEL);
if(grantLabelNode != null){
grant.setIndividualLabel(grantLabelNode.toString());
}
RDFNode grantStartDateNode = solution.get(QueryFieldLabels.GRANT_START_DATE);
if(grantStartDateNode != null){
grant.setGrantStartDate(grantStartDateNode.toString());
}
RDFNode grantEndDateNode = solution.get(QueryFieldLabels.GRANT_END_DATE);
if(grantEndDateNode != null){
grant.setGrantEndDate(grantEndDateNode.toString());
}
/*
* Since we are getting grant count for just one PI at a time we need
* to create only one "Individual" instance. We test against the null for "PI" to
* make sure that it has not already been instantiated.
* */
RDFNode PIURLNode = solution.get(QueryFieldLabels.PI_URL);
if (PIURLNode != null && principalInvestigator == null) {
principalInvestigator = new Individual(PIURLNode.toString());
RDFNode PILabelNode = solution.get(QueryFieldLabels.PI_LABEL);
if (PILabelNode != null) {
principalInvestigator.setIndividualLabel(PILabelNode.toString());
}
}
PIGrant.add(grant);
}
return PIGrant;
}
private ResultSet executeQuery(String queryURI, DataSource dataSource){
QueryExecution queryExecution = null;
Query query = QueryFactory.create(getSparqlQuery(queryURI), SYNTAX);
queryExecution = QueryExecutionFactory.create(query,dataSource);
return queryExecution.execSelect();
}
private String getSparqlQuery(String queryURI){
String sparqlQuery = QueryConstants.getSparqlPrefixQuery()
+ SPARQL_QUERY_COMMON_SELECT_CLAUSE
+ "(str(<" + queryURI + ">) as ?PILit "
+ "WHERE {"
+ "<" + queryURI + "> rdfs:label ?PILabel;"
+ "core:hasCo-PrincipalInvestigatorRole ?Role ."
+ "?Role core:roleIn ?Grant ."
+ "?Grant rdfs:label ?GrantLabel ; core:startDate ?GrantStartDate ; core:endDate ?GrantEndDate ."
+ "}";
System.out.println("SPARQL query for person grant count -> \n"+ sparqlQuery);
return sparqlQuery;
}
public Set<Grant> getQueryResult() throws MalformedQueryParametersException{
if(StringUtils.isNotBlank(this.personURI)){
/*
* To test the validity of the URI submitted
*/
IRIFactory iriFactory = IRIFactory.jenaImplementation();
IRI iri = iriFactory.create(this.personURI);
if(iri.hasViolation(false)){
String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage();
log.error("Grant Count vis Query " + errorMsg);
throw new MalformedQueryParametersException(
"URI provided for an individual is malformed.");
}
} else {
throw new MalformedQueryParametersException("URL parameter is either null or empty.");
}
ResultSet resultSet = executeQuery(this.personURI, this.dataSource);
return createJavaValueObjects(resultSet);
}
}

View file

@ -0,0 +1,376 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.visualization.persongrantcount;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.skife.csv.CSVWriter;
import org.skife.csv.SimpleWriter;
import com.hp.hpl.jena.query.DataSource;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter;
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Grant;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler;
/**
*
* This request handler is used to serve the content related to an individual's
* grants over the years like,
* 1. Sparkline representing this
* 2. An entire page dedicated to the sparkline vis which will also have links to
* download the data using which the sparkline was rendered & its tabular representation etc.
* 3. Downloadable CSV file containing number of grants over the years.
* 4. Downloadable PDf file containing the grant content, among other things.
* Currently this is disabled because the feature is half-baked. We plan to activate this in
* the next major release.
*
* @author bkoniden
* Deepak Konidena
*/
public class PersonGrantCountRequestHandler implements VisualizationRequestHandler {
public void generateVisualization(VitroRequest vitroRequest,
HttpServletRequest request,
HttpServletResponse response,
Log log,
DataSource dataSource) {
String personURI = vitroRequest.getParameter(
VisualizationFrameworkConstants
.INDIVIDUAL_URI_KEY);
String renderMode = vitroRequest.getParameter(
VisualizationFrameworkConstants
.RENDER_MODE_KEY);
String visMode = vitroRequest.getParameter(
VisualizationFrameworkConstants
.VIS_MODE_KEY);
String visContainer = vitroRequest.getParameter(
VisualizationFrameworkConstants
.VIS_CONTAINER_KEY);
QueryRunner<Set<BiboDocument>> queryManager =
new PersonGrantCountQueryRunner(personURI, dataSource, log);
try {
Set<Grant> authorDocuments = queryManager.getQueryResult();
/*
* Create a map from the year to number of publications. Use the BiboDocument'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;
}
/*
* For now we are disabling the capability to render pdf file.
* */
/*
if (VisualizationFrameworkConstants.PDF_RENDER_MODE
.equalsIgnoreCase(renderMode)) {
preparePDFResponse(author,
authorDocuments,
yearToPublicationCount,
response);
return;
}
*/
/*
* 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;
}
}
private void writePublicationsOverTimeCSV(
Map<String, Integer> yearToPublicationCount,
PrintWriter responseWriter) {
CSVWriter csvWriter = new SimpleWriter(responseWriter);
try {
csvWriter.append(new String[] { "Year", "Publications" });
for (Entry<String, Integer> currentEntry : yearToPublicationCount
.entrySet()) {
csvWriter.append(new Object[] { currentEntry.getKey(),
currentEntry.getValue() });
}
} catch (IOException e) {
e.printStackTrace();
}
responseWriter.flush();
}
/**
* Provides response when csv file containing the publication count over the years
* is requested.
* @param author
* @param authorDocuments
* @param yearToPublicationCount
* @param response
*/
private void prepareDataResponse(
Individual author,
Set<BiboDocument> authorDocuments,
Map<String, Integer> yearToPublicationCount,
HttpServletResponse response) {
String authorName = null;
/*
* To protect against cases where there are no author documents associated with the
* individual.
* */
if (authorDocuments.size() > 0) {
authorName = author.getIndividualLabel();
}
/*
* To make sure that null/empty records for author names do not cause any mischief.
* */
if (StringUtils.isBlank(authorName)) {
authorName = "no-author";
}
String outputFileName = UtilityFunctions.slugify(authorName)
+ "_publications-per-year" + ".csv";
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName);
try {
PrintWriter responseWriter = response.getWriter();
/*
* We are side-effecting responseWriter since we are directly manipulating the response
* object of the servlet.
* */
writePublicationsOverTimeCSV(yearToPublicationCount, responseWriter);
responseWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Provides response when an entire page dedicated to publication sparkline is requested.
* @param request
* @param response
* @param vreq
* @param valueObjectContainer
*/
private void prepareStandaloneResponse(HttpServletRequest request,
HttpServletResponse response, VitroRequest vreq,
SparklineData valueObjectContainer) {
Portal portal = vreq.getPortal();
request.setAttribute("sparklineVO", valueObjectContainer);
request.setAttribute("bodyJsp", "/templates/visualization/publication_count.jsp");
request.setAttribute("portalBean", portal);
request.setAttribute("title", "Individual Publication Count visualization");
request.setAttribute("scripts", "/templates/visualization/visualization_scripts.jsp");
}
/**
* Provides response when the publication sparkline has to be rendered in already existing
* page, e.g. profile page.
* @param request
* @param response
* @param vreq
* @param valueObjectContainer
* @param yearToPublicationCount
*/
private void prepareDynamicResponse(
HttpServletRequest request,
HttpServletResponse response,
VitroRequest vreq,
SparklineData valueObjectContainer,
Map<String, Integer> yearToPublicationCount) {
Portal portal = vreq.getPortal();
request.setAttribute("sparklineVO", valueObjectContainer);
if (yearToPublicationCount.size() > 0) {
request.setAttribute("shouldVIVOrenderVis", true);
} else {
request.setAttribute("shouldVIVOrenderVis", false);
}
request.setAttribute("portalBean", portal);
request.setAttribute("bodyJsp", "/templates/visualization/ajax_vis_content.jsp");
}
private void preparePDFResponse(Individual author,
Set<BiboDocument> authorDocuments,
Map<String, Integer> yearToPublicationCount,
HttpServletResponse response) {
String authorName = null;
/*
* To protect against cases where there are no author documents
* associated with the individual.
*/
if (authorDocuments.size() > 0) {
authorName = author.getIndividualLabel();
}
/*
* To make sure that null/empty records for author names do not cause
* any mischief.
*/
if (StringUtils.isBlank(authorName)) {
authorName = "no-author";
}
String outputFileName = UtilityFunctions.slugify(authorName)
+ "_report" + ".pdf";
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment;filename="
+ outputFileName);
ServletOutputStream responseOutputStream;
try {
responseOutputStream = response.getOutputStream();
Document document = new Document();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
document.open();
PDFDocument pdfDocument = new PDFDocument(authorName,
yearToPublicationCount, document, pdfWriter);
document.close();
// setting some response headers & content type
response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentLength(baos.size());
// write ByteArrayOutputStream to the ServletOutputStream
baos.writeTo(responseOutputStream);
responseOutputStream.flush();
responseOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,7 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.visualization.persongrantcount;
public class PersonGrantCountVisCodeGenerator {
}

View file

@ -23,6 +23,7 @@ import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
@SuppressWarnings("serial")
public class PersonPublicationCountVisCodeGenerator {
@ -549,8 +550,11 @@ public class PersonPublicationCountVisCodeGenerator {
+ "&" + VisualizationFrameworkConstants.RENDER_MODE_KEY
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
.DATA_RENDER_MODE,
VisualizationController.URL_ENCODING_SCHEME)
.toString();
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&"
+ VisualizationFrameworkConstants.VIS_MODE_KEY
+ "=" + URLEncoder.encode("coauthorship",
VisualizationController.URL_ENCODING_SCHEME).toString();
return downloadURL;
} else {
return null;
@ -585,6 +589,10 @@ public class PersonPublicationCountVisCodeGenerator {
+ VisualizationFrameworkConstants.RENDER_MODE_KEY
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
.STANDALONE_RENDER_MODE,
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&"
+ VisualizationFrameworkConstants.VIS_MODE_KEY
+ "=" + URLEncoder.encode("coauthorship",
VisualizationController.URL_ENCODING_SCHEME).toString();
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View all VIVO "

View file

@ -0,0 +1,196 @@
@CHARSET "UTF-8";
head,#body {
font: 0.9em Helvetica;
}
#body {
background-color: #fff;
min-height: 800px;
width: 100%;
min-width: 900px;
margin: auto;
}
h1 {
padding-top: 10px;
font-size: 1.5em;
margin-left: 5%;
}
h2 {
font-size: 1.1em;
margin-top: 10px;
margin-bottom: 5px;
}
h3 {
font-size: 1.01em;
}
button{
margin-top: 10px;
float:right;
}
form{
margin-top:70px;
margin-bottom: -50px;
}
#yaxislabel{
font-size: 12px;
float:right;
background-color: white;
color:black;
display: block;
height: 150px;
text-align: center;
padding-top: 50px;
}
#xaxislabel{
font-size: 12px;
margin-top: -5px;
text-align: center;
}
#functions{
margin-top: 20px;
margin-bottom: -40px;
}
#bar {
height: 20px;
float: left;
background-color: #fff;
width: 250px;
margin-left: 10px;
}
#checkbox{
float:left;
}
#label {
float: left;
font-size: 12px;
width: 160px;
text-align: right;
}
#searchresult {
margin-top: 50px;
}
#bottom,#graphContainer {
float: right;
}
#graphContainer {
margin-bottom: 15px;
}
#leftblock {
float: left;
margin-left: 5%;
width: 36%;
}
#text {
margin-left: 5px;
}
#searchresult a {
text-decoration: none;
color: black;
font-family: Helvetica;
font-size: 13px;
font-weight: normal;
}
#label a,#text {
text-decoration: none;
color: black;
font-family: Helvetica;
font-size: 1em;
}
#rightblock {
float:right;
margin-right:5%;
width:54%;
}
#counter,#total {
color: red;
}
#heading {
margin-top: 10px;
}
li{
padding: 5px;
list-style: none;
}
#paginatedTable{
margin-top: 10px;
}
.sDomSearchBar{
margin-bottom: 10px;
margin-left: 41%;
}
.datatablerowhighlight {
background-color: #ECFFB3 !important;
}
.metallic{
background-color: #212D34;
color: white;
margin-left: 20px;
}
#leftUpper{
border: 1px #3D454E solid;
border-top: 10px #3D454E solid;
background-color: #D9D9D9;
}
#leftLower{
border: 1px #3D454E solid;
border-top: 10px #3D454E solid;
}
#navcontainer{
background: none repeat scroll 0 0 #3D454E;
height: 1%;
padding: 8px 22em 8px 20px;
position: relative;
}
#navlist li
{
display: inline;
list-style-type: none;
padding: 20px;
}
#navlist li a{
color: white;
text-decoration: none;
}
#bottomButtons{
width: 50%;
float:right;
margin-right: 5%;
}
#stopwordsdiv{
margin-top: 10px;
}
p.displayCounter{
padding-bottom: 4px;
border-bottom: 1px solid gray;
}