diff --git a/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java index ab302841..023c2a6a 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java +++ b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java @@ -2,34 +2,6 @@ package edu.cornell.mannlib.vitro.webapp.controller.visualization; -/* -Copyright (c) 2010, Cornell University -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Cornell University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - import java.io.IOException; import java.util.Map; @@ -51,7 +23,6 @@ import com.hp.hpl.jena.query.Syntax; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelMaker; -import edu.cornell.mannlib.vedit.beans.LoginFormBean; import edu.cornell.mannlib.vedit.controller.BaseEditController; import edu.cornell.mannlib.vitro.webapp.beans.Portal; import edu.cornell.mannlib.vitro.webapp.controller.Controllers; @@ -69,8 +40,6 @@ public class VisualizationController extends BaseEditController { private Map visualizationIDsToClass; - private static final String VIS_TYPE_URL_HANDLE = "vis"; - public static final String URL_ENCODING_SCHEME = "UTF-8"; private static final long serialVersionUID = 1L; @@ -79,25 +48,11 @@ public class VisualizationController extends BaseEditController { protected static final Syntax SYNTAX = Syntax.syntaxARQ; - //TODO: For later, might want to improve these names for clarity. - public static final String PERSON_PUBLICATION_COUNT_VIS_URL_VALUE - = "person_pub_count"; - - public static final String PDF_REPORT_VIS_URL_VALUE - = "pdf_report"; - - public static final String COLLEGE_PUBLICATION_COUNT_VIS_URL_VALUE - = "college_pub_count"; - - public static final String COAUTHORSHIP_VIS_URL_VALUE - = "coauthorship"; - - public static final String PERSON_LEVEL_VIS_URL_VALUE - = "person_level"; - - public static final String UTILITIES_URL_VALUE - = "utilities"; - + /* This method is overridden to inject vis dependencies i.e. the vis algorithms that are + * being implemented into the vis controller. Modified Dependency Injection pattern is + * used here. XML file containing the location of all the vis is saved in accessible folder. + * @see javax.servlet.GenericServlet#init() + */ @Override public void init() throws ServletException { super.init(); @@ -135,36 +90,42 @@ public class VisualizationController extends BaseEditController { throws ServletException, IOException { super.doGet(request, response); - VitroRequest vreq = handleLoginAuthentication(request, response); - - String visTypeURLHandle = vreq.getParameter(VIS_TYPE_URL_HANDLE); + VitroRequest vitroRequest = new VitroRequest(request); - VisualizationRequestHandler visRequestHandler = null; - try { - visRequestHandler = visualizationIDsToClass.get(visTypeURLHandle); - } catch (NullPointerException nullKey) { - - /* - * This is side-effecting because the error content is directly - * added to the request object. From where it is redirected to - * the error page. - * */ - handleMalformedParameters("Inappropriate query parameters were submitted. ", - request, - response); - } + /* + * Based on the query parameters passed via URI get the appropriate visualization + * request handler. + * */ + VisualizationRequestHandler visRequestHandler = + getVisualizationRequestHandler(request, response, vitroRequest); - DataSource dataSource = setupJENADataSource(request, + /* + * Pass the query to the selected visualization request handler & render the visualization. + * Since the visualization content is directly added to the response object we are side- + * effecting this method. + * */ + renderVisualization(request, response, vitroRequest, visRequestHandler); + + return; + } + + + private void renderVisualization(HttpServletRequest request, + HttpServletResponse response, + VitroRequest vitroRequest, + VisualizationRequestHandler visRequestHandler) + throws ServletException, IOException { + + DataSource dataSource = setupJENADataSource(request, response, - vreq); - + vitroRequest); if (dataSource != null && visRequestHandler != null) { - /* - * This is side-effecting because the visualization content is added - * to the request object. - * */ - visRequestHandler.generateVisualization(vreq, request, response, log, dataSource); + visRequestHandler.generateVisualization(vitroRequest, + request, + response, + log, + dataSource); } else { @@ -177,46 +138,31 @@ public class VisualizationController extends BaseEditController { log.error(errorMessage); } + } - return; - } + private VisualizationRequestHandler getVisualizationRequestHandler( + HttpServletRequest request, + HttpServletResponse response, + VitroRequest vitroRequest) + throws ServletException, IOException { + + String visType = vitroRequest.getParameter(VisualizationFrameworkConstants + .VIS_TYPE_KEY); + VisualizationRequestHandler visRequestHandler = null; + try { + visRequestHandler = visualizationIDsToClass.get(visType); + } catch (NullPointerException nullKeyException) { - private VitroRequest handleLoginAuthentication(HttpServletRequest request, - HttpServletResponse response) throws IOException { - // This might not be required - /* - * why are there multiple places where the login is checked? shud be abtracted into - * new methoid? - * */ -// if( !checkLoginStatus(request, response) ) -// return null; - - VitroRequest vreq = new VitroRequest(request); - - Object obj = vreq.getSession().getAttribute("loginHandler"); - LoginFormBean loginHandler = null; - - - if (obj != null && obj instanceof LoginFormBean) { - loginHandler = ((LoginFormBean) obj); - } - - /* - * what is the speciality of 5 in the conditions? - * - if( loginHandler == null || - ! "authenticated".equalsIgnoreCase(loginHandler.getLoginStatus()) || - Integer.parseInt(loginHandler.getLoginRole()) <= 5 ){ - HttpSession session = request.getSession(true); - - session.setAttribute("postLoginRequest", - vreq.getRequestURI()+( vreq.getQueryString()!=null?('?' + vreq.getQueryString()):"" )); - String redirectURL = request.getContextPath() + Controllers.SITE_ADMIN + "?login=block"; - response.sendRedirect(redirectURL); - return null; - } - */ - return vreq; + /* + * This is side-effecting because the error content is directly + * added to the request object. From where it is redirected to + * the error page. + * */ + handleMalformedParameters("Inappropriate query parameters were submitted. ", + request, + response); + } + return visRequestHandler; } private DataSource setupJENADataSource(HttpServletRequest request, 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 f07bc6f2..e513171e 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationFrameworkConstants.java +++ b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationFrameworkConstants.java @@ -3,39 +3,67 @@ package edu.cornell.mannlib.vitro.webapp.controller.visualization; public class VisualizationFrameworkConstants { - + /* - * Contains the location of bean containing info on all the visualizations available - * in that instance. Currently it is stored under "productMods/WEB-INF..." - * */ + * Contains the location of bean containing info on all the visualizations + * available in that instance. Currently it is stored under + * "productMods/WEB-INF..." + */ public static final String RELATIVE_LOCATION_OF_VISUALIZATIONS_BEAN = - "/WEB-INF/visualization/visualizations-beans-injection.xml"; - + "/WEB-INF/visualization/visualizations-beans-injection.xml"; + /* * Vis URL prefix that is seen by all the users - * */ + */ public static final String VISUALIZATION_URL_PREFIX = "/visualization"; - - public static final String VIS_TYPE_URL_HANDLE = "vis"; - public static final String VIS_CONTAINER_URL_HANDLE = "container"; - public static final String INDIVIDUAL_URI_URL_HANDLE = "uri"; - public static final String VIS_MODE_URL_HANDLE = "vis_mode"; - public static final String RENDER_MODE_URL_HANDLE = "render_mode"; - - public static final String STANDALONE_RENDER_MODE_URL_VALUE = "standalone"; - public static final String DYNAMIC_RENDER_MODE_URL_VALUE = "dynamic"; - public static final String DATA_RENDER_MODE_URL_VALUE = "data"; - public static final String PDF_RENDER_MODE_URL_VALUE = "pdf"; - public static final String IMAGE_VIS_MODE_URL_VALUE = "image"; - public static final String SPARKLINE_VIS_MODE_URL_VALUE = "sparkline"; - public static final String COAUTHORSLIST_VIS_MODE_URL_VALUE = "coauthors"; + public static final String INDIVIDUAL_URL_PREFIX = "/individual"; + + /* + * These represent possible query keys in a URI for visualization purposes. + * Examples, + * 1. http://vivo.indiana.edu/visualization?uri=http://vivoweb.org/ontology/core/Person10979&vis=person_level&render_mode=standalone + * 2. http://vivo.indiana.edu/visualization?uri=http://vivoweb.org/ontology/core/Person72&vis=person_pub_count&render_mode=dynamic&container=vis_container + * */ + public static final String VIS_TYPE_KEY = "vis"; + public static final String VIS_CONTAINER_KEY = "container"; + public static final String INDIVIDUAL_URI_KEY = "uri"; + public static final String VIS_MODE_KEY = "vis_mode"; + public static final String RENDER_MODE_KEY = "render_mode"; + + /* + * These values represent possible render modes. + * */ + public static final String STANDALONE_RENDER_MODE = "standalone"; + public static final String DYNAMIC_RENDER_MODE = "dynamic"; + public static final String DATA_RENDER_MODE = "data"; + public static final String PDF_RENDER_MODE = "pdf"; + + /* + * These values represent possible sub-vis modes. + * */ + public static final String IMAGE_VIS_MODE = "image"; + public static final String SPARKLINE_VIS_MODE = "sparkline"; + public static final String COAUTHORSLIST_VIS_MODE = "coauthors"; + public static final String SHORT_SPARKLINE_VIS_MODE = "short"; + public static final String FULL_SPARKLINE_VIS_MODE = "full"; + + /* + * These values represent possible utilities vis modes. + * */ public static final String PROFILE_INFO_UTILS_VIS_MODE = "PROFILE_INFO"; 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 IMAGE_UTILS_VIS_MODE = "IMAGE_URL"; - - - - + + /* + * 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 PDF_REPORT_VIS = "pdf_report"; + public static final String COLLEGE_PUBLICATION_COUNT_VIS = "college_pub_count"; + public static final String COAUTHORSHIP_VIS = "coauthorship"; + public static final String PERSON_LEVEL_VIS = "person_level"; + public static final String UTILITIES_VIS = "utilities"; + } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipGraphMLWriter.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipGraphMLWriter.java index 76b5e738..1ba9ee80 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipGraphMLWriter.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipGraphMLWriter.java @@ -12,7 +12,7 @@ import java.util.Set; 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.valueobjects.CoAuthorshipVOContainer; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.CoAuthorshipData; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Edge; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node; @@ -28,7 +28,7 @@ public class CoAuthorshipGraphMLWriter { private final String GRAPHML_FOOTER = ""; - public CoAuthorshipGraphMLWriter(CoAuthorshipVOContainer visVOContainer) { + public CoAuthorshipGraphMLWriter(CoAuthorshipData visVOContainer) { coAuthorshipGraphMLContent = createCoAuthorshipGraphMLContent(visVOContainer); @@ -39,7 +39,7 @@ public class CoAuthorshipGraphMLWriter { } private StringBuilder createCoAuthorshipGraphMLContent( - CoAuthorshipVOContainer visVOContainer) { + CoAuthorshipData coAuthorshipData) { StringBuilder graphMLContent = new StringBuilder(); @@ -50,30 +50,30 @@ public class CoAuthorshipGraphMLWriter { * another String object to hold key definition data will be redundant & will * not serve the purpose. * */ - generateKeyDefinitionContent(visVOContainer, graphMLContent); + generateKeyDefinitionContent(coAuthorshipData, graphMLContent); /* * Used to generate graph content. It will contain both the nodes & edge information. * We are side-effecting "graphMLContent". * */ - generateGraphContent(visVOContainer, graphMLContent); + generateGraphContent(coAuthorshipData, graphMLContent); graphMLContent.append(GRAPHML_FOOTER); return graphMLContent; } - private void generateGraphContent(CoAuthorshipVOContainer visVOContainer, + private void generateGraphContent(CoAuthorshipData coAuthorshipData, StringBuilder graphMLContent) { graphMLContent.append("\n\n"); - if (visVOContainer.getNodes() != null & visVOContainer.getNodes().size() > 0) { - generateNodeSectionContent(visVOContainer, graphMLContent); + if (coAuthorshipData.getNodes() != null & coAuthorshipData.getNodes().size() > 0) { + generateNodeSectionContent(coAuthorshipData, graphMLContent); } - if (visVOContainer.getEdges() != null & visVOContainer.getEdges().size() > 0) { - generateEdgeSectionContent(visVOContainer, graphMLContent); + if (coAuthorshipData.getEdges() != null & coAuthorshipData.getEdges().size() > 0) { + generateEdgeSectionContent(coAuthorshipData, graphMLContent); } graphMLContent.append("\n"); @@ -83,12 +83,12 @@ public class CoAuthorshipGraphMLWriter { } - private void generateEdgeSectionContent(CoAuthorshipVOContainer visVOContainer, + private void generateEdgeSectionContent(CoAuthorshipData coAuthorshipData, StringBuilder graphMLContent) { graphMLContent.append("\n"); - Set edges = visVOContainer.getEdges(); + Set edges = coAuthorshipData.getEdges(); List orderedEdges = new ArrayList(edges); @@ -108,11 +108,6 @@ public class CoAuthorshipGraphMLWriter { private void getEdgeContent(StringBuilder graphMLContent, Edge currentEdge) { - /* - System.out.print("EDGE_ID:" + currentEdge.getEdgeID() + "|"); - System.out.print("EDGE_SOURCE:" + currentEdge.getSourceNode().getNodeURL() + "|"); - System.out.println("EDGE_TARGET:" + currentEdge.getTargetNode().getNodeURL()); - */ graphMLContent.append(" publicationInfo : currentEdge.getEarliestCollaborationYearCount().entrySet()) { @@ -148,8 +142,6 @@ public class CoAuthorshipGraphMLWriter { graphMLContent.append("\t" + publicationInfo.getValue() + "\n"); - - } } @@ -179,17 +171,15 @@ public class CoAuthorshipGraphMLWriter { } graphMLContent.append("\n"); - - } - private void generateNodeSectionContent(CoAuthorshipVOContainer visVOContainer, + private void generateNodeSectionContent(CoAuthorshipData coAuthorshipData, StringBuilder graphMLContent) { graphMLContent.append("\n"); - Node egoNode = visVOContainer.getEgoNode(); - Set authorNodes = visVOContainer.getNodes(); + Node egoNode = coAuthorshipData.getEgoNode(); + Set authorNodes = coAuthorshipData.getNodes(); /* * This method actually creates the XML code for a single node. "graphMLContent" @@ -224,21 +214,17 @@ public class CoAuthorshipGraphMLWriter { String profileURL = null; try { - profileURL = "/individual?" - + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE - + "=" + URLEncoder.encode(node.getNodeURL(), + profileURL = VisualizationFrameworkConstants.INDIVIDUAL_URL_PREFIX + "?" + + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY + + "=" + URLEncoder.encode(node.getNodeURI(), VisualizationController .URL_ENCODING_SCHEME).toString(); } catch (UnsupportedEncodingException e) { System.err.println("URL Encoding ERRor. Move this to use log.error ASAP"); } - -// System.out.print("NODE_ID:" + node.getNodeID() + "|"); graphMLContent.append("\n"); - graphMLContent.append("\t" + node.getNodeURL() + "\n"); -// graphMLContent.append("\t" + node.getNodeName() + "\n"); -// System.out.println("NODE_NAME:" + node.getNodeURL()); + graphMLContent.append("\t" + node.getNodeURI() + "\n"); graphMLContent.append("\t" + node.getNodeName() + "\n"); if (profileURL != null) { @@ -267,8 +253,6 @@ public class CoAuthorshipGraphMLWriter { graphMLContent.append("\t" + publicationInfo.getValue() + "\n"); - - } } @@ -285,8 +269,6 @@ public class CoAuthorshipGraphMLWriter { graphMLContent.append("\t" + publicationInfo.getValue() + "\n"); - - } } @@ -302,7 +284,7 @@ public class CoAuthorshipGraphMLWriter { graphMLContent.append("\n"); } - private void generateKeyDefinitionContent(CoAuthorshipVOContainer visVOContainer, + private void generateKeyDefinitionContent(CoAuthorshipData visVOContainer, StringBuilder graphMLContent) { /* @@ -345,8 +327,6 @@ public class CoAuthorshipGraphMLWriter { } else { graphMLContent.append("/>\n"); } - } } - } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryRunner.java similarity index 86% rename from src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryHandler.java rename to src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryRunner.java index 53f1309c..131fbb2f 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipQueryRunner.java @@ -30,25 +30,27 @@ 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.BiboDocument; -import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.CoAuthorshipVOContainer; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.CoAuthorshipData; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Edge; 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.visutils.QueryHandler; +import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UniqueIDGenerator; - - /** + * This query runner is used to execute a sparql query to get all the publications + * for a particular individual. It will also fetch all the authors that worked + * on that particular publication. + * * @author cdtank */ -public class CoAuthorshipQueryHandler implements QueryHandler { +public class CoAuthorshipQueryRunner implements QueryRunner { private static final int MAX_AUTHORS_PER_PAPER_ALLOWED = 100; protected static final Syntax SYNTAX = Syntax.syntaxARQ; - private String egoURLParam; + private String egoURI; private Map collegeURLToVO = new HashMap(); @@ -60,10 +62,10 @@ public class CoAuthorshipQueryHandler implements QueryHandler nodes = new HashSet(); @@ -149,11 +151,6 @@ public class CoAuthorshipQueryHandler implements QueryHandler coAuthorsForCurrentBiboDocument; @@ -190,11 +187,49 @@ public class CoAuthorshipQueryHandler implements QueryHandler nodes, + Map biboDocumentURLToVO, + Map> biboDocumentURLToCoAuthors, + Set edges) { + + Set nodesToBeRemoved = new HashSet(); for (Map.Entry> currentBiboDocumentEntry : biboDocumentURLToCoAuthors.entrySet()) { @@ -218,31 +253,16 @@ public class CoAuthorshipQueryHandler implements QueryHandler> currentBiboDocumentEntry : biboDocumentURLToCoAuthors.entrySet()) { + /* * If there was only one co-author (other than ego) then we dont have to create any * edges. so the below condition will take care of that. @@ -312,9 +333,9 @@ public class CoAuthorshipQueryHandler implements QueryHandler edgeUniqueIdentifierToVO) { + Node collaboratingNode1, + Node collaboratingNode2, + Map edgeUniqueIdentifierToVO) { String edgeUniqueIdentifier = getEdgeUniqueIdentifier(collaboratingNode1.getNodeID(), collaboratingNode2.getNodeID()); @@ -438,25 +459,21 @@ public class CoAuthorshipQueryHandler implements QueryHandler queryManager = - new CoAuthorshipQueryHandler(egoURIParam, - dataSource, - log); + .VIS_MODE_KEY); + QueryRunner queryManager = + new CoAuthorshipQueryRunner(egoURI, dataSource, log); + try { + CoAuthorshipData authorNodesAndEdges = + queryManager.getQueryResult(); - CoAuthorshipVOContainer authorNodesAndEdges = - queryManager.getVisualizationJavaValueObjects(); - - /* - * 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! - * */ - if (VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE + if (VisualizationFrameworkConstants.DATA_RENDER_MODE .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. + * flash vis. We will use "VIS_MODE_KEY" as a modifier to differentiate + * between these two. The default will be to render the coauthorship network vis. * */ - - if (VisualizationFrameworkConstants.SPARKLINE_VIS_MODE_URL_VALUE + if (VisualizationFrameworkConstants.SPARKLINE_VIS_MODE .equalsIgnoreCase(visMode)) { /* * When the csv file is required - based on which sparkline visualization will * be rendered. * */ - prepareVisualizationQuerySparklineDataResponse(authorNodesAndEdges, + prepareSparklineDataResponse(authorNodesAndEdges, response); return; @@ -92,14 +87,20 @@ public class CoAuthorshipRequestHandler implements VisualizationRequestHandler { * When the graphML file is required - based on which coauthorship network * visualization will be rendered. * */ - prepareVisualizationQueryNetworkDataResponse(authorNodesAndEdges, response); + prepareNetworkDataResponse(authorNodesAndEdges, response); return; } } } catch (MalformedQueryParametersException e) { try { - handleMalformedParameters(e.getMessage(), vitroRequest, request, response, log); + UtilityFunctions.handleMalformedParameters( + e.getMessage(), + "Visualization Query Error - Co-authorship Network", + vitroRequest, + request, + response, + log); } catch (ServletException e1) { log.error(e1.getStackTrace()); } catch (IOException e1) { @@ -110,9 +111,90 @@ public class CoAuthorshipRequestHandler implements VisualizationRequestHandler { } - private void prepareVisualizationQueryNetworkDataResponse( - CoAuthorshipVOContainer authorNodesAndEdges, HttpServletResponse response) { + private void writeCoauthorsPerYearCSV(Map> yearToCoauthors, + PrintWriter printWriter) { + +// printWriter.append("\"Year\", \"Count\", \"Co-Author(s)\"\n"); + printWriter.append("Year, Count, Co-Author(s)\n"); + + for (Entry> currentEntry : yearToCoauthors.entrySet()) { + + printWriter.append("\"" + currentEntry.getKey() + "\"," + + "\"" + currentEntry.getValue().size() + "\"," + + "\"" + getCoauthorNamesAsString(currentEntry.getValue()) + + "\"\n"); + } + + printWriter.flush(); + } + + private String getCoauthorNamesAsString(Set coAuthors) { + + StringBuilder coAuthorsMerged = new StringBuilder(); + + String coAuthorSeparator = "; "; + for (Node currCoAuthor : coAuthors) { + coAuthorsMerged.append(currCoAuthor.getNodeName() + coAuthorSeparator); + } + + return StringUtils.removeEnd(coAuthorsMerged.toString(), coAuthorSeparator); + } + /** + * Provides response when a csv file containing number & names of unique co-authors per + * year is requested. + * @param authorNodesAndEdges + * @param response + */ + private void prepareSparklineDataResponse(CoAuthorshipData authorNodesAndEdges, + HttpServletResponse response) { + + String outputFileName; + Map> yearToCoauthors = new TreeMap>(); + + if (authorNodesAndEdges.getNodes() != null && authorNodesAndEdges.getNodes().size() > 0) { + + outputFileName = UtilityFunctions.slugify(authorNodesAndEdges + .getEgoNode().getNodeName()) + + "_coauthors-per-year" + ".csv"; + + yearToCoauthors = UtilityFunctions.getPublicationYearToCoAuthors(authorNodesAndEdges); + + } else { + + outputFileName = "no_coauthors-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. + * */ + writeCoauthorsPerYearCSV(yearToCoauthors, responseWriter); + + responseWriter.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Provides a response when graphml formatted co-authorship network is requested, typically by + * the flash vis. + * @param authorNodesAndEdges + * @param response + */ + private void prepareNetworkDataResponse( + CoAuthorshipData authorNodesAndEdges, HttpServletResponse response) { + response.setContentType("text/xml"); try { @@ -135,138 +217,4 @@ public class CoAuthorshipRequestHandler implements VisualizationRequestHandler { } } - private void prepareVisualizationQuerySparklineDataResponse( - CoAuthorshipVOContainer authorNodesAndEdges, HttpServletResponse response) { - - String outputFileName; - Map> yearToCoauthors = new TreeMap>(); - - if (authorNodesAndEdges.getNodes() != null && authorNodesAndEdges.getNodes().size() > 0) { - - outputFileName = UtilityFunctions.slugify(authorNodesAndEdges - .getEgoNode().getNodeName()) - + "_coauthors-per-year" + ".csv"; - - yearToCoauthors = getCoAuthorsStats(authorNodesAndEdges); - - } else { - - outputFileName = "no_coauthors-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. - * */ - generateCsvFileBuffer(yearToCoauthors, - responseWriter); - - responseWriter.close(); - - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void generateCsvFileBuffer(Map> yearToCoauthors, - PrintWriter printWriter) { - - printWriter.append("\"Year\", \"Number of Co-Authors\", \"Co-Author(s)\"\n"); - - for (Entry> currentEntry : yearToCoauthors.entrySet()) { - - printWriter.append("\"" + currentEntry.getKey() + "\"," - + "\"" + currentEntry.getValue().size() + "\"," - + "\"" + getCoauthorsString(currentEntry.getValue()) + "\"\n" - ); - } - - printWriter.flush(); - } - - private String getCoauthorsString(Set coAuthors) { - - StringBuilder coAuthorsMerged = new StringBuilder(); - - String coAuthorSeparator = "; "; - for (Node currCoAuthor : coAuthors) { - coAuthorsMerged.append(currCoAuthor.getNodeName() + coAuthorSeparator); - } - - return StringUtils.removeEnd(coAuthorsMerged.toString(), coAuthorSeparator); - } - - private Map> getCoAuthorsStats(CoAuthorshipVOContainer 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 handleMalformedParameters(String errorMessage, - VitroRequest vitroRequest, - HttpServletRequest request, - HttpServletResponse response, - Log log) - throws ServletException, IOException { - - Portal portal = vitroRequest.getPortal(); - - request.setAttribute("error", errorMessage); - - RequestDispatcher requestDispatcher = - request.getRequestDispatcher(Controllers.BASIC_JSP); - request.setAttribute("bodyJsp", - "/templates/visualization/visualization_error.jsp"); - request.setAttribute("portalBean", portal); - request.setAttribute("title", - "Visualization Query Error - Individual Publication Count"); - - try { - requestDispatcher.forward(request, response); - } catch (Exception e) { - log.error("EntityEditController could not forward to view."); - log.error(e.getMessage()); - log.error(e.getStackTrace()); - } - } - } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipVisCodeGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipVisCodeGenerator.java index 7859ce87..58cbec08 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipVisCodeGenerator.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipVisCodeGenerator.java @@ -18,14 +18,23 @@ 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.Node; -import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData; +@SuppressWarnings("serial") public class CoAuthorshipVisCodeGenerator { - private static final int MINIMUM_YEARS_CONSIDERED = 10; - + /* + * 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 coauthors 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 yeras. + * */ private static final Map VIS_DIV_NAMES = new HashMap() { { put("SHORT_SPARK", "unique_coauthors_short_sparkline_vis"); @@ -37,47 +46,52 @@ public class CoAuthorshipVisCodeGenerator { private static final String DEFAULT_VISCONTAINER_DIV_ID = "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> yearToUniqueCoauthors; private Log log; - private SparklineVOContainer valueObjectContainer; + private SparklineData sparklineData; private String contextPath; - private String individualURIParam; + private String individualURI; public CoAuthorshipVisCodeGenerator(String contextPath, - String individualURIParam, + String individualURI, String visMode, String visContainer, Map> yearToUniqueCoauthors, - SparklineVOContainer valueObjectContainer, Log log) { this.contextPath = contextPath; - this.individualURIParam = individualURIParam; + this.individualURI = individualURI; this.yearToUniqueCoauthors = yearToUniqueCoauthors; - this.valueObjectContainer = valueObjectContainer; + 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) { - valueObjectContainer.setSparklineContent(getMainVisualizationCode(visMode, + sparklineData.setSparklineContent(getMainVisualizationCode(visMode, visContainer)); - - valueObjectContainer.setSparklineContext(getVisualizationContextCode(visMode)); + sparklineData.setSparklineContext(getVisualizationContextCode(visMode)); } @@ -86,13 +100,15 @@ public class CoAuthorshipVisCodeGenerator { int numOfYearsToBeRendered = 0; int currentYear = Calendar.getInstance().get(Calendar.YEAR); - int shortSparkMinYear = currentYear - MINIMUM_YEARS_CONSIDERED + 1; + 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_PUBLICATION_YEAR". * */ - Set publishedYears = new HashSet(yearToUniqueCoauthors.keySet()); + Set publishedYears = new HashSet(yearToUniqueCoauthors.keySet()); publishedYears.remove(VOConstants.DEFAULT_PUBLICATION_YEAR); /* @@ -159,7 +175,6 @@ public class CoAuthorshipVisCodeGenerator { + "data.addRows(" + numOfYearsToBeRendered + ");\n"); int uniqueCoAuthorCounter = 0; - int totalUniqueCoAuthors = 0; int renderedFullSparks = 0; Set allCoAuthorsWithKnownAuthorshipYears = new HashSet(); @@ -167,8 +182,8 @@ public class CoAuthorshipVisCodeGenerator { publicationYear <= currentYear; publicationYear++) { - String stringPublishedYear = String.valueOf(publicationYear); - Set currentCoAuthors = yearToUniqueCoauthors.get(stringPublishedYear); + String publicationYearAsString = String.valueOf(publicationYear); + Set currentCoAuthors = yearToUniqueCoauthors.get(publicationYearAsString); Integer currentUniqueCoAuthors = null; @@ -182,7 +197,7 @@ public class CoAuthorshipVisCodeGenerator { visualizationCode.append("data.setValue(" + uniqueCoAuthorCounter + ", 0, '" - + stringPublishedYear + + publicationYearAsString + "');\n"); visualizationCode.append("data.setValue(" @@ -193,22 +208,20 @@ public class CoAuthorshipVisCodeGenerator { uniqueCoAuthorCounter++; } - totalUniqueCoAuthors = allCoAuthorsWithKnownAuthorshipYears.size(); - /* - * Sparks that will be rendered in full mode will always be the one's which has any year + * For the purpose of this visualization I have come up with a term "Sparks" which + * essentially means data points. + * Sparks that will be rendered in full mode will always be the one's which have any year * associated with it. Hence. * */ - renderedFullSparks = totalUniqueCoAuthors; + renderedFullSparks = allCoAuthorsWithKnownAuthorshipYears.size(); /* * Total publications will also consider publications that have no year associated with - * it. Hence. + * them. Hence. * */ Integer unknownYearCoauthors = 0; if (yearToUniqueCoauthors.get(VOConstants.DEFAULT_PUBLICATION_YEAR) != null) { - totalUniqueCoAuthors += yearToUniqueCoauthors - .get(VOConstants.DEFAULT_PUBLICATION_YEAR).size(); unknownYearCoauthors = yearToUniqueCoauthors .get(VOConstants.DEFAULT_PUBLICATION_YEAR).size(); } @@ -228,12 +241,12 @@ public class CoAuthorshipVisCodeGenerator { * "short" sparkline mode we will set the Earliest RenderedPublication year to * "currentYear - 10". * */ - valueObjectContainer.setEarliestRenderedPublicationYear(minPublishedYear); - valueObjectContainer.setLatestRenderedPublicationYear(currentYear); + sparklineData.setEarliestRenderedPublicationYear(minPublishedYear); + sparklineData.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. + * SHORT_SPARKLINE_MODE_KEY then we render the short sparkline and not otherwise. * */ @@ -242,15 +255,14 @@ public class CoAuthorshipVisCodeGenerator { * 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)) { + if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE.equalsIgnoreCase(visMode)) { - valueObjectContainer.setEarliestRenderedPublicationYear(shortSparkMinYear); + sparklineData.setEarliestRenderedPublicationYear(shortSparkMinYear); generateShortSparklineVisualizationContent(currentYear, shortSparkMinYear, visContainerID, visualizationCode, unknownYearCoauthors, - totalUniqueCoAuthors, sparklineDisplayOptions); } else { generateFullSparklineVisualizationContent(currentYear, @@ -268,9 +280,11 @@ public class CoAuthorshipVisCodeGenerator { } private void generateShortSparklineVisualizationContent(int currentYear, - int shortSparkMinYear, String visContainerID, - StringBuilder visualizationCode, int unknownYearCoauthors, - int totalUniqueCoAuthors, String sparklineDisplayOptions) { + int shortSparkMinYear, + String visContainerID, + StringBuilder visualizationCode, + int unknownYearCoauthors, + String sparklineDisplayOptions) { /* * Create a view of the data containing only the column pertaining to publication count. @@ -345,27 +359,22 @@ public class CoAuthorshipVisCodeGenerator { } - private void generateFullSparklineVisualizationContent( - int currentYear, - int minPubYearConsidered, - String visContainerID, - StringBuilder visualizationCode, - int unknownYearCoauthors, - int renderedFullSparks, - String sparklineDisplayOptions) { + private void generateFullSparklineVisualizationContent(int currentYear, + int minPubYearConsidered, + String visContainerID, + StringBuilder visualizationCode, + int unknownYearCoauthors, + int renderedFullSparks, + String sparklineDisplayOptions) { String csvDownloadURLHref = ""; try { if (getCSVDownloadURL() != null) { - csvDownloadURLHref = "(.CSV File)"; - } else { - csvDownloadURLHref = ""; - } } catch (UnsupportedEncodingException e) { @@ -454,7 +463,7 @@ public class CoAuthorshipVisCodeGenerator { private String getVisualizationContextCode(String visMode) { String visualizationContextCode = ""; - if (SHORT_SPARKLINE_MODE_URL_HANDLE.equalsIgnoreCase(visMode)) { + if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE.equalsIgnoreCase(visMode)) { visualizationContextCode = generateShortVisContext(); } else { visualizationContextCode = generateFullVisContext(); @@ -478,12 +487,10 @@ public class CoAuthorshipVisCodeGenerator { csvDownloadURLHref = "Download data as .csv file.
"; - valueObjectContainer.setDownloadDataLink(getCSVDownloadURL()); + sparklineData.setDownloadDataLink(getCSVDownloadURL()); } else { - csvDownloadURLHref = ""; - } } catch (UnsupportedEncodingException e) { @@ -496,16 +503,14 @@ public class CoAuthorshipVisCodeGenerator { String tableCode = generateDataTable(); - divContextCode.append("

" + tableCode - + csvDownloadURLHref + "

"); + divContextCode.append("

" + tableCode + csvDownloadURLHref + "

"); - valueObjectContainer.setTable(tableCode); + sparklineData.setTable(tableCode); return divContextCode.toString(); } - private String getCSVDownloadURL() - throws UnsupportedEncodingException { + private String getCSVDownloadURL() throws UnsupportedEncodingException { if (yearToUniqueCoauthors.size() > 0) { @@ -517,25 +522,24 @@ public class CoAuthorshipVisCodeGenerator { String downloadURL = contextPath + secondaryContextPath - + "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE - + "=" + URLEncoder.encode(individualURIParam, + + "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY + + "=" + URLEncoder.encode(individualURI, VisualizationController.URL_ENCODING_SCHEME).toString() - + "&" + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE - + "=" + URLEncoder.encode(VisualizationController - .COAUTHORSHIP_VIS_URL_VALUE, + + "&" + VisualizationFrameworkConstants.VIS_TYPE_KEY + + "=" + URLEncoder.encode(VisualizationFrameworkConstants + .COAUTHORSHIP_VIS, VisualizationController.URL_ENCODING_SCHEME).toString() - + "&" + VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE + + "&" + VisualizationFrameworkConstants.VIS_MODE_KEY + "=" + URLEncoder.encode("sparkline", VisualizationController.URL_ENCODING_SCHEME).toString() - + "&" + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE - + "=" + URLEncoder.encode(VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE, + + "&" + VisualizationFrameworkConstants.RENDER_MODE_KEY + + "=" + URLEncoder.encode(VisualizationFrameworkConstants.DATA_RENDER_MODE, VisualizationController.URL_ENCODING_SCHEME).toString(); return downloadURL; } else { return null; } - } private String generateShortVisContext() { @@ -555,33 +559,31 @@ public class CoAuthorshipVisCodeGenerator { String fullTimelineNetworkURL = contextPath + secondaryContextPath + "?" - + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE - + "=" + URLEncoder.encode(individualURIParam, + + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY + + "=" + URLEncoder.encode(individualURI, VisualizationController.URL_ENCODING_SCHEME).toString() + "&" - + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + + VisualizationFrameworkConstants.VIS_TYPE_KEY + "=" + URLEncoder.encode("person_level", VisualizationController.URL_ENCODING_SCHEME).toString() + "&" - + VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE + + VisualizationFrameworkConstants.VIS_CONTAINER_KEY + "=" + URLEncoder.encode("ego_sparkline", VisualizationController.URL_ENCODING_SCHEME).toString() + "&" - + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + + VisualizationFrameworkConstants.RENDER_MODE_KEY + "=" + URLEncoder.encode( VisualizationFrameworkConstants - .STANDALONE_RENDER_MODE_URL_VALUE, + .STANDALONE_RENDER_MODE, VisualizationController.URL_ENCODING_SCHEME).toString(); fullTimelineLink = "View full timeline and co-author network
"; - valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL); + sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL); } else { - fullTimelineLink = "No data available to render full timeline.
"; - } divContextCode.append("

" + fullTimelineLink + "

"); @@ -619,4 +621,8 @@ public class CoAuthorshipVisCodeGenerator { return dataTable.toString(); } + + public SparklineData getValueObjectContainer() { + return sparklineData; + } } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/EdgeComparator.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/EdgeComparator.java index 9c5baf44..8e11a0dc 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/EdgeComparator.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/EdgeComparator.java @@ -7,6 +7,11 @@ import java.util.Comparator; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Edge; +/** + * This Comparator is used to sort the edges based on their IDs in ascending order. + * @author cdtank + * + */ public class EdgeComparator implements Comparator { @Override diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/NodeComparator.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/NodeComparator.java index 50999502..b43512ea 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/NodeComparator.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/NodeComparator.java @@ -7,6 +7,10 @@ import java.util.Comparator; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node; +/** + * This Comparator is used to sort the nodes based on their IDs in ascending order. + * @author cdtank + */ public class NodeComparator implements Comparator { @Override diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/CollegePublicationCountQueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/CollegePublicationCountQueryRunner.java similarity index 93% rename from src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/CollegePublicationCountQueryHandler.java rename to src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/CollegePublicationCountQueryRunner.java index 131167b3..c2654b7a 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/CollegePublicationCountQueryHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/CollegePublicationCountQueryRunner.java @@ -31,29 +31,28 @@ import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; 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.valueobjects.VivoEmployee; -import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryHandler; +import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner; /** * @author cdtank - * */ -public class CollegePublicationCountQueryHandler implements QueryHandler> { +public class CollegePublicationCountQueryRunner implements QueryRunner> { protected static final Syntax SYNTAX = Syntax.syntaxARQ; - private String collegeURIParam; + private String collegeURI; private Map collegeURLToVO = new HashMap(); private DataSource dataSource; private Log log; - public CollegePublicationCountQueryHandler(String collegeURIParam, + public CollegePublicationCountQueryRunner(String collegeURI, DataSource dataSource, Log log) { - this.collegeURIParam = collegeURIParam; + this.collegeURI = collegeURI; this.dataSource = dataSource; this.log = log; @@ -296,15 +295,15 @@ public class CollegePublicationCountQueryHandler implements QueryHandler getVisualizationJavaValueObjects() + public Set getQueryResult() throws MalformedQueryParametersException { - if (StringUtils.isNotBlank(this.collegeURIParam)) { + if (StringUtils.isNotBlank(this.collegeURI)) { /* * To test for the validity of the URI submitted. * */ IRIFactory iRIFactory = IRIFactory.jenaImplementation(); - IRI iri = iRIFactory.create(this.collegeURIParam); + IRI iri = iRIFactory.create(this.collegeURI); if (iri.hasViolation(false)) { String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage(); log.error("Pub Count Vis Query " + errorMsg); @@ -315,7 +314,7 @@ public class CollegePublicationCountQueryHandler implements QueryHandler> queryManager = - new CollegePublicationCountQueryHandler(collegeURIParam, + QueryRunner> queryManager = + new CollegePublicationCountQueryRunner(collegeURIParam, dataSource, log); try { - Set employees = queryManager.getVisualizationJavaValueObjects(); + Set employees = queryManager.getQueryResult(); Map> departmentToPublicationsOverTime = new HashMap>(); @@ -111,10 +108,10 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque * HTML code to render sparkline, tables etc. Ideally I would want to avoid this flow. * It is ugly! * */ - if (VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) { - prepareVisualizationQueryDataResponse( + if (VisualizationFrameworkConstants.DATA_RENDER_MODE.equalsIgnoreCase(renderMode)) { + prepareDataResponse( departmentToPublicationsOverTime, - ((CollegePublicationCountQueryHandler) queryManager).getCollegeURLToVO(), + ((CollegePublicationCountQueryRunner) queryManager).getCollegeURLToVO(), response); log.debug(publishedYearsForCollege); @@ -143,7 +140,13 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque } catch (MalformedQueryParametersException e) { try { - handleMalformedParameters(e.getMessage(), vitroRequest, request, response, log); + UtilityFunctions.handleMalformedParameters( + e.getMessage(), + "Visualization Query Error - College Publication Count", + vitroRequest, + request, + response, + log); } catch (ServletException e1) { log.error(e1.getStackTrace()); } catch (IOException e1) { @@ -204,7 +207,7 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque return departmentYearToPublicationCount; } - private void prepareVisualizationQueryPDFResponse(Individual college, + private void preparePDFResponse(Individual college, List authorDocuments, Map yearToPublicationCount, HttpServletResponse response) { @@ -264,7 +267,7 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque } } - private void prepareVisualizationQueryDataResponse( + private void prepareDataResponse( Map> departmentToPublicationsOverTime, Map collegeURLToVO, HttpServletResponse response) { @@ -358,7 +361,7 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque } - private void prepareVisualizationQueryStandaloneResponse(HttpServletRequest request, + private void prepareStandaloneResponse(HttpServletRequest request, HttpServletResponse response, VitroRequest vreq, String visContentCode, String visContextCode) { @@ -374,7 +377,7 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque } - private void prepareVisualizationQueryDynamicResponse(HttpServletRequest request, + private void prepareDynamicResponse(HttpServletRequest request, HttpServletResponse response, VitroRequest vreq, String visContentCode, String visContextCode) { @@ -388,29 +391,4 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque } - private void handleMalformedParameters(String errorMessage, - VitroRequest vitroRequest, - HttpServletRequest request, - HttpServletResponse response, - Log log) - throws ServletException, IOException { - - Portal portal = vitroRequest.getPortal(); - - request.setAttribute("error", errorMessage); - - RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); - request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp"); - request.setAttribute("portalBean", portal); - request.setAttribute("title", "Visualization Query Error - Individual Publication Count"); - - try { - requestDispatcher.forward(request, response); - } catch (Exception e) { - log.error("EntityEditController could not forward to view."); - log.error(e.getMessage()); - log.error(e.getStackTrace()); - } - } - } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryConstants.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryConstants.java index 16591b6c..22809eb0 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryConstants.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryConstants.java @@ -5,6 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.visualization.constants; import java.util.HashMap; import java.util.Map; +@SuppressWarnings("serial") public class QueryConstants { public static final Map PREFIX_TO_NAMESPACE = new HashMap() { { @@ -47,17 +48,12 @@ public class QueryConstants { StringBuilder prefixSection = new StringBuilder(); - for (Map.Entry prefixEntry : PREFIX_TO_NAMESPACE.entrySet()) { + for (Map.Entry prefixEntry : PREFIX_TO_NAMESPACE.entrySet()) { prefixSection.append("PREFIX " + prefixEntry.getKey() + ": <" + prefixEntry.getValue() + ">\n"); } - - return prefixSection.toString(); - } - - } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryFieldLabels.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryFieldLabels.java index e35f1bd1..012a7ad9 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryFieldLabels.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryFieldLabels.java @@ -2,6 +2,10 @@ package edu.cornell.mannlib.vitro.webapp.visualization.constants; +/** + * Thsi contains the sparql fields which are used to capture data for the value objects. + * @author cdtank + */ public class QueryFieldLabels { /* @@ -23,7 +27,6 @@ public class QueryFieldLabels { public static final String DOCUMENT_PUBLICATION_YEAR_MONTH = "publicationYearMonthLit"; public static final String DOCUMENT_PUBLICATION_DATE = "publicationDateLit"; - /* * Image related field labels * */ diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VOConstants.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VOConstants.java index 6aba7e9b..48907a95 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VOConstants.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VOConstants.java @@ -2,6 +2,12 @@ package edu.cornell.mannlib.vitro.webapp.visualization.constants; +import java.util.Calendar; + +/** + * This contains the constants related to all the value objects. + * @author cdtank + */ public class VOConstants { public static final String DEFAULT_PUBLICATION_YEAR = "Unknown"; @@ -13,4 +19,9 @@ public class VOConstants { ACADEMIC_FACULTY_EMPLOYEE, ACADEMIC_STAFF_EMPLOYEE } + public static final int NUM_CHARS_IN_YEAR_FORMAT = 4; + public static final int MINIMUM_PUBLICATION_YEAR = 1800; + public static final int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR); + + } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VisConstants.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VisConstants.java index b7cda606..8b6f07d4 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VisConstants.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VisConstants.java @@ -2,12 +2,16 @@ package edu.cornell.mannlib.vitro.webapp.visualization.constants; +/** + * This contains constants related to the visualization code. + * @author cdtank + */ public class VisConstants { public static final int MAX_NAME_TEXT_LENGTH = 20; + public static final int MINIMUM_YEARS_CONSIDERED_FOR_SPARKLINE = 10; public static final String RESULT_FORMAT_PARAM = "RS_TEXT"; public static final String RDF_RESULT_FORMAT_PARAM = "RDF/XML-ABBREV"; - } 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 7ce987df..9421c5a6 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/personlevel/PersonLevelRequestHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personlevel/PersonLevelRequestHandler.java @@ -4,8 +4,6 @@ package edu.cornell.mannlib.vitro.webapp.visualization.personlevel; import java.io.IOException; import java.io.PrintWriter; -import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -25,19 +23,29 @@ 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.coauthorship.CoAuthorshipGraphMLWriter; -import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipQueryHandler; +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.personpubcount.PersonPublicationCountQueryHandler; +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.CoAuthorshipVOContainer; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.CoAuthorshipData; 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.QueryHandler; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData; +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 content rendered on the person level vis page + * like, + * 1. Front end of the vis including the co-author & publication sparkline. + * 2. Downloadable file having the co-author network in graphml format. + * 3. Downloadable file having the list of co-authors that the individual has + * worked with & count of such co-authorships. + * + * @author cdtank + */ public class PersonLevelRequestHandler implements VisualizationRequestHandler { private static final String EGO_PUB_SPARKLINE_VIS_CONTAINER_ID = "ego_pub_sparkline"; @@ -50,55 +58,42 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler { Log log, DataSource dataSource) { - String egoURIParam = vitroRequest.getParameter( - VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE); + String egoURI = vitroRequest.getParameter( + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY); String renderMode = vitroRequest.getParameter( - VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE); + VisualizationFrameworkConstants.RENDER_MODE_KEY); String visMode = vitroRequest.getParameter( - VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE); + VisualizationFrameworkConstants.VIS_MODE_KEY); - QueryHandler - coAuthorshipQueryManager = - new CoAuthorshipQueryHandler(egoURIParam, - dataSource, - log); + QueryRunner coAuthorshipQueryManager = + new CoAuthorshipQueryRunner(egoURI, dataSource, log); - QueryHandler> publicationQueryManager = - new PersonPublicationCountQueryHandler(egoURIParam, - dataSource, - log); + QueryRunner> publicationQueryManager = + new PersonPublicationCountQueryRunner(egoURI, dataSource, log); try { - CoAuthorshipVOContainer coAuthorshipVO = coAuthorshipQueryManager - .getVisualizationJavaValueObjects(); - - /* - * 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! - * */ - if (VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE + CoAuthorshipData coAuthorshipData = coAuthorshipQueryManager.getQueryResult(); + + if (VisualizationFrameworkConstants.DATA_RENDER_MODE .equalsIgnoreCase(renderMode)) { /* * We will be using the same visualization package for providing data for both * list of unique coauthors & network of coauthors (used in the flash vis). - * We will use "VIS_MODE_URL_HANDLE" as a modifier to differentiate between - * these two. The defualt will be to provide data used to render the co- + * We will use "VIS_MODE_KEY" as a modifier to differentiate between + * these two. The default will be to provide data used to render the co- * authorship network vis. * */ - - if (VisualizationFrameworkConstants.COAUTHORSLIST_VIS_MODE_URL_VALUE + if (VisualizationFrameworkConstants.COAUTHORSLIST_VIS_MODE .equalsIgnoreCase(visMode)) { /* - * When the csv file is required - containing the unique co-authors vs how + * When the csv file is required - containing the co-authors & how * many times they have co-authored with the ego. * */ - prepareVisualizationQueryListCoauthorsDataResponse(coAuthorshipVO, + prepareListCoauthorsDataResponse(coAuthorshipData, response); return; @@ -107,15 +102,21 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler { * When the graphML file is required - based on which co-authorship * network visualization will be rendered. * */ - prepareVisualizationQueryNetworkDataResponse(coAuthorshipVO, response); + prepareNetworkDataResponse(coAuthorshipData, + response); return; } - - } - Set authorDocuments = publicationQueryManager - .getVisualizationJavaValueObjects(); + + /* + * When the front-end for the person level vis has to be displayed we render couple of + * sparklines. This will prepare all the data for the sparklines & other requested + * files. + * */ + + Set authorDocuments = publicationQueryManager.getQueryResult(); + /* * Create a map from the year to number of publications. Use the BiboDocument's * parsedPublicationYear to populate the data. @@ -126,39 +127,39 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler { /* * Computations required to generate HTML for the sparklines & related context. * */ - - SparklineVOContainer publicationSparklineVO = new SparklineVOContainer(); - SparklineVOContainer uniqueCoauthorsSparklineVO = new SparklineVOContainer(); - PersonPublicationCountVisCodeGenerator personPubCountVisCodeGenerator = new PersonPublicationCountVisCodeGenerator( vitroRequest.getRequestURI(), - egoURIParam, - PersonPublicationCountVisCodeGenerator.FULL_SPARKLINE_MODE_URL_HANDLE, + egoURI, + VisualizationFrameworkConstants.FULL_SPARKLINE_VIS_MODE, EGO_PUB_SPARKLINE_VIS_CONTAINER_ID, authorDocuments, yearToPublicationCount, - publicationSparklineVO, log); + SparklineData publicationSparklineVO = personPubCountVisCodeGenerator + .getValueObjectContainer(); + CoAuthorshipVisCodeGenerator uniqueCoauthorsVisCodeGenerator = new CoAuthorshipVisCodeGenerator( vitroRequest.getRequestURI(), - egoURIParam, - PersonPublicationCountVisCodeGenerator.FULL_SPARKLINE_MODE_URL_HANDLE, + egoURI, + VisualizationFrameworkConstants.FULL_SPARKLINE_VIS_MODE, UNIQUE_COAUTHORS_SPARKLINE_VIS_CONTAINER_ID, - getUniqueCoAuthorsPerYear(coAuthorshipVO), - uniqueCoauthorsSparklineVO, + UtilityFunctions.getPublicationYearToCoAuthors(coAuthorshipData), log); + + SparklineData uniqueCoauthorsSparklineVO = uniqueCoauthorsVisCodeGenerator + .getValueObjectContainer(); RequestDispatcher requestDispatcher = null; - prepareVisualizationQueryStandaloneResponse( - egoURIParam, + prepareStandaloneResponse( + egoURI, publicationSparklineVO, uniqueCoauthorsSparklineVO, - coAuthorshipVO, + coAuthorshipData, EGO_PUB_SPARKLINE_VIS_CONTAINER_ID, UNIQUE_COAUTHORS_SPARKLINE_VIS_CONTAINER_ID, vitroRequest, @@ -176,11 +177,14 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler { } catch (MalformedQueryParametersException e) { try { - handleMalformedParameters(e.getMessage(), - vitroRequest, - request, - response, - log); + UtilityFunctions.handleMalformedParameters( + e.getMessage(), + "Visualization Query Error - Person Level Visualization", + vitroRequest, + request, + response, + log); + } catch (ServletException e1) { log.error(e1.getStackTrace()); } catch (IOException e1) { @@ -190,124 +194,7 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler { } } - private Map> getUniqueCoAuthorsPerYear( - CoAuthorshipVOContainer 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 prepareVisualizationQueryNetworkDataResponse( - CoAuthorshipVOContainer coAuthorsipVO, HttpServletResponse response) { - - String outputFileName = ""; - - if (coAuthorsipVO.getNodes() != null && coAuthorsipVO.getNodes().size() > 0) { - - outputFileName = UtilityFunctions.slugify(coAuthorsipVO.getEgoNode().getNodeName()) - + "_coauthor-network.graphml" + ".xml"; - - } else { - - outputFileName = "no_coauthor-network.graphml" + ".xml"; - - } - - 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. - * */ - CoAuthorshipGraphMLWriter coAuthorShipGraphMLWriter = - new CoAuthorshipGraphMLWriter(coAuthorsipVO); - - responseWriter.append(coAuthorShipGraphMLWriter.getCoAuthorshipGraphMLContent()); - - responseWriter.close(); - - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void prepareVisualizationQueryListCoauthorsDataResponse( - CoAuthorshipVOContainer coAuthorshipVO, HttpServletResponse response) { - - String outputFileName = ""; - Map coAuthorsToCount = new TreeMap(); - - if (coAuthorshipVO.getNodes() != null && coAuthorshipVO.getNodes().size() > 0) { - - outputFileName = UtilityFunctions.slugify(coAuthorshipVO.getEgoNode().getNodeName()) - + "_coauthors" + ".csv"; - - coAuthorsToCount = getCoAuthorsList(coAuthorshipVO); - - } else { - - outputFileName = "no_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(coAuthorsToCount, - responseWriter); - - responseWriter.close(); - - } catch (IOException e) { - e.printStackTrace(); - } - } - - - private Map getCoAuthorsList(CoAuthorshipVOContainer coAuthorsipVO) { + private Map getCoAuthorsList(CoAuthorshipData coAuthorsipVO) { Map coAuthorsToCount = new TreeMap(); @@ -325,10 +212,11 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler { return coAuthorsToCount; } - private void generateCsvFileBuffer(Map coAuthorsToCount, - PrintWriter printWriter) { + private void writeCoAuthorsToWorksCSV(Map coAuthorsToCount, + PrintWriter printWriter) { - printWriter.append("\"Co-Author\", \"Count\"\n"); +// printWriter.append("\"Co-Author\", \"Count\"\n"); + printWriter.append("Co-Author, Count\n"); for (Entry currentEntry : coAuthorsToCount.entrySet()) { @@ -340,11 +228,106 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler { printWriter.flush(); } - private void prepareVisualizationQueryStandaloneResponse( - String egoURIParam, - SparklineVOContainer egoPubSparklineVO, - SparklineVOContainer uniqueCoauthorsSparklineVO, - CoAuthorshipVOContainer coAuthorshipVO, + /** + * Provide response when graphml file for the co-authorship network is requested. + * @param coAuthorsipData + * @param response + */ + private void prepareNetworkDataResponse( + CoAuthorshipData coAuthorsipData, HttpServletResponse response) { + + String outputFileName = ""; + + if (coAuthorsipData.getNodes() != null && coAuthorsipData.getNodes().size() > 0) { + + outputFileName = UtilityFunctions.slugify(coAuthorsipData.getEgoNode().getNodeName()) + + "_coauthor-network.graphml" + ".xml"; + + } else { + outputFileName = "no_coauthor-network.graphml" + ".xml"; + } + + 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. + * */ + CoAuthorshipGraphMLWriter coAuthorShipGraphMLWriter = + new CoAuthorshipGraphMLWriter(coAuthorsipData); + + responseWriter.append(coAuthorShipGraphMLWriter.getCoAuthorshipGraphMLContent()); + responseWriter.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Provides response when a csv file containing co-author names & number of co-authored works + * is requested. + * @param coAuthorshipData + * @param response + */ + private void prepareListCoauthorsDataResponse( + CoAuthorshipData coAuthorshipData, HttpServletResponse response) { + + String outputFileName = ""; + Map coAuthorsToCount = new TreeMap(); + + if (coAuthorshipData.getNodes() != null && coAuthorshipData.getNodes().size() > 0) { + + outputFileName = UtilityFunctions.slugify(coAuthorshipData.getEgoNode().getNodeName()) + + "_coauthors" + ".csv"; + + coAuthorsToCount = getCoAuthorsList(coAuthorshipData); + + } else { + outputFileName = "no_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. + * */ + writeCoAuthorsToWorksCSV(coAuthorsToCount, responseWriter); + + responseWriter.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * When the page for person level visualization is requested. + * @param egoURI + * @param egoPubSparklineVO + * @param uniqueCoauthorsSparklineVO + * @param coAuthorshipVO + * @param egoPubSparklineVisContainer + * @param uniqueCoauthorsSparklineVisContainer + * @param vitroRequest + * @param request + */ + private void prepareStandaloneResponse ( + String egoURI, + SparklineData egoPubSparklineVO, + SparklineData uniqueCoauthorsSparklineVO, + CoAuthorshipData coAuthorshipVO, String egoPubSparklineVisContainer, String uniqueCoauthorsSparklineVisContainer, VitroRequest vitroRequest, @@ -352,12 +335,12 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler { Portal portal = vitroRequest.getPortal(); - request.setAttribute("egoURIParam", egoURIParam); + request.setAttribute("egoURIParam", egoURI); String title = ""; if (coAuthorshipVO.getNodes() != null && coAuthorshipVO.getNodes().size() > 0) { request.setAttribute("numOfAuthors", coAuthorshipVO.getNodes().size()); - title = "for " + coAuthorshipVO.getEgoNode().getNodeName(); + title = coAuthorshipVO.getEgoNode().getNodeName() + " - "; } if (coAuthorshipVO.getEdges() != null && coAuthorshipVO.getEdges().size() > 0) { @@ -372,36 +355,9 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler { request.setAttribute("uniqueCoauthorsSparklineVisContainerID", uniqueCoauthorsSparklineVisContainer); - request.setAttribute("title", "Person Level Visualization " + title); + request.setAttribute("title", title + "Person Level Visualization"); request.setAttribute("portalBean", portal); request.setAttribute("scripts", "/templates/visualization/person_level_inject_head.jsp"); - request.setAttribute("bodyJsp", "/templates/visualization/person_level.jsp"); } - - private void handleMalformedParameters(String errorMessage, - VitroRequest vitroRequest, - HttpServletRequest request, - HttpServletResponse response, - Log log) - throws ServletException, IOException { - - Portal portal = vitroRequest.getPortal(); - - request.setAttribute("error", errorMessage); - - RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); - request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp"); - request.setAttribute("portalBean", portal); - request.setAttribute("title", "Visualization Query Error - Individual Publication Count"); - - try { - requestDispatcher.forward(request, response); - } catch (Exception e) { - log.error("EntityEditController could not forward to view."); - log.error(e.getMessage()); - log.error(e.getStackTrace()); - } - } - } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryRunner.java similarity index 88% rename from src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryHandler.java rename to src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryRunner.java index ccb87403..54aeefc5 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountQueryRunner.java @@ -2,12 +2,8 @@ package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount; -import java.util.ArrayList; import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; -import java.util.TreeMap; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; @@ -30,19 +26,21 @@ 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.BiboDocument; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual; -import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryHandler; +import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner; /** + * This query runner is used to execute a sparql query that will fetch all the publications + * defined by bibo:Document property for a particular individual. + * * @author cdtank - * */ -public class PersonPublicationCountQueryHandler implements QueryHandler> { +public class PersonPublicationCountQueryRunner implements QueryRunner> { protected static final Syntax SYNTAX = Syntax.syntaxARQ; - private String queryParam; + private String personURI; private DataSource dataSource; private Individual author; @@ -74,10 +72,10 @@ public class PersonPublicationCountQueryHandler implements QueryHandler getVisualizationJavaValueObjects() + public Set getQueryResult() throws MalformedQueryParametersException { - if (StringUtils.isNotBlank(this.queryParam)) { + if (StringUtils.isNotBlank(this.personURI)) { /* * To test for the validity of the URI submitted. * */ IRIFactory iRIFactory = IRIFactory.jenaImplementation(); - IRI iri = iRIFactory.create(this.queryParam); + IRI iri = iRIFactory.create(this.personURI); if (iri.hasViolation(false)) { String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage(); log.error("Pub Count vis Query " + errorMsg); @@ -215,7 +212,7 @@ public class PersonPublicationCountQueryHandler implements QueryHandler> queryManager = - new PersonPublicationCountQueryHandler(individualURIParam, - dataSource, - log); + QueryRunner> queryManager = + new PersonPublicationCountQueryRunner(peronURI, dataSource, log); try { - Set authorDocuments = queryManager.getVisualizationJavaValueObjects(); + Set authorDocuments = queryManager.getQueryResult(); /* * Create a map from the year to number of publications. Use the BiboDocument's @@ -77,17 +89,12 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques Map yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments); - /* - * 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! - * */ - Individual author = ((PersonPublicationCountQueryHandler) queryManager).getAuthor(); - if (VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE + Individual author = ((PersonPublicationCountQueryRunner) queryManager).getAuthor(); + + if (VisualizationFrameworkConstants.DATA_RENDER_MODE .equalsIgnoreCase(renderMode)) { - prepareVisualizationQueryDataResponse(author, + prepareDataResponse(author, authorDocuments, yearToPublicationCount, response); @@ -95,32 +102,35 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques } - if (VisualizationFrameworkConstants.PDF_RENDER_MODE_URL_VALUE + /* + * For now we are disabling the capability to render pdf file. + * */ + /* + if (VisualizationFrameworkConstants.PDF_RENDER_MODE .equalsIgnoreCase(renderMode)) { - prepareVisualizationQueryPDFResponse(author, + preparePDFResponse(author, authorDocuments, yearToPublicationCount, response); return; } + */ /* - * Computations required to generate HTML for the sparklines & related context. + * Computations required to generate HTML for the sparkline & related context. * */ - - SparklineVOContainer valueObjectContainer = new SparklineVOContainer(); - PersonPublicationCountVisCodeGenerator visualizationCodeGenerator = new PersonPublicationCountVisCodeGenerator(vitroRequest.getContextPath(), - individualURIParam, + peronURI, visMode, visContainer, authorDocuments, yearToPublicationCount, - valueObjectContainer, log); + SparklineData sparklineData = visualizationCodeGenerator + .getValueObjectContainer(); /* * This is side-effecting because the response of this method is just to redirect to @@ -128,17 +138,21 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques * */ RequestDispatcher requestDispatcher = null; - if (VisualizationFrameworkConstants.DYNAMIC_RENDER_MODE_URL_VALUE + if (VisualizationFrameworkConstants.DYNAMIC_RENDER_MODE .equalsIgnoreCase(renderMode)) { - prepareVisualizationQueryDynamicResponse(request, response, vitroRequest, - valueObjectContainer, yearToPublicationCount); + prepareDynamicResponse(request, + response, + vitroRequest, + sparklineData, + yearToPublicationCount); requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp"); } else { - prepareVisualizationQueryStandaloneResponse(request, response, vitroRequest, - valueObjectContainer); - + prepareStandaloneResponse(request, + response, + vitroRequest, + sparklineData); requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); } @@ -152,7 +166,13 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques } catch (MalformedQueryParametersException e) { try { - handleMalformedParameters(e.getMessage(), vitroRequest, request, response, log); + UtilityFunctions.handleMalformedParameters( + e.getMessage(), + "Visualization Query Error - Individual Publication Count", + vitroRequest, + request, + response, + log); } catch (ServletException e1) { log.error(e1.getStackTrace()); } catch (IOException e1) { @@ -160,72 +180,35 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques } return; } - } - private void prepareVisualizationQueryPDFResponse( - Individual author, - Set authorDocuments, - Map yearToPublicationCount, - HttpServletResponse response) { + private void writePublicationsOverTimeCSV(Map yearToPublicationCount, + PrintWriter responseWriter) { - 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 (authorName == null) { - authorName = "no"; - } - - 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(); + CSVWriter csvWriter = new SimpleWriter(responseWriter); + + try { + csvWriter.append(new String[]{"Year", "Publications"}); + for (Entry currentEntry : yearToPublicationCount.entrySet()) { + csvWriter.append(new Object[]{currentEntry.getKey(), currentEntry.getValue()}); } + } catch (IOException e) { + e.printStackTrace(); + } + + responseWriter.flush(); + } - private void prepareVisualizationQueryDataResponse( + /** + * 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 authorDocuments, Map yearToPublicationCount, @@ -244,7 +227,7 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques /* * To make sure that null/empty records for author names do not cause any mischief. * */ - if (authorName == null) { + if (StringUtils.isBlank(authorName)) { authorName = "no-author"; } @@ -262,8 +245,7 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques * We are side-effecting responseWriter since we are directly manipulating the response * object of the servlet. * */ - generateCsvFileBuffer(yearToPublicationCount, - responseWriter); + writePublicationsOverTimeCSV(yearToPublicationCount, responseWriter); responseWriter.close(); @@ -272,28 +254,16 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques } } - private void generateCsvFileBuffer(Map yearToPublicationCount, - PrintWriter responseWriter) { - - CSVWriter csvWriter = new SimpleWriter(responseWriter); - - try { - csvWriter.append(new String[]{"Year", "Publications"}); - for (Entry currentEntry : yearToPublicationCount.entrySet()) { - csvWriter.append(new Object[]{currentEntry.getKey(), currentEntry.getValue()}); - } - - } catch (IOException e) { - e.printStackTrace(); - } - - responseWriter.flush(); - - } - - private void prepareVisualizationQueryStandaloneResponse(HttpServletRequest request, + /** + * 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, - SparklineVOContainer valueObjectContainer) { + SparklineData valueObjectContainer) { Portal portal = vreq.getPortal(); @@ -306,11 +276,20 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques } - private void prepareVisualizationQueryDynamicResponse( + /** + * 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, - SparklineVOContainer valueObjectContainer, + SparklineData valueObjectContainer, Map yearToPublicationCount) { Portal portal = vreq.getPortal(); @@ -325,32 +304,67 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques request.setAttribute("portalBean", portal); request.setAttribute("bodyJsp", "/templates/visualization/ajax_vis_content.jsp"); - } - private void handleMalformedParameters(String errorMessage, - VitroRequest vitroRequest, - HttpServletRequest request, - HttpServletResponse response, - Log log) - throws ServletException, IOException { - - Portal portal = vitroRequest.getPortal(); + private void preparePDFResponse( + Individual author, + Set authorDocuments, + Map yearToPublicationCount, + HttpServletResponse response) { - request.setAttribute("error", errorMessage); - - RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); - request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp"); - request.setAttribute("portalBean", portal); - request.setAttribute("title", "Visualization Query Error - Individual Publication Count"); - - try { - requestDispatcher.forward(request, response); - } catch (Exception e) { - log.error("EntityEditController could not forward to view."); - log.error(e.getMessage()); - log.error(e.getStackTrace()); + 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(); + } } - } 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 6136a8ec..f9153de9 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountVisCodeGenerator.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/PersonPublicationCountVisCodeGenerator.java @@ -18,14 +18,23 @@ 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.BiboDocument; -import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData; +@SuppressWarnings("serial") public class PersonPublicationCountVisCodeGenerator { - private static final int MINIMUM_YEARS_CONSIDERED = 10; - + /* + * 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 publications 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 yeras. + * */ private static final Map VIS_DIV_NAMES = new HashMap() { { put("SHORT_SPARK", "pub_count_short_sparkline_vis"); @@ -37,19 +46,15 @@ public class PersonPublicationCountVisCodeGenerator { private static final String DEFAULT_VIS_CONTAINER_DIV_ID = "pub_count_vis_container"; - public static final String SHORT_SPARKLINE_MODE_URL_HANDLE = "short"; - - public static final String FULL_SPARKLINE_MODE_URL_HANDLE = "full"; - private Map yearToPublicationCount; private Log log; - private SparklineVOContainer valueObjectContainer; + private SparklineData sparklineData; private String contextPath; - private String individualURIParam; + private String individualURI; public PersonPublicationCountVisCodeGenerator(String contextPath, String individualURIParam, @@ -57,35 +62,41 @@ public class PersonPublicationCountVisCodeGenerator { String visContainer, Set authorDocuments, Map yearToPublicationCount, - SparklineVOContainer valueObjectContainer, Log log) { this.contextPath = contextPath; - this.individualURIParam = individualURIParam; + this.individualURI = individualURIParam; this.yearToPublicationCount = yearToPublicationCount; - this.valueObjectContainer = valueObjectContainer; + this.sparklineData = new SparklineData(); this.log = log; - - generateVisualizationCode(visMode, - visContainer, - authorDocuments); - - + generateVisualizationCode(visMode, visContainer, authorDocuments); } + /** + * 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 authorDocuments + */ private void generateVisualizationCode(String visMode, String visContainer, Set authorDocuments) { - valueObjectContainer.setSparklineContent(getMainVisualizationCode(authorDocuments, - visMode, - visContainer)); + sparklineData.setSparklineContent(getMainVisualizationCode(authorDocuments, + visMode, + visContainer)); - valueObjectContainer.setSparklineContext(getVisualizationContextCode(visMode)); + sparklineData.setSparklineContext(getVisualizationContextCode(visMode)); } @@ -95,13 +106,15 @@ public class PersonPublicationCountVisCodeGenerator { int numOfYearsToBeRendered = 0; int currentYear = Calendar.getInstance().get(Calendar.YEAR); - int shortSparkMinYear = currentYear - MINIMUM_YEARS_CONSIDERED + 1; + 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_PUBLICATION_YEAR". * */ - Set publishedYears = new HashSet(yearToPublicationCount.keySet()); + Set publishedYears = new HashSet(yearToPublicationCount.keySet()); publishedYears.remove(VOConstants.DEFAULT_PUBLICATION_YEAR); /* @@ -175,7 +188,13 @@ public class PersonPublicationCountVisCodeGenerator { + "data.addRows(" + numOfYearsToBeRendered + ");\n"); int publicationCounter = 0; - int totalPublications = 0; + + /* + * For the purpose of this visualization I have come up with a term "Sparks" which + * essentially means data points. + * Sparks that will be rendered in full mode will always be the one's which have any year + * associated with it. Hence. + * */ int renderedFullSparks = 0; @@ -202,23 +221,20 @@ public class PersonPublicationCountVisCodeGenerator { + currentPublications + ");\n"); - totalPublications += currentPublications; + /* + * Sparks that will be rendered in full mode will always be the one's which has + * any year associated with it. Hence. + * */ + renderedFullSparks += 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. * */ Integer unknownYearPublications = 0; if (yearToPublicationCount.get(VOConstants.DEFAULT_PUBLICATION_YEAR) != null) { - totalPublications += yearToPublicationCount.get(VOConstants.DEFAULT_PUBLICATION_YEAR); unknownYearPublications = yearToPublicationCount .get(VOConstants.DEFAULT_PUBLICATION_YEAR); } @@ -238,8 +254,8 @@ public class PersonPublicationCountVisCodeGenerator { * "short" sparkline mode we will set the Earliest RenderedPublication year to * "currentYear - 10". * */ - valueObjectContainer.setEarliestRenderedPublicationYear(minPublishedYear); - valueObjectContainer.setLatestRenderedPublicationYear(currentYear); + sparklineData.setEarliestRenderedPublicationYear(minPublishedYear); + sparklineData.setLatestRenderedPublicationYear(currentYear); /* * The Full Sparkline will be rendered by default. Only if the url has specific mention of @@ -252,9 +268,9 @@ public class PersonPublicationCountVisCodeGenerator { * 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)) { + if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE.equalsIgnoreCase(visMode)) { - valueObjectContainer.setEarliestRenderedPublicationYear(shortSparkMinYear); + sparklineData.setEarliestRenderedPublicationYear(shortSparkMinYear); generateShortSparklineVisualizationContent(currentYear, shortSparkMinYear, visContainerID, @@ -370,9 +386,7 @@ public class PersonPublicationCountVisCodeGenerator { + "\" class=\"inline_href\">(.CSV File)"; } else { - csvDownloadURLHref = ""; - } } catch (UnsupportedEncodingException e) { @@ -464,7 +478,7 @@ public class PersonPublicationCountVisCodeGenerator { private String getVisualizationContextCode(String visMode) { String visualizationContextCode = ""; - if (SHORT_SPARKLINE_MODE_URL_HANDLE.equalsIgnoreCase(visMode)) { + if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE.equalsIgnoreCase(visMode)) { visualizationContextCode = generateShortVisContext(); } else { visualizationContextCode = generateFullVisContext(); @@ -488,19 +502,15 @@ public class PersonPublicationCountVisCodeGenerator { csvDownloadURLHref = "Download data as .csv file.
"; - valueObjectContainer.setDownloadDataLink(getCSVDownloadURL()); + sparklineData.setDownloadDataLink(getCSVDownloadURL()); } else { - csvDownloadURLHref = ""; - } } catch (UnsupportedEncodingException e) { csvDownloadURLHref = ""; } - - } else { csvDownloadURLHref = "No data available to export.
"; } @@ -509,10 +519,9 @@ public class PersonPublicationCountVisCodeGenerator { divContextCode.append("

" + tableCode + csvDownloadURLHref + "

"); - valueObjectContainer.setTable(tableCode); + sparklineData.setTable(tableCode); return divContextCode.toString(); - } private String getCSVDownloadURL() @@ -525,22 +534,21 @@ public class PersonPublicationCountVisCodeGenerator { secondaryContextPath = VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX; } - String downloadURL = contextPath + secondaryContextPath - + "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE - + "=" + URLEncoder.encode(individualURIParam, + + "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY + + "=" + URLEncoder.encode(individualURI, VisualizationController.URL_ENCODING_SCHEME) .toString() - + "&" + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + + "&" + VisualizationFrameworkConstants.VIS_TYPE_KEY + "=" + URLEncoder.encode( - VisualizationController - .PERSON_PUBLICATION_COUNT_VIS_URL_VALUE, + VisualizationFrameworkConstants + .PERSON_PUBLICATION_COUNT_VIS, VisualizationController.URL_ENCODING_SCHEME) .toString() - + "&" + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + + "&" + VisualizationFrameworkConstants.RENDER_MODE_KEY + "=" + URLEncoder.encode(VisualizationFrameworkConstants - .DATA_RENDER_MODE_URL_VALUE, + .DATA_RENDER_MODE, VisualizationController.URL_ENCODING_SCHEME) .toString(); return downloadURL; @@ -566,28 +574,26 @@ public class PersonPublicationCountVisCodeGenerator { String fullTimelineNetworkURL = contextPath + secondaryContextPath + "?" - + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE - + "=" + URLEncoder.encode(individualURIParam, + + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY + + "=" + URLEncoder.encode(individualURI, VisualizationController.URL_ENCODING_SCHEME).toString() + "&" - + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + + VisualizationFrameworkConstants.VIS_TYPE_KEY + "=" + URLEncoder.encode("person_level", VisualizationController.URL_ENCODING_SCHEME).toString() + "&" - + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + + VisualizationFrameworkConstants.RENDER_MODE_KEY + "=" + URLEncoder.encode(VisualizationFrameworkConstants - .STANDALONE_RENDER_MODE_URL_VALUE, + .STANDALONE_RENDER_MODE, VisualizationController.URL_ENCODING_SCHEME).toString(); fullTimelineLink = "View all VIVO " + "publications and corresponding co-author network.
"; - valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL); + sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL); } else { - fullTimelineLink = "No data available to render full timeline.
"; - } divContextCode.append("" + fullTimelineLink + ""); @@ -595,9 +601,7 @@ public class PersonPublicationCountVisCodeGenerator { } catch (UnsupportedEncodingException e) { log.error(e); } - return divContextCode.toString(); - } private String generateDataTable() { @@ -606,15 +610,10 @@ public class PersonPublicationCountVisCodeGenerator { try { if (getCSVDownloadURL() != null) { - csvDownloadURLHref = "(.CSV File)"; - } else { - csvDownloadURLHref = ""; - } - } catch (UnsupportedEncodingException e) { csvDownloadURLHref = ""; } @@ -643,7 +642,7 @@ public class PersonPublicationCountVisCodeGenerator { return dataTable.toString(); } - - - + public SparklineData getValueObjectContainer() { + return sparklineData; + } } 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 c08f3eb1..3e77e0e3 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/utilities/UtilitiesRequestHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/utilities/UtilitiesRequestHandler.java @@ -9,7 +9,6 @@ import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; -import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -22,8 +21,6 @@ import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.rdf.model.RDFNode; -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.VisualizationController; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; @@ -31,11 +28,22 @@ import edu.cornell.mannlib.vitro.webapp.filestorage.FileServingHelper; 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.GenericQueryMap; -import edu.cornell.mannlib.vitro.webapp.visualization.visutils.AllPropertiesQueryHandler; -import edu.cornell.mannlib.vitro.webapp.visualization.visutils.GenericQueryHandler; -import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryHandler; +import edu.cornell.mannlib.vitro.webapp.visualization.visutils.AllPropertiesQueryRunner; +import edu.cornell.mannlib.vitro.webapp.visualization.visutils.GenericQueryRunner; +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 when you need helpful information to add more context + * to the visualization. It does not have any code for generating the visualization, + * just fires sparql queries to get info for specific cases like, + * 1. thumbnail/image location for a particular individual + * 2. profile information for a particular individual like label, moniker etc + * 3. person level vis url for a particular individual + * etc. + * @author cdtank + */ public class UtilitiesRequestHandler implements VisualizationRequestHandler { public void generateVisualization(VitroRequest vitroRequest, @@ -44,12 +52,11 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler { Log log, DataSource dataSource) { - String individualURIParam = vitroRequest.getParameter( - VisualizationFrameworkConstants - .INDIVIDUAL_URI_URL_HANDLE); + String individualURI = vitroRequest.getParameter( + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY); - String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants - .VIS_MODE_URL_HANDLE); + String visMode = vitroRequest.getParameter( + VisualizationFrameworkConstants.VIS_MODE_KEY); String preparedURL = ""; @@ -67,8 +74,8 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler { + "|| ?predicate = vitro:moniker " + "|| ?predicate = rdfs:label"; - QueryHandler profileQueryHandler = - new AllPropertiesQueryHandler(individualURIParam, + QueryRunner profileQueryHandler = + new AllPropertiesQueryRunner(individualURI, filterRule, dataSource, log); @@ -76,14 +83,14 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler { try { GenericQueryMap profilePropertiesToValues = - profileQueryHandler.getVisualizationJavaValueObjects(); + profileQueryHandler.getQueryResult(); profilePropertiesToValues.addEntry("imageContextPath", request.getContextPath()); Gson profileInformation = new Gson(); - prepareVisualizationQueryResponse( + prepareUtilitiesResponse( profileInformation.toJson(profilePropertiesToValues), response); @@ -92,11 +99,13 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler { } catch (MalformedQueryParametersException e) { try { - handleMalformedParameters(e.getMessage(), - vitroRequest, - request, - response, - log); + UtilityFunctions.handleMalformedParameters( + e.getMessage(), + "Visualization Query Error - Utilities Profile Info", + vitroRequest, + request, + response, + log); } catch (ServletException e1) { log.error(e1.getStackTrace()); } catch (IOException e1) { @@ -104,8 +113,6 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler { } return; } - - } else if (VisualizationFrameworkConstants.IMAGE_UTILS_VIS_MODE .equalsIgnoreCase(visMode)) { /* @@ -118,15 +125,15 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler { QueryFieldLabels.THUMBNAIL_LOCATION_URL); fieldLabelToOutputFieldLabel.put("fileName", QueryFieldLabels.THUMBNAIL_FILENAME); - String whereClause = "<" + individualURIParam + String whereClause = "<" + individualURI + "> j.2:thumbnailImage ?thumbnailImage . " + "?thumbnailImage j.2:downloadLocation " + "?downloadLocation ; j.2:filename ?fileName ."; - QueryHandler imageQueryHandler = - new GenericQueryHandler(individualURIParam, + QueryRunner imageQueryHandler = + new GenericQueryRunner(individualURI, fieldLabelToOutputFieldLabel, whereClause, dataSource, @@ -136,20 +143,22 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler { String thumbnailAccessURL = getThumbnailInformation( - imageQueryHandler.getVisualizationJavaValueObjects(), + imageQueryHandler.getQueryResult(), fieldLabelToOutputFieldLabel); - prepareVisualizationQueryResponse(thumbnailAccessURL, response); + prepareUtilitiesResponse(thumbnailAccessURL, response); return; } catch (MalformedQueryParametersException e) { try { - handleMalformedParameters(e.getMessage(), - vitroRequest, - request, - response, - log); + UtilityFunctions.handleMalformedParameters( + e.getMessage(), + "Visualization Query Error - Utilities Image Info", + vitroRequest, + request, + response, + log); } catch (ServletException e1) { log.error(e1.getStackTrace()); } catch (IOException e1) { @@ -157,76 +166,69 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler { } return; } - - } else if (VisualizationFrameworkConstants.COAUTHOR_UTILS_VIS_MODE .equalsIgnoreCase(visMode)) { + /* * By default we will be generating profile url else some specific url like * coAuthorShip vis url for that individual. * */ - preparedURL += request.getContextPath() + VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX + "?" - + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE - + "=" + URLEncoder.encode(individualURIParam, + + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY + + "=" + URLEncoder.encode(individualURI, VisualizationController.URL_ENCODING_SCHEME).toString() + "&" - + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + + VisualizationFrameworkConstants.VIS_TYPE_KEY + "=" + URLEncoder.encode("coauthorship", VisualizationController.URL_ENCODING_SCHEME).toString() + "&" - + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + + VisualizationFrameworkConstants.RENDER_MODE_KEY + "=" + URLEncoder.encode(VisualizationFrameworkConstants - .STANDALONE_RENDER_MODE_URL_VALUE, + .STANDALONE_RENDER_MODE, VisualizationController.URL_ENCODING_SCHEME) .toString(); - prepareVisualizationQueryResponse(preparedURL, response); + prepareUtilitiesResponse(preparedURL, response); return; - } else if (VisualizationFrameworkConstants.PERSON_LEVEL_UTILS_VIS_MODE .equalsIgnoreCase(visMode)) { /* * By default we will be generating profile url else some specific url like * coAuthorShip vis url for that individual. * */ - preparedURL += request.getContextPath() + VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX + "?" - + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE - + "=" + URLEncoder.encode(individualURIParam, + + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY + + "=" + URLEncoder.encode(individualURI, VisualizationController.URL_ENCODING_SCHEME).toString() + "&" - + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + + VisualizationFrameworkConstants.VIS_TYPE_KEY + "=" + URLEncoder.encode("person_level", VisualizationController.URL_ENCODING_SCHEME).toString() + "&" - + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + + VisualizationFrameworkConstants.RENDER_MODE_KEY + "=" + URLEncoder.encode(VisualizationFrameworkConstants - .STANDALONE_RENDER_MODE_URL_VALUE, + .STANDALONE_RENDER_MODE, VisualizationController.URL_ENCODING_SCHEME).toString(); - prepareVisualizationQueryResponse(preparedURL, response); + prepareUtilitiesResponse(preparedURL, response); return; - } else { preparedURL += request.getContextPath() - + "/individual" + + VisualizationFrameworkConstants.INDIVIDUAL_URL_PREFIX + "?" - + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE - + "=" + URLEncoder.encode(individualURIParam, + + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY + + "=" + URLEncoder.encode(individualURI, VisualizationController.URL_ENCODING_SCHEME).toString(); - prepareVisualizationQueryResponse(preparedURL, response); + prepareUtilitiesResponse(preparedURL, response); return; - } - } catch (UnsupportedEncodingException e) { log.error(e.getLocalizedMessage()); } @@ -253,53 +255,22 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler { .getBytestreamAliasUrl(downloadLocationNode.toString(), fileNameNode.toString()); } - } - return finalThumbNailLocation; } - private void prepareVisualizationQueryResponse(String preparedURL, + private void prepareUtilitiesResponse(String preparedURL, HttpServletResponse response) { response.setContentType("text/plain"); try { - - PrintWriter responseWriter = response.getWriter(); - - responseWriter.append(preparedURL); - - responseWriter.close(); - + PrintWriter responseWriter = response.getWriter(); + responseWriter.append(preparedURL); + responseWriter.close(); } catch (IOException e) { e.printStackTrace(); } } - - private void handleMalformedParameters(String errorMessage, - VitroRequest vitroRequest, - HttpServletRequest request, - HttpServletResponse response, - Log log) - throws ServletException, IOException { - - Portal portal = vitroRequest.getPortal(); - - request.setAttribute("error", errorMessage); - - RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); - request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp"); - request.setAttribute("portalBean", portal); - request.setAttribute("title", "Visualization Query Error - Individual Publication Count"); - - try { - requestDispatcher.forward(request, response); - } catch (Exception e) { - log.error("EntityEditController could not forward to view."); - log.error(e.getMessage()); - log.error(e.getStackTrace()); - } - } - } + diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java index 08b27f12..759e76a5 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java @@ -2,7 +2,6 @@ package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; -import java.util.Calendar; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -14,10 +13,6 @@ import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants; */ public class BiboDocument extends Individual { - private static final int NUM_CHARS_IN_YEAR_FORMAT = 4; - public static final int MINIMUM_PUBLICATION_YEAR = 1800; - private static final int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR); - private String documentMoniker; private String documentBlurb; private String documentDescription; @@ -31,7 +26,7 @@ public class BiboDocument extends Individual { } public String getDocumentURL() { - return this.getIndividualURL(); + return this.getIndividualURI(); } public String getDocumentMoniker() { @@ -68,7 +63,6 @@ public class BiboDocument extends Individual { * This pattern will match all group of numbers which have only 4 digits * delimited by the word boundary. * */ -// String pattern = "\\b\\d{4}\\b"; String pattern = "(?= MINIMUM_PUBLICATION_YEAR) { + if (candidateYearInteger <= VOConstants.CURRENT_YEAR + && candidateYearInteger >= VOConstants.MINIMUM_PUBLICATION_YEAR) { publishedYear = candidateYearInteger.toString(); } @@ -117,20 +111,22 @@ public class BiboDocument extends Individual { * core:yearMonth points to internally. * */ if (publicationYearMonth != null - && publicationYearMonth.length() >= NUM_CHARS_IN_YEAR_FORMAT + && publicationYearMonth.length() >= VOConstants.NUM_CHARS_IN_YEAR_FORMAT && isValidPublicationYear(publicationYearMonth.substring( 0, - NUM_CHARS_IN_YEAR_FORMAT))) { + VOConstants.NUM_CHARS_IN_YEAR_FORMAT))) { - return publicationYearMonth.substring(0, NUM_CHARS_IN_YEAR_FORMAT); + return publicationYearMonth.substring(0, VOConstants.NUM_CHARS_IN_YEAR_FORMAT); } if (publicationDate != null - && publicationDate.length() >= NUM_CHARS_IN_YEAR_FORMAT - && isValidPublicationYear(publicationDate.substring(0, NUM_CHARS_IN_YEAR_FORMAT))) { + && publicationDate.length() >= VOConstants.NUM_CHARS_IN_YEAR_FORMAT + && isValidPublicationYear(publicationDate + .substring(0, + VOConstants.NUM_CHARS_IN_YEAR_FORMAT))) { - return publicationDate.substring(0, NUM_CHARS_IN_YEAR_FORMAT); + return publicationDate.substring(0, VOConstants.NUM_CHARS_IN_YEAR_FORMAT); } /* @@ -175,9 +171,9 @@ public class BiboDocument extends Individual { private boolean isValidPublicationYear(String testPublicationYear) { if (testPublicationYear.length() != 0 - && testPublicationYear.trim().length() == NUM_CHARS_IN_YEAR_FORMAT + && testPublicationYear.trim().length() == VOConstants.NUM_CHARS_IN_YEAR_FORMAT && testPublicationYear.matches("\\d+") - && Integer.parseInt(testPublicationYear) >= MINIMUM_PUBLICATION_YEAR) { + && Integer.parseInt(testPublicationYear) >= VOConstants.MINIMUM_PUBLICATION_YEAR) { return true; } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/CoAuthorshipVOContainer.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/CoAuthorshipData.java similarity index 94% rename from src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/CoAuthorshipVOContainer.java rename to src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/CoAuthorshipData.java index 2c9f3061..4bc11dc5 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/CoAuthorshipVOContainer.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/CoAuthorshipData.java @@ -7,8 +7,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; - -public class CoAuthorshipVOContainer { +public class CoAuthorshipData { private Set nodes; private Set edges; @@ -16,7 +15,7 @@ public class CoAuthorshipVOContainer { private Set> NODE_SCHEMA; private Set> EDGE_SCHEMA; - public CoAuthorshipVOContainer(Node egoNode, Set nodes, Set edges) { + public CoAuthorshipData(Node egoNode, Set nodes, Set edges) { this.egoNode = egoNode; this.nodes = nodes; this.edges = edges; diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Edge.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Edge.java index cfbeeb01..f576aa5b 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Edge.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Edge.java @@ -14,7 +14,8 @@ import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions; /** * - * This is the Value Object for storing edge information mainly for co-author vis. + * This is stores edge information mainly for co-author vis. + * * @author cdtank * */ @@ -129,7 +130,6 @@ public class Edge { } } - @SuppressWarnings("serial") public Integer getUnknownCollaborationYearCount() { if (yearToPublicationCount == null) { yearToPublicationCount = UtilityFunctions diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/GenericQueryMap.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/GenericQueryMap.java index 883fdc93..2c01d34d 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/GenericQueryMap.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/GenericQueryMap.java @@ -10,8 +10,8 @@ import java.util.Set; * Right now this is just acting as a hashmap but in future we would want to provide * more detailed info other than just what properties had what values. E.g. we * could parse properties (& its values) to look for what namespaces are used. + * * @author cdtank - * */ @SuppressWarnings("serial") public class GenericQueryMap extends HashMap> { diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Individual.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Individual.java index f4afa724..89c6ddd5 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Individual.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Individual.java @@ -5,15 +5,15 @@ package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; public class Individual { private String individualLabel; - private String individualURL; + private String individualURI; - public Individual(String individualURL, String individualLabel) { - this.individualURL = individualURL; + public Individual(String individualURI, String individualLabel) { + this.individualURI = individualURI; this.individualLabel = individualLabel; } - public Individual(String individualURL) { - this(individualURL, ""); + public Individual(String individualURI) { + this(individualURI, ""); } public String getIndividualLabel() { @@ -24,8 +24,8 @@ public class Individual { this.individualLabel = individualLabel; } - public String getIndividualURL() { - return individualURL; + public String getIndividualURI() { + return individualURI; } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java index 5dc80717..242d9e81 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java @@ -14,9 +14,9 @@ import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions; /** * - * This is the Value Object for storing node information mainly for co-author vis. + * This stores node information mainly for co-author vis. + * * @author cdtank - * */ public class Node extends Individual { @@ -25,9 +25,9 @@ public class Node extends Individual { private Set authorDocuments = new HashSet(); - public Node(String nodeURL, + public Node(String nodeURI, UniqueIDGenerator uniqueIDGenerator) { - super(nodeURL); + super(nodeURI); nodeID = uniqueIDGenerator.getNextNumericID(); } @@ -35,8 +35,8 @@ public class Node extends Individual { return nodeID; } - public String getNodeURL() { - return this.getIndividualURL(); + public String getNodeURI() { + return this.getIndividualURI(); } public String getNodeName() { @@ -59,13 +59,13 @@ public class Node extends Individual { this.authorDocuments.add(authorDocument); } - 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 @@ -153,6 +153,4 @@ public class Node extends Individual { return null; } } - - } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineVOContainer.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineData.java similarity index 94% rename from src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineVOContainer.java rename to src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineData.java index f51a7347..884d3084 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineVOContainer.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineData.java @@ -2,7 +2,7 @@ package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; -public class SparklineVOContainer { +public class SparklineData { /* * For now sparklineNumPublicationsText & sparklinePublicationRangeText is left @@ -26,45 +26,58 @@ public class SparklineVOContainer { public String getSparklineNumPublicationsText() { return sparklineNumPublicationsText; } + public void setSparklineNumPublicationsText(String sparklineNumPublicationsText) { this.sparklineNumPublicationsText = sparklineNumPublicationsText; } + public String getSparklinePublicationRangeText() { return sparklinePublicationRangeText; } + public void setSparklinePublicationRangeText( String sparklinePublicationRangeText) { this.sparklinePublicationRangeText = sparklinePublicationRangeText; } + public Integer getEarliestRenderedPublicationYear() { return earliestRenderedPublicationYear; } + public void setEarliestRenderedPublicationYear( Integer earliestRenderedPublicationYear) { this.earliestRenderedPublicationYear = earliestRenderedPublicationYear; } + public Integer getLatestRenderedPublicationYear() { return latestRenderedPublicationYear; } + public void setLatestRenderedPublicationYear( Integer latestRenderedPublicationYear) { this.latestRenderedPublicationYear = latestRenderedPublicationYear; } + public String getTable() { return table; } + public void setTable(String table) { this.table = table; } + public String getDownloadDataLink() { return downloadDataLink; } + public void setDownloadDataLink(String downloadDataLink) { this.downloadDataLink = downloadDataLink; } + public String getFullTimelineNetworkLink() { return fullTimelineNetworkLink; } + public void setFullTimelineNetworkLink(String fullTimelineNetworkLink) { this.fullTimelineNetworkLink = fullTimelineNetworkLink; } @@ -72,6 +85,7 @@ public class SparklineVOContainer { public String getSparklineContent() { return sparklineContent; } + public void setSparklineContent(String shortSparklineContent) { this.sparklineContent = shortSparklineContent; } @@ -79,8 +93,8 @@ public class SparklineVOContainer { public String getSparklineContext() { return sparklineContext; } + public void setSparklineContext(String shortSparklineContext) { this.sparklineContext = shortSparklineContext; } - } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java index 71b20641..5b4dc8a6 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java @@ -7,16 +7,16 @@ import java.util.Set; /** * - * This is the Value Object equivalent for vivo:CollegeOrSchoolWithinUniversity object type. + * This is equivalent for vivo:CollegeOrSchoolWithinUniversity object type. + * * @author cdtank - * */ public class VivoCollegeOrSchool extends Individual { private Set departments = new HashSet(); - public VivoCollegeOrSchool(String collegeURL) { - super(collegeURL); + public VivoCollegeOrSchool(String collegeURI) { + super(collegeURI); } public Set getDepartments() { @@ -27,8 +27,8 @@ public class VivoCollegeOrSchool extends Individual { this.departments.add(department); } - public String getCollegeURL() { - return this.getIndividualURL(); + public String getCollegeURI() { + return this.getIndividualURI(); } public String getCollegeLabel() { diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java index 4e0f21cd..771df4ef 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java @@ -7,16 +7,16 @@ import java.util.Set; /** * - * This is the Value Object equivalent for vivo:AcademicDepartmentOrDivision object type. + * This is equivalent for vivo:AcademicDepartmentOrDivision object type. + * * @author cdtank - * */ public class VivoDepartmentOrDivision extends Individual { private Set parentColleges = new HashSet(); - public VivoDepartmentOrDivision(String departmentURL, VivoCollegeOrSchool parentCollege) { - super(departmentURL); + public VivoDepartmentOrDivision(String departmentURI, VivoCollegeOrSchool parentCollege) { + super(departmentURI); addParentCollege(parentCollege); } @@ -28,8 +28,8 @@ public class VivoDepartmentOrDivision extends Individual { this.parentColleges.add(parentCollege); } - public String getDepartmentURL() { - return this.getIndividualURL(); + public String getDepartmentURI() { + return this.getIndividualURI(); } public String getDepartmentLabel() { diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java index 7f9fa1a9..8d3f5623 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java @@ -9,9 +9,9 @@ import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants.Empl /** * - * This is the Value Object equivalent for vivo's Employee object type. + * This is the equivalent for vivo's Employee object type. + * * @author cdtank - * */ public class VivoEmployee extends Individual { @@ -27,8 +27,8 @@ public class VivoEmployee extends Individual { addParentDepartment(parentDepartment); } - public String getEmployeeURL() { - return this.getIndividualURL(); + public String getEmployeeURI() { + return this.getIndividualURI(); } public String getEmployeeName() { diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/AllPropertiesQueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/AllPropertiesQueryRunner.java similarity index 83% rename from src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/AllPropertiesQueryHandler.java rename to src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/AllPropertiesQueryRunner.java index f854429d..f7960b8c 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/AllPropertiesQueryHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/AllPropertiesQueryRunner.java @@ -26,25 +26,26 @@ import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.GenericQueryM /** - * Very dumb name of the class. change it. + * This query runner is used to execute a sparql query that will fetch all the + * properties available for the provided individual URI. + * * @author cdtank - * */ -public class AllPropertiesQueryHandler implements QueryHandler { +public class AllPropertiesQueryRunner implements QueryRunner { protected static final Syntax SYNTAX = Syntax.syntaxARQ; - private String filterRule, individualURLParam; + private String filterRule, individualURI; private DataSource dataSource; private Log log; - public AllPropertiesQueryHandler(String individualURLParam, + public AllPropertiesQueryRunner(String individualURI, String filterRule, DataSource dataSource, Log log) { - this.individualURLParam = individualURLParam; + this.individualURI = individualURI; this.filterRule = filterRule; this.dataSource = dataSource; this.log = log; @@ -53,7 +54,7 @@ public class AllPropertiesQueryHandler implements QueryHandler private GenericQueryMap createJavaValueObjects(ResultSet resultSet) { - GenericQueryMap queryResultVO = new GenericQueryMap(); + GenericQueryMap queryResult = new GenericQueryMap(); while (resultSet.hasNext()) { QuerySolution solution = resultSet.nextSolution(); @@ -63,16 +64,15 @@ public class AllPropertiesQueryHandler implements QueryHandler RDFNode objectNode = solution.get(QueryFieldLabels.OBJECT); if (predicateNode != null && objectNode != null) { - queryResultVO.addEntry(predicateNode.toString(), + queryResult.addEntry(predicateNode.toString(), objectNode.toString()); } } - return queryResultVO; + return queryResult; } - private ResultSet executeQuery(String queryText, DataSource dataSource) { @@ -118,16 +118,15 @@ public class AllPropertiesQueryHandler implements QueryHandler return sparqlQuery; } - - public GenericQueryMap getVisualizationJavaValueObjects() + public GenericQueryMap getQueryResult() throws MalformedQueryParametersException { - if (StringUtils.isNotBlank(this.individualURLParam)) { + if (StringUtils.isNotBlank(this.individualURI)) { /* * To test for the validity of the URI submitted. * */ IRIFactory iRIFactory = IRIFactory.jenaImplementation(); - IRI iri = iRIFactory.create(this.individualURLParam); + IRI iri = iRIFactory.create(this.individualURI); if (iri.hasViolation(false)) { String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage(); log.error("Generic Query " + errorMsg); @@ -140,12 +139,10 @@ public class AllPropertiesQueryHandler implements QueryHandler } ResultSet resultSet = executeQuery(generateGenericSparqlQuery( - this.individualURLParam, + this.individualURI, this.filterRule), this.dataSource); return createJavaValueObjects(resultSet); } - - } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/GenericQueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/GenericQueryRunner.java similarity index 90% rename from src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/GenericQueryHandler.java rename to src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/GenericQueryRunner.java index 6bf9204e..dd119aa0 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/GenericQueryHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/GenericQueryRunner.java @@ -24,10 +24,12 @@ import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryP /** + * This query runner is used to run a generic sparql query based on the "select", + * "where" & "filter" rules provided to it. + * * @author cdtank - * */ -public class GenericQueryHandler implements QueryHandler { +public class GenericQueryRunner implements QueryRunner { protected static final Syntax SYNTAX = Syntax.syntaxARQ; @@ -38,7 +40,7 @@ public class GenericQueryHandler implements QueryHandler { private Map fieldLabelToOutputFieldLabel; - public GenericQueryHandler(String individualURLParam, + public GenericQueryRunner(String individualURLParam, Map fieldLabelToOutputFieldLabel, String whereClause, DataSource dataSource, @@ -102,9 +104,8 @@ public class GenericQueryHandler implements QueryHandler { return sparqlQuery.toString(); } - - public ResultSet getVisualizationJavaValueObjects() + public ResultSet getQueryResult() throws MalformedQueryParametersException { if (StringUtils.isNotBlank(this.individualURLParam)) { /* @@ -127,6 +128,4 @@ public class GenericQueryHandler implements QueryHandler { return resultSet; } - - } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/QueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/QueryRunner.java similarity index 62% rename from src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/QueryHandler.java rename to src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/QueryRunner.java index ad03de2a..58a572ae 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/QueryHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/QueryRunner.java @@ -4,8 +4,8 @@ package edu.cornell.mannlib.vitro.webapp.visualization.visutils; import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; -public interface QueryHandler { +public interface QueryRunner { - QueryResponse getVisualizationJavaValueObjects() throws MalformedQueryParametersException; + QueryResult getQueryResult() throws MalformedQueryParametersException; } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UtilityFunctions.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UtilityFunctions.java index 995ff73b..f0147347 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UtilityFunctions.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UtilityFunctions.java @@ -2,14 +2,27 @@ package edu.cornell.mannlib.vitro.webapp.visualization.visutils; +import java.io.IOException; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; -import org.apache.commons.lang.StringUtils; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; + +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.visualization.constants.VisConstants; 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.Node; public class UtilityFunctions { @@ -31,8 +44,8 @@ public class UtilityFunctions { * I am pushing the logic to check for validity of year in "getPublicationYear" itself * because, * 1. We will be using getPub... multiple times & this will save us duplication of code - * 2. If we change the logic of validity of a pub year we would not have to make changes - * all throughout the codebase. + * 2. If we change the logic of validity of a pub year we would not have to make + * changes all throughout the codebase. * 3. We are asking for a publication year & we should get a proper one or NOT at all. * */ String publicationYear; @@ -56,6 +69,49 @@ public class UtilityFunctions { return yearToPublicationCount; } + /** + * This method is used to return a mapping between publication year & all the co-authors + * that published with ego in that year. + * @param authorNodesAndEdges + * @return + */ + public static Map> getPublicationYearToCoAuthors( + CoAuthorshipData 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; + } + /** * Currently the approach for slugifying filenames is naive. In future if there is need, * we can write more sophisticated method. @@ -70,5 +126,32 @@ public class UtilityFunctions { VisConstants.MAX_NAME_TEXT_LENGTH), textBlockSeparator); } + + + public static void handleMalformedParameters(String errorMessage, + String errorPageTitle, + VitroRequest vitroRequest, + HttpServletRequest request, + HttpServletResponse response, + Log log) + throws ServletException, IOException { + + Portal portal = vitroRequest.getPortal(); + + request.setAttribute("error", errorMessage); + + RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); + request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp"); + request.setAttribute("portalBean", portal); + request.setAttribute("title", errorPageTitle); + + try { + requestDispatcher.forward(request, response); + } catch (Exception e) { + log.error("EntityEditController could not forward to view."); + log.error(e.getMessage()); + log.error(e.getStackTrace()); + } + } } diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/VisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/VisualizationRequestHandler.java index 18ffd8db..ecfa6bbd 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/VisualizationRequestHandler.java +++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/VisualizationRequestHandler.java @@ -10,6 +10,16 @@ import com.hp.hpl.jena.query.DataSource; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +/** + * This interface is being implemented by all the visualization request handlers like + * PersonLevelRequestHandler, PersonPublicationCountRequestHandler, UtilitiesRequestHandler + * etc. All the future visualizations must implement this because the ability of + * a visualization to be served to the users is dependent on it. We have implemented + * dependency injection mechanism & one of the conditions that is used to enable a visualization + * handler is its implementation of VisualizationRequestHandler. + * + * @author cdtank + */ public interface VisualizationRequestHandler { void generateVisualization(VitroRequest vitroRequest,