1. Refactoered code.

2. Handled the case when a person does not have any publications by generating dummy graphml file.
3. Added handlers for multiple sparklines on same page.
4. Added sparkline code generator for unique co-authors over time.
This commit is contained in:
cdtank 2010-07-08 21:28:05 +00:00
parent 7e7f5c6bc7
commit 9e4836bd79
10 changed files with 801 additions and 46 deletions

View file

@ -62,9 +62,13 @@ public class CoAuthorshipGraphMLWriter {
graphMLContent.append("\n<graph edgedefault=\"undirected\">\n"); graphMLContent.append("\n<graph edgedefault=\"undirected\">\n");
if (visVOContainer.getNodes() != null & visVOContainer.getNodes().size() > 0) {
generateNodeSectionContent(visVOContainer, graphMLContent); generateNodeSectionContent(visVOContainer, graphMLContent);
}
if (visVOContainer.getEdges() != null & visVOContainer.getEdges().size() > 0) {
generateEdgeSectionContent(visVOContainer, graphMLContent); generateEdgeSectionContent(visVOContainer, graphMLContent);
}
graphMLContent.append("</graph>\n"); graphMLContent.append("</graph>\n");

View file

@ -0,0 +1,633 @@
package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship;
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.valueobjects.SparklineVOContainer;
public class VisualizationCodeGenerator {
private final static Map<String, String> visDivNames = new HashMap<String, String>() {{
put("SHORT_SPARK", "unique_coauthors_short_sparkline_vis");
put("FULL_SPARK", "unique_coauthors_full_sparkline_vis");
}};
private static final String visualizationStyleClass = "sparkline_style";
private static final String defaultVisContainerDivID = "unique_coauthors_vis_container";
public static final String SHORT_SPARKLINE_MODE_URL_HANDLE = "short";
public static final String FULL_SPARKLINE_MODE_URL_HANDLE = "full";
private Map<String, Integer> yearToUniqueCoauthorsCount;
private Log log;
private SparklineVOContainer valueObjectContainer;
private String contextPath;
private String individualURIParam;
public VisualizationCodeGenerator(String contextPath,
String individualURIParam,
String visMode,
String visContainer,
Map<String, Integer> yearToUniqueCoauthorsCount,
SparklineVOContainer valueObjectContainer,
Log log) {
this.contextPath = contextPath;
this.individualURIParam = individualURIParam;
this.yearToUniqueCoauthorsCount = yearToUniqueCoauthorsCount;
this.valueObjectContainer = valueObjectContainer;
this.log = log;
generateVisualizationCode(visMode,
visContainer);
}
private void generateVisualizationCode(String visMode,
String visContainer) {
valueObjectContainer.setSparklineContent(getMainVisualizationCode(visMode,
visContainer));
valueObjectContainer.setSparklineContext(getVisualizationContextCode(visMode));
}
private String getMainVisualizationCode(String visMode,
String providedVisContainerID) {
int numOfYearsToBeRendered = 0;
int currentYear = Calendar.getInstance().get(Calendar.YEAR);
int shortSparkMinYear = currentYear - 10 + 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_PUBLICATION_YEAR".
* */
Set<String> publishedYears = new HashSet(yearToUniqueCoauthorsCount.keySet());
publishedYears.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
/*
* We are setting the default value of minPublishedYear to be 10 years before
* the current year (which is suitably represented by the shortSparkMinYear),
* this in case we run into invalid set of published years.
* */
int minPublishedYear = shortSparkMinYear;
String visContainerID = null;
StringBuilder visualizationCode = new StringBuilder();
// System.out.println(yearToPublicationCount);
if (yearToUniqueCoauthorsCount.size() > 0) {
try {
minPublishedYear = Integer.parseInt(Collections.min(publishedYears));
System.out.println("min pub year - " + minPublishedYear);
} catch (NoSuchElementException e1) {
log.debug("vis: " + e1.getMessage() + " error occurred for " + yearToUniqueCoauthorsCount.toString());
} catch (NumberFormatException e2) {
log.debug("vis: " + e2.getMessage() + " error occurred for " + yearToUniqueCoauthorsCount.toString());
}
}
int minPubYearConsidered = 0;
/*
* There might be a case that the author has made his first publication 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 minPubYearConsidered to
* "currentYear - 10" which is also given by "shortSparkMinYear".
* */
if (minPublishedYear > shortSparkMinYear) {
minPubYearConsidered = shortSparkMinYear;
} else {
minPubYearConsidered = minPublishedYear;
}
numOfYearsToBeRendered = currentYear - minPubYearConsidered + 1;
visualizationCode.append("<style type='text/css'>" +
"." + visualizationStyleClass + " table{" +
" margin: 0;" +
" padding: 0;" +
" width: auto;" +
" border-collapse: collapse;" +
" border-spacing: 0;" +
" vertical-align: inherit;" +
"}" +
/*".sparkline_wrapper_table table{" +
" vertical-align: bottom;" +
"}" +*/
"td.sparkline_number { text-align:right; padding-right:5px; }" +
"td.sparkline_text {text-align:left;}" +
/*"#sparkline_data_table {" +
"width: auto;" +
"}" +
"#sparkline_data_table tfoot {" +
"color: red;" +
"font-size:0.9em;" +
"}" +
".sparkline_text {" +
"margin-left:72px;" +
"position:absolute;" +
"}" +
".sparkline_range {" +
"color:#7BA69E;" +
"font-size:0.9em;" +
"font-style:italic;" +
"}" +*/
"</style>\n");
// .sparkline {display:inline; margin:0; padding:0; width:600px }
// td.sparkline-img {margin:0; padding:0; }
visualizationCode.append("<script type=\"text/javascript\">\n" +
"function drawUniqueCoauthorCountVisualization(providedSparklineImgTD) {\n" +
"var data = new google.visualization.DataTable();\n" +
"data.addColumn('string', 'Year');\n" +
"data.addColumn('number', 'Publications');\n" +
"data.addRows(" + numOfYearsToBeRendered + ");\n");
int publicationCounter = 0;
int totalPublications = 0;
int renderedFullSparks = 0;
for (int publicationYear = minPubYearConsidered; publicationYear <= currentYear; publicationYear++) {
String stringPublishedYear = String.valueOf(publicationYear);
Integer currentPublications = yearToUniqueCoauthorsCount.get(stringPublishedYear);
if (currentPublications == null) {
currentPublications = 0;
}
visualizationCode.append("data.setValue("
+ publicationCounter
+ ", 0, '"
+ stringPublishedYear
+ "');\n");
visualizationCode.append("data.setValue("
+ publicationCounter
+ ", 1, "
+ currentPublications
+ ");\n");
totalPublications += currentPublications;
publicationCounter++;
}
/*
* Sparks that will be rendered in full mode will always be the one's which has any year
* associated with it. Hence.
* */
renderedFullSparks = totalPublications;
/*
* Total publications will also consider publications that have no year associated with
* it. Hence.
* */
if (yearToUniqueCoauthorsCount.get(VOConstants.DEFAULT_PUBLICATION_YEAR) != null) {
totalPublications += yearToUniqueCoauthorsCount.get(VOConstants.DEFAULT_PUBLICATION_YEAR);
}
String sparklineDisplayOptions = "{width: 63, height: 21, showAxisLines: false, " +
"showValueLabels: false, labelPosition: 'none'}";
if (providedVisContainerID != null) {
visContainerID = providedVisContainerID;
} else {
visContainerID = defaultVisContainerDivID;
}
/*
* By default these represents the range of the rendered sparks. Only in case of
* "short" sparkline mode we will set the Earliest RenderedPublication year to
* "currentYear - 10".
* */
valueObjectContainer.setEarliestRenderedPublicationYear(minPublishedYear);
valueObjectContainer.setLatestRenderedPublicationYear(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 (SHORT_SPARKLINE_MODE_URL_HANDLE.equalsIgnoreCase(visMode)) {
valueObjectContainer.setEarliestRenderedPublicationYear(shortSparkMinYear);
generateShortSparklineVisualizationContent(currentYear,
shortSparkMinYear,
visContainerID,
visualizationCode,
totalPublications,
sparklineDisplayOptions);
} else {
generateFullSparklineVisualizationContent(currentYear,
minPubYearConsidered,
visContainerID,
visualizationCode,
totalPublications,
renderedFullSparks,
sparklineDisplayOptions);
}
// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
log.debug(visualizationCode);
// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
return visualizationCode.toString();
}
private void generateShortSparklineVisualizationContent(int currentYear,
int shortSparkMinYear, String visContainerID,
StringBuilder visualizationCode, int totalPublications,
String sparklineDisplayOptions) {
/*
* Create a view of the data containing only the column pertaining to publication 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 publication 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(" +
// "document.getElementById('" + visDivNames.get("SHORT_SPARK") + "')" +
"providedSparklineImgTD[0]" +
");\n" +
"short_spark.draw(shortSparklineView, " + sparklineDisplayOptions + ");\n");
/*
* We want to display how many publication 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.
* */
visualizationCode.append("$('#" + visDivNames.get("SHORT_SPARK") + " td.sparkline_number').text(renderedShortSparks);");
visualizationCode.append("var shortSparksText = ''" +
"+ ' Papers with year from '" +
"+ ' " + totalPublications + " '" +
"+ ' total " +
"<span class=\"sparkline_range\">" +
"(" + shortSparkMinYear + " - " + currentYear + ")" +
"</span>'" +
"+ '';" +
"$('#" + visDivNames.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 drawUniqueCoauthorCountVisualization function.
* */
visualizationCode.append(generateVisualizationActivator(visDivNames.get("SHORT_SPARK"), visContainerID));
}
private void generateFullSparklineVisualizationContent(
int currentYear, int minPubYearConsidered, String visContainerID, StringBuilder visualizationCode,
int totalPublications, int renderedFullSparks,
String sparklineDisplayOptions) {
String csvDownloadURL = "";
try {
csvDownloadURL = getCSVDownloadURL();
} catch (UnsupportedEncodingException e) {
csvDownloadURL = "#";
}
visualizationCode.append("var fullSparklineView = new google.visualization.DataView(data);\n" +
"fullSparklineView.setColumns([1]);\n");
visualizationCode.append("var full_spark = new google.visualization.ImageSparkLine(" +
// "document.getElementById('" + visDivNames.get("FULL_SPARK") + "')" +
"providedSparklineImgTD[0]" +
");\n" +
"full_spark.draw(fullSparklineView, " + sparklineDisplayOptions + ");\n");
visualizationCode.append("$('#" + visDivNames.get("FULL_SPARK") + " td.sparkline_number').text('" + renderedFullSparks + "');");
visualizationCode.append("var allSparksText = ''" +
"+ ' papers with year from '" +
"+ ' " + totalPublications + " '" +
"+ ' total " +
"<span class=\"sparkline_range\">" +
"(" + minPubYearConsidered + " - " + currentYear + ")" +
"</span> '" +
"+ ' <a href='\"" + csvDownloadURL + "\"' class='inline_href'>(.CSV File)</a>';" +
"$('#" + visDivNames.get("FULL_SPARK") + " td.sparkline_text').html(allSparksText);");
visualizationCode.append("}\n ");
visualizationCode.append(generateVisualizationActivator(visDivNames.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', '75');" +
"sparklineImgTD.attr('align', 'right');" +
"sparklineImgTD.attr('class', '" + visualizationStyleClass + "');" +
"row.append(sparklineImgTD);" +
"var sparklineNumberTD = $('<td>');" +
"sparklineNumberTD.attr('width', '36');" +
"sparklineNumberTD.attr('align', 'right');" +
"sparklineNumberTD.attr('class', 'sparkline_number');" +
"row.append(sparklineNumberTD);" +
"var sparklineTextTD = $('<td>');" +
"sparklineTextTD.attr('width', '350');" +
"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': '" + visualizationStyleClass + "'" +
"}).prependTo('#" + visContainerID + "');" +
sparklineTableWrapper +
"}" +
"drawUniqueCoauthorCountVisualization(sparklineImgTD);" +
"});" +
"</script>\n";
}
private String getVisualizationContextCode(String visMode) {
String visualizationContextCode = "";
if (SHORT_SPARKLINE_MODE_URL_HANDLE.equalsIgnoreCase(visMode)) {
visualizationContextCode = generateShortVisContext();
} else {
visualizationContextCode = generateFullVisContext();
}
// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
log.debug(visualizationContextCode);
// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
return visualizationContextCode;
}
private String generateFullVisContext() {
StringBuilder divContextCode = new StringBuilder();
try {
String downloadFileCode;
if (yearToUniqueCoauthorsCount.size() > 0) {
String downloadURL = getCSVDownloadURL();
downloadFileCode = "Download data as <a href='" + downloadURL + "'>.csv</a> file.<br />";
valueObjectContainer.setDownloadDataLink(downloadURL);
} else {
downloadFileCode = "No data available to export.<br />";
}
String tableCode = generateDataTable();
divContextCode.append("<p>" + tableCode +
downloadFileCode + "</p>");
valueObjectContainer.setTable(tableCode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return divContextCode.toString();
}
private String getCSVDownloadURL()
throws UnsupportedEncodingException {
if (yearToUniqueCoauthorsCount.size() > 0) {
String downloadURL = contextPath
// + "/admin/visQuery"
+ "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ "=" + URLEncoder.encode(individualURIParam,
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE
+ "=" + URLEncoder.encode(VisualizationController
.COAUTHORSHIP_VIS_URL_VALUE,
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE
+ "=" + URLEncoder.encode("sparkline",
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE,
VisualizationController.URL_ENCODING_SCHEME).toString();
System.out.println(" ----- >>>> " + contextPath + " XX " + individualURIParam + " XX " + downloadURL);
return downloadURL;
} else {
return "#";
}
}
private String generateShortVisContext() {
StringBuilder divContextCode = new StringBuilder();
try {
String fullTimelineLink;
if (yearToUniqueCoauthorsCount.size() > 0) {
// String fullTimelineNetworkURL = uri.toString() + "?" +
// VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE +
// "=" + URLEncoder.encode(individualURI,
// VisualizationController.URL_ENCODING_SCHEME).toString() +
// "&" +
// "vis" +
// "=" + URLEncoder.encode(VisualizationController
// .PERSON_PUBLICATION_COUNT_VIS_URL_VALUE,
// VisualizationController.URL_ENCODING_SCHEME).toString() +
// "&" +
// VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE +
// "=" + URLEncoder.encode(VisualizationFrameworkConstants.STANDALONE_RENDER_MODE_URL_VALUE,
// VisualizationController.URL_ENCODING_SCHEME).toString();
String fullTimelineNetworkURL = contextPath
+ "/admin/visQuery"
+ "?"
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ "=" + URLEncoder.encode(individualURIParam,
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&"
+ VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE
+ "=" + URLEncoder.encode("person_level",
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&"
+ VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE
+ "=" + URLEncoder.encode("ego_sparkline",
VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&"
+ VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants.STANDALONE_RENDER_MODE_URL_VALUE,
VisualizationController.URL_ENCODING_SCHEME).toString();
System.out.println("context parth full n/w " + contextPath);
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View full timeline and co-author network</a><br />";
valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL);
} else {
fullTimelineLink = "No data available to render full timeline.<br />";
}
divContextCode.append("<p>" + fullTimelineLink + "</p>");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return divContextCode.toString();
}
private String generateDataTable() {
StringBuilder dataTable = new StringBuilder();
dataTable.append("<table id='sparkline_data_table'>" +
"<caption>Unique Co-Authors per year</caption>" +
"<thead>" +
"<tr>" +
"<th>Year</th>" +
"<th>Count</th>" +
"</tr>" +
"</thead>" +
"<tbody>");
for (Entry<String, Integer> currentEntry : yearToUniqueCoauthorsCount.entrySet()) {
dataTable.append("<tr>" +
"<td>" + currentEntry.getKey() + "</td>" +
"<td>" + currentEntry.getValue() + "</td>" +
"</tr>");
}
dataTable.append("</tbody>\n" +
// "<tfoot>" +
// "<tr><td colspan='2'>*DNA - Data not available</td></tr>" +
// "</tfoot>\n" +
"</table>\n");
return dataTable.toString();
}
}

View file

@ -194,12 +194,24 @@ public class VisualizationRequestHandler {
private void prepareVisualizationQuerySparklineDataResponse(VisVOContainer authorNodesAndEdges) { private void prepareVisualizationQuerySparklineDataResponse(VisVOContainer authorNodesAndEdges) {
String outputFileName = "";
Map<String, Set<Node>> yearToCoauthors = new TreeMap<String, Set<Node>>();
Map<String, Set<Node>> yearToCoauthors = getCoAuthorsStats(authorNodesAndEdges); if (authorNodesAndEdges.getNodes() == null || authorNodesAndEdges.getNodes().size() < 1 ) {
String outputFileName = UtilityFunctions.slugify(authorNodesAndEdges.getEgoNode().getNodeName()) outputFileName = "no-coauthorship-net" + ".graphml";
} else {
outputFileName = UtilityFunctions.slugify(authorNodesAndEdges.getEgoNode().getNodeName())
+ "-coauthors" + ".csv"; + "-coauthors" + ".csv";
yearToCoauthors = getCoAuthorsStats(authorNodesAndEdges);
}
response.setContentType("application/octet-stream"); response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName); response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName);

View file

@ -2,8 +2,12 @@ package edu.cornell.mannlib.vitro.webapp.visualization.personlevel;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException; import javax.servlet.ServletException;
@ -17,14 +21,14 @@ import com.hp.hpl.jena.query.DataSource;
import edu.cornell.mannlib.vitro.webapp.beans.Portal; import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers; import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipGraphMLWriter; import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipGraphMLWriter;
import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.QueryHandler;
import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisVOContainer; import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisVOContainer;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationCodeGenerator; import edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationCodeGenerator;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
public class VisualizationRequestHandler { public class VisualizationRequestHandler {
@ -55,7 +59,8 @@ public class VisualizationRequestHandler {
String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE); String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE);
String visContainer = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE); String egoPubSparklineVisContainerID = "ego_pub_sparkline";
String uniqueCoauthorsSparklineVisContainerID = "unique_coauthors_sparkline";
edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.QueryHandler coAuthorshipQueryManager = edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.QueryHandler coAuthorshipQueryManager =
new edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.QueryHandler(egoURIParam, new edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.QueryHandler(egoURIParam,
@ -64,7 +69,7 @@ public class VisualizationRequestHandler {
dataSource, dataSource,
log); log);
edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.QueryHandler sparklineQueryManager = edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.QueryHandler publicationQueryManager =
new edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.QueryHandler(egoURIParam, new edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.QueryHandler(egoURIParam,
resultFormatParam, resultFormatParam,
rdfResultFormatParam, rdfResultFormatParam,
@ -94,38 +99,57 @@ public class VisualizationRequestHandler {
} }
List<BiboDocument> authorDocuments = sparklineQueryManager.getVisualizationJavaValueObjects(); List<BiboDocument> authorDocuments = publicationQueryManager.getVisualizationJavaValueObjects();
/* /*
* Create a map from the year to number of publications. Use the BiboDocument's * Create a map from the year to number of publications. Use the BiboDocument's
* parsedPublicationYear to populate the data. * parsedPublicationYear to populate the data.
* */ * */
Map<String, Integer> yearToPublicationCount = sparklineQueryManager Map<String, Integer> yearToPublicationCount = publicationQueryManager
.getYearToPublicationCount(authorDocuments); .getYearToPublicationCount(authorDocuments);
Map<String, Integer> yearToUniqueCoauthorCount = getUniqueCoauthorsCountPerYear(coAuthorshipVO);
/* /*
* Computations required to generate HTML for the sparklines & related context. * Computations required to generate HTML for the sparklines & related context.
* */ * */
edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisVOContainer sparklineVO = SparklineVOContainer publicationSparklineVO = new SparklineVOContainer();
new edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisVOContainer(); SparklineVOContainer uniqueCoauthorsSparklineVO = new SparklineVOContainer();
edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationCodeGenerator visualizationCodeGenerator = edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationCodeGenerator personPubCountVisCodeGenerator =
new edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationCodeGenerator( new edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationCodeGenerator(
vitroRequest.getRequestURI(), vitroRequest.getRequestURI(),
egoURIParam, egoURIParam,
VisualizationCodeGenerator.FULL_SPARKLINE_MODE_URL_HANDLE, VisualizationCodeGenerator.FULL_SPARKLINE_MODE_URL_HANDLE,
visContainer, egoPubSparklineVisContainerID,
authorDocuments, authorDocuments,
yearToPublicationCount, yearToPublicationCount,
sparklineVO, publicationSparklineVO,
log);
edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisualizationCodeGenerator uniqueCoauthorsVisCodeGenerator =
new edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisualizationCodeGenerator(
vitroRequest.getRequestURI(),
egoURIParam,
VisualizationCodeGenerator.FULL_SPARKLINE_MODE_URL_HANDLE,
uniqueCoauthorsSparklineVisContainerID,
yearToUniqueCoauthorCount,
uniqueCoauthorsSparklineVO,
log); log);
RequestDispatcher requestDispatcher = null; RequestDispatcher requestDispatcher = null;
prepareVisualizationQueryStandaloneResponse(egoURIParam, sparklineVO, request, response, vitroRequest); prepareVisualizationQueryStandaloneResponse(egoURIParam,
publicationSparklineVO,
uniqueCoauthorsSparklineVO,
egoPubSparklineVisContainerID,
uniqueCoauthorsSparklineVisContainerID,
request,
response,
vitroRequest);
// requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp"); // requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp");
requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
@ -151,11 +175,75 @@ public class VisualizationRequestHandler {
} }
private Map<String, Integer> getUniqueCoauthorsCountPerYear(
edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisVOContainer coAuthorshipVO) {
Map<String, Integer> yearToUniqueCoauthorCount = new TreeMap<String, Integer>();
Map<String, Set<Node>> yearToUniqueCoauthors = getUniqueCoAuthorsPerYear(coAuthorshipVO);
for (Entry<String, Set<Node>> currentEntry : yearToUniqueCoauthors.entrySet()) {
yearToUniqueCoauthorCount.put(currentEntry.getKey(), currentEntry.getValue().size());
}
return yearToUniqueCoauthorCount;
}
private Map<String, Set<Node>> getUniqueCoAuthorsPerYear(edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisVOContainer authorNodesAndEdges) {
Map<String, Set<Node>> yearToCoAuthors = new TreeMap<String, Set<Node>>();
Node egoNode = authorNodesAndEdges.getEgoNode();
for (Node currNode : authorNodesAndEdges.getNodes()) {
/*
* We have already printed the Ego Node info.
* */
if (currNode != egoNode) {
for (String year : currNode.getYearToPublicationCount().keySet()) {
Set<Node> coAuthorNodes;
if (yearToCoAuthors.containsKey(year)) {
coAuthorNodes = yearToCoAuthors.get(year);
coAuthorNodes.add(currNode);
} else {
coAuthorNodes = new HashSet<Node>();
coAuthorNodes.add(currNode);
yearToCoAuthors.put(year, coAuthorNodes);
}
}
}
}
return yearToCoAuthors;
}
private void prepareVisualizationQueryDataResponse(VisVOContainer coAuthorsipVO) { private void prepareVisualizationQueryDataResponse(VisVOContainer coAuthorsipVO) {
String outputFileName = UtilityFunctions.slugify(coAuthorsipVO.getEgoNode().getNodeName()) String outputFileName = "";
if (coAuthorsipVO.getNodes() == null || coAuthorsipVO.getNodes().size() < 1) {
outputFileName = "no-coauthorship-net" + ".graphml";
} else {
outputFileName = UtilityFunctions.slugify(coAuthorsipVO.getEgoNode().getNodeName())
+ "-coauthor-net" + ".graphml"; + "-coauthor-net" + ".graphml";
}
response.setContentType("application/octet-stream"); response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName); response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName);
@ -167,7 +255,6 @@ public class VisualizationRequestHandler {
* We are side-effecting responseWriter since we are directly manipulating the response * We are side-effecting responseWriter since we are directly manipulating the response
* object of the servlet. * object of the servlet.
* */ * */
CoAuthorshipGraphMLWriter coAuthorShipGraphMLWriter = new CoAuthorshipGraphMLWriter(coAuthorsipVO); CoAuthorshipGraphMLWriter coAuthorShipGraphMLWriter = new CoAuthorshipGraphMLWriter(coAuthorsipVO);
responseWriter.append(coAuthorShipGraphMLWriter.getCoAuthorshipGraphMLContent()); responseWriter.append(coAuthorShipGraphMLWriter.getCoAuthorshipGraphMLContent());
@ -181,15 +268,20 @@ public class VisualizationRequestHandler {
private void prepareVisualizationQueryStandaloneResponse( private void prepareVisualizationQueryStandaloneResponse(
String egoURIParam, String egoURIParam,
edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisVOContainer sparklineVO, SparklineVOContainer egoPubSparklineVO,
HttpServletRequest request, SparklineVOContainer uniqueCoauthorsSparklineVO, String egoPubSparklineVisContainer, String uniqueCoauthorsSparklineVisContainer, HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response,
VitroRequest vreq) { VitroRequest vreq) {
Portal portal = vreq.getPortal(); Portal portal = vreq.getPortal();
request.setAttribute("egoURIParam", egoURIParam); request.setAttribute("egoURIParam", egoURIParam);
request.setAttribute("sparklineVO", sparklineVO);
request.setAttribute("egoPubSparklineVO", egoPubSparklineVO);
request.setAttribute("uniqueCoauthorsSparklineVO", uniqueCoauthorsSparklineVO);
request.setAttribute("egoPubSparklineContainerID", egoPubSparklineVisContainer);
request.setAttribute("uniqueCoauthorsSparklineVisContainerID", uniqueCoauthorsSparklineVisContainer);
request.setAttribute("title", "Person Level Visualization"); request.setAttribute("title", "Person Level Visualization");
request.setAttribute("portalBean", portal); request.setAttribute("portalBean", portal);

View file

@ -18,6 +18,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationCo
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; 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.VOConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer;
public class VisualizationCodeGenerator { public class VisualizationCodeGenerator {
@ -31,7 +32,7 @@ public class VisualizationCodeGenerator {
private static final String visualizationStyleClass = "sparkline_style"; private static final String visualizationStyleClass = "sparkline_style";
private static final String defaultVisContainerDivID = "vis_container"; private static final String defaultVisContainerDivID = "pub_count_vis_container";
public static final String SHORT_SPARKLINE_MODE_URL_HANDLE = "short"; public static final String SHORT_SPARKLINE_MODE_URL_HANDLE = "short";
@ -41,7 +42,7 @@ public class VisualizationCodeGenerator {
private Log log; private Log log;
private VisVOContainer valueObjectContainer; private SparklineVOContainer valueObjectContainer;
private String contextPath; private String contextPath;
@ -53,7 +54,7 @@ public class VisualizationCodeGenerator {
String visContainer, String visContainer,
List<BiboDocument> authorDocuments, List<BiboDocument> authorDocuments,
Map<String, Integer> yearToPublicationCount, Map<String, Integer> yearToPublicationCount,
VisVOContainer valueObjectContainer, SparklineVOContainer valueObjectContainer,
Log log) { Log log) {
this.contextPath = contextPath; this.contextPath = contextPath;
@ -179,7 +180,7 @@ public class VisualizationCodeGenerator {
visualizationCode.append("<script type=\"text/javascript\">\n" + visualizationCode.append("<script type=\"text/javascript\">\n" +
"function drawVisualization(providedSparklineImgTD) {\n" + "function drawPubCountVisualization(providedSparklineImgTD) {\n" +
"var data = new google.visualization.DataTable();\n" + "var data = new google.visualization.DataTable();\n" +
"data.addColumn('string', 'Year');\n" + "data.addColumn('string', 'Year');\n" +
"data.addColumn('number', 'Publications');\n" + "data.addColumn('number', 'Publications');\n" +
@ -349,7 +350,7 @@ public class VisualizationCodeGenerator {
/* /*
* Generate the code that will activate the visualization. It takes care of creating div elements to hold * 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 drawVisualization function. * the actual sparkline image and then calling the drawPubCountVisualization function.
* */ * */
visualizationCode.append(generateVisualizationActivator(visDivNames.get("SHORT_SPARK"), visContainerID)); visualizationCode.append(generateVisualizationActivator(visDivNames.get("SHORT_SPARK"), visContainerID));
@ -445,7 +446,7 @@ public class VisualizationCodeGenerator {
"}" + "}" +
"drawVisualization(sparklineImgTD);" + "drawPubCountVisualization(sparklineImgTD);" +
"});" + "});" +
"</script>\n"; "</script>\n";
} }

View file

@ -34,6 +34,7 @@ import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; 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.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
public class VisualizationRequestHandler { public class VisualizationRequestHandler {
@ -110,7 +111,7 @@ public class VisualizationRequestHandler {
* Computations required to generate HTML for the sparklines & related context. * Computations required to generate HTML for the sparklines & related context.
* */ * */
VisVOContainer valueObjectContainer = new VisVOContainer(); SparklineVOContainer valueObjectContainer = new SparklineVOContainer();
VisualizationCodeGenerator visualizationCodeGenerator = VisualizationCodeGenerator visualizationCodeGenerator =
new VisualizationCodeGenerator(vitroRequest.getContextPath(), new VisualizationCodeGenerator(vitroRequest.getContextPath(),
@ -290,7 +291,7 @@ public class VisualizationRequestHandler {
private void prepareVisualizationQueryStandaloneResponse(HttpServletRequest request, private void prepareVisualizationQueryStandaloneResponse(HttpServletRequest request,
HttpServletResponse response, VitroRequest vreq, HttpServletResponse response, VitroRequest vreq,
VisVOContainer valueObjectContainer) { SparklineVOContainer valueObjectContainer) {
Portal portal = vreq.getPortal(); Portal portal = vreq.getPortal();
@ -304,7 +305,7 @@ public class VisualizationRequestHandler {
} }
private void prepareVisualizationQueryDynamicResponse(HttpServletRequest request, private void prepareVisualizationQueryDynamicResponse(HttpServletRequest request,
HttpServletResponse response, VitroRequest vreq, VisVOContainer valueObjectContainer) { HttpServletResponse response, VitroRequest vreq, SparklineVOContainer valueObjectContainer) {
Portal portal = vreq.getPortal(); Portal portal = vreq.getPortal();

View file

@ -1,6 +1,6 @@
package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount; package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
public class VisVOContainer { public class SparklineVOContainer {
/* /*
* For now sparklineNumPublicationsText & sparklinePublicationRangeText is left * For now sparklineNumPublicationsText & sparklinePublicationRangeText is left

View file

@ -1,4 +1,4 @@
<%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisVOContainer" %> <%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<c:set var='sparkline' value='${requestScope.sparklineVO}'/> <c:set var='sparkline' value='${requestScope.sparklineVO}'/>

View file

@ -1,4 +1,4 @@
<%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisVOContainer"%> <%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer"%>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
@ -7,7 +7,11 @@
<c:url var="visImageContextPath" value="/${themeDir}site_icons/visualization/" /> <c:url var="visImageContextPath" value="/${themeDir}site_icons/visualization/" />
<c:url var="loadingImageLink" value="/${themeDir}site_icons/visualization/ajax-loader.gif"></c:url> <c:url var="loadingImageLink" value="/${themeDir}site_icons/visualization/ajax-loader.gif"></c:url>
<c:set var='sparkline' value='${requestScope.sparklineVO}' /> <c:set var='egoPubSparkline' value='${requestScope.egoPubSparklineVO}' />
<c:set var='uniqueCoauthorsSparkline' value='${requestScope.uniqueCoauthorsSparklineVO}' />
<c:set var='egoPubSparklineContainerID' value='${requestScope.egoPubSparklineContainerID}' />
<c:set var='uniqueCoauthorsSparklineVisContainerID' value='${requestScope.uniqueCoauthorsSparklineVisContainerID}' />
<c:url var="egoSparklineDataURL" value="/admin/visQuery"> <c:url var="egoSparklineDataURL" value="/admin/visQuery">
<c:param name="render_mode" value="data" /> <c:param name="render_mode" value="data" />
@ -37,6 +41,11 @@
font-weight: bold; font-weight: bold;
} }
.neutral_author_name {
color: black;
font-weight: bold;
}
.author_moniker { .author_moniker {
color: #9C9C9C; color: #9C9C9C;
} }
@ -114,12 +123,15 @@
<%-- Sparkline --%> <%-- Sparkline --%>
<h2 class="sub_headings">General Statistics</h2> <h2 class="sub_headings">General Statistics</h2>
<div id="ego_sparkline"> <div id="${egoPubSparklineContainerID}">
${sparkline.sparklineContent} ${egoPubSparkline.sparklineContent}
</div> </div>
<div id="${uniqueCoauthorsSparklineVisContainerID}">
${uniqueCoauthorsSparkline.sparklineContent}
</div>
<h2 class="sub_headings">Ego-Centric Co-Author Network <a href="${coAuthorshipDownloadFile}">(.GraphML File)</a></h2> <h2 class="sub_headings">Co-Author Network <a href="${coAuthorshipDownloadFile}">(.GraphML File)</a></h2>
</div> </div>
@ -129,7 +141,7 @@
<div id="bodyPannel" style="height: 900px;"> <div id="bodyPannel" style="height: 900px;">
<br class="spacer" /> <br class="spacer" />
<div id="visPanel" style="float: left; width: 610px;"> <div id="visPanel" style="float: left; width: 600px;">
<script language="JavaScript" type="text/javascript"> <script language="JavaScript" type="text/javascript">
<!-- <!--
renderCoAuthorshipVisualization(); renderCoAuthorshipVisualization();
@ -141,7 +153,7 @@
<div id="profileImage"></div> <div id="profileImage"></div>
<div class="bold"><strong><span id="authorName" class="author_name">&nbsp;</span></strong></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 class="italicize"><span id="profileMoniker" class="author_moniker"></span></div>
<br /> <br />

View file

@ -1,4 +1,4 @@
<%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisVOContainer" %> <%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>