diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationRequestHandler.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationRequestHandler.java index 9bc6efbe5..fb64bfb4f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationRequestHandler.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationRequestHandler.java @@ -2,6 +2,12 @@ package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship; import java.io.IOException; 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.ServletException; @@ -9,6 +15,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; +import org.skife.csv.CSVWriter; +import org.skife.csv.SimpleWriter; 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.visualization.VisualizationFrameworkConstants; 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 { @@ -48,6 +60,8 @@ public class VisualizationRequestHandler { String visContainer = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE); + String sparklineVisMode = "sparkline"; + QueryHandler queryManager = new QueryHandler(egoURIParam, resultFormatParam, @@ -64,19 +78,36 @@ public class VisualizationRequestHandler { * In order to avoid unneeded computations we have pushed this "if" condition up. * This case arises when the render mode is data. In that case we dont want to generate * 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)) { + + /* + * 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 just the graphML file is required - based on which actual visualization will + * When the csv file is required - based on which sparkline visualization will * be rendered. * */ - prepareVisualizationQueryDataResponse(authorNodesAndEdges); - return; - - + prepareVisualizationQuerySparklineDataResponse(authorNodesAndEdges); + 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. @@ -137,7 +168,7 @@ public class VisualizationRequestHandler { } - private void prepareVisualizationQueryDataResponse(VisVOContainer authorNodesAndEdges) { + private void prepareVisualizationQueryNetworkDataResponse(VisVOContainer authorNodesAndEdges) { response.setContentType("text/xml"); @@ -161,6 +192,107 @@ public class VisualizationRequestHandler { } } + private void prepareVisualizationQuerySparklineDataResponse(VisVOContainer authorNodesAndEdges) { + + + Map> 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> yearToCoauthors, PrintWriter printWriter) { + + CSVWriter csvWriter = new SimpleWriter(printWriter); + + try { + csvWriter.append(new String[]{"Year", "Number of Authors", "Authors"}); + + for (Entry> 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 coAuthors) { + + StringBuilder coAuthorsMerged = new StringBuilder(); + + for (Node currCoAuthor : coAuthors) { + coAuthorsMerged.append(currCoAuthor.getNodeName() + ", "); + } + + return coAuthorsMerged.toString(); + } + + private Map> getCoAuthorsStats(VisVOContainer authorNodesAndEdges) { + + Map> yearToCoAuthors = new TreeMap>(); + + 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 coAuthorNodes; + + if (yearToCoAuthors.containsKey(year)) { + + coAuthorNodes = yearToCoAuthors.get(year); + coAuthorNodes.add(currNode); + + } else { + + coAuthorNodes = new HashSet(); + coAuthorNodes.add(currNode); + yearToCoAuthors.put(year, coAuthorNodes); + } + + } + + } + } + + + return yearToCoAuthors; + } + private void prepareVisualizationQueryStandaloneResponse(String egoURIParam, HttpServletRequest request, HttpServletResponse response, diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationCodeGenerator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationCodeGenerator.java index c09837f28..223a632d3 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationCodeGenerator.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationCodeGenerator.java @@ -82,13 +82,6 @@ public class VisualizationCodeGenerator { } -// public VisVOContainer getValueObjectContainer() { -// -// -// -// return valueObjectContainer; -// } - private String getMainVisualizationCode(List authorDocuments, String visMode, String providedVisContainerID) { @@ -514,7 +507,7 @@ public class VisualizationCodeGenerator { + "=" + URLEncoder.encode(VisualizationFrameworkConstants.STANDALONE_RENDER_MODE_URL_VALUE, VisualizationController.URL_ENCODING_SCHEME).toString(); - fullTimelineLink = "View full timeline and network.
"; + fullTimelineLink = "View full timeline and co-author network
"; valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java index 63be5ac4c..d8811773f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java @@ -20,6 +20,7 @@ public class Node extends Individual { private int nodeID; private Map yearToPublicationCount; + private Set authorDocuments = new HashSet(); public Node(String nodeURL, @@ -57,6 +58,12 @@ public class Node extends Individual { } + public Map getYearToPublicationCount() { + if (yearToPublicationCount == null) { + yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments); + } + return yearToPublicationCount; + } /* * 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 @@ -66,7 +73,6 @@ public class Node extends Individual { public Map getEarliestPublicationYearCount() { if (yearToPublicationCount == null) { yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments); - System.out.println("early - " + yearToPublicationCount); } /* diff --git a/webapp/web/templates/visualization/person_level.jsp b/webapp/web/templates/visualization/person_level.jsp index bee69e677..216f89944 100644 --- a/webapp/web/templates/visualization/person_level.jsp +++ b/webapp/web/templates/visualization/person_level.jsp @@ -28,7 +28,7 @@ #ego_profile { padding: 10px; - height: 100px; + min-height: 100px; } #ego_label { @@ -51,12 +51,20 @@ #ego_sparkline { cursor:pointer; height:36px; + /* margin-left:10px; margin-top:69px; - position:absolute; + position:absolute;*/ width:471px; } +#dataPanel { + /* + float: left; + width: 150px; + visibility:hidden;*/ +} + .thumbnail { width: 100px; } @@ -74,8 +82,9 @@ <%-- Image --%> + <%-- Sparkline --%> - ${sparkline.sparklineContent} +
${sparkline.sparklineContent}
@@ -93,8 +102,7 @@ -
-





+
@@ -116,8 +124,8 @@
- - + +