1. Code cleanup & refactor.

2. More code documentation.
3. Minor change in wordings.
This commit is contained in:
cdtank 2010-08-03 23:04:44 +00:00
parent fc6da3a68f
commit 0846299deb
34 changed files with 1127 additions and 1173 deletions

View file

@ -2,34 +2,6 @@
package edu.cornell.mannlib.vitro.webapp.controller.visualization; 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.io.IOException;
import java.util.Map; 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.Model;
import com.hp.hpl.jena.rdf.model.ModelMaker; 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.vedit.controller.BaseEditController;
import edu.cornell.mannlib.vitro.webapp.beans.Portal; import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers; import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
@ -69,8 +40,6 @@ public class VisualizationController extends BaseEditController {
private Map<String, VisualizationRequestHandler> visualizationIDsToClass; private Map<String, VisualizationRequestHandler> visualizationIDsToClass;
private static final String VIS_TYPE_URL_HANDLE = "vis";
public static final String URL_ENCODING_SCHEME = "UTF-8"; public static final String URL_ENCODING_SCHEME = "UTF-8";
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -79,25 +48,11 @@ public class VisualizationController extends BaseEditController {
protected static final Syntax SYNTAX = Syntax.syntaxARQ; protected static final Syntax SYNTAX = Syntax.syntaxARQ;
//TODO: For later, might want to improve these names for clarity. /* This method is overridden to inject vis dependencies i.e. the vis algorithms that are
public static final String PERSON_PUBLICATION_COUNT_VIS_URL_VALUE * being implemented into the vis controller. Modified Dependency Injection pattern is
= "person_pub_count"; * used here. XML file containing the location of all the vis is saved in accessible folder.
* @see javax.servlet.GenericServlet#init()
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";
@Override @Override
public void init() throws ServletException { public void init() throws ServletException {
super.init(); super.init();
@ -135,36 +90,42 @@ public class VisualizationController extends BaseEditController {
throws ServletException, IOException { throws ServletException, IOException {
super.doGet(request, response); super.doGet(request, response);
VitroRequest vreq = handleLoginAuthentication(request, response); VitroRequest vitroRequest = new VitroRequest(request);
String visTypeURLHandle = vreq.getParameter(VIS_TYPE_URL_HANDLE);
VisualizationRequestHandler visRequestHandler = null; /*
try { * Based on the query parameters passed via URI get the appropriate visualization
visRequestHandler = visualizationIDsToClass.get(visTypeURLHandle); * request handler.
} catch (NullPointerException nullKey) { * */
VisualizationRequestHandler visRequestHandler =
/* getVisualizationRequestHandler(request, response, vitroRequest);
* 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);
}
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, response,
vreq); vitroRequest);
if (dataSource != null && visRequestHandler != null) { if (dataSource != null && visRequestHandler != null) {
/* visRequestHandler.generateVisualization(vitroRequest,
* This is side-effecting because the visualization content is added request,
* to the request object. response,
* */ log,
visRequestHandler.generateVisualization(vreq, request, response, log, dataSource); dataSource);
} else { } else {
@ -177,46 +138,31 @@ public class VisualizationController extends BaseEditController {
log.error(errorMessage); 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 is side-effecting because the error content is directly
// This might not be required * added to the request object. From where it is redirected to
/* * the error page.
* why are there multiple places where the login is checked? shud be abtracted into * */
* new methoid? handleMalformedParameters("Inappropriate query parameters were submitted. ",
* */ request,
// if( !checkLoginStatus(request, response) ) response);
// return null; }
return visRequestHandler;
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;
} }
private DataSource setupJENADataSource(HttpServletRequest request, private DataSource setupJENADataSource(HttpServletRequest request,

View file

@ -3,39 +3,67 @@
package edu.cornell.mannlib.vitro.webapp.controller.visualization; package edu.cornell.mannlib.vitro.webapp.controller.visualization;
public class VisualizationFrameworkConstants { public class VisualizationFrameworkConstants {
/* /*
* Contains the location of bean containing info on all the visualizations available * Contains the location of bean containing info on all the visualizations
* in that instance. Currently it is stored under "productMods/WEB-INF..." * available in that instance. Currently it is stored under
* */ * "productMods/WEB-INF..."
*/
public static final String RELATIVE_LOCATION_OF_VISUALIZATIONS_BEAN = 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 * Vis URL prefix that is seen by all the users
* */ */
public static final String VISUALIZATION_URL_PREFIX = "/visualization"; public static final String VISUALIZATION_URL_PREFIX = "/visualization";
public static final String INDIVIDUAL_URL_PREFIX = "/individual";
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"; * These represent possible query keys in a URI for visualization purposes.
public static final String VIS_MODE_URL_HANDLE = "vis_mode"; * Examples,
public static final String RENDER_MODE_URL_HANDLE = "render_mode"; * 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 STANDALONE_RENDER_MODE_URL_VALUE = "standalone"; * */
public static final String DYNAMIC_RENDER_MODE_URL_VALUE = "dynamic"; public static final String VIS_TYPE_KEY = "vis";
public static final String DATA_RENDER_MODE_URL_VALUE = "data"; public static final String VIS_CONTAINER_KEY = "container";
public static final String PDF_RENDER_MODE_URL_VALUE = "pdf"; public static final String INDIVIDUAL_URI_KEY = "uri";
public static final String IMAGE_VIS_MODE_URL_VALUE = "image"; public static final String VIS_MODE_KEY = "vis_mode";
public static final String SPARKLINE_VIS_MODE_URL_VALUE = "sparkline"; public static final String RENDER_MODE_KEY = "render_mode";
public static final String COAUTHORSLIST_VIS_MODE_URL_VALUE = "coauthors";
/*
* 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_INFO_UTILS_VIS_MODE = "PROFILE_INFO";
public static final String PROFILE_UTILS_VIS_MODE = "PROFILE_URL"; public static final String PROFILE_UTILS_VIS_MODE = "PROFILE_URL";
public static final String COAUTHOR_UTILS_VIS_MODE = "COAUTHORSHIP_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 PERSON_LEVEL_UTILS_VIS_MODE = "PERSON_LEVEL_URL";
public static final String IMAGE_UTILS_VIS_MODE = "IMAGE_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";
} }

View file

@ -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.VisualizationController;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.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.Edge;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
@ -28,7 +28,7 @@ public class CoAuthorshipGraphMLWriter {
private final String GRAPHML_FOOTER = "</graphml>"; private final String GRAPHML_FOOTER = "</graphml>";
public CoAuthorshipGraphMLWriter(CoAuthorshipVOContainer visVOContainer) { public CoAuthorshipGraphMLWriter(CoAuthorshipData visVOContainer) {
coAuthorshipGraphMLContent = createCoAuthorshipGraphMLContent(visVOContainer); coAuthorshipGraphMLContent = createCoAuthorshipGraphMLContent(visVOContainer);
@ -39,7 +39,7 @@ public class CoAuthorshipGraphMLWriter {
} }
private StringBuilder createCoAuthorshipGraphMLContent( private StringBuilder createCoAuthorshipGraphMLContent(
CoAuthorshipVOContainer visVOContainer) { CoAuthorshipData coAuthorshipData) {
StringBuilder graphMLContent = new StringBuilder(); StringBuilder graphMLContent = new StringBuilder();
@ -50,30 +50,30 @@ public class CoAuthorshipGraphMLWriter {
* another String object to hold key definition data will be redundant & will * another String object to hold key definition data will be redundant & will
* not serve the purpose. * not serve the purpose.
* */ * */
generateKeyDefinitionContent(visVOContainer, graphMLContent); generateKeyDefinitionContent(coAuthorshipData, graphMLContent);
/* /*
* Used to generate graph content. It will contain both the nodes & edge information. * Used to generate graph content. It will contain both the nodes & edge information.
* We are side-effecting "graphMLContent". * We are side-effecting "graphMLContent".
* */ * */
generateGraphContent(visVOContainer, graphMLContent); generateGraphContent(coAuthorshipData, graphMLContent);
graphMLContent.append(GRAPHML_FOOTER); graphMLContent.append(GRAPHML_FOOTER);
return graphMLContent; return graphMLContent;
} }
private void generateGraphContent(CoAuthorshipVOContainer visVOContainer, private void generateGraphContent(CoAuthorshipData coAuthorshipData,
StringBuilder graphMLContent) { StringBuilder graphMLContent) {
graphMLContent.append("\n<graph edgedefault=\"undirected\">\n"); graphMLContent.append("\n<graph edgedefault=\"undirected\">\n");
if (visVOContainer.getNodes() != null & visVOContainer.getNodes().size() > 0) { if (coAuthorshipData.getNodes() != null & coAuthorshipData.getNodes().size() > 0) {
generateNodeSectionContent(visVOContainer, graphMLContent); generateNodeSectionContent(coAuthorshipData, graphMLContent);
} }
if (visVOContainer.getEdges() != null & visVOContainer.getEdges().size() > 0) { if (coAuthorshipData.getEdges() != null & coAuthorshipData.getEdges().size() > 0) {
generateEdgeSectionContent(visVOContainer, graphMLContent); generateEdgeSectionContent(coAuthorshipData, graphMLContent);
} }
graphMLContent.append("</graph>\n"); graphMLContent.append("</graph>\n");
@ -83,12 +83,12 @@ public class CoAuthorshipGraphMLWriter {
} }
private void generateEdgeSectionContent(CoAuthorshipVOContainer visVOContainer, private void generateEdgeSectionContent(CoAuthorshipData coAuthorshipData,
StringBuilder graphMLContent) { StringBuilder graphMLContent) {
graphMLContent.append("<!-- edges -->\n"); graphMLContent.append("<!-- edges -->\n");
Set<Edge> edges = visVOContainer.getEdges(); Set<Edge> edges = coAuthorshipData.getEdges();
List<Edge> orderedEdges = new ArrayList<Edge>(edges); List<Edge> orderedEdges = new ArrayList<Edge>(edges);
@ -108,11 +108,6 @@ public class CoAuthorshipGraphMLWriter {
private void getEdgeContent(StringBuilder graphMLContent, Edge currentEdge) { 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("<edge " graphMLContent.append("<edge "
+ "id=\"" + currentEdge.getEdgeID() + "\" " + "id=\"" + currentEdge.getEdgeID() + "\" "
+ "source=\"" + currentEdge.getSourceNode().getNodeID() + "\" " + "source=\"" + currentEdge.getSourceNode().getNodeID() + "\" "
@ -136,7 +131,6 @@ public class CoAuthorshipGraphMLWriter {
/* /*
* There is no clean way of getting the map contents in java even though * There is no clean way of getting the map contents in java even though
* we are sure to have only one entry on the map. So using the for loop. * we are sure to have only one entry on the map. So using the for loop.
* I am feeling dirty just about now.
* */ * */
for (Map.Entry<String, Integer> publicationInfo for (Map.Entry<String, Integer> publicationInfo
: currentEdge.getEarliestCollaborationYearCount().entrySet()) { : currentEdge.getEarliestCollaborationYearCount().entrySet()) {
@ -148,8 +142,6 @@ public class CoAuthorshipGraphMLWriter {
graphMLContent.append("\t<data key=\"num_earliest_collaboration\">" graphMLContent.append("\t<data key=\"num_earliest_collaboration\">"
+ publicationInfo.getValue() + publicationInfo.getValue()
+ "</data>\n"); + "</data>\n");
} }
} }
@ -179,17 +171,15 @@ public class CoAuthorshipGraphMLWriter {
} }
graphMLContent.append("</edge>\n"); graphMLContent.append("</edge>\n");
} }
private void generateNodeSectionContent(CoAuthorshipVOContainer visVOContainer, private void generateNodeSectionContent(CoAuthorshipData coAuthorshipData,
StringBuilder graphMLContent) { StringBuilder graphMLContent) {
graphMLContent.append("<!-- nodes -->\n"); graphMLContent.append("<!-- nodes -->\n");
Node egoNode = visVOContainer.getEgoNode(); Node egoNode = coAuthorshipData.getEgoNode();
Set<Node> authorNodes = visVOContainer.getNodes(); Set<Node> authorNodes = coAuthorshipData.getNodes();
/* /*
* This method actually creates the XML code for a single node. "graphMLContent" * This method actually creates the XML code for a single node. "graphMLContent"
@ -224,21 +214,17 @@ public class CoAuthorshipGraphMLWriter {
String profileURL = null; String profileURL = null;
try { try {
profileURL = "/individual?" profileURL = VisualizationFrameworkConstants.INDIVIDUAL_URL_PREFIX + "?"
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
+ "=" + URLEncoder.encode(node.getNodeURL(), + "=" + URLEncoder.encode(node.getNodeURI(),
VisualizationController VisualizationController
.URL_ENCODING_SCHEME).toString(); .URL_ENCODING_SCHEME).toString();
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
System.err.println("URL Encoding ERRor. Move this to use log.error ASAP"); System.err.println("URL Encoding ERRor. Move this to use log.error ASAP");
} }
// System.out.print("NODE_ID:" + node.getNodeID() + "|");
graphMLContent.append("<node id=\"" + node.getNodeID() + "\">\n"); graphMLContent.append("<node id=\"" + node.getNodeID() + "\">\n");
graphMLContent.append("\t<data key=\"url\">" + node.getNodeURL() + "</data>\n"); graphMLContent.append("\t<data key=\"url\">" + node.getNodeURI() + "</data>\n");
// graphMLContent.append("\t<data key=\"name\">" + node.getNodeName() + "</data>\n");
// System.out.println("NODE_NAME:" + node.getNodeURL());
graphMLContent.append("\t<data key=\"label\">" + node.getNodeName() + "</data>\n"); graphMLContent.append("\t<data key=\"label\">" + node.getNodeName() + "</data>\n");
if (profileURL != null) { if (profileURL != null) {
@ -267,8 +253,6 @@ public class CoAuthorshipGraphMLWriter {
graphMLContent.append("\t<data key=\"num_earliest_publication\">" graphMLContent.append("\t<data key=\"num_earliest_publication\">"
+ publicationInfo.getValue() + publicationInfo.getValue()
+ "</data>\n"); + "</data>\n");
} }
} }
@ -285,8 +269,6 @@ public class CoAuthorshipGraphMLWriter {
graphMLContent.append("\t<data key=\"num_latest_publication\">" graphMLContent.append("\t<data key=\"num_latest_publication\">"
+ publicationInfo.getValue() + publicationInfo.getValue()
+ "</data>\n"); + "</data>\n");
} }
} }
@ -302,7 +284,7 @@ public class CoAuthorshipGraphMLWriter {
graphMLContent.append("</node>\n"); graphMLContent.append("</node>\n");
} }
private void generateKeyDefinitionContent(CoAuthorshipVOContainer visVOContainer, private void generateKeyDefinitionContent(CoAuthorshipData visVOContainer,
StringBuilder graphMLContent) { StringBuilder graphMLContent) {
/* /*
@ -345,8 +327,6 @@ public class CoAuthorshipGraphMLWriter {
} else { } else {
graphMLContent.append("/>\n"); graphMLContent.append("/>\n");
} }
} }
} }
} }

View file

@ -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.constants.QueryFieldLabels;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.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.Edge;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoCollegeOrSchool; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.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; 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 * @author cdtank
*/ */
public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOContainer> { public class CoAuthorshipQueryRunner implements QueryRunner<CoAuthorshipData> {
private static final int MAX_AUTHORS_PER_PAPER_ALLOWED = 100; private static final int MAX_AUTHORS_PER_PAPER_ALLOWED = 100;
protected static final Syntax SYNTAX = Syntax.syntaxARQ; protected static final Syntax SYNTAX = Syntax.syntaxARQ;
private String egoURLParam; private String egoURI;
private Map<String, VivoCollegeOrSchool> collegeURLToVO = private Map<String, VivoCollegeOrSchool> collegeURLToVO =
new HashMap<String, VivoCollegeOrSchool>(); new HashMap<String, VivoCollegeOrSchool>();
@ -60,10 +62,10 @@ public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOCont
private UniqueIDGenerator edgeIDGenerator; private UniqueIDGenerator edgeIDGenerator;
public CoAuthorshipQueryHandler(String egoURLParam, public CoAuthorshipQueryRunner(String egoURI,
DataSource dataSource, Log log) { DataSource dataSource, Log log) {
this.egoURLParam = egoURLParam; this.egoURI = egoURI;
this.dataSource = dataSource; this.dataSource = dataSource;
this.log = log; this.log = log;
@ -72,7 +74,7 @@ public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOCont
} }
private CoAuthorshipVOContainer createJavaValueObjects(ResultSet resultSet) { private CoAuthorshipData createQueryResult(ResultSet resultSet) {
Set<Node> nodes = new HashSet<Node>(); Set<Node> nodes = new HashSet<Node>();
@ -149,11 +151,6 @@ public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOCont
} }
} }
/*
System.out.print("PERSON_URL:" + egoAuthorURLNode.toString() + "|");
System.out.print("DOCUMENT_URL:" + documentNode.toString() + "|");
System.out.println("CO_AUTHOR_URL:" + coAuthorURLNode.toString());
*/
coAuthorNode.addAuthorDocument(biboDocument); coAuthorNode.addAuthorDocument(biboDocument);
Set<Node> coAuthorsForCurrentBiboDocument; Set<Node> coAuthorsForCurrentBiboDocument;
@ -190,11 +187,49 @@ public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOCont
} }
/* /*
* This code snippet takes out all the edges belong to documents that have more than * This method takes out all the authors & edges between authors that belong to documents
* 100 authors. We conjecture that these papers do not provide much insight. However, * that have more than 100 authors. We conjecture that these papers do not provide much
* we have left the documents be, just the edges are removed. * insight. However, we have left the documents be.
*
* This method side-effects "nodes" & "edges".
* */ * */
removeLowQualityNodesAndEdges(nodes,
biboDocumentURLToVO,
biboDocumentURLToCoAuthors,
edges);
/*
* We need to create edges between 2 co-authors. E.g. On a paper there were 3 authors
* ego, A & B then we have already created edges like,
* ego - A
* ego - B
* The below sub-routine will take care of,
* A - B
*
* We are side-effecting "edges" here. The only reason to do this is because we are adding
* edges en masse for all the co-authors on all the publications considered so far. The
* other reason being we dont want to compare against 2 sets of edges (edges created before
* & co-author edges created during the course of this method) when we are creating a new
* edge.
* */
createCoAuthorEdges(biboDocumentURLToVO,
biboDocumentURLToCoAuthors,
edges,
edgeUniqueIdentifierToVO);
return new CoAuthorshipData(egoNode, nodes, edges);
}
private void removeLowQualityNodesAndEdges(Set<Node> nodes,
Map<String, BiboDocument> biboDocumentURLToVO,
Map<String, Set<Node>> biboDocumentURLToCoAuthors,
Set<Edge> edges) {
Set<Node> nodesToBeRemoved = new HashSet<Node>();
for (Map.Entry<String, Set<Node>> currentBiboDocumentEntry for (Map.Entry<String, Set<Node>> currentBiboDocumentEntry
: biboDocumentURLToCoAuthors.entrySet()) { : biboDocumentURLToCoAuthors.entrySet()) {
@ -218,31 +253,16 @@ public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOCont
} }
edges.removeAll(edgesToBeRemoved); edges.removeAll(edgesToBeRemoved);
for (Node currentCoAuthor : currentBiboDocumentEntry.getValue()) {
currentCoAuthor.getAuthorDocuments().remove(currentBiboDocument);
if (currentCoAuthor.getAuthorDocuments().isEmpty()) {
nodesToBeRemoved.add(currentCoAuthor);
}
}
} }
} }
nodes.removeAll(nodesToBeRemoved);
/*
* We need to create edges between 2 co-authors. E.g. On a paper there were 3 authors
* ego, A & B then we have already created edges like,
* ego - A
* ego - B
* The below sub-routine will take care of,
* A - B
*
* We are side-effecting "edges" here. The only reason to do this is because we are adding
* edges en masse for all the co-authors on all the publications considered so far. The
* other reason being we dont want to compare against 2 sets of edges (edges created before
* & co-author edges created during the course of this method) when we are creating a new
* edge.
* */
createCoAuthorEdges(biboDocumentURLToVO,
biboDocumentURLToCoAuthors,
edges,
edgeUniqueIdentifierToVO);
return new CoAuthorshipVOContainer(egoNode, nodes, edges);
} }
private void createCoAuthorEdges( private void createCoAuthorEdges(
@ -252,6 +272,7 @@ public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOCont
for (Map.Entry<String, Set<Node>> currentBiboDocumentEntry for (Map.Entry<String, Set<Node>> currentBiboDocumentEntry
: biboDocumentURLToCoAuthors.entrySet()) { : biboDocumentURLToCoAuthors.entrySet()) {
/* /*
* If there was only one co-author (other than ego) then we dont have to create any * 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. * edges. so the below condition will take care of that.
@ -312,9 +333,9 @@ public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOCont
} }
private Edge getExistingEdge( private Edge getExistingEdge(
Node collaboratingNode1, Node collaboratingNode1,
Node collaboratingNode2, Node collaboratingNode2,
Map<String, Edge> edgeUniqueIdentifierToVO) { Map<String, Edge> edgeUniqueIdentifierToVO) {
String edgeUniqueIdentifier = getEdgeUniqueIdentifier(collaboratingNode1.getNodeID(), String edgeUniqueIdentifier = getEdgeUniqueIdentifier(collaboratingNode1.getNodeID(),
collaboratingNode2.getNodeID()); collaboratingNode2.getNodeID());
@ -438,25 +459,21 @@ public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOCont
+ "} " + "} "
+ "ORDER BY ?document ?coAuthorPerson"; + "ORDER BY ?document ?coAuthorPerson";
System.out.println("COAUTHORSHIP QUERY - " + sparqlQuery); // System.out.println("COAUTHORSHIP QUERY - " + sparqlQuery);
return sparqlQuery; return sparqlQuery;
} }
public CoAuthorshipVOContainer getVisualizationJavaValueObjects() public CoAuthorshipData getQueryResult()
throws MalformedQueryParametersException { throws MalformedQueryParametersException {
/*
System.out.println("***************************************************************************************"); if (StringUtils.isNotBlank(this.egoURI)) {
System.out.println("Entered into coauthorship query handler at " + System.currentTimeMillis());
System.out.println("***************************************************************************************");
*/
if (StringUtils.isNotBlank(this.egoURLParam)) {
/* /*
* To test for the validity of the URI submitted. * To test for the validity of the URI submitted.
* */ * */
IRIFactory iRIFactory = IRIFactory.jenaImplementation(); IRIFactory iRIFactory = IRIFactory.jenaImplementation();
IRI iri = iRIFactory.create(this.egoURLParam); IRI iri = iRIFactory.create(this.egoURI);
if (iri.hasViolation(false)) { if (iri.hasViolation(false)) {
String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage(); String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage();
log.error("Ego Co-Authorship Vis Query " + errorMsg); log.error("Ego Co-Authorship Vis Query " + errorMsg);
@ -467,13 +484,9 @@ public class CoAuthorshipQueryHandler implements QueryHandler<CoAuthorshipVOCont
throw new MalformedQueryParametersException("URI parameter is either null or empty."); throw new MalformedQueryParametersException("URI parameter is either null or empty.");
} }
ResultSet resultSet = executeQuery(generateEgoCoAuthorshipSparqlQuery(this.egoURLParam), ResultSet resultSet = executeQuery(generateEgoCoAuthorshipSparqlQuery(this.egoURI),
this.dataSource); this.dataSource);
/* return createQueryResult(resultSet);
System.out.println("***************************************************************************************");
System.out.println("***************************************************************************************");
*/
return createJavaValueObjects(resultSet);
} }
} }

View file

@ -4,13 +4,11 @@ package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -20,17 +18,24 @@ import org.apache.commons.logging.Log;
import com.hp.hpl.jena.query.DataSource; import com.hp.hpl.jena.query.DataSource;
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.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.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.Node;
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.UtilityFunctions; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler;
/**
* This request handler is used when information related to co-authorship network
* for an individual is requested. It currently provides 2 outputs,
* 1. Graphml content representing the individual's co-authorship network
* 1. CSV file containing the list(& count) of unique co-authors with which
* the individual has worked over the years. This data powers the related sparkline.
*
* @author cdtank
*/
public class CoAuthorshipRequestHandler implements VisualizationRequestHandler { public class CoAuthorshipRequestHandler implements VisualizationRequestHandler {
public void generateVisualization(VitroRequest vitroRequest, public void generateVisualization(VitroRequest vitroRequest,
@ -39,51 +44,41 @@ public class CoAuthorshipRequestHandler implements VisualizationRequestHandler {
Log log, Log log,
DataSource dataSource) { DataSource dataSource) {
String egoURIParam = vitroRequest.getParameter( String egoURI = vitroRequest.getParameter(
VisualizationFrameworkConstants VisualizationFrameworkConstants
.INDIVIDUAL_URI_URL_HANDLE); .INDIVIDUAL_URI_KEY);
String renderMode = vitroRequest.getParameter( String renderMode = vitroRequest.getParameter(
VisualizationFrameworkConstants VisualizationFrameworkConstants
.RENDER_MODE_URL_HANDLE); .RENDER_MODE_KEY);
String visMode = vitroRequest.getParameter( String visMode = vitroRequest.getParameter(
VisualizationFrameworkConstants VisualizationFrameworkConstants
.VIS_MODE_URL_HANDLE); .VIS_MODE_KEY);
QueryHandler<CoAuthorshipVOContainer> queryManager =
new CoAuthorshipQueryHandler(egoURIParam,
dataSource,
log);
QueryRunner<CoAuthorshipData> queryManager =
new CoAuthorshipQueryRunner(egoURI, dataSource, log);
try { 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)) { .equalsIgnoreCase(renderMode)) {
/* /*
* We will be using the same visualization package for both sparkline & coauthorship * 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 * flash vis. We will use "VIS_MODE_KEY" as a modifier to differentiate
* between these two. The defualt will be to render the coauthorship network vis. * between these two. The default will be to render the coauthorship network vis.
* */ * */
if (VisualizationFrameworkConstants.SPARKLINE_VIS_MODE
if (VisualizationFrameworkConstants.SPARKLINE_VIS_MODE_URL_VALUE
.equalsIgnoreCase(visMode)) { .equalsIgnoreCase(visMode)) {
/* /*
* When the csv file is required - based on which sparkline visualization will * When the csv file is required - based on which sparkline visualization will
* be rendered. * be rendered.
* */ * */
prepareVisualizationQuerySparklineDataResponse(authorNodesAndEdges, prepareSparklineDataResponse(authorNodesAndEdges,
response); response);
return; return;
@ -92,14 +87,20 @@ public class CoAuthorshipRequestHandler implements VisualizationRequestHandler {
* When the graphML file is required - based on which coauthorship network * When the graphML file is required - based on which coauthorship network
* visualization will be rendered. * visualization will be rendered.
* */ * */
prepareVisualizationQueryNetworkDataResponse(authorNodesAndEdges, response); prepareNetworkDataResponse(authorNodesAndEdges, response);
return; return;
} }
} }
} catch (MalformedQueryParametersException e) { } catch (MalformedQueryParametersException e) {
try { 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) { } catch (ServletException e1) {
log.error(e1.getStackTrace()); log.error(e1.getStackTrace());
} catch (IOException e1) { } catch (IOException e1) {
@ -110,9 +111,90 @@ public class CoAuthorshipRequestHandler implements VisualizationRequestHandler {
} }
private void prepareVisualizationQueryNetworkDataResponse( private void writeCoauthorsPerYearCSV(Map<String, Set<Node>> yearToCoauthors,
CoAuthorshipVOContainer authorNodesAndEdges, HttpServletResponse response) { PrintWriter printWriter) {
// printWriter.append("\"Year\", \"Count\", \"Co-Author(s)\"\n");
printWriter.append("Year, Count, Co-Author(s)\n");
for (Entry<String, Set<Node>> currentEntry : yearToCoauthors.entrySet()) {
printWriter.append("\"" + currentEntry.getKey() + "\","
+ "\"" + currentEntry.getValue().size() + "\","
+ "\"" + getCoauthorNamesAsString(currentEntry.getValue())
+ "\"\n");
}
printWriter.flush();
}
private String getCoauthorNamesAsString(Set<Node> 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<String, Set<Node>> yearToCoauthors = new TreeMap<String, Set<Node>>();
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"); response.setContentType("text/xml");
try { try {
@ -135,138 +217,4 @@ public class CoAuthorshipRequestHandler implements VisualizationRequestHandler {
} }
} }
private void prepareVisualizationQuerySparklineDataResponse(
CoAuthorshipVOContainer authorNodesAndEdges, HttpServletResponse response) {
String outputFileName;
Map<String, Set<Node>> yearToCoauthors = new TreeMap<String, Set<Node>>();
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<String, Set<Node>> yearToCoauthors,
PrintWriter printWriter) {
printWriter.append("\"Year\", \"Number of Co-Authors\", \"Co-Author(s)\"\n");
for (Entry<String, Set<Node>> currentEntry : yearToCoauthors.entrySet()) {
printWriter.append("\"" + currentEntry.getKey() + "\","
+ "\"" + currentEntry.getValue().size() + "\","
+ "\"" + getCoauthorsString(currentEntry.getValue()) + "\"\n"
);
}
printWriter.flush();
}
private String getCoauthorsString(Set<Node> coAuthors) {
StringBuilder coAuthorsMerged = new StringBuilder();
String coAuthorSeparator = "; ";
for (Node currCoAuthor : coAuthors) {
coAuthorsMerged.append(currCoAuthor.getNodeName() + coAuthorSeparator);
}
return StringUtils.removeEnd(coAuthorsMerged.toString(), coAuthorSeparator);
}
private Map<String, Set<Node>> getCoAuthorsStats(CoAuthorshipVOContainer authorNodesAndEdges) {
Map<String, Set<Node>> yearToCoAuthors = new TreeMap<String, Set<Node>>();
Node egoNode = authorNodesAndEdges.getEgoNode();
for (Node currNode : authorNodesAndEdges.getNodes()) {
/*
* We have already printed the Ego Node info.
* */
if (currNode != egoNode) {
for (String year : currNode.getYearToPublicationCount().keySet()) {
Set<Node> coAuthorNodes;
if (yearToCoAuthors.containsKey(year)) {
coAuthorNodes = yearToCoAuthors.get(year);
coAuthorNodes.add(currNode);
} else {
coAuthorNodes = new HashSet<Node>();
coAuthorNodes.add(currNode);
yearToCoAuthors.put(year, coAuthorNodes);
}
}
}
}
return yearToCoAuthors;
}
private void 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());
}
}
} }

View file

@ -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.VisualizationController;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants; 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.Node;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
@SuppressWarnings("serial")
public class CoAuthorshipVisCodeGenerator { 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<String, String> VIS_DIV_NAMES = new HashMap<String, String>() { { private static final Map<String, String> VIS_DIV_NAMES = new HashMap<String, String>() { {
put("SHORT_SPARK", "unique_coauthors_short_sparkline_vis"); 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"; 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<String, Set<Node>> yearToUniqueCoauthors; private Map<String, Set<Node>> yearToUniqueCoauthors;
private Log log; private Log log;
private SparklineVOContainer valueObjectContainer; private SparklineData sparklineData;
private String contextPath; private String contextPath;
private String individualURIParam; private String individualURI;
public CoAuthorshipVisCodeGenerator(String contextPath, public CoAuthorshipVisCodeGenerator(String contextPath,
String individualURIParam, String individualURI,
String visMode, String visMode,
String visContainer, String visContainer,
Map<String, Set<Node>> yearToUniqueCoauthors, Map<String, Set<Node>> yearToUniqueCoauthors,
SparklineVOContainer valueObjectContainer,
Log log) { Log log) {
this.contextPath = contextPath; this.contextPath = contextPath;
this.individualURIParam = individualURIParam; this.individualURI = individualURI;
this.yearToUniqueCoauthors = yearToUniqueCoauthors; this.yearToUniqueCoauthors = yearToUniqueCoauthors;
this.valueObjectContainer = valueObjectContainer; this.sparklineData = new SparklineData();
this.log = log; this.log = log;
generateVisualizationCode(visMode, visContainer); 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, private void generateVisualizationCode(String visMode,
String visContainer) { String visContainer) {
valueObjectContainer.setSparklineContent(getMainVisualizationCode(visMode, sparklineData.setSparklineContent(getMainVisualizationCode(visMode,
visContainer)); visContainer));
sparklineData.setSparklineContext(getVisualizationContextCode(visMode));
valueObjectContainer.setSparklineContext(getVisualizationContextCode(visMode));
} }
@ -86,13 +100,15 @@ public class CoAuthorshipVisCodeGenerator {
int numOfYearsToBeRendered = 0; int numOfYearsToBeRendered = 0;
int currentYear = Calendar.getInstance().get(Calendar.YEAR); 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 * 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". * was rendered we dont want to be influenced by the "DEFAULT_PUBLICATION_YEAR".
* */ * */
Set<String> publishedYears = new HashSet(yearToUniqueCoauthors.keySet()); Set<String> publishedYears = new HashSet<String>(yearToUniqueCoauthors.keySet());
publishedYears.remove(VOConstants.DEFAULT_PUBLICATION_YEAR); publishedYears.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
/* /*
@ -159,7 +175,6 @@ public class CoAuthorshipVisCodeGenerator {
+ "data.addRows(" + numOfYearsToBeRendered + ");\n"); + "data.addRows(" + numOfYearsToBeRendered + ");\n");
int uniqueCoAuthorCounter = 0; int uniqueCoAuthorCounter = 0;
int totalUniqueCoAuthors = 0;
int renderedFullSparks = 0; int renderedFullSparks = 0;
Set<Node> allCoAuthorsWithKnownAuthorshipYears = new HashSet<Node>(); Set<Node> allCoAuthorsWithKnownAuthorshipYears = new HashSet<Node>();
@ -167,8 +182,8 @@ public class CoAuthorshipVisCodeGenerator {
publicationYear <= currentYear; publicationYear <= currentYear;
publicationYear++) { publicationYear++) {
String stringPublishedYear = String.valueOf(publicationYear); String publicationYearAsString = String.valueOf(publicationYear);
Set<Node> currentCoAuthors = yearToUniqueCoauthors.get(stringPublishedYear); Set<Node> currentCoAuthors = yearToUniqueCoauthors.get(publicationYearAsString);
Integer currentUniqueCoAuthors = null; Integer currentUniqueCoAuthors = null;
@ -182,7 +197,7 @@ public class CoAuthorshipVisCodeGenerator {
visualizationCode.append("data.setValue(" visualizationCode.append("data.setValue("
+ uniqueCoAuthorCounter + uniqueCoAuthorCounter
+ ", 0, '" + ", 0, '"
+ stringPublishedYear + publicationYearAsString
+ "');\n"); + "');\n");
visualizationCode.append("data.setValue(" visualizationCode.append("data.setValue("
@ -193,22 +208,20 @@ public class CoAuthorshipVisCodeGenerator {
uniqueCoAuthorCounter++; 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. * associated with it. Hence.
* */ * */
renderedFullSparks = totalUniqueCoAuthors; renderedFullSparks = allCoAuthorsWithKnownAuthorshipYears.size();
/* /*
* Total publications will also consider publications that have no year associated with * Total publications will also consider publications that have no year associated with
* it. Hence. * them. Hence.
* */ * */
Integer unknownYearCoauthors = 0; Integer unknownYearCoauthors = 0;
if (yearToUniqueCoauthors.get(VOConstants.DEFAULT_PUBLICATION_YEAR) != null) { if (yearToUniqueCoauthors.get(VOConstants.DEFAULT_PUBLICATION_YEAR) != null) {
totalUniqueCoAuthors += yearToUniqueCoauthors
.get(VOConstants.DEFAULT_PUBLICATION_YEAR).size();
unknownYearCoauthors = yearToUniqueCoauthors unknownYearCoauthors = yearToUniqueCoauthors
.get(VOConstants.DEFAULT_PUBLICATION_YEAR).size(); .get(VOConstants.DEFAULT_PUBLICATION_YEAR).size();
} }
@ -228,12 +241,12 @@ public class CoAuthorshipVisCodeGenerator {
* "short" sparkline mode we will set the Earliest RenderedPublication year to * "short" sparkline mode we will set the Earliest RenderedPublication year to
* "currentYear - 10". * "currentYear - 10".
* */ * */
valueObjectContainer.setEarliestRenderedPublicationYear(minPublishedYear); sparklineData.setEarliestRenderedPublicationYear(minPublishedYear);
valueObjectContainer.setLatestRenderedPublicationYear(currentYear); sparklineData.setLatestRenderedPublicationYear(currentYear);
/* /*
* The Full Sparkline will be rendered by default. Only if the url has specific mention of * 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 * essentially a side-effecting process, we have both the activators method as
* side-effecting. They both side-effect "visualizationCode" * 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, generateShortSparklineVisualizationContent(currentYear,
shortSparkMinYear, shortSparkMinYear,
visContainerID, visContainerID,
visualizationCode, visualizationCode,
unknownYearCoauthors, unknownYearCoauthors,
totalUniqueCoAuthors,
sparklineDisplayOptions); sparklineDisplayOptions);
} else { } else {
generateFullSparklineVisualizationContent(currentYear, generateFullSparklineVisualizationContent(currentYear,
@ -268,9 +280,11 @@ public class CoAuthorshipVisCodeGenerator {
} }
private void generateShortSparklineVisualizationContent(int currentYear, private void generateShortSparklineVisualizationContent(int currentYear,
int shortSparkMinYear, String visContainerID, int shortSparkMinYear,
StringBuilder visualizationCode, int unknownYearCoauthors, String visContainerID,
int totalUniqueCoAuthors, String sparklineDisplayOptions) { StringBuilder visualizationCode,
int unknownYearCoauthors,
String sparklineDisplayOptions) {
/* /*
* Create a view of the data containing only the column pertaining to publication count. * Create a view of the data containing only the column pertaining to publication count.
@ -345,27 +359,22 @@ public class CoAuthorshipVisCodeGenerator {
} }
private void generateFullSparklineVisualizationContent( private void generateFullSparklineVisualizationContent(int currentYear,
int currentYear, int minPubYearConsidered,
int minPubYearConsidered, String visContainerID,
String visContainerID, StringBuilder visualizationCode,
StringBuilder visualizationCode, int unknownYearCoauthors,
int unknownYearCoauthors, int renderedFullSparks,
int renderedFullSparks, String sparklineDisplayOptions) {
String sparklineDisplayOptions) {
String csvDownloadURLHref = ""; String csvDownloadURLHref = "";
try { try {
if (getCSVDownloadURL() != null) { if (getCSVDownloadURL() != null) {
csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL() csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL()
+ "\" class=\"inline_href\">(.CSV File)</a>"; + "\" class=\"inline_href\">(.CSV File)</a>";
} else { } else {
csvDownloadURLHref = ""; csvDownloadURLHref = "";
} }
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
@ -454,7 +463,7 @@ public class CoAuthorshipVisCodeGenerator {
private String getVisualizationContextCode(String visMode) { private String getVisualizationContextCode(String visMode) {
String visualizationContextCode = ""; String visualizationContextCode = "";
if (SHORT_SPARKLINE_MODE_URL_HANDLE.equalsIgnoreCase(visMode)) { if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE.equalsIgnoreCase(visMode)) {
visualizationContextCode = generateShortVisContext(); visualizationContextCode = generateShortVisContext();
} else { } else {
visualizationContextCode = generateFullVisContext(); visualizationContextCode = generateFullVisContext();
@ -478,12 +487,10 @@ public class CoAuthorshipVisCodeGenerator {
csvDownloadURLHref = "Download data as <a href='" csvDownloadURLHref = "Download data as <a href='"
+ getCSVDownloadURL() + "'>.csv</a> file.<br />"; + getCSVDownloadURL() + "'>.csv</a> file.<br />";
valueObjectContainer.setDownloadDataLink(getCSVDownloadURL()); sparklineData.setDownloadDataLink(getCSVDownloadURL());
} else { } else {
csvDownloadURLHref = ""; csvDownloadURLHref = "";
} }
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
@ -496,16 +503,14 @@ public class CoAuthorshipVisCodeGenerator {
String tableCode = generateDataTable(); String tableCode = generateDataTable();
divContextCode.append("<p>" + tableCode divContextCode.append("<p>" + tableCode + csvDownloadURLHref + "</p>");
+ csvDownloadURLHref + "</p>");
valueObjectContainer.setTable(tableCode); sparklineData.setTable(tableCode);
return divContextCode.toString(); return divContextCode.toString();
} }
private String getCSVDownloadURL() private String getCSVDownloadURL() throws UnsupportedEncodingException {
throws UnsupportedEncodingException {
if (yearToUniqueCoauthors.size() > 0) { if (yearToUniqueCoauthors.size() > 0) {
@ -517,25 +522,24 @@ public class CoAuthorshipVisCodeGenerator {
String downloadURL = contextPath String downloadURL = contextPath
+ secondaryContextPath + secondaryContextPath
+ "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE + "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
+ "=" + URLEncoder.encode(individualURIParam, + "=" + URLEncoder.encode(individualURI,
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + "&" + VisualizationFrameworkConstants.VIS_TYPE_KEY
+ "=" + URLEncoder.encode(VisualizationController + "=" + URLEncoder.encode(VisualizationFrameworkConstants
.COAUTHORSHIP_VIS_URL_VALUE, .COAUTHORSHIP_VIS,
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE + "&" + VisualizationFrameworkConstants.VIS_MODE_KEY
+ "=" + URLEncoder.encode("sparkline", + "=" + URLEncoder.encode("sparkline",
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + "&" + VisualizationFrameworkConstants.RENDER_MODE_KEY
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE, + "=" + URLEncoder.encode(VisualizationFrameworkConstants.DATA_RENDER_MODE,
VisualizationController.URL_ENCODING_SCHEME).toString(); VisualizationController.URL_ENCODING_SCHEME).toString();
return downloadURL; return downloadURL;
} else { } else {
return null; return null;
} }
} }
private String generateShortVisContext() { private String generateShortVisContext() {
@ -555,33 +559,31 @@ public class CoAuthorshipVisCodeGenerator {
String fullTimelineNetworkURL = contextPath String fullTimelineNetworkURL = contextPath
+ secondaryContextPath + secondaryContextPath
+ "?" + "?"
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
+ "=" + URLEncoder.encode(individualURIParam, + "=" + URLEncoder.encode(individualURI,
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + "&"
+ VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + VisualizationFrameworkConstants.VIS_TYPE_KEY
+ "=" + URLEncoder.encode("person_level", + "=" + URLEncoder.encode("person_level",
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + "&"
+ VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE + VisualizationFrameworkConstants.VIS_CONTAINER_KEY
+ "=" + URLEncoder.encode("ego_sparkline", + "=" + URLEncoder.encode("ego_sparkline",
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + "&"
+ VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + VisualizationFrameworkConstants.RENDER_MODE_KEY
+ "=" + URLEncoder.encode( + "=" + URLEncoder.encode(
VisualizationFrameworkConstants VisualizationFrameworkConstants
.STANDALONE_RENDER_MODE_URL_VALUE, .STANDALONE_RENDER_MODE,
VisualizationController.URL_ENCODING_SCHEME).toString(); VisualizationController.URL_ENCODING_SCHEME).toString();
fullTimelineLink = "<a href='" + fullTimelineNetworkURL fullTimelineLink = "<a href='" + fullTimelineNetworkURL
+ "'>View full timeline and co-author network</a><br />"; + "'>View full timeline and co-author network</a><br />";
valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL); sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL);
} else { } else {
fullTimelineLink = "No data available to render full timeline.<br />"; fullTimelineLink = "No data available to render full timeline.<br />";
} }
divContextCode.append("<p>" + fullTimelineLink + "</p>"); divContextCode.append("<p>" + fullTimelineLink + "</p>");
@ -619,4 +621,8 @@ public class CoAuthorshipVisCodeGenerator {
return dataTable.toString(); return dataTable.toString();
} }
public SparklineData getValueObjectContainer() {
return sparklineData;
}
} }

View file

@ -7,6 +7,11 @@ import java.util.Comparator;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Edge; 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<Edge> { public class EdgeComparator implements Comparator<Edge> {
@Override @Override

View file

@ -7,6 +7,10 @@ import java.util.Comparator;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node; 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<Node> { public class NodeComparator implements Comparator<Node> {
@Override @Override

View file

@ -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.VivoCollegeOrSchool;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoDepartmentOrDivision; 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.valueobjects.VivoEmployee;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryHandler; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
/** /**
* @author cdtank * @author cdtank
*
*/ */
public class CollegePublicationCountQueryHandler implements QueryHandler<Set<VivoEmployee>> { public class CollegePublicationCountQueryRunner implements QueryRunner<Set<VivoEmployee>> {
protected static final Syntax SYNTAX = Syntax.syntaxARQ; protected static final Syntax SYNTAX = Syntax.syntaxARQ;
private String collegeURIParam; private String collegeURI;
private Map<String, VivoCollegeOrSchool> collegeURLToVO = private Map<String, VivoCollegeOrSchool> collegeURLToVO =
new HashMap<String, VivoCollegeOrSchool>(); new HashMap<String, VivoCollegeOrSchool>();
private DataSource dataSource; private DataSource dataSource;
private Log log; private Log log;
public CollegePublicationCountQueryHandler(String collegeURIParam, public CollegePublicationCountQueryRunner(String collegeURI,
DataSource dataSource, Log log) { DataSource dataSource, Log log) {
this.collegeURIParam = collegeURIParam; this.collegeURI = collegeURI;
this.dataSource = dataSource; this.dataSource = dataSource;
this.log = log; this.log = log;
@ -296,15 +295,15 @@ public class CollegePublicationCountQueryHandler implements QueryHandler<Set<Viv
} }
public Set<VivoEmployee> getVisualizationJavaValueObjects() public Set<VivoEmployee> getQueryResult()
throws MalformedQueryParametersException { throws MalformedQueryParametersException {
if (StringUtils.isNotBlank(this.collegeURIParam)) { if (StringUtils.isNotBlank(this.collegeURI)) {
/* /*
* To test for the validity of the URI submitted. * To test for the validity of the URI submitted.
* */ * */
IRIFactory iRIFactory = IRIFactory.jenaImplementation(); IRIFactory iRIFactory = IRIFactory.jenaImplementation();
IRI iri = iRIFactory.create(this.collegeURIParam); IRI iri = iRIFactory.create(this.collegeURI);
if (iri.hasViolation(false)) { if (iri.hasViolation(false)) {
String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage(); String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage();
log.error("Pub Count Vis Query " + errorMsg); log.error("Pub Count Vis Query " + errorMsg);
@ -315,7 +314,7 @@ public class CollegePublicationCountQueryHandler implements QueryHandler<Set<Viv
throw new MalformedQueryParametersException("URI parameter is either null or empty."); throw new MalformedQueryParametersException("URI parameter is either null or empty.");
} }
ResultSet resultSet = executeQuery(generateCollegeEmployeeSparqlQuery(this.collegeURIParam), ResultSet resultSet = executeQuery(generateCollegeEmployeeSparqlQuery(this.collegeURI),
this.dataSource); this.dataSource);
return createJavaValueObjects(resultSet); return createJavaValueObjects(resultSet);

View file

@ -14,10 +14,8 @@ import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -31,7 +29,6 @@ import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter; import com.itextpdf.text.pdf.PdfWriter;
import edu.cornell.mannlib.vitro.webapp.beans.Portal; import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants; import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
@ -42,7 +39,7 @@ import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoCollegeOr
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoDepartmentOrDivision; 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.valueobjects.VivoEmployee;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument;
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.UtilityFunctions; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler;
@ -55,25 +52,25 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque
DataSource dataSource) { DataSource dataSource) {
String collegeURIParam = vitroRequest.getParameter( String collegeURIParam = vitroRequest.getParameter(
VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE); VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
String renderMode = vitroRequest.getParameter( String renderMode = vitroRequest.getParameter(
VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE); VisualizationFrameworkConstants.RENDER_MODE_KEY);
String visMode = vitroRequest.getParameter( String visMode = vitroRequest.getParameter(
VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE); VisualizationFrameworkConstants.VIS_MODE_KEY);
String visContainer = vitroRequest.getParameter( String visContainer = vitroRequest.getParameter(
VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE); VisualizationFrameworkConstants.VIS_CONTAINER_KEY);
QueryHandler<Set<VivoEmployee>> queryManager = QueryRunner<Set<VivoEmployee>> queryManager =
new CollegePublicationCountQueryHandler(collegeURIParam, new CollegePublicationCountQueryRunner(collegeURIParam,
dataSource, dataSource,
log); log);
try { try {
Set<VivoEmployee> employees = queryManager.getVisualizationJavaValueObjects(); Set<VivoEmployee> employees = queryManager.getQueryResult();
Map<VivoDepartmentOrDivision, Map<String, Integer>> departmentToPublicationsOverTime = Map<VivoDepartmentOrDivision, Map<String, Integer>> departmentToPublicationsOverTime =
new HashMap<VivoDepartmentOrDivision, Map<String, Integer>>(); new HashMap<VivoDepartmentOrDivision, Map<String, Integer>>();
@ -111,10 +108,10 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque
* HTML code to render sparkline, tables etc. Ideally I would want to avoid this flow. * HTML code to render sparkline, tables etc. Ideally I would want to avoid this flow.
* It is ugly! * It is ugly!
* */ * */
if (VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) { if (VisualizationFrameworkConstants.DATA_RENDER_MODE.equalsIgnoreCase(renderMode)) {
prepareVisualizationQueryDataResponse( prepareDataResponse(
departmentToPublicationsOverTime, departmentToPublicationsOverTime,
((CollegePublicationCountQueryHandler) queryManager).getCollegeURLToVO(), ((CollegePublicationCountQueryRunner) queryManager).getCollegeURLToVO(),
response); response);
log.debug(publishedYearsForCollege); log.debug(publishedYearsForCollege);
@ -143,7 +140,13 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque
} catch (MalformedQueryParametersException e) { } catch (MalformedQueryParametersException e) {
try { 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) { } catch (ServletException e1) {
log.error(e1.getStackTrace()); log.error(e1.getStackTrace());
} catch (IOException e1) { } catch (IOException e1) {
@ -204,7 +207,7 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque
return departmentYearToPublicationCount; return departmentYearToPublicationCount;
} }
private void prepareVisualizationQueryPDFResponse(Individual college, private void preparePDFResponse(Individual college,
List<BiboDocument> authorDocuments, List<BiboDocument> authorDocuments,
Map<String, Integer> yearToPublicationCount, Map<String, Integer> yearToPublicationCount,
HttpServletResponse response) { HttpServletResponse response) {
@ -264,7 +267,7 @@ public class CollegePublicationCountRequestHandler implements VisualizationReque
} }
} }
private void prepareVisualizationQueryDataResponse( private void prepareDataResponse(
Map<VivoDepartmentOrDivision, Map<String, Integer>> departmentToPublicationsOverTime, Map<VivoDepartmentOrDivision, Map<String, Integer>> departmentToPublicationsOverTime,
Map<String, VivoCollegeOrSchool> collegeURLToVO, HttpServletResponse response) { Map<String, VivoCollegeOrSchool> 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, HttpServletResponse response, VitroRequest vreq,
String visContentCode, String visContextCode) { 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, HttpServletResponse response, VitroRequest vreq,
String visContentCode, String visContextCode) { 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());
}
}
} }

View file

@ -5,6 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.visualization.constants;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@SuppressWarnings("serial")
public class QueryConstants { public class QueryConstants {
public static final Map<String, String> PREFIX_TO_NAMESPACE = new HashMap<String, String>() { { public static final Map<String, String> PREFIX_TO_NAMESPACE = new HashMap<String, String>() { {
@ -47,17 +48,12 @@ public class QueryConstants {
StringBuilder prefixSection = new StringBuilder(); StringBuilder prefixSection = new StringBuilder();
for (Map.Entry prefixEntry : PREFIX_TO_NAMESPACE.entrySet()) { for (Map.Entry<String, String> prefixEntry : PREFIX_TO_NAMESPACE.entrySet()) {
prefixSection.append("PREFIX " + prefixEntry.getKey() prefixSection.append("PREFIX " + prefixEntry.getKey()
+ ": <" + prefixEntry.getValue() + ">\n"); + ": <" + prefixEntry.getValue() + ">\n");
} }
return prefixSection.toString(); return prefixSection.toString();
} }
} }

View file

@ -2,6 +2,10 @@
package edu.cornell.mannlib.vitro.webapp.visualization.constants; 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 { 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_YEAR_MONTH = "publicationYearMonthLit";
public static final String DOCUMENT_PUBLICATION_DATE = "publicationDateLit"; public static final String DOCUMENT_PUBLICATION_DATE = "publicationDateLit";
/* /*
* Image related field labels * Image related field labels
* */ * */

View file

@ -2,6 +2,12 @@
package edu.cornell.mannlib.vitro.webapp.visualization.constants; 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 class VOConstants {
public static final String DEFAULT_PUBLICATION_YEAR = "Unknown"; public static final String DEFAULT_PUBLICATION_YEAR = "Unknown";
@ -13,4 +19,9 @@ public class VOConstants {
ACADEMIC_FACULTY_EMPLOYEE, ACADEMIC_STAFF_EMPLOYEE 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);
} }

View file

@ -2,12 +2,16 @@
package edu.cornell.mannlib.vitro.webapp.visualization.constants; package edu.cornell.mannlib.vitro.webapp.visualization.constants;
/**
* This contains constants related to the visualization code.
* @author cdtank
*/
public class VisConstants { public class VisConstants {
public static final int MAX_NAME_TEXT_LENGTH = 20; 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 RESULT_FORMAT_PARAM = "RS_TEXT";
public static final String RDF_RESULT_FORMAT_PARAM = "RDF/XML-ABBREV"; public static final String RDF_RESULT_FORMAT_PARAM = "RDF/XML-ABBREV";
} }

View file

@ -4,8 +4,6 @@ package edu.cornell.mannlib.vitro.webapp.visualization.personlevel;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; 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.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipGraphMLWriter; 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.coauthorship.CoAuthorshipVisCodeGenerator;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.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.personpubcount.PersonPublicationCountVisCodeGenerator;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.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.Node;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
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.UtilityFunctions; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler; 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 { public class PersonLevelRequestHandler implements VisualizationRequestHandler {
private static final String EGO_PUB_SPARKLINE_VIS_CONTAINER_ID = "ego_pub_sparkline"; private static final String EGO_PUB_SPARKLINE_VIS_CONTAINER_ID = "ego_pub_sparkline";
@ -50,55 +58,42 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
Log log, Log log,
DataSource dataSource) { DataSource dataSource) {
String egoURIParam = vitroRequest.getParameter( String egoURI = vitroRequest.getParameter(
VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE); VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
String renderMode = vitroRequest.getParameter( String renderMode = vitroRequest.getParameter(
VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE); VisualizationFrameworkConstants.RENDER_MODE_KEY);
String visMode = vitroRequest.getParameter( String visMode = vitroRequest.getParameter(
VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE); VisualizationFrameworkConstants.VIS_MODE_KEY);
QueryHandler<CoAuthorshipVOContainer> QueryRunner<CoAuthorshipData> coAuthorshipQueryManager =
coAuthorshipQueryManager = new CoAuthorshipQueryRunner(egoURI, dataSource, log);
new CoAuthorshipQueryHandler(egoURIParam,
dataSource,
log);
QueryHandler<Set<BiboDocument>> publicationQueryManager = QueryRunner<Set<BiboDocument>> publicationQueryManager =
new PersonPublicationCountQueryHandler(egoURIParam, new PersonPublicationCountQueryRunner(egoURI, dataSource, log);
dataSource,
log);
try { try {
CoAuthorshipVOContainer coAuthorshipVO = coAuthorshipQueryManager CoAuthorshipData coAuthorshipData = coAuthorshipQueryManager.getQueryResult();
.getVisualizationJavaValueObjects();
if (VisualizationFrameworkConstants.DATA_RENDER_MODE
/*
* 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
.equalsIgnoreCase(renderMode)) { .equalsIgnoreCase(renderMode)) {
/* /*
* We will be using the same visualization package for providing data for both * 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). * 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 * We will use "VIS_MODE_KEY" as a modifier to differentiate between
* these two. The defualt will be to provide data used to render the co- * these two. The default will be to provide data used to render the co-
* authorship network vis. * authorship network vis.
* */ * */
if (VisualizationFrameworkConstants.COAUTHORSLIST_VIS_MODE
if (VisualizationFrameworkConstants.COAUTHORSLIST_VIS_MODE_URL_VALUE
.equalsIgnoreCase(visMode)) { .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. * many times they have co-authored with the ego.
* */ * */
prepareVisualizationQueryListCoauthorsDataResponse(coAuthorshipVO, prepareListCoauthorsDataResponse(coAuthorshipData,
response); response);
return; return;
@ -107,15 +102,21 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
* When the graphML file is required - based on which co-authorship * When the graphML file is required - based on which co-authorship
* network visualization will be rendered. * network visualization will be rendered.
* */ * */
prepareVisualizationQueryNetworkDataResponse(coAuthorshipVO, response); prepareNetworkDataResponse(coAuthorshipData,
response);
return; return;
} }
} }
Set<BiboDocument> 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<BiboDocument> authorDocuments = publicationQueryManager.getQueryResult();
/* /*
* Create a map from the year to number of publications. Use the BiboDocument's * Create a map from the year to number of publications. Use the BiboDocument's
* parsedPublicationYear to populate the data. * parsedPublicationYear to populate the data.
@ -126,39 +127,39 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
/* /*
* Computations required to generate HTML for the sparklines & related context. * Computations required to generate HTML for the sparklines & related context.
* */ * */
SparklineVOContainer publicationSparklineVO = new SparklineVOContainer();
SparklineVOContainer uniqueCoauthorsSparklineVO = new SparklineVOContainer();
PersonPublicationCountVisCodeGenerator personPubCountVisCodeGenerator = PersonPublicationCountVisCodeGenerator personPubCountVisCodeGenerator =
new PersonPublicationCountVisCodeGenerator( new PersonPublicationCountVisCodeGenerator(
vitroRequest.getRequestURI(), vitroRequest.getRequestURI(),
egoURIParam, egoURI,
PersonPublicationCountVisCodeGenerator.FULL_SPARKLINE_MODE_URL_HANDLE, VisualizationFrameworkConstants.FULL_SPARKLINE_VIS_MODE,
EGO_PUB_SPARKLINE_VIS_CONTAINER_ID, EGO_PUB_SPARKLINE_VIS_CONTAINER_ID,
authorDocuments, authorDocuments,
yearToPublicationCount, yearToPublicationCount,
publicationSparklineVO,
log); log);
SparklineData publicationSparklineVO = personPubCountVisCodeGenerator
.getValueObjectContainer();
CoAuthorshipVisCodeGenerator uniqueCoauthorsVisCodeGenerator = CoAuthorshipVisCodeGenerator uniqueCoauthorsVisCodeGenerator =
new CoAuthorshipVisCodeGenerator( new CoAuthorshipVisCodeGenerator(
vitroRequest.getRequestURI(), vitroRequest.getRequestURI(),
egoURIParam, egoURI,
PersonPublicationCountVisCodeGenerator.FULL_SPARKLINE_MODE_URL_HANDLE, VisualizationFrameworkConstants.FULL_SPARKLINE_VIS_MODE,
UNIQUE_COAUTHORS_SPARKLINE_VIS_CONTAINER_ID, UNIQUE_COAUTHORS_SPARKLINE_VIS_CONTAINER_ID,
getUniqueCoAuthorsPerYear(coAuthorshipVO), UtilityFunctions.getPublicationYearToCoAuthors(coAuthorshipData),
uniqueCoauthorsSparklineVO,
log); log);
SparklineData uniqueCoauthorsSparklineVO = uniqueCoauthorsVisCodeGenerator
.getValueObjectContainer();
RequestDispatcher requestDispatcher = null; RequestDispatcher requestDispatcher = null;
prepareVisualizationQueryStandaloneResponse( prepareStandaloneResponse(
egoURIParam, egoURI,
publicationSparklineVO, publicationSparklineVO,
uniqueCoauthorsSparklineVO, uniqueCoauthorsSparklineVO,
coAuthorshipVO, coAuthorshipData,
EGO_PUB_SPARKLINE_VIS_CONTAINER_ID, EGO_PUB_SPARKLINE_VIS_CONTAINER_ID,
UNIQUE_COAUTHORS_SPARKLINE_VIS_CONTAINER_ID, UNIQUE_COAUTHORS_SPARKLINE_VIS_CONTAINER_ID,
vitroRequest, vitroRequest,
@ -176,11 +177,14 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
} catch (MalformedQueryParametersException e) { } catch (MalformedQueryParametersException e) {
try { try {
handleMalformedParameters(e.getMessage(), UtilityFunctions.handleMalformedParameters(
vitroRequest, e.getMessage(),
request, "Visualization Query Error - Person Level Visualization",
response, vitroRequest,
log); request,
response,
log);
} catch (ServletException e1) { } catch (ServletException e1) {
log.error(e1.getStackTrace()); log.error(e1.getStackTrace());
} catch (IOException e1) { } catch (IOException e1) {
@ -190,124 +194,7 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
} }
} }
private Map<String, Set<Node>> getUniqueCoAuthorsPerYear( private Map<String, Integer> getCoAuthorsList(CoAuthorshipData coAuthorsipVO) {
CoAuthorshipVOContainer authorNodesAndEdges) {
Map<String, Set<Node>> yearToCoAuthors = new TreeMap<String, Set<Node>>();
Node egoNode = authorNodesAndEdges.getEgoNode();
for (Node currNode : authorNodesAndEdges.getNodes()) {
/*
* We have already printed the Ego Node info.
* */
if (currNode != egoNode) {
for (String year : currNode.getYearToPublicationCount().keySet()) {
Set<Node> coAuthorNodes;
if (yearToCoAuthors.containsKey(year)) {
coAuthorNodes = yearToCoAuthors.get(year);
coAuthorNodes.add(currNode);
} else {
coAuthorNodes = new HashSet<Node>();
coAuthorNodes.add(currNode);
yearToCoAuthors.put(year, coAuthorNodes);
}
}
}
}
return yearToCoAuthors;
}
private void 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<String, Integer> coAuthorsToCount = new TreeMap<String, Integer>();
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<String, Integer> getCoAuthorsList(CoAuthorshipVOContainer coAuthorsipVO) {
Map<String, Integer> coAuthorsToCount = new TreeMap<String, Integer>(); Map<String, Integer> coAuthorsToCount = new TreeMap<String, Integer>();
@ -325,10 +212,11 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
return coAuthorsToCount; return coAuthorsToCount;
} }
private void generateCsvFileBuffer(Map<String, Integer> coAuthorsToCount, private void writeCoAuthorsToWorksCSV(Map<String, Integer> coAuthorsToCount,
PrintWriter printWriter) { PrintWriter printWriter) {
printWriter.append("\"Co-Author\", \"Count\"\n"); // printWriter.append("\"Co-Author\", \"Count\"\n");
printWriter.append("Co-Author, Count\n");
for (Entry<String, Integer> currentEntry : coAuthorsToCount.entrySet()) { for (Entry<String, Integer> currentEntry : coAuthorsToCount.entrySet()) {
@ -340,11 +228,106 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
printWriter.flush(); printWriter.flush();
} }
private void prepareVisualizationQueryStandaloneResponse( /**
String egoURIParam, * Provide response when graphml file for the co-authorship network is requested.
SparklineVOContainer egoPubSparklineVO, * @param coAuthorsipData
SparklineVOContainer uniqueCoauthorsSparklineVO, * @param response
CoAuthorshipVOContainer coAuthorshipVO, */
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<String, Integer> coAuthorsToCount = new TreeMap<String, Integer>();
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 egoPubSparklineVisContainer,
String uniqueCoauthorsSparklineVisContainer, String uniqueCoauthorsSparklineVisContainer,
VitroRequest vitroRequest, VitroRequest vitroRequest,
@ -352,12 +335,12 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
Portal portal = vitroRequest.getPortal(); Portal portal = vitroRequest.getPortal();
request.setAttribute("egoURIParam", egoURIParam); request.setAttribute("egoURIParam", egoURI);
String title = ""; String title = "";
if (coAuthorshipVO.getNodes() != null && coAuthorshipVO.getNodes().size() > 0) { if (coAuthorshipVO.getNodes() != null && coAuthorshipVO.getNodes().size() > 0) {
request.setAttribute("numOfAuthors", coAuthorshipVO.getNodes().size()); request.setAttribute("numOfAuthors", coAuthorshipVO.getNodes().size());
title = "for " + coAuthorshipVO.getEgoNode().getNodeName(); title = coAuthorshipVO.getEgoNode().getNodeName() + " - ";
} }
if (coAuthorshipVO.getEdges() != null && coAuthorshipVO.getEdges().size() > 0) { if (coAuthorshipVO.getEdges() != null && coAuthorshipVO.getEdges().size() > 0) {
@ -372,36 +355,9 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
request.setAttribute("uniqueCoauthorsSparklineVisContainerID", request.setAttribute("uniqueCoauthorsSparklineVisContainerID",
uniqueCoauthorsSparklineVisContainer); uniqueCoauthorsSparklineVisContainer);
request.setAttribute("title", "Person Level Visualization " + title); request.setAttribute("title", title + "Person Level Visualization");
request.setAttribute("portalBean", portal); request.setAttribute("portalBean", portal);
request.setAttribute("scripts", "/templates/visualization/person_level_inject_head.jsp"); request.setAttribute("scripts", "/templates/visualization/person_level_inject_head.jsp");
request.setAttribute("bodyJsp", "/templates/visualization/person_level.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());
}
}
} }

View file

@ -2,12 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount; package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; 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.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual;
import edu.cornell.mannlib.vitro.webapp.visualization.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 * @author cdtank
*
*/ */
public class PersonPublicationCountQueryHandler implements QueryHandler<Set<BiboDocument>> { public class PersonPublicationCountQueryRunner implements QueryRunner<Set<BiboDocument>> {
protected static final Syntax SYNTAX = Syntax.syntaxARQ; protected static final Syntax SYNTAX = Syntax.syntaxARQ;
private String queryParam; private String personURI;
private DataSource dataSource; private DataSource dataSource;
private Individual author; private Individual author;
@ -74,10 +72,10 @@ public class PersonPublicationCountQueryHandler implements QueryHandler<Set<Bibo
+ "OPTIONAL { ?document vitro:blurb ?documentBlurb } ." + "OPTIONAL { ?document vitro:blurb ?documentBlurb } ."
+ "OPTIONAL { ?document vitro:description ?documentDescription }"; + "OPTIONAL { ?document vitro:description ?documentDescription }";
public PersonPublicationCountQueryHandler(String queryParam, public PersonPublicationCountQueryRunner(String personURI,
DataSource dataSource, Log log) { DataSource dataSource, Log log) {
this.queryParam = queryParam; this.personURI = personURI;
this.dataSource = dataSource; this.dataSource = dataSource;
this.log = log; this.log = log;
@ -143,7 +141,6 @@ public class PersonPublicationCountQueryHandler implements QueryHandler<Set<Bibo
if (authorLabelNode != null) { if (authorLabelNode != null) {
author.setIndividualLabel(authorLabelNode.toString()); author.setIndividualLabel(authorLabelNode.toString());
} }
} }
authorDocuments.add(biboDocument); authorDocuments.add(biboDocument);
@ -156,7 +153,7 @@ public class PersonPublicationCountQueryHandler implements QueryHandler<Set<Bibo
QueryExecution queryExecution = null; QueryExecution queryExecution = null;
try { try {
Query query = QueryFactory.create(generateSparqlQuery(queryURI), SYNTAX); Query query = QueryFactory.create(getSparqlQuery(queryURI), SYNTAX);
// QuerySolutionMap qs = new QuerySolutionMap(); // QuerySolutionMap qs = new QuerySolutionMap();
// qs.add("authPerson", queryParam); // bind resource to s // qs.add("authPerson", queryParam); // bind resource to s
@ -175,7 +172,7 @@ public class PersonPublicationCountQueryHandler implements QueryHandler<Set<Bibo
return null; return null;
} }
private String generateSparqlQuery(String queryURI) { private String getSparqlQuery(String queryURI) {
// Resource uri1 = ResourceFactory.createResource(queryURI); // Resource uri1 = ResourceFactory.createResource(queryURI);
String sparqlQuery = QueryConstants.getSparqlPrefixQuery() String sparqlQuery = QueryConstants.getSparqlPrefixQuery()
@ -194,16 +191,16 @@ public class PersonPublicationCountQueryHandler implements QueryHandler<Set<Bibo
return sparqlQuery; return sparqlQuery;
} }
public Set<BiboDocument> getVisualizationJavaValueObjects() public Set<BiboDocument> getQueryResult()
throws MalformedQueryParametersException { throws MalformedQueryParametersException {
if (StringUtils.isNotBlank(this.queryParam)) { if (StringUtils.isNotBlank(this.personURI)) {
/* /*
* To test for the validity of the URI submitted. * To test for the validity of the URI submitted.
* */ * */
IRIFactory iRIFactory = IRIFactory.jenaImplementation(); IRIFactory iRIFactory = IRIFactory.jenaImplementation();
IRI iri = iRIFactory.create(this.queryParam); IRI iri = iRIFactory.create(this.personURI);
if (iri.hasViolation(false)) { if (iri.hasViolation(false)) {
String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage(); String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage();
log.error("Pub Count vis Query " + errorMsg); log.error("Pub Count vis Query " + errorMsg);
@ -215,7 +212,7 @@ public class PersonPublicationCountQueryHandler implements QueryHandler<Set<Bibo
throw new MalformedQueryParametersException("URL parameter is either null or empty."); throw new MalformedQueryParametersException("URL parameter is either null or empty.");
} }
ResultSet resultSet = executeQuery(this.queryParam, ResultSet resultSet = executeQuery(this.personURI,
this.dataSource); this.dataSource);
return createJavaValueObjects(resultSet); return createJavaValueObjects(resultSet);

View file

@ -5,7 +5,6 @@ package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -16,6 +15,7 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.skife.csv.CSVWriter; import org.skife.csv.CSVWriter;
import org.skife.csv.SimpleWriter; import org.skife.csv.SimpleWriter;
@ -32,12 +32,26 @@ import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFr
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument;
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.UtilityFunctions; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler;
/**
*
* This request handler is used to serve the content related to an individual's
* publications over the years like,
* 1. Sprakline representing this
* 2. An entire page dedicated to the sparkline vis which will also have links to
* download the data using which the sparkline was rendered & its tabular representation etc.
* 3. Downloadable CSV file containing number of publications over the years.
* 4. Downloadable PDf file containing the publications content, among other things.
* Currently this is disabled because the feature is half-baked. We plan to activate this in
* the next major release.
*
* @author cdtank
*/
public class PersonPublicationCountRequestHandler implements VisualizationRequestHandler { public class PersonPublicationCountRequestHandler implements VisualizationRequestHandler {
public void generateVisualization(VitroRequest vitroRequest, public void generateVisualization(VitroRequest vitroRequest,
@ -46,29 +60,27 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques
Log log, Log log,
DataSource dataSource) { DataSource dataSource) {
String individualURIParam = vitroRequest.getParameter( String peronURI = vitroRequest.getParameter(
VisualizationFrameworkConstants VisualizationFrameworkConstants
.INDIVIDUAL_URI_URL_HANDLE); .INDIVIDUAL_URI_KEY);
String renderMode = vitroRequest.getParameter( String renderMode = vitroRequest.getParameter(
VisualizationFrameworkConstants VisualizationFrameworkConstants
.RENDER_MODE_URL_HANDLE); .RENDER_MODE_KEY);
String visMode = vitroRequest.getParameter( String visMode = vitroRequest.getParameter(
VisualizationFrameworkConstants VisualizationFrameworkConstants
.VIS_MODE_URL_HANDLE); .VIS_MODE_KEY);
String visContainer = vitroRequest.getParameter( String visContainer = vitroRequest.getParameter(
VisualizationFrameworkConstants VisualizationFrameworkConstants
.VIS_CONTAINER_URL_HANDLE); .VIS_CONTAINER_KEY);
QueryHandler<Set<BiboDocument>> queryManager = QueryRunner<Set<BiboDocument>> queryManager =
new PersonPublicationCountQueryHandler(individualURIParam, new PersonPublicationCountQueryRunner(peronURI, dataSource, log);
dataSource,
log);
try { try {
Set<BiboDocument> authorDocuments = queryManager.getVisualizationJavaValueObjects(); Set<BiboDocument> authorDocuments = queryManager.getQueryResult();
/* /*
* Create a map from the year to number of publications. Use the BiboDocument's * Create a map from the year to number of publications. Use the BiboDocument's
@ -77,17 +89,12 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques
Map<String, Integer> yearToPublicationCount = Map<String, Integer> yearToPublicationCount =
UtilityFunctions.getYearToPublicationCount(authorDocuments); UtilityFunctions.getYearToPublicationCount(authorDocuments);
/* Individual author = ((PersonPublicationCountQueryRunner) queryManager).getAuthor();
* 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 if (VisualizationFrameworkConstants.DATA_RENDER_MODE
* 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
.equalsIgnoreCase(renderMode)) { .equalsIgnoreCase(renderMode)) {
prepareVisualizationQueryDataResponse(author, prepareDataResponse(author,
authorDocuments, authorDocuments,
yearToPublicationCount, yearToPublicationCount,
response); 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)) { .equalsIgnoreCase(renderMode)) {
prepareVisualizationQueryPDFResponse(author, preparePDFResponse(author,
authorDocuments, authorDocuments,
yearToPublicationCount, yearToPublicationCount,
response); response);
return; 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 = PersonPublicationCountVisCodeGenerator visualizationCodeGenerator =
new PersonPublicationCountVisCodeGenerator(vitroRequest.getContextPath(), new PersonPublicationCountVisCodeGenerator(vitroRequest.getContextPath(),
individualURIParam, peronURI,
visMode, visMode,
visContainer, visContainer,
authorDocuments, authorDocuments,
yearToPublicationCount, yearToPublicationCount,
valueObjectContainer,
log); log);
SparklineData sparklineData = visualizationCodeGenerator
.getValueObjectContainer();
/* /*
* This is side-effecting because the response of this method is just to redirect to * 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; RequestDispatcher requestDispatcher = null;
if (VisualizationFrameworkConstants.DYNAMIC_RENDER_MODE_URL_VALUE if (VisualizationFrameworkConstants.DYNAMIC_RENDER_MODE
.equalsIgnoreCase(renderMode)) { .equalsIgnoreCase(renderMode)) {
prepareVisualizationQueryDynamicResponse(request, response, vitroRequest, prepareDynamicResponse(request,
valueObjectContainer, yearToPublicationCount); response,
vitroRequest,
sparklineData,
yearToPublicationCount);
requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp"); requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp");
} else { } else {
prepareVisualizationQueryStandaloneResponse(request, response, vitroRequest, prepareStandaloneResponse(request,
valueObjectContainer); response,
vitroRequest,
sparklineData);
requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
} }
@ -152,7 +166,13 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques
} catch (MalformedQueryParametersException e) { } catch (MalformedQueryParametersException e) {
try { 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) { } catch (ServletException e1) {
log.error(e1.getStackTrace()); log.error(e1.getStackTrace());
} catch (IOException e1) { } catch (IOException e1) {
@ -160,72 +180,35 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques
} }
return; return;
} }
} }
private void prepareVisualizationQueryPDFResponse( private void writePublicationsOverTimeCSV(Map<String, Integer> yearToPublicationCount,
Individual author, PrintWriter responseWriter) {
Set<BiboDocument> authorDocuments,
Map<String, Integer> yearToPublicationCount,
HttpServletResponse response) {
String authorName = null; CSVWriter csvWriter = new SimpleWriter(responseWriter);
/* try {
* To protect against cases where there are no author documents associated with the csvWriter.append(new String[]{"Year", "Publications"});
* individual. for (Entry<String, Integer> currentEntry : yearToPublicationCount.entrySet()) {
* */ csvWriter.append(new Object[]{currentEntry.getKey(), currentEntry.getValue()});
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();
} }
} 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, Individual author,
Set<BiboDocument> authorDocuments, Set<BiboDocument> authorDocuments,
Map<String, Integer> yearToPublicationCount, Map<String, Integer> 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. * 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"; authorName = "no-author";
} }
@ -262,8 +245,7 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques
* We are side-effecting responseWriter since we are directly manipulating the response * We are side-effecting responseWriter since we are directly manipulating the response
* object of the servlet. * object of the servlet.
* */ * */
generateCsvFileBuffer(yearToPublicationCount, writePublicationsOverTimeCSV(yearToPublicationCount, responseWriter);
responseWriter);
responseWriter.close(); responseWriter.close();
@ -272,28 +254,16 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques
} }
} }
private void generateCsvFileBuffer(Map<String, Integer> yearToPublicationCount, /**
PrintWriter responseWriter) { * Provides response when an entire page dedicated to publication sparkline is requested.
* @param request
CSVWriter csvWriter = new SimpleWriter(responseWriter); * @param response
* @param vreq
try { * @param valueObjectContainer
csvWriter.append(new String[]{"Year", "Publications"}); */
for (Entry<String, Integer> currentEntry : yearToPublicationCount.entrySet()) { private void prepareStandaloneResponse(HttpServletRequest request,
csvWriter.append(new Object[]{currentEntry.getKey(), currentEntry.getValue()});
}
} catch (IOException e) {
e.printStackTrace();
}
responseWriter.flush();
}
private void prepareVisualizationQueryStandaloneResponse(HttpServletRequest request,
HttpServletResponse response, VitroRequest vreq, HttpServletResponse response, VitroRequest vreq,
SparklineVOContainer valueObjectContainer) { SparklineData valueObjectContainer) {
Portal portal = vreq.getPortal(); 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, HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response,
VitroRequest vreq, VitroRequest vreq,
SparklineVOContainer valueObjectContainer, SparklineData valueObjectContainer,
Map<String, Integer> yearToPublicationCount) { Map<String, Integer> yearToPublicationCount) {
Portal portal = vreq.getPortal(); Portal portal = vreq.getPortal();
@ -325,32 +304,67 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques
request.setAttribute("portalBean", portal); request.setAttribute("portalBean", portal);
request.setAttribute("bodyJsp", "/templates/visualization/ajax_vis_content.jsp"); request.setAttribute("bodyJsp", "/templates/visualization/ajax_vis_content.jsp");
} }
private void handleMalformedParameters(String errorMessage, private void preparePDFResponse(
VitroRequest vitroRequest, Individual author,
HttpServletRequest request, Set<BiboDocument> authorDocuments,
HttpServletResponse response, Map<String, Integer> yearToPublicationCount,
Log log) HttpServletResponse response) {
throws ServletException, IOException {
Portal portal = vitroRequest.getPortal();
request.setAttribute("error", errorMessage); String authorName = null;
RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); /*
request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp"); * To protect against cases where there are no author documents associated with the
request.setAttribute("portalBean", portal); * individual.
request.setAttribute("title", "Visualization Query Error - Individual Publication Count"); * */
if (authorDocuments.size() > 0) {
try { authorName = author.getIndividualLabel();
requestDispatcher.forward(request, response);
} catch (Exception e) {
log.error("EntityEditController could not forward to view.");
log.error(e.getMessage());
log.error(e.getStackTrace());
} }
/*
* To make sure that null/empty records for author names do not cause any mischief.
* */
if (StringUtils.isBlank(authorName)) {
authorName = "no-author";
}
String outputFileName = UtilityFunctions.slugify(authorName) + "_report" + ".pdf";
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName);
ServletOutputStream responseOutputStream;
try {
responseOutputStream = response.getOutputStream();
Document document = new Document();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
document.open();
PDFDocument pdfDocument = new PDFDocument(authorName,
yearToPublicationCount,
document,
pdfWriter);
document.close();
// setting some response headers & content type
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentLength(baos.size());
// write ByteArrayOutputStream to the ServletOutputStream
baos.writeTo(responseOutputStream);
responseOutputStream.flush();
responseOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
} }
} }

View file

@ -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.VisualizationController;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants; 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.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
@SuppressWarnings("serial")
public class PersonPublicationCountVisCodeGenerator { 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<String, String> VIS_DIV_NAMES = new HashMap<String, String>() { { private static final Map<String, String> VIS_DIV_NAMES = new HashMap<String, String>() { {
put("SHORT_SPARK", "pub_count_short_sparkline_vis"); 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"; 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<String, Integer> yearToPublicationCount; private Map<String, Integer> yearToPublicationCount;
private Log log; private Log log;
private SparklineVOContainer valueObjectContainer; private SparklineData sparklineData;
private String contextPath; private String contextPath;
private String individualURIParam; private String individualURI;
public PersonPublicationCountVisCodeGenerator(String contextPath, public PersonPublicationCountVisCodeGenerator(String contextPath,
String individualURIParam, String individualURIParam,
@ -57,35 +62,41 @@ public class PersonPublicationCountVisCodeGenerator {
String visContainer, String visContainer,
Set<BiboDocument> authorDocuments, Set<BiboDocument> authorDocuments,
Map<String, Integer> yearToPublicationCount, Map<String, Integer> yearToPublicationCount,
SparklineVOContainer valueObjectContainer,
Log log) { Log log) {
this.contextPath = contextPath; this.contextPath = contextPath;
this.individualURIParam = individualURIParam; this.individualURI = individualURIParam;
this.yearToPublicationCount = yearToPublicationCount; this.yearToPublicationCount = yearToPublicationCount;
this.valueObjectContainer = valueObjectContainer; this.sparklineData = new SparklineData();
this.log = log; 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, private void generateVisualizationCode(String visMode,
String visContainer, String visContainer,
Set<BiboDocument> authorDocuments) { Set<BiboDocument> authorDocuments) {
valueObjectContainer.setSparklineContent(getMainVisualizationCode(authorDocuments, sparklineData.setSparklineContent(getMainVisualizationCode(authorDocuments,
visMode, visMode,
visContainer)); visContainer));
valueObjectContainer.setSparklineContext(getVisualizationContextCode(visMode)); sparklineData.setSparklineContext(getVisualizationContextCode(visMode));
} }
@ -95,13 +106,15 @@ public class PersonPublicationCountVisCodeGenerator {
int numOfYearsToBeRendered = 0; int numOfYearsToBeRendered = 0;
int currentYear = Calendar.getInstance().get(Calendar.YEAR); 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 * 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". * was rendered we dont want to be influenced by the "DEFAULT_PUBLICATION_YEAR".
* */ * */
Set<String> publishedYears = new HashSet(yearToPublicationCount.keySet()); Set<String> publishedYears = new HashSet<String>(yearToPublicationCount.keySet());
publishedYears.remove(VOConstants.DEFAULT_PUBLICATION_YEAR); publishedYears.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
/* /*
@ -175,7 +188,13 @@ public class PersonPublicationCountVisCodeGenerator {
+ "data.addRows(" + numOfYearsToBeRendered + ");\n"); + "data.addRows(" + numOfYearsToBeRendered + ");\n");
int publicationCounter = 0; 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; int renderedFullSparks = 0;
@ -202,23 +221,20 @@ public class PersonPublicationCountVisCodeGenerator {
+ currentPublications + currentPublications
+ ");\n"); + ");\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++; 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 * Total publications will also consider publications that have no year associated with
* it. Hence. * it. Hence.
* */ * */
Integer unknownYearPublications = 0; Integer unknownYearPublications = 0;
if (yearToPublicationCount.get(VOConstants.DEFAULT_PUBLICATION_YEAR) != null) { if (yearToPublicationCount.get(VOConstants.DEFAULT_PUBLICATION_YEAR) != null) {
totalPublications += yearToPublicationCount.get(VOConstants.DEFAULT_PUBLICATION_YEAR);
unknownYearPublications = yearToPublicationCount unknownYearPublications = yearToPublicationCount
.get(VOConstants.DEFAULT_PUBLICATION_YEAR); .get(VOConstants.DEFAULT_PUBLICATION_YEAR);
} }
@ -238,8 +254,8 @@ public class PersonPublicationCountVisCodeGenerator {
* "short" sparkline mode we will set the Earliest RenderedPublication year to * "short" sparkline mode we will set the Earliest RenderedPublication year to
* "currentYear - 10". * "currentYear - 10".
* */ * */
valueObjectContainer.setEarliestRenderedPublicationYear(minPublishedYear); sparklineData.setEarliestRenderedPublicationYear(minPublishedYear);
valueObjectContainer.setLatestRenderedPublicationYear(currentYear); sparklineData.setLatestRenderedPublicationYear(currentYear);
/* /*
* The Full Sparkline will be rendered by default. Only if the url has specific mention of * 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- * essentially a side-effecting process, we have both the activators method as side-
* effecting. They both side-effect "visualizationCode" * 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, generateShortSparklineVisualizationContent(currentYear,
shortSparkMinYear, shortSparkMinYear,
visContainerID, visContainerID,
@ -370,9 +386,7 @@ public class PersonPublicationCountVisCodeGenerator {
+ "\" class=\"inline_href\">(.CSV File)</a>"; + "\" class=\"inline_href\">(.CSV File)</a>";
} else { } else {
csvDownloadURLHref = ""; csvDownloadURLHref = "";
} }
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
@ -464,7 +478,7 @@ public class PersonPublicationCountVisCodeGenerator {
private String getVisualizationContextCode(String visMode) { private String getVisualizationContextCode(String visMode) {
String visualizationContextCode = ""; String visualizationContextCode = "";
if (SHORT_SPARKLINE_MODE_URL_HANDLE.equalsIgnoreCase(visMode)) { if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE.equalsIgnoreCase(visMode)) {
visualizationContextCode = generateShortVisContext(); visualizationContextCode = generateShortVisContext();
} else { } else {
visualizationContextCode = generateFullVisContext(); visualizationContextCode = generateFullVisContext();
@ -488,19 +502,15 @@ public class PersonPublicationCountVisCodeGenerator {
csvDownloadURLHref = "Download data as <a href='" csvDownloadURLHref = "Download data as <a href='"
+ getCSVDownloadURL() + "'>.csv</a> file.<br />"; + getCSVDownloadURL() + "'>.csv</a> file.<br />";
valueObjectContainer.setDownloadDataLink(getCSVDownloadURL()); sparklineData.setDownloadDataLink(getCSVDownloadURL());
} else { } else {
csvDownloadURLHref = ""; csvDownloadURLHref = "";
} }
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
csvDownloadURLHref = ""; csvDownloadURLHref = "";
} }
} else { } else {
csvDownloadURLHref = "No data available to export.<br />"; csvDownloadURLHref = "No data available to export.<br />";
} }
@ -509,10 +519,9 @@ public class PersonPublicationCountVisCodeGenerator {
divContextCode.append("<p>" + tableCode + csvDownloadURLHref + "</p>"); divContextCode.append("<p>" + tableCode + csvDownloadURLHref + "</p>");
valueObjectContainer.setTable(tableCode); sparklineData.setTable(tableCode);
return divContextCode.toString(); return divContextCode.toString();
} }
private String getCSVDownloadURL() private String getCSVDownloadURL()
@ -525,22 +534,21 @@ public class PersonPublicationCountVisCodeGenerator {
secondaryContextPath = VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX; secondaryContextPath = VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX;
} }
String downloadURL = contextPath String downloadURL = contextPath
+ secondaryContextPath + secondaryContextPath
+ "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE + "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
+ "=" + URLEncoder.encode(individualURIParam, + "=" + URLEncoder.encode(individualURI,
VisualizationController.URL_ENCODING_SCHEME) VisualizationController.URL_ENCODING_SCHEME)
.toString() .toString()
+ "&" + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + "&" + VisualizationFrameworkConstants.VIS_TYPE_KEY
+ "=" + URLEncoder.encode( + "=" + URLEncoder.encode(
VisualizationController VisualizationFrameworkConstants
.PERSON_PUBLICATION_COUNT_VIS_URL_VALUE, .PERSON_PUBLICATION_COUNT_VIS,
VisualizationController.URL_ENCODING_SCHEME) VisualizationController.URL_ENCODING_SCHEME)
.toString() .toString()
+ "&" + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + "&" + VisualizationFrameworkConstants.RENDER_MODE_KEY
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants + "=" + URLEncoder.encode(VisualizationFrameworkConstants
.DATA_RENDER_MODE_URL_VALUE, .DATA_RENDER_MODE,
VisualizationController.URL_ENCODING_SCHEME) VisualizationController.URL_ENCODING_SCHEME)
.toString(); .toString();
return downloadURL; return downloadURL;
@ -566,28 +574,26 @@ public class PersonPublicationCountVisCodeGenerator {
String fullTimelineNetworkURL = contextPath String fullTimelineNetworkURL = contextPath
+ secondaryContextPath + secondaryContextPath
+ "?" + "?"
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
+ "=" + URLEncoder.encode(individualURIParam, + "=" + URLEncoder.encode(individualURI,
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + "&"
+ VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + VisualizationFrameworkConstants.VIS_TYPE_KEY
+ "=" + URLEncoder.encode("person_level", + "=" + URLEncoder.encode("person_level",
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + "&"
+ VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + VisualizationFrameworkConstants.RENDER_MODE_KEY
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants + "=" + URLEncoder.encode(VisualizationFrameworkConstants
.STANDALONE_RENDER_MODE_URL_VALUE, .STANDALONE_RENDER_MODE,
VisualizationController.URL_ENCODING_SCHEME).toString(); VisualizationController.URL_ENCODING_SCHEME).toString();
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View all VIVO " fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View all VIVO "
+ "publications and corresponding co-author network</a>.<br />"; + "publications and corresponding co-author network</a>.<br />";
valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL); sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL);
} else { } else {
fullTimelineLink = "No data available to render full timeline.<br />"; fullTimelineLink = "No data available to render full timeline.<br />";
} }
divContextCode.append("<span class=\"vis_link\">" + fullTimelineLink + "</span>"); divContextCode.append("<span class=\"vis_link\">" + fullTimelineLink + "</span>");
@ -595,9 +601,7 @@ public class PersonPublicationCountVisCodeGenerator {
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
log.error(e); log.error(e);
} }
return divContextCode.toString(); return divContextCode.toString();
} }
private String generateDataTable() { private String generateDataTable() {
@ -606,15 +610,10 @@ public class PersonPublicationCountVisCodeGenerator {
try { try {
if (getCSVDownloadURL() != null) { if (getCSVDownloadURL() != null) {
csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL() + "\">(.CSV File)</a>"; csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL() + "\">(.CSV File)</a>";
} else { } else {
csvDownloadURLHref = ""; csvDownloadURLHref = "";
} }
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
csvDownloadURLHref = ""; csvDownloadURLHref = "";
} }
@ -643,7 +642,7 @@ public class PersonPublicationCountVisCodeGenerator {
return dataTable.toString(); return dataTable.toString();
} }
public SparklineData getValueObjectContainer() {
return sparklineData;
}
} }

View file

@ -9,7 +9,6 @@ import java.net.URLEncoder;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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.query.ResultSet;
import com.hp.hpl.jena.rdf.model.RDFNode; 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.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController;
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants; import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
@ -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.constants.QueryFieldLabels;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.GenericQueryMap; 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.AllPropertiesQueryRunner;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.GenericQueryHandler; import edu.cornell.mannlib.vitro.webapp.visualization.visutils.GenericQueryRunner;
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.UtilityFunctions;
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler; 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 class UtilitiesRequestHandler implements VisualizationRequestHandler {
public void generateVisualization(VitroRequest vitroRequest, public void generateVisualization(VitroRequest vitroRequest,
@ -44,12 +52,11 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
Log log, Log log,
DataSource dataSource) { DataSource dataSource) {
String individualURIParam = vitroRequest.getParameter( String individualURI = vitroRequest.getParameter(
VisualizationFrameworkConstants VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
.INDIVIDUAL_URI_URL_HANDLE);
String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants String visMode = vitroRequest.getParameter(
.VIS_MODE_URL_HANDLE); VisualizationFrameworkConstants.VIS_MODE_KEY);
String preparedURL = ""; String preparedURL = "";
@ -67,8 +74,8 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
+ "|| ?predicate = vitro:moniker " + "|| ?predicate = vitro:moniker "
+ "|| ?predicate = rdfs:label"; + "|| ?predicate = rdfs:label";
QueryHandler<GenericQueryMap> profileQueryHandler = QueryRunner<GenericQueryMap> profileQueryHandler =
new AllPropertiesQueryHandler(individualURIParam, new AllPropertiesQueryRunner(individualURI,
filterRule, filterRule,
dataSource, dataSource,
log); log);
@ -76,14 +83,14 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
try { try {
GenericQueryMap profilePropertiesToValues = GenericQueryMap profilePropertiesToValues =
profileQueryHandler.getVisualizationJavaValueObjects(); profileQueryHandler.getQueryResult();
profilePropertiesToValues.addEntry("imageContextPath", profilePropertiesToValues.addEntry("imageContextPath",
request.getContextPath()); request.getContextPath());
Gson profileInformation = new Gson(); Gson profileInformation = new Gson();
prepareVisualizationQueryResponse( prepareUtilitiesResponse(
profileInformation.toJson(profilePropertiesToValues), profileInformation.toJson(profilePropertiesToValues),
response); response);
@ -92,11 +99,13 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
} catch (MalformedQueryParametersException e) { } catch (MalformedQueryParametersException e) {
try { try {
handleMalformedParameters(e.getMessage(), UtilityFunctions.handleMalformedParameters(
vitroRequest, e.getMessage(),
request, "Visualization Query Error - Utilities Profile Info",
response, vitroRequest,
log); request,
response,
log);
} catch (ServletException e1) { } catch (ServletException e1) {
log.error(e1.getStackTrace()); log.error(e1.getStackTrace());
} catch (IOException e1) { } catch (IOException e1) {
@ -104,8 +113,6 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
} }
return; return;
} }
} else if (VisualizationFrameworkConstants.IMAGE_UTILS_VIS_MODE } else if (VisualizationFrameworkConstants.IMAGE_UTILS_VIS_MODE
.equalsIgnoreCase(visMode)) { .equalsIgnoreCase(visMode)) {
/* /*
@ -118,15 +125,15 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
QueryFieldLabels.THUMBNAIL_LOCATION_URL); QueryFieldLabels.THUMBNAIL_LOCATION_URL);
fieldLabelToOutputFieldLabel.put("fileName", QueryFieldLabels.THUMBNAIL_FILENAME); fieldLabelToOutputFieldLabel.put("fileName", QueryFieldLabels.THUMBNAIL_FILENAME);
String whereClause = "<" + individualURIParam String whereClause = "<" + individualURI
+ "> j.2:thumbnailImage ?thumbnailImage . " + "> j.2:thumbnailImage ?thumbnailImage . "
+ "?thumbnailImage j.2:downloadLocation " + "?thumbnailImage j.2:downloadLocation "
+ "?downloadLocation ; j.2:filename ?fileName ."; + "?downloadLocation ; j.2:filename ?fileName .";
QueryHandler<ResultSet> imageQueryHandler = QueryRunner<ResultSet> imageQueryHandler =
new GenericQueryHandler(individualURIParam, new GenericQueryRunner(individualURI,
fieldLabelToOutputFieldLabel, fieldLabelToOutputFieldLabel,
whereClause, whereClause,
dataSource, dataSource,
@ -136,20 +143,22 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
String thumbnailAccessURL = String thumbnailAccessURL =
getThumbnailInformation( getThumbnailInformation(
imageQueryHandler.getVisualizationJavaValueObjects(), imageQueryHandler.getQueryResult(),
fieldLabelToOutputFieldLabel); fieldLabelToOutputFieldLabel);
prepareVisualizationQueryResponse(thumbnailAccessURL, response); prepareUtilitiesResponse(thumbnailAccessURL, response);
return; return;
} catch (MalformedQueryParametersException e) { } catch (MalformedQueryParametersException e) {
try { try {
handleMalformedParameters(e.getMessage(), UtilityFunctions.handleMalformedParameters(
vitroRequest, e.getMessage(),
request, "Visualization Query Error - Utilities Image Info",
response, vitroRequest,
log); request,
response,
log);
} catch (ServletException e1) { } catch (ServletException e1) {
log.error(e1.getStackTrace()); log.error(e1.getStackTrace());
} catch (IOException e1) { } catch (IOException e1) {
@ -157,76 +166,69 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
} }
return; return;
} }
} else if (VisualizationFrameworkConstants.COAUTHOR_UTILS_VIS_MODE } else if (VisualizationFrameworkConstants.COAUTHOR_UTILS_VIS_MODE
.equalsIgnoreCase(visMode)) { .equalsIgnoreCase(visMode)) {
/* /*
* By default we will be generating profile url else some specific url like * By default we will be generating profile url else some specific url like
* coAuthorShip vis url for that individual. * coAuthorShip vis url for that individual.
* */ * */
preparedURL += request.getContextPath() preparedURL += request.getContextPath()
+ VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX + VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX
+ "?" + "?"
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
+ "=" + URLEncoder.encode(individualURIParam, + "=" + URLEncoder.encode(individualURI,
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + "&"
+ VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + VisualizationFrameworkConstants.VIS_TYPE_KEY
+ "=" + URLEncoder.encode("coauthorship", + "=" + URLEncoder.encode("coauthorship",
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + "&"
+ VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + VisualizationFrameworkConstants.RENDER_MODE_KEY
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants + "=" + URLEncoder.encode(VisualizationFrameworkConstants
.STANDALONE_RENDER_MODE_URL_VALUE, .STANDALONE_RENDER_MODE,
VisualizationController.URL_ENCODING_SCHEME) VisualizationController.URL_ENCODING_SCHEME)
.toString(); .toString();
prepareVisualizationQueryResponse(preparedURL, response); prepareUtilitiesResponse(preparedURL, response);
return; return;
} else if (VisualizationFrameworkConstants.PERSON_LEVEL_UTILS_VIS_MODE } else if (VisualizationFrameworkConstants.PERSON_LEVEL_UTILS_VIS_MODE
.equalsIgnoreCase(visMode)) { .equalsIgnoreCase(visMode)) {
/* /*
* By default we will be generating profile url else some specific url like * By default we will be generating profile url else some specific url like
* coAuthorShip vis url for that individual. * coAuthorShip vis url for that individual.
* */ * */
preparedURL += request.getContextPath() preparedURL += request.getContextPath()
+ VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX + VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX
+ "?" + "?"
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
+ "=" + URLEncoder.encode(individualURIParam, + "=" + URLEncoder.encode(individualURI,
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + "&"
+ VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE + VisualizationFrameworkConstants.VIS_TYPE_KEY
+ "=" + URLEncoder.encode("person_level", + "=" + URLEncoder.encode("person_level",
VisualizationController.URL_ENCODING_SCHEME).toString() VisualizationController.URL_ENCODING_SCHEME).toString()
+ "&" + "&"
+ VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE + VisualizationFrameworkConstants.RENDER_MODE_KEY
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants + "=" + URLEncoder.encode(VisualizationFrameworkConstants
.STANDALONE_RENDER_MODE_URL_VALUE, .STANDALONE_RENDER_MODE,
VisualizationController.URL_ENCODING_SCHEME).toString(); VisualizationController.URL_ENCODING_SCHEME).toString();
prepareVisualizationQueryResponse(preparedURL, response); prepareUtilitiesResponse(preparedURL, response);
return; return;
} else { } else {
preparedURL += request.getContextPath() preparedURL += request.getContextPath()
+ "/individual" + VisualizationFrameworkConstants.INDIVIDUAL_URL_PREFIX
+ "?" + "?"
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
+ "=" + URLEncoder.encode(individualURIParam, + "=" + URLEncoder.encode(individualURI,
VisualizationController.URL_ENCODING_SCHEME).toString(); VisualizationController.URL_ENCODING_SCHEME).toString();
prepareVisualizationQueryResponse(preparedURL, response); prepareUtilitiesResponse(preparedURL, response);
return; return;
} }
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
log.error(e.getLocalizedMessage()); log.error(e.getLocalizedMessage());
} }
@ -253,53 +255,22 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
.getBytestreamAliasUrl(downloadLocationNode.toString(), .getBytestreamAliasUrl(downloadLocationNode.toString(),
fileNameNode.toString()); fileNameNode.toString());
} }
} }
return finalThumbNailLocation; return finalThumbNailLocation;
} }
private void prepareVisualizationQueryResponse(String preparedURL, private void prepareUtilitiesResponse(String preparedURL,
HttpServletResponse response) { HttpServletResponse response) {
response.setContentType("text/plain"); response.setContentType("text/plain");
try { try {
PrintWriter responseWriter = response.getWriter();
PrintWriter responseWriter = response.getWriter(); responseWriter.append(preparedURL);
responseWriter.close();
responseWriter.append(preparedURL);
responseWriter.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); 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());
}
}
} }

View file

@ -2,7 +2,6 @@
package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
import java.util.Calendar;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -14,10 +13,6 @@ import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
*/ */
public class BiboDocument extends Individual { 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 documentMoniker;
private String documentBlurb; private String documentBlurb;
private String documentDescription; private String documentDescription;
@ -31,7 +26,7 @@ public class BiboDocument extends Individual {
} }
public String getDocumentURL() { public String getDocumentURL() {
return this.getIndividualURL(); return this.getIndividualURI();
} }
public String getDocumentMoniker() { 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 * This pattern will match all group of numbers which have only 4 digits
* delimited by the word boundary. * delimited by the word boundary.
* */ * */
// String pattern = "\\b\\d{4}\\b";
String pattern = "(?<!-)\\b\\d{4}\\b(?=[^-])"; String pattern = "(?<!-)\\b\\d{4}\\b(?=[^-])";
Pattern yearPattern = Pattern.compile(pattern); Pattern yearPattern = Pattern.compile(pattern);
@ -86,8 +80,8 @@ public class BiboDocument extends Individual {
* Published year has to be equal or less than the current year * Published year has to be equal or less than the current year
* and more than a minimum default year. * and more than a minimum default year.
* */ * */
if (candidateYearInteger <= CURRENT_YEAR if (candidateYearInteger <= VOConstants.CURRENT_YEAR
&& candidateYearInteger >= MINIMUM_PUBLICATION_YEAR) { && candidateYearInteger >= VOConstants.MINIMUM_PUBLICATION_YEAR) {
publishedYear = candidateYearInteger.toString(); publishedYear = candidateYearInteger.toString();
} }
@ -117,20 +111,22 @@ public class BiboDocument extends Individual {
* core:yearMonth points to internally. * core:yearMonth points to internally.
* */ * */
if (publicationYearMonth != null if (publicationYearMonth != null
&& publicationYearMonth.length() >= NUM_CHARS_IN_YEAR_FORMAT && publicationYearMonth.length() >= VOConstants.NUM_CHARS_IN_YEAR_FORMAT
&& isValidPublicationYear(publicationYearMonth.substring( && isValidPublicationYear(publicationYearMonth.substring(
0, 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 if (publicationDate != null
&& publicationDate.length() >= NUM_CHARS_IN_YEAR_FORMAT && publicationDate.length() >= VOConstants.NUM_CHARS_IN_YEAR_FORMAT
&& isValidPublicationYear(publicationDate.substring(0, 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) { private boolean isValidPublicationYear(String testPublicationYear) {
if (testPublicationYear.length() != 0 if (testPublicationYear.length() != 0
&& testPublicationYear.trim().length() == NUM_CHARS_IN_YEAR_FORMAT && testPublicationYear.trim().length() == VOConstants.NUM_CHARS_IN_YEAR_FORMAT
&& testPublicationYear.matches("\\d+") && testPublicationYear.matches("\\d+")
&& Integer.parseInt(testPublicationYear) >= MINIMUM_PUBLICATION_YEAR) { && Integer.parseInt(testPublicationYear) >= VOConstants.MINIMUM_PUBLICATION_YEAR) {
return true; return true;
} }

View file

@ -7,8 +7,7 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
public class CoAuthorshipData {
public class CoAuthorshipVOContainer {
private Set<Node> nodes; private Set<Node> nodes;
private Set<Edge> edges; private Set<Edge> edges;
@ -16,7 +15,7 @@ public class CoAuthorshipVOContainer {
private Set<Map<String, String>> NODE_SCHEMA; private Set<Map<String, String>> NODE_SCHEMA;
private Set<Map<String, String>> EDGE_SCHEMA; private Set<Map<String, String>> EDGE_SCHEMA;
public CoAuthorshipVOContainer(Node egoNode, Set<Node> nodes, Set<Edge> edges) { public CoAuthorshipData(Node egoNode, Set<Node> nodes, Set<Edge> edges) {
this.egoNode = egoNode; this.egoNode = egoNode;
this.nodes = nodes; this.nodes = nodes;
this.edges = edges; this.edges = edges;

View file

@ -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 * @author cdtank
* *
*/ */
@ -129,7 +130,6 @@ public class Edge {
} }
} }
@SuppressWarnings("serial")
public Integer getUnknownCollaborationYearCount() { public Integer getUnknownCollaborationYearCount() {
if (yearToPublicationCount == null) { if (yearToPublicationCount == null) {
yearToPublicationCount = UtilityFunctions yearToPublicationCount = UtilityFunctions

View file

@ -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 * 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 * 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. * could parse properties (& its values) to look for what namespaces are used.
*
* @author cdtank * @author cdtank
*
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class GenericQueryMap extends HashMap<String, Set<String>> { public class GenericQueryMap extends HashMap<String, Set<String>> {

View file

@ -5,15 +5,15 @@ package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
public class Individual { public class Individual {
private String individualLabel; private String individualLabel;
private String individualURL; private String individualURI;
public Individual(String individualURL, String individualLabel) { public Individual(String individualURI, String individualLabel) {
this.individualURL = individualURL; this.individualURI = individualURI;
this.individualLabel = individualLabel; this.individualLabel = individualLabel;
} }
public Individual(String individualURL) { public Individual(String individualURI) {
this(individualURL, ""); this(individualURI, "");
} }
public String getIndividualLabel() { public String getIndividualLabel() {
@ -24,8 +24,8 @@ public class Individual {
this.individualLabel = individualLabel; this.individualLabel = individualLabel;
} }
public String getIndividualURL() { public String getIndividualURI() {
return individualURL; return individualURI;
} }

View file

@ -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 * @author cdtank
*
*/ */
public class Node extends Individual { public class Node extends Individual {
@ -25,9 +25,9 @@ public class Node extends Individual {
private Set<BiboDocument> authorDocuments = new HashSet<BiboDocument>(); private Set<BiboDocument> authorDocuments = new HashSet<BiboDocument>();
public Node(String nodeURL, public Node(String nodeURI,
UniqueIDGenerator uniqueIDGenerator) { UniqueIDGenerator uniqueIDGenerator) {
super(nodeURL); super(nodeURI);
nodeID = uniqueIDGenerator.getNextNumericID(); nodeID = uniqueIDGenerator.getNextNumericID();
} }
@ -35,8 +35,8 @@ public class Node extends Individual {
return nodeID; return nodeID;
} }
public String getNodeURL() { public String getNodeURI() {
return this.getIndividualURL(); return this.getIndividualURI();
} }
public String getNodeName() { public String getNodeName() {
@ -59,13 +59,13 @@ public class Node extends Individual {
this.authorDocuments.add(authorDocument); this.authorDocuments.add(authorDocument);
} }
public Map<String, Integer> getYearToPublicationCount() { public Map<String, Integer> getYearToPublicationCount() {
if (yearToPublicationCount == null) { if (yearToPublicationCount == null) {
yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments); yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments);
} }
return yearToPublicationCount; return yearToPublicationCount;
} }
/* /*
* getEarliest, Latest & Unknown Publication YearCount should only be used after * getEarliest, Latest & Unknown Publication YearCount should only be used after
* the parsing of the entire sparql is done. Else it will give results based on * the parsing of the entire sparql is done. Else it will give results based on
@ -153,6 +153,4 @@ public class Node extends Individual {
return null; return null;
} }
} }
} }

View file

@ -2,7 +2,7 @@
package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
public class SparklineVOContainer { public class SparklineData {
/* /*
* For now sparklineNumPublicationsText & sparklinePublicationRangeText is left * For now sparklineNumPublicationsText & sparklinePublicationRangeText is left
@ -26,45 +26,58 @@ public class SparklineVOContainer {
public String getSparklineNumPublicationsText() { public String getSparklineNumPublicationsText() {
return sparklineNumPublicationsText; return sparklineNumPublicationsText;
} }
public void setSparklineNumPublicationsText(String sparklineNumPublicationsText) { public void setSparklineNumPublicationsText(String sparklineNumPublicationsText) {
this.sparklineNumPublicationsText = sparklineNumPublicationsText; this.sparklineNumPublicationsText = sparklineNumPublicationsText;
} }
public String getSparklinePublicationRangeText() { public String getSparklinePublicationRangeText() {
return sparklinePublicationRangeText; return sparklinePublicationRangeText;
} }
public void setSparklinePublicationRangeText( public void setSparklinePublicationRangeText(
String sparklinePublicationRangeText) { String sparklinePublicationRangeText) {
this.sparklinePublicationRangeText = sparklinePublicationRangeText; this.sparklinePublicationRangeText = sparklinePublicationRangeText;
} }
public Integer getEarliestRenderedPublicationYear() { public Integer getEarliestRenderedPublicationYear() {
return earliestRenderedPublicationYear; return earliestRenderedPublicationYear;
} }
public void setEarliestRenderedPublicationYear( public void setEarliestRenderedPublicationYear(
Integer earliestRenderedPublicationYear) { Integer earliestRenderedPublicationYear) {
this.earliestRenderedPublicationYear = earliestRenderedPublicationYear; this.earliestRenderedPublicationYear = earliestRenderedPublicationYear;
} }
public Integer getLatestRenderedPublicationYear() { public Integer getLatestRenderedPublicationYear() {
return latestRenderedPublicationYear; return latestRenderedPublicationYear;
} }
public void setLatestRenderedPublicationYear( public void setLatestRenderedPublicationYear(
Integer latestRenderedPublicationYear) { Integer latestRenderedPublicationYear) {
this.latestRenderedPublicationYear = latestRenderedPublicationYear; this.latestRenderedPublicationYear = latestRenderedPublicationYear;
} }
public String getTable() { public String getTable() {
return table; return table;
} }
public void setTable(String table) { public void setTable(String table) {
this.table = table; this.table = table;
} }
public String getDownloadDataLink() { public String getDownloadDataLink() {
return downloadDataLink; return downloadDataLink;
} }
public void setDownloadDataLink(String downloadDataLink) { public void setDownloadDataLink(String downloadDataLink) {
this.downloadDataLink = downloadDataLink; this.downloadDataLink = downloadDataLink;
} }
public String getFullTimelineNetworkLink() { public String getFullTimelineNetworkLink() {
return fullTimelineNetworkLink; return fullTimelineNetworkLink;
} }
public void setFullTimelineNetworkLink(String fullTimelineNetworkLink) { public void setFullTimelineNetworkLink(String fullTimelineNetworkLink) {
this.fullTimelineNetworkLink = fullTimelineNetworkLink; this.fullTimelineNetworkLink = fullTimelineNetworkLink;
} }
@ -72,6 +85,7 @@ public class SparklineVOContainer {
public String getSparklineContent() { public String getSparklineContent() {
return sparklineContent; return sparklineContent;
} }
public void setSparklineContent(String shortSparklineContent) { public void setSparklineContent(String shortSparklineContent) {
this.sparklineContent = shortSparklineContent; this.sparklineContent = shortSparklineContent;
} }
@ -79,8 +93,8 @@ public class SparklineVOContainer {
public String getSparklineContext() { public String getSparklineContext() {
return sparklineContext; return sparklineContext;
} }
public void setSparklineContext(String shortSparklineContext) { public void setSparklineContext(String shortSparklineContext) {
this.sparklineContext = shortSparklineContext; this.sparklineContext = shortSparklineContext;
} }
} }

View file

@ -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 * @author cdtank
*
*/ */
public class VivoCollegeOrSchool extends Individual { public class VivoCollegeOrSchool extends Individual {
private Set<VivoDepartmentOrDivision> departments = new HashSet<VivoDepartmentOrDivision>(); private Set<VivoDepartmentOrDivision> departments = new HashSet<VivoDepartmentOrDivision>();
public VivoCollegeOrSchool(String collegeURL) { public VivoCollegeOrSchool(String collegeURI) {
super(collegeURL); super(collegeURI);
} }
public Set<VivoDepartmentOrDivision> getDepartments() { public Set<VivoDepartmentOrDivision> getDepartments() {
@ -27,8 +27,8 @@ public class VivoCollegeOrSchool extends Individual {
this.departments.add(department); this.departments.add(department);
} }
public String getCollegeURL() { public String getCollegeURI() {
return this.getIndividualURL(); return this.getIndividualURI();
} }
public String getCollegeLabel() { public String getCollegeLabel() {

View file

@ -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 * @author cdtank
*
*/ */
public class VivoDepartmentOrDivision extends Individual { public class VivoDepartmentOrDivision extends Individual {
private Set<VivoCollegeOrSchool> parentColleges = new HashSet<VivoCollegeOrSchool>(); private Set<VivoCollegeOrSchool> parentColleges = new HashSet<VivoCollegeOrSchool>();
public VivoDepartmentOrDivision(String departmentURL, VivoCollegeOrSchool parentCollege) { public VivoDepartmentOrDivision(String departmentURI, VivoCollegeOrSchool parentCollege) {
super(departmentURL); super(departmentURI);
addParentCollege(parentCollege); addParentCollege(parentCollege);
} }
@ -28,8 +28,8 @@ public class VivoDepartmentOrDivision extends Individual {
this.parentColleges.add(parentCollege); this.parentColleges.add(parentCollege);
} }
public String getDepartmentURL() { public String getDepartmentURI() {
return this.getIndividualURL(); return this.getIndividualURI();
} }
public String getDepartmentLabel() { public String getDepartmentLabel() {

View file

@ -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 * @author cdtank
*
*/ */
public class VivoEmployee extends Individual { public class VivoEmployee extends Individual {
@ -27,8 +27,8 @@ public class VivoEmployee extends Individual {
addParentDepartment(parentDepartment); addParentDepartment(parentDepartment);
} }
public String getEmployeeURL() { public String getEmployeeURI() {
return this.getIndividualURL(); return this.getIndividualURI();
} }
public String getEmployeeName() { public String getEmployeeName() {

View file

@ -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 * @author cdtank
*
*/ */
public class AllPropertiesQueryHandler implements QueryHandler<GenericQueryMap> { public class AllPropertiesQueryRunner implements QueryRunner<GenericQueryMap> {
protected static final Syntax SYNTAX = Syntax.syntaxARQ; protected static final Syntax SYNTAX = Syntax.syntaxARQ;
private String filterRule, individualURLParam; private String filterRule, individualURI;
private DataSource dataSource; private DataSource dataSource;
private Log log; private Log log;
public AllPropertiesQueryHandler(String individualURLParam, public AllPropertiesQueryRunner(String individualURI,
String filterRule, String filterRule,
DataSource dataSource, DataSource dataSource,
Log log) { Log log) {
this.individualURLParam = individualURLParam; this.individualURI = individualURI;
this.filterRule = filterRule; this.filterRule = filterRule;
this.dataSource = dataSource; this.dataSource = dataSource;
this.log = log; this.log = log;
@ -53,7 +54,7 @@ public class AllPropertiesQueryHandler implements QueryHandler<GenericQueryMap>
private GenericQueryMap createJavaValueObjects(ResultSet resultSet) { private GenericQueryMap createJavaValueObjects(ResultSet resultSet) {
GenericQueryMap queryResultVO = new GenericQueryMap(); GenericQueryMap queryResult = new GenericQueryMap();
while (resultSet.hasNext()) { while (resultSet.hasNext()) {
QuerySolution solution = resultSet.nextSolution(); QuerySolution solution = resultSet.nextSolution();
@ -63,16 +64,15 @@ public class AllPropertiesQueryHandler implements QueryHandler<GenericQueryMap>
RDFNode objectNode = solution.get(QueryFieldLabels.OBJECT); RDFNode objectNode = solution.get(QueryFieldLabels.OBJECT);
if (predicateNode != null && objectNode != null) { if (predicateNode != null && objectNode != null) {
queryResultVO.addEntry(predicateNode.toString(), queryResult.addEntry(predicateNode.toString(),
objectNode.toString()); objectNode.toString());
} }
} }
return queryResultVO; return queryResult;
} }
private ResultSet executeQuery(String queryText, private ResultSet executeQuery(String queryText,
DataSource dataSource) { DataSource dataSource) {
@ -118,16 +118,15 @@ public class AllPropertiesQueryHandler implements QueryHandler<GenericQueryMap>
return sparqlQuery; return sparqlQuery;
} }
public GenericQueryMap getVisualizationJavaValueObjects() public GenericQueryMap getQueryResult()
throws MalformedQueryParametersException { throws MalformedQueryParametersException {
if (StringUtils.isNotBlank(this.individualURLParam)) { if (StringUtils.isNotBlank(this.individualURI)) {
/* /*
* To test for the validity of the URI submitted. * To test for the validity of the URI submitted.
* */ * */
IRIFactory iRIFactory = IRIFactory.jenaImplementation(); IRIFactory iRIFactory = IRIFactory.jenaImplementation();
IRI iri = iRIFactory.create(this.individualURLParam); IRI iri = iRIFactory.create(this.individualURI);
if (iri.hasViolation(false)) { if (iri.hasViolation(false)) {
String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage(); String errorMsg = ((Violation) iri.violations(false).next()).getShortMessage();
log.error("Generic Query " + errorMsg); log.error("Generic Query " + errorMsg);
@ -140,12 +139,10 @@ public class AllPropertiesQueryHandler implements QueryHandler<GenericQueryMap>
} }
ResultSet resultSet = executeQuery(generateGenericSparqlQuery( ResultSet resultSet = executeQuery(generateGenericSparqlQuery(
this.individualURLParam, this.individualURI,
this.filterRule), this.filterRule),
this.dataSource); this.dataSource);
return createJavaValueObjects(resultSet); return createJavaValueObjects(resultSet);
} }
} }

View file

@ -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 * @author cdtank
*
*/ */
public class GenericQueryHandler implements QueryHandler<ResultSet> { public class GenericQueryRunner implements QueryRunner<ResultSet> {
protected static final Syntax SYNTAX = Syntax.syntaxARQ; protected static final Syntax SYNTAX = Syntax.syntaxARQ;
@ -38,7 +40,7 @@ public class GenericQueryHandler implements QueryHandler<ResultSet> {
private Map<String, String> fieldLabelToOutputFieldLabel; private Map<String, String> fieldLabelToOutputFieldLabel;
public GenericQueryHandler(String individualURLParam, public GenericQueryRunner(String individualURLParam,
Map<String, String> fieldLabelToOutputFieldLabel, Map<String, String> fieldLabelToOutputFieldLabel,
String whereClause, String whereClause,
DataSource dataSource, DataSource dataSource,
@ -102,9 +104,8 @@ public class GenericQueryHandler implements QueryHandler<ResultSet> {
return sparqlQuery.toString(); return sparqlQuery.toString();
} }
public ResultSet getVisualizationJavaValueObjects() public ResultSet getQueryResult()
throws MalformedQueryParametersException { throws MalformedQueryParametersException {
if (StringUtils.isNotBlank(this.individualURLParam)) { if (StringUtils.isNotBlank(this.individualURLParam)) {
/* /*
@ -127,6 +128,4 @@ public class GenericQueryHandler implements QueryHandler<ResultSet> {
return resultSet; return resultSet;
} }
} }

View file

@ -4,8 +4,8 @@ package edu.cornell.mannlib.vitro.webapp.visualization.visutils;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
public interface QueryHandler<QueryResponse> { public interface QueryRunner<QueryResult> {
QueryResponse getVisualizationJavaValueObjects() throws MalformedQueryParametersException; QueryResult getQueryResult() throws MalformedQueryParametersException;
} }

View file

@ -2,14 +2,27 @@
package edu.cornell.mannlib.vitro.webapp.visualization.visutils; package edu.cornell.mannlib.vitro.webapp.visualization.visutils;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; 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.constants.VisConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.CoAuthorshipData;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
public class UtilityFunctions { public class UtilityFunctions {
@ -31,8 +44,8 @@ public class UtilityFunctions {
* I am pushing the logic to check for validity of year in "getPublicationYear" itself * I am pushing the logic to check for validity of year in "getPublicationYear" itself
* because, * because,
* 1. We will be using getPub... multiple times & this will save us duplication of code * 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 * 2. If we change the logic of validity of a pub year we would not have to make
* all throughout the codebase. * changes all throughout the codebase.
* 3. We are asking for a publication year & we should get a proper one or NOT at all. * 3. We are asking for a publication year & we should get a proper one or NOT at all.
* */ * */
String publicationYear; String publicationYear;
@ -56,6 +69,49 @@ public class UtilityFunctions {
return yearToPublicationCount; 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<String, Set<Node>> getPublicationYearToCoAuthors(
CoAuthorshipData authorNodesAndEdges) {
Map<String, Set<Node>> yearToCoAuthors = new TreeMap<String, Set<Node>>();
Node egoNode = authorNodesAndEdges.getEgoNode();
for (Node currNode : authorNodesAndEdges.getNodes()) {
/*
* We have already printed the Ego Node info.
* */
if (currNode != egoNode) {
for (String year : currNode.getYearToPublicationCount().keySet()) {
Set<Node> coAuthorNodes;
if (yearToCoAuthors.containsKey(year)) {
coAuthorNodes = yearToCoAuthors.get(year);
coAuthorNodes.add(currNode);
} else {
coAuthorNodes = new HashSet<Node>();
coAuthorNodes.add(currNode);
yearToCoAuthors.put(year, coAuthorNodes);
}
}
}
}
return yearToCoAuthors;
}
/** /**
* Currently the approach for slugifying filenames is naive. In future if there is need, * Currently the approach for slugifying filenames is naive. In future if there is need,
* we can write more sophisticated method. * we can write more sophisticated method.
@ -70,5 +126,32 @@ public class UtilityFunctions {
VisConstants.MAX_NAME_TEXT_LENGTH), VisConstants.MAX_NAME_TEXT_LENGTH),
textBlockSeparator); 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());
}
}
} }

View file

@ -10,6 +10,16 @@ import com.hp.hpl.jena.query.DataSource;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; 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 <b>must</b> 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 { public interface VisualizationRequestHandler {
void generateVisualization(VitroRequest vitroRequest, void generateVisualization(VitroRequest vitroRequest,