1. Added handler for unique coauthors in csv data format for coauthorship visualization.

2. Added another method for nodes to get yearToPublicationsCouts directly.
3. Changed styling of person level vis.
4. Cleaned up code
This commit is contained in:
cdtank 2010-07-06 20:35:29 +00:00
parent 264b9ef213
commit 6a499d164f
4 changed files with 164 additions and 25 deletions

View file

@ -2,6 +2,12 @@ package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
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;
@ -9,6 +15,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; 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.hp.hpl.jena.query.DataSource;
@ -17,6 +25,10 @@ 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.VisualizationFrameworkConstants; 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.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoCollegeOrSchool;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoDepartmentOrDivision;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
public class VisualizationRequestHandler { public class VisualizationRequestHandler {
@ -48,6 +60,8 @@ public class VisualizationRequestHandler {
String visContainer = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE); String visContainer = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE);
String sparklineVisMode = "sparkline";
QueryHandler queryManager = QueryHandler queryManager =
new QueryHandler(egoURIParam, new QueryHandler(egoURIParam,
resultFormatParam, resultFormatParam,
@ -66,17 +80,34 @@ public class VisualizationRequestHandler {
* HTML code to render sparkline, tables etc. Ideally I would want to avoid this flow. * HTML code to render sparkline, tables etc. Ideally I would want to avoid this flow.
* It is ugly! * It is ugly!
* */ * */
if (VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) { if (VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) {
/* /*
* When just the graphML file is required - based on which actual visualization will * We will be using the same visualization package for both sparkline & coauthorship flash
* vis. We will use "VIS_MODE_URL_HANDLE" as a modifier to differentiate between these two.
* The defualt will be to render the coauthorship network vis.
* */
if (sparklineVisMode.equalsIgnoreCase(visMode)) {
/*
* When the csv file is required - based on which sparkline visualization will
* be rendered. * be rendered.
* */ * */
prepareVisualizationQueryDataResponse(authorNodesAndEdges); prepareVisualizationQuerySparklineDataResponse(authorNodesAndEdges);
return; return;
} else {
/*
* When the graphML file is required - based on which coauthorship network visualization
* will be rendered.
* */
prepareVisualizationQueryNetworkDataResponse(authorNodesAndEdges);
return;
} }
}
/* /*
* Computations required to generate HTML for the sparklines & related context. * Computations required to generate HTML for the sparklines & related context.
@ -137,7 +168,7 @@ public class VisualizationRequestHandler {
} }
private void prepareVisualizationQueryDataResponse(VisVOContainer authorNodesAndEdges) { private void prepareVisualizationQueryNetworkDataResponse(VisVOContainer authorNodesAndEdges) {
response.setContentType("text/xml"); response.setContentType("text/xml");
@ -161,6 +192,107 @@ public class VisualizationRequestHandler {
} }
} }
private void prepareVisualizationQuerySparklineDataResponse(VisVOContainer authorNodesAndEdges) {
Map<String, Set<Node>> yearToCoauthors = getCoAuthorsStats(authorNodesAndEdges);
String outputFileName = UtilityFunctions.slugify(authorNodesAndEdges.getEgoNode().getNodeName())
+ "-coauthors" + ".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.
* */
generateCsvFileBuffer(yearToCoauthors,
responseWriter);
responseWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void generateCsvFileBuffer(Map<String, Set<Node>> yearToCoauthors, PrintWriter printWriter) {
CSVWriter csvWriter = new SimpleWriter(printWriter);
try {
csvWriter.append(new String[]{"Year", "Number of Authors", "Authors"});
for (Entry<String, Set<Node>> currentEntry : yearToCoauthors.entrySet()) {
csvWriter.append(new Object[]{currentEntry.getKey(),
currentEntry.getValue().size(),
getCoauthorsString(currentEntry.getValue())});
}
} catch (IOException e) {
e.printStackTrace();
}
printWriter.flush();
}
private String getCoauthorsString(Set<Node> coAuthors) {
StringBuilder coAuthorsMerged = new StringBuilder();
for (Node currCoAuthor : coAuthors) {
coAuthorsMerged.append(currCoAuthor.getNodeName() + ", ");
}
return coAuthorsMerged.toString();
}
private Map<String, Set<Node>> getCoAuthorsStats(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 prepareVisualizationQueryStandaloneResponse(String egoURIParam, private void prepareVisualizationQueryStandaloneResponse(String egoURIParam,
HttpServletRequest request, HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response,

View file

@ -82,13 +82,6 @@ public class VisualizationCodeGenerator {
} }
// public VisVOContainer getValueObjectContainer() {
//
//
//
// return valueObjectContainer;
// }
private String getMainVisualizationCode(List<BiboDocument> authorDocuments, private String getMainVisualizationCode(List<BiboDocument> authorDocuments,
String visMode, String visMode,
String providedVisContainerID) { String providedVisContainerID) {
@ -514,7 +507,7 @@ public class VisualizationCodeGenerator {
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants.STANDALONE_RENDER_MODE_URL_VALUE, + "=" + URLEncoder.encode(VisualizationFrameworkConstants.STANDALONE_RENDER_MODE_URL_VALUE,
VisualizationController.URL_ENCODING_SCHEME).toString(); VisualizationController.URL_ENCODING_SCHEME).toString();
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View full timeline and network.</a><br />"; fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View full timeline and co-author network</a><br />";
valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL); valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL);

View file

@ -20,6 +20,7 @@ public class Node extends Individual {
private int nodeID; private int nodeID;
private Map<String, Integer> yearToPublicationCount; private Map<String, Integer> yearToPublicationCount;
private Set<BiboDocument> authorDocuments = new HashSet<BiboDocument>(); private Set<BiboDocument> authorDocuments = new HashSet<BiboDocument>();
public Node(String nodeURL, public Node(String nodeURL,
@ -57,6 +58,12 @@ public class Node extends Individual {
} }
public Map<String, Integer> getYearToPublicationCount() {
if (yearToPublicationCount == null) {
yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments);
}
return yearToPublicationCount;
}
/* /*
* getEarliest, Latest & Unknown Publication YearCount should only be used after * getEarliest, Latest & Unknown Publication YearCount should only be used after
* the parsing of the entire sparql is done. Else it will give results based on * the parsing of the entire sparql is done. Else it will give results based on
@ -66,7 +73,6 @@ public class Node extends Individual {
public Map<String, Integer> getEarliestPublicationYearCount() { public Map<String, Integer> getEarliestPublicationYearCount() {
if (yearToPublicationCount == null) { if (yearToPublicationCount == null) {
yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments); yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments);
System.out.println("early - " + yearToPublicationCount);
} }
/* /*

View file

@ -28,7 +28,7 @@
#ego_profile { #ego_profile {
padding: 10px; padding: 10px;
height: 100px; min-height: 100px;
} }
#ego_label { #ego_label {
@ -51,12 +51,20 @@
#ego_sparkline { #ego_sparkline {
cursor:pointer; cursor:pointer;
height:36px; height:36px;
/*
margin-left:10px; margin-left:10px;
margin-top:69px; margin-top:69px;
position:absolute; position:absolute;*/
width:471px; width:471px;
} }
#dataPanel {
/*
float: left;
width: 150px;
visibility:hidden;*/
}
.thumbnail { .thumbnail {
width: 100px; width: 100px;
} }
@ -74,8 +82,9 @@
<%-- Image --%> <%-- Image --%>
<span id="ego_profile_image" class="thumbnail"></span> <span id="ego_profile_image" class="thumbnail"></span>
<%-- Sparkline --%> <%-- Sparkline --%>
<span id="ego_sparkline">${sparkline.sparklineContent}</span> <div id="ego_sparkline">${sparkline.sparklineContent}</div>
</div> </div>
@ -93,8 +102,7 @@
</script> </script>
</div> </div>
<div id="dataPanel" style="float: left; width: 150px;" style="visibility:hidden;" > <div id="dataPanel">
<br /><br /><br /><br /><br /><br />
<div id="profileImage"></div> <div id="profileImage"></div>