');
+
+ row.append($('').html(item.name));
+ row.append($(' ').html(item.number_of_authored_works));
+
+ table.append(row);
+
+ });
+
+ table.prependTo('#' + tableContainer);
+ $('#' + tableContainer + " #loadingData").remove();
+}
+
+function nodeClickedJS(json){
+
+ var obj = jQuery.parseJSON(json);
+
+ $("#dataPanel").attr("style","visibility:visible");
+ $("#authorName").empty().append(obj.name);
+ $("#works").empty().append(obj.number_of_authored_works);
+
+ /*
+ * Here obj.url points to the uri of that individual
+ */
+ if(obj.url){
+
+ if (obj.url == egoURI) {
+
+ $("#authorName").addClass('author_name').removeClass('neutral_author_name');
+ $('#num_works > .author_stats_text').text('Work(s)');
+ $('#num_authors > .author_stats_text').text('Co-author(s)');
+
+ } else {
+
+ $("#authorName").addClass('neutral_author_name').removeClass('author_name');
+ $('#num_works > .author_stats_text').text('Joint Work(s)');
+ $('#num_authors > .author_stats_text').text('Joint Co-author(s)');
+
+ }
+
+ $("#profileUrl").attr("href", getWellFormedURLs(obj.url, "profile"));
+ $("#coAuthorshipVisUrl").attr("href", getWellFormedURLs(obj.url, "coauthorship"));
+ processProfileInformation("",
+ "profileMoniker",
+ "profileImage",
+ jQuery.parseJSON(getWellFormedURLs(obj.url, "profile_info")),
+ true);
+
+
+
+ } else{
+ $("#profileUrl").attr("href","#");
+ $("#coAuthorshipVisUrl").attr("href","#");
+ }
+
+ $("#coAuthorName").empty().append(obj.name);
+
+ $("#coAuthors").empty().append(obj.num_coauthors);
+
+ $("#firstPublication").empty().append(obj.earliest_publication);
+ (obj.earliest_publication)?$("#fPub").attr("style","visibility:visible"):$("#fPub").attr("style","visibility:hidden");
+ $("#lastPublication").empty().append(obj.latest_publication);
+ (obj.latest_publication)?$("#lPub").attr("style","visibility:visible"):$("#lPub").attr("style","visibility:hidden");
+
+ // obj.url:the url parameter for node
+
+}
+
+function renderCoAuthorshipVisualization() {
+
+ // Version check for the Flash Player that has the ability to start Player
+ // Product Install (6.0r65)
+ var hasProductInstall = DetectFlashVer(6, 0, 65);
+
+ // Version check based upon the values defined in globals
+ var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
+
+ if ( hasProductInstall && !hasRequestedVersion ) {
+ // DO NOT MODIFY THE FOLLOWING FOUR LINES
+ // Location visited after installation is complete if installation is
+ // required
+ var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn";
+ var MMredirectURL = window.location;
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ var MMdoctitle = document.title;
+
+ AC_FL_RunContent(
+ "src", "playerProductInstall",
+ "FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"",
+ "width", "600",
+ "height", "840",
+ "align", "middle",
+ "id", "CoAuthor",
+ "quality", "high",
+ "bgcolor", "#ffffff",
+ "name", "CoAuthor",
+ "allowScriptAccess","sameDomain",
+ "type", "application/x-shockwave-flash",
+ "pluginspage", "http://www.adobe.com/go/getflashplayer"
+ );
+ } else if (hasRequestedVersion) {
+ // if we've detected an acceptable version
+ // embed the Flash Content SWF when all tests are passed
+ AC_FL_RunContent(
+ "src", swfLink,
+ "flashVars", "graphmlUrl=" + egoCoAuthorshipDataFeederURL,
+ "width", "600",
+ "height", "790",
+ "align", "top",
+ "id", "CoAuthor",
+ "quality", "high",
+ "bgcolor", "#ffffff",
+ "name", "CoAuthor",
+ "allowScriptAccess","sameDomain",
+ "type", "application/x-shockwave-flash",
+ "pluginspage", "http://www.adobe.com/go/getflashplayer"
+ );
+ } else { // flash is too old or we can't detect the plugin
+ var alternateContent = 'Alternate HTML content should be placed here. '
+ + 'This content requires the Adobe Flash Player. '
+ + 'Get Flash ';
+ document.write(alternateContent); // insert non-flash content
+ }
+
+}
\ No newline at end of file
diff --git a/productMods/templates/entity/sparklineVisualization.jsp b/productMods/templates/entity/sparklineVisualization.jsp
new file mode 100644
index 00000000..7cb6010e
--- /dev/null
+++ b/productMods/templates/entity/sparklineVisualization.jsp
@@ -0,0 +1,158 @@
+<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
+
+<%@ page import="edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean"%>
+<%@ page import="edu.cornell.mannlib.vitro.webapp.beans.Individual" %>
+<%@ page import="edu.cornell.mannlib.vitro.webapp.beans.VClass" %>
+<%@ page import="edu.cornell.mannlib.vitro.webapp.flags.PortalFlagChoices" %>
+<%@ page import="edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory" %>
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
+<%@ page errorPage="/error.jsp"%>
+<% /***********************************************
+ Displays the little group of things at the bottom of the page
+ for administrators and editors.
+
+ request.attributes:
+ an Entity object with the name "entity"
+
+
+ request.parameters:
+ None, should only work with requestScope attributes for security reasons.
+
+ Consider sticking < % = MiscWebUtils.getReqInfo(request) % > in the html output
+ for debugging info.
+
+ bdc34 2006-01-22 created
+ **********************************************/
+ Individual entity = (Individual)request.getAttribute("entity");
+ boolean displayVisualization = false;
+
+
+
+ if (entity == null){
+ String e = "sparklineVisuzalition.jsp expects that request attribute 'entity' be set to the Entity object to display.";
+ displayVisualization = false;
+ throw new JspException(e);
+ } else {
+ for (VClass currClass : entity.getVClasses()) {
+ //System.out.println(">> " + currClass.getName());
+ if (currClass.getName().equalsIgnoreCase("Person")) {
+ displayVisualization = true;
+ break;
+ }
+
+ }
+ }
+ //System.out.println("visualization is supposed to be displayed? > " + displayVisualization);
+ if (displayVisualization) {
+
+%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <%-- PDF Visualization URL
+
+ For now we have disabled this.
+
+
+
+
+
+
+
+
+
+ --%>
+
+
+
+
+
+
+
+
+
+
+
+ <%--
+
+ For now we have disabled PDF report vis.
+
+
+ This is the
link to PDF report.
+
+
+ --%>
+
+
+
+<%
+
+ }
+
+%>
diff --git a/productMods/templates/visualization/ajax_vis_content.jsp b/productMods/templates/visualization/ajax_vis_content.jsp
new file mode 100644
index 00000000..f0e0bfaa
--- /dev/null
+++ b/productMods/templates/visualization/ajax_vis_content.jsp
@@ -0,0 +1,12 @@
+<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
+
+<%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer" %>
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
+
+
+
+
+
+ ${sparkline.sparklineContent}
+ ${sparkline.sparklineContext}
+
diff --git a/productMods/templates/visualization/co_authorship.jsp b/productMods/templates/visualization/co_authorship.jsp
new file mode 100644
index 00000000..62623ac0
--- /dev/null
+++ b/productMods/templates/visualization/co_authorship.jsp
@@ -0,0 +1,279 @@
+<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
+
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Co-Authorship Visualization
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<%-- Label --%>
+
+
+<%-- Moniker--%>
+
+
+<%-- Image --%>
+
+
+<%-- Sparkline --%>
+
+
+
+
+ ${requestScope.egoURIParam}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
6 Works
+
78 Co-author(s)
+
+
First
+ Publication
+
Last Publication
+
+
+
+
+
+
+
+
+
+
+Download co-authorship newtwork as
.graphml file.
+
+
+
+
+
+
+
+
+
+ Publications per year
+
+
+ Year
+ Publications
+
+
+
+
+ 2004
+ 4
+
+
+ 2005
+ 2
+
+
+ 11
+
+
+ Unknown
+ 1
+
+
+
+
+Download data as
.csv file.
+
+
+ Co - Authorhips
+
+
+ Name
+ Publications
+
+
+
+
+ 2004
+ 4
+
+
+ 2005
+ 2
+
+
+ 11
+
+
+ Unknown
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/productMods/templates/visualization/dummy_vis_client.jsp b/productMods/templates/visualization/dummy_vis_client.jsp
new file mode 100644
index 00000000..50b86d12
--- /dev/null
+++ b/productMods/templates/visualization/dummy_vis_client.jsp
@@ -0,0 +1,409 @@
+<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
+
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/productMods/templates/visualization/person_level.jsp b/productMods/templates/visualization/person_level.jsp
new file mode 100644
index 00000000..c5237e99
--- /dev/null
+++ b/productMods/templates/visualization/person_level.jsp
@@ -0,0 +1,269 @@
+<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
+
+<%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer"%>
+
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <%-- Image --%>
+
+
+ <%-- Label --%>
+
+
+ <%-- Moniker--%>
+
+
+
+
+
+
This information is based solely on publications which have been loaded into the VIVO system.
+ This may only be a small sample of the person's total work.
+
+ <%-- Sparkline --%>
+
General Statistics
+
+ ${egoPubSparkline.sparklineContent}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Currently there are no ${authorsText} papers for
+ this author in the VIVO database.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Work(s)
+
Co-author(s)
+
+
First Publication
+
Last Publication
+
+
+
+
+
+
+
+
+
+
+
+
Tables
+
+
+
+ ${egoPubSparkline.table}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/productMods/templates/visualization/person_level_inject_head.jsp b/productMods/templates/visualization/person_level_inject_head.jsp
new file mode 100644
index 00000000..089d0266
--- /dev/null
+++ b/productMods/templates/visualization/person_level_inject_head.jsp
@@ -0,0 +1,64 @@
+<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
+
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/productMods/templates/visualization/publication_count.jsp b/productMods/templates/visualization/publication_count.jsp
new file mode 100644
index 00000000..662c79ee
--- /dev/null
+++ b/productMods/templates/visualization/publication_count.jsp
@@ -0,0 +1,17 @@
+<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
+
+<%@ page import="edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer" %>
+
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
+
+
+
+
+
+
+
+${sparkline.sparklineContent}
+
+${sparkline.sparklineContext}
+
diff --git a/productMods/templates/visualization/visualization_error.jsp b/productMods/templates/visualization/visualization_error.jsp
new file mode 100644
index 00000000..c35cd9ef
--- /dev/null
+++ b/productMods/templates/visualization/visualization_error.jsp
@@ -0,0 +1,11 @@
+<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
+
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
+
+
+
+${requestScope.error}
+
+
+
diff --git a/productMods/templates/visualization/visualization_scripts.jsp b/productMods/templates/visualization/visualization_scripts.jsp
new file mode 100644
index 00000000..4bbecb74
--- /dev/null
+++ b/productMods/templates/visualization/visualization_scripts.jsp
@@ -0,0 +1,26 @@
+<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
+
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
+
+<% /***********************************************
+ This file is used to inject and
+****************************************************/ %>
+
+
+
+
+
+
diff --git a/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/DummyVisClientController.java b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/DummyVisClientController.java
new file mode 100644
index 00000000..6c85942b
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/DummyVisClientController.java
@@ -0,0 +1,138 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+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 javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import edu.cornell.mannlib.vedit.beans.LoginFormBean;
+import edu.cornell.mannlib.vedit.controller.BaseEditController;
+import edu.cornell.mannlib.vitro.webapp.beans.Portal;
+import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+
+/**
+ * Services a sparql query. This will return a simple error message and a 501 if
+ * there is no jena Model.
+ *
+ * @author bdc34
+ *
+ */
+public class DummyVisClientController extends BaseEditController {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final Log log = LogFactory.getLog(DummyVisClientController.class.getName());
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ this.doGet(request,response);
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ super.doGet(request, response);
+
+ VitroRequest vreq = handleLoginAuthentication(request, response);
+ prepareVisualizationQueryResponse(request, response, vreq);
+
+ return;
+ }
+
+ private void prepareVisualizationQueryResponse(HttpServletRequest request,
+ HttpServletResponse response, VitroRequest vreq) {
+
+ Portal portal = vreq.getPortal();
+
+ RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+ request.setAttribute("bodyJsp", "/templates/visualization/dummy_vis_client.jsp");
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("title", "Dummy Visualization Client");
+ request.setAttribute("scripts", "/templates/visualization/visualization_scripts.jsp");
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+
+ }
+
+ private VitroRequest handleLoginAuthentication(HttpServletRequest request,
+ HttpServletResponse response) throws IOException {
+ // This might not be required
+ /*
+ * why are there multiple places where the login is checked? shud be abtracted into
+ * new methoid?
+ * */
+// if( !checkLoginStatus(request, response) )
+// return null;
+
+ VitroRequest vreq = new VitroRequest(request);
+
+ Object obj = vreq.getSession().getAttribute("loginHandler");
+ LoginFormBean loginHandler = null;
+
+ if( obj != null && obj instanceof LoginFormBean )
+ loginHandler = ((LoginFormBean)obj);
+
+
+ /*
+ * what is the speciality of 5 in the conditions?
+ *
+ if( loginHandler == null ||
+ ! "authenticated".equalsIgnoreCase(loginHandler.getLoginStatus()) ||
+ Integer.parseInt(loginHandler.getLoginRole()) <= 5 ){
+ HttpSession session = request.getSession(true);
+
+ session.setAttribute("postLoginRequest",
+ vreq.getRequestURI()+( vreq.getQueryString()!=null?('?' + vreq.getQueryString()):"" ));
+ String redirectURL = request.getContextPath() + Controllers.SITE_ADMIN + "?login=block";
+ response.sendRedirect(redirectURL);
+ return null;
+ }*/
+ return vreq;
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java
new file mode 100644
index 00000000..599d56bc
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java
@@ -0,0 +1,381 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.controller.visualization;
+
+/*
+Copyright (c) 2010, Cornell University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of Cornell University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.hp.hpl.jena.query.DataSource;
+import com.hp.hpl.jena.query.DatasetFactory;
+import com.hp.hpl.jena.query.Syntax;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelMaker;
+import com.hp.hpl.jena.sparql.resultset.ResultSetFormat;
+
+import edu.cornell.mannlib.vedit.beans.LoginFormBean;
+import edu.cornell.mannlib.vedit.controller.BaseEditController;
+import edu.cornell.mannlib.vitro.webapp.beans.Portal;
+import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+
+/**
+ * Services a sparql query. This will return a simple error message and a 501 if
+ * there is no jena Model.
+ *
+ * @author bdc34
+ *
+ */
+public class VisualizationController extends BaseEditController {
+
+ private static final String VIS_TYPE_URL_HANDLE = "vis";
+
+ public static final String URL_ENCODING_SCHEME = "UTF-8";
+
+ private static final long serialVersionUID = 1L;
+
+ private static final Log log = LogFactory.getLog(VisualizationController.class.getName());
+
+ protected static final Syntax SYNTAX = Syntax.syntaxARQ;
+
+ protected static HashMap formatSymbols = new HashMap();
+ static{
+ formatSymbols.put( ResultSetFormat.syntaxXML.getSymbol(), ResultSetFormat.syntaxXML);
+ formatSymbols.put( ResultSetFormat.syntaxRDF_XML.getSymbol(), ResultSetFormat.syntaxRDF_XML);
+ formatSymbols.put( ResultSetFormat.syntaxRDF_N3.getSymbol(), ResultSetFormat.syntaxRDF_N3);
+ formatSymbols.put( ResultSetFormat.syntaxText.getSymbol() , ResultSetFormat.syntaxText);
+ formatSymbols.put( ResultSetFormat.syntaxJSON.getSymbol() , ResultSetFormat.syntaxJSON);
+ formatSymbols.put( "vitro:csv", null);
+ }
+
+ protected static HashMap rdfFormatSymbols = new HashMap();
+ static {
+ rdfFormatSymbols.put( "RDF/XML", "application/rdf+xml" );
+ rdfFormatSymbols.put( "RDF/XML-ABBREV", "application/rdf+xml" );
+ rdfFormatSymbols.put( "N3", "text/n3" );
+ rdfFormatSymbols.put( "N-TRIPLE", "text/plain" );
+ rdfFormatSymbols.put( "TTL", "application/x-turtle" );
+ }
+
+ protected static HashMap mimeTypes = new HashMap();
+ static{
+ mimeTypes.put( ResultSetFormat.syntaxXML.getSymbol() , "text/xml" );
+ mimeTypes.put( ResultSetFormat.syntaxRDF_XML.getSymbol(), "application/rdf+xml" );
+ mimeTypes.put( ResultSetFormat.syntaxRDF_N3.getSymbol(), "text/plain" );
+ mimeTypes.put( ResultSetFormat.syntaxText.getSymbol() , "text/plain");
+ mimeTypes.put( ResultSetFormat.syntaxJSON.getSymbol(), "application/javascript" );
+ mimeTypes.put( "vitro:csv", "text/csv");
+ }
+
+ public static final String PERSON_PUBLICATION_COUNT_VIS_URL_VALUE
+ = "person_pub_count";
+
+ public static final String PDF_REPORT_VIS_URL_VALUE
+ = "pdf_report";
+
+ public static final String COLLEGE_PUBLICATION_COUNT_VIS_URL_VALUE
+ = "college_pub_count";
+
+ public static final String COAUTHORSHIP_VIS_URL_VALUE
+ = "coauthorship";
+
+ public static final String PERSON_LEVEL_VIS_URL_VALUE
+ = "person_level";
+
+ public static final String UTILITIES_URL_VALUE
+ = "utilities";
+
+
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ this.doGet(request,response);
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ super.doGet(request, response);
+
+ VitroRequest vreq = handleLoginAuthentication(request, response);
+
+
+ if (PERSON_PUBLICATION_COUNT_VIS_URL_VALUE
+ .equalsIgnoreCase(vreq.getParameter(VIS_TYPE_URL_HANDLE))) {
+
+ edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationRequestHandler visRequestHandler =
+ new edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationRequestHandler(vreq, request, response, log);
+
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ DataSource dataSource = setupJENADataSource(request,
+ response,
+ vreq,
+ rdfResultFormatParam);
+
+ if (dataSource != null) {
+
+ /*
+ * This is side-effecting because the visualization content is added
+ * to the request object.
+ * */
+ visRequestHandler.generateVisualization(dataSource);
+
+ } else {
+
+ log.error("ERROR! Data Model Empty");
+ }
+
+ } else if (COLLEGE_PUBLICATION_COUNT_VIS_URL_VALUE
+ .equalsIgnoreCase(vreq.getParameter(VIS_TYPE_URL_HANDLE))) {
+
+ edu.cornell.mannlib.vitro.webapp.visualization.collegepubcount.VisualizationRequestHandler visRequestHandler =
+ new edu.cornell.mannlib.vitro.webapp.visualization.collegepubcount.VisualizationRequestHandler(vreq, request, response, log);
+
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ DataSource dataSource = setupJENADataSource(request,
+ response,
+ vreq,
+ rdfResultFormatParam);
+
+ if (dataSource != null) {
+
+ /*
+ * This is side-effecting because the visualization content is added
+ * to the request object.
+ * */
+ visRequestHandler.generateVisualization(dataSource);
+
+ } else {
+ log.error("ERROR! data model empoty");
+ }
+
+ } else if (COAUTHORSHIP_VIS_URL_VALUE
+ .equalsIgnoreCase(vreq.getParameter(VIS_TYPE_URL_HANDLE))) {
+
+ edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisualizationRequestHandler visRequestHandler =
+ new edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisualizationRequestHandler(vreq, request, response, log);
+
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ DataSource dataSource = setupJENADataSource(request,
+ response,
+ vreq,
+ rdfResultFormatParam);
+
+ if (dataSource != null) {
+
+ /*
+ * This is side-effecting because the visualization content is added
+ * to the request object.
+ * */
+ visRequestHandler.generateVisualization(dataSource);
+
+ } else {
+ log.error("ERROR! data model empoty");
+ }
+
+ } else if (PERSON_LEVEL_VIS_URL_VALUE
+ .equalsIgnoreCase(vreq.getParameter(VIS_TYPE_URL_HANDLE))) {
+
+ edu.cornell.mannlib.vitro.webapp.visualization.personlevel.VisualizationRequestHandler visRequestHandler =
+ new edu.cornell.mannlib.vitro.webapp.visualization.personlevel.VisualizationRequestHandler(vreq, request, response, log);
+
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ DataSource dataSource = setupJENADataSource(request,
+ response,
+ vreq,
+ rdfResultFormatParam);
+
+ if (dataSource != null) {
+
+ /*
+ * This is side-effecting because the visualization content is added
+ * to the request object.
+ * */
+ visRequestHandler.generateVisualization(dataSource);
+
+ } else {
+ log.error("ERROR! data model empoty");
+ }
+
+ } else if (PDF_REPORT_VIS_URL_VALUE
+ .equalsIgnoreCase(vreq.getParameter(VIS_TYPE_URL_HANDLE))) {
+
+ } else if (UTILITIES_URL_VALUE
+ .equalsIgnoreCase(vreq.getParameter(VIS_TYPE_URL_HANDLE))) {
+
+ edu.cornell.mannlib.vitro.webapp.visualization.utilities.VisualizationRequestHandler visRequestHandler =
+ new edu.cornell.mannlib.vitro.webapp.visualization.utilities.VisualizationRequestHandler(vreq, request, response, log);
+
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ DataSource dataSource = setupJENADataSource(request,
+ response,
+ vreq,
+ rdfResultFormatParam);
+
+ if (dataSource != null) {
+
+ /*
+ * This is side-effecting because the visualization content is added
+ * to the request object.
+ * */
+ visRequestHandler.generateVisualization(dataSource);
+
+ } else {
+ log.error("ERROR! data model empoty");
+ }
+
+ } else {
+
+ log.debug("vis uqery parameter value -> " + vreq.getParameter("vis"));
+ log.debug("uri uqery parameter value -> " + vreq.getParameter("uri"));
+ log.debug("render_mode query parameter value -> " + vreq.getParameter("render_mode"));
+
+ /*
+ * This is side-effecting because the error content is directly
+ * added to the request object. From where it is redirected to
+ * the error page.
+ * */
+ handleMalformedParameters("Inappropriate query parameters were submitted. ", request, response);
+ }
+
+ return;
+ }
+
+ private VitroRequest handleLoginAuthentication(HttpServletRequest request,
+ HttpServletResponse response) throws IOException {
+ // This might not be required
+ /*
+ * why are there multiple places where the login is checked? shud be abtracted into
+ * new methoid?
+ * */
+// if( !checkLoginStatus(request, response) )
+// return null;
+
+ VitroRequest vreq = new VitroRequest(request);
+
+ Object obj = vreq.getSession().getAttribute("loginHandler");
+ LoginFormBean loginHandler = null;
+
+
+ if( obj != null && obj instanceof LoginFormBean )
+ loginHandler = ((LoginFormBean)obj);
+
+ /*
+ * what is the speciality of 5 in the conditions?
+ *
+ if( loginHandler == null ||
+ ! "authenticated".equalsIgnoreCase(loginHandler.getLoginStatus()) ||
+ Integer.parseInt(loginHandler.getLoginRole()) <= 5 ){
+ HttpSession session = request.getSession(true);
+
+ session.setAttribute("postLoginRequest",
+ vreq.getRequestURI()+( vreq.getQueryString()!=null?('?' + vreq.getQueryString()):"" ));
+ String redirectURL = request.getContextPath() + Controllers.SITE_ADMIN + "?login=block";
+ response.sendRedirect(redirectURL);
+ return null;
+ }
+ */
+ return vreq;
+ }
+
+ private DataSource setupJENADataSource(HttpServletRequest request,
+ HttpServletResponse response, VitroRequest vreq,
+ String rdfResultFormatParam) {
+
+ Model model = vreq.getJenaOntModel(); // getModel()
+ if( model == null ){
+ doNoModelInContext(request,response);
+ return null;
+ }
+
+ log.debug("rdfResultFormat was: " + rdfResultFormatParam);
+
+ DataSource dataSource = DatasetFactory.create() ;
+ ModelMaker maker = (ModelMaker) getServletContext().getAttribute("vitroJenaModelMaker");
+
+ dataSource.setDefaultModel(model) ;
+
+ return dataSource;
+ }
+
+ private void doNoModelInContext(HttpServletRequest request, HttpServletResponse res){
+ try {
+ res.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);
+ ServletOutputStream sos = res.getOutputStream();
+ sos.println("this service is not supporeted by the current " +
+ "webapp configuration. A jena model is required in the servlet context." );
+ } catch (IOException e) {
+ log.error("Could not write to ServletOutputStream");
+ }
+ }
+
+
+ private void handleMalformedParameters(String errorMessage, HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+
+ VitroRequest vreq = new VitroRequest(request);
+ Portal portal = vreq.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");
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+ }
+
+}
+
diff --git a/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationFrameworkConstants.java b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationFrameworkConstants.java
new file mode 100644
index 00000000..aa71d5f4
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationFrameworkConstants.java
@@ -0,0 +1,22 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.controller.visualization;
+
+public class VisualizationFrameworkConstants {
+
+ public static final String VIS_TYPE_URL_HANDLE = "vis";
+ public static final String VIS_CONTAINER_URL_HANDLE = "container";
+ public static final String INDIVIDUAL_URI_URL_HANDLE = "uri";
+ public static final String VIS_MODE_URL_HANDLE = "vis_mode";
+ public static final String RENDER_MODE_URL_HANDLE = "render_mode";
+
+
+
+ public static final String STANDALONE_RENDER_MODE_URL_VALUE = "standalone";
+ public static final String DYNAMIC_RENDER_MODE_URL_VALUE = "dynamic";
+ public static final String DATA_RENDER_MODE_URL_VALUE = "data";
+ public static final String PDF_RENDER_MODE_URL_VALUE = "pdf";
+ public static final String IMAGE_VIS_MODE_URL_VALUE = "image";
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/PDFDocument.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/PDFDocument.java
new file mode 100644
index 00000000..c8ea6fb0
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/PDFDocument.java
@@ -0,0 +1,297 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Stroke;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import com.itextpdf.text.BadElementException;
+import com.itextpdf.text.BaseColor;
+import com.itextpdf.text.Chunk;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Element;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.FontFactory;
+import com.itextpdf.text.Image;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.Phrase;
+import com.itextpdf.text.pdf.ColumnText;
+import com.itextpdf.text.pdf.PdfContentByte;
+import com.itextpdf.text.pdf.PdfGState;
+import com.itextpdf.text.pdf.PdfPCell;
+import com.itextpdf.text.pdf.PdfPTable;
+import com.itextpdf.text.pdf.PdfWriter;
+
+public class PDFDocument{
+
+
+ static Stroke stroke = new BasicStroke(5.f, BasicStroke.CAP_ROUND,
+ BasicStroke.JOIN_ROUND);
+
+ final static Color bg = Color.green;
+
+ final static Color fg = Color.black;
+
+ public PDFDocument(String authorName,
+ Map yearToPublicationCount,
+ Document document,
+ PdfWriter pdfWriter) {
+
+// setPreferredSize(new Dimension(600,400));
+
+ try {
+
+ document.addTitle("PDF Pipeline iText Prototype");
+ document.addAuthor(authorName);
+ document.addSubject("This example tests text, color, image, transparency & table functionality.");
+ document.addKeywords("text, color, image, transparency, table");
+ document.addCreator("Standalone PDF Renderer using iText");
+
+ Paragraph header = new Paragraph();
+
+ Font pageHeaderStyle = FontFactory.getFont(FontFactory.TIMES_ROMAN, 15, Font.BOLDITALIC | Font.UNDERLINE);
+ Font featureHeaderStyle = FontFactory.getFont(FontFactory.TIMES_ROMAN, 10, new BaseColor(Color.red));
+
+ header.add(new Chunk("PDF Pipeline Prototype v2 using iText\n",
+ pageHeaderStyle));
+
+ header.setSpacingAfter(15f);
+
+
+ document.add(header);
+
+
+ Paragraph content = new Paragraph();
+
+ content.add(new Chunk("Publication Count - Author Name - " + authorName,
+ featureHeaderStyle));
+
+ content.setSpacingAfter(15f);
+
+ document.add(content);
+ // step4
+
+ PdfPTable publicationCount = createTable(yearToPublicationCount);
+
+ document.add(publicationCount);
+
+ content = new Paragraph();
+
+ content.add(new Chunk("Transparency of Shapes",
+ featureHeaderStyle));
+
+ content.setSpacingAfter(15f);
+
+ document.add(content);
+
+ createTransparencyShapes(document, pdfWriter);
+
+
+ createImage(document, pdfWriter, featureHeaderStyle);
+
+ } catch (DocumentException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+
+ private void createImage(Document document, PdfWriter writer,
+ Font featureHeaderStyle) throws BadElementException,
+ MalformedURLException, IOException, DocumentException {
+ Image imageSprite = Image.getInstance(new URL("http://lh3.ggpht.com/_4msVPAgKJv8/SCRYD-pPVKI/AAAAAAAAAYU/zUN963EPoZc/s1024/102_0609.JPG"));
+ imageSprite.setAbsolutePosition(400, 500);
+ imageSprite.scaleAbsolute(171.0f, 250.0f);
+ float imageSpriteY = document.getPageSize().getHeight() * 0.60f;
+ float imageSpriteX = document.getPageSize().getWidth() * 0.65f;
+ imageSprite.setAlignment(Image.UNDERLYING);
+
+ document.add(imageSprite);
+
+ PdfContentByte cb = writer.getDirectContent();
+ ColumnText ct = new ColumnText(cb);
+ Chunk imageHeader = new Chunk("Images",
+ featureHeaderStyle);
+ ct.addText(imageHeader);
+ ct.setAlignment(Element.ALIGN_LEFT);
+ ct.setSimpleColumn(imageSpriteX, imageSpriteY - imageSprite.getScaledHeight(),
+ imageSpriteX + imageSprite.getScaledWidth(), imageSpriteY + imageSprite.getScaledHeight() + 20);
+ ct.go();
+
+ ct = new ColumnText(cb);
+ Chunk imageFooter = new Chunk("Footer to be set for a figure. Similar to 'image cpation'.",
+ FontFactory.getFont(FontFactory.TIMES_ROMAN, 8));
+ ct.addText(imageFooter);
+ ct.setAlignment(Element.ALIGN_CENTER);
+ ct.setSimpleColumn(imageSpriteX, imageSpriteY - 150, imageSpriteX + imageSprite.getScaledWidth(), imageSpriteY);
+ ct.go();
+ }
+
+ private void createTransparencyShapes(Document document,
+ PdfWriter writer) throws Exception {
+ PdfContentByte cb = writer.getDirectContent();
+
+ pictureBackdrop(document.leftMargin(), 350, cb);
+ cb.saveState();
+ PdfGState gs1 = new PdfGState();
+ gs1.setFillOpacity(0.5f);
+ cb.setGState(gs1);
+ pictureCircles(document.leftMargin(), 350, cb);
+ cb.restoreState();
+
+ cb.resetRGBColorFill();
+ }
+
+ /**
+ * Prints a square and fills half of it with a gray rectangle.
+ * @param x
+ * @param y
+ * @param cb
+ * @throws Exception
+ */
+ public void pictureBackdrop(float x, float y, PdfContentByte cb) throws Exception {
+ cb.setColorStroke(new BaseColor(Color.black));
+ cb.setColorFill(new BaseColor(Color.gray));
+ cb.rectangle(x, y, 100, 200);
+ cb.fill();
+ cb.setLineWidth(2);
+ cb.rectangle(x, y, 200, 200);
+ cb.stroke();
+ }
+
+ /**
+ * Prints 3 circles in different colors that intersect with eachother.
+ * @param x
+ * @param y
+ * @param cb
+ * @throws Exception
+ */
+ public void pictureCircles(float x, float y, PdfContentByte cb) throws Exception {
+
+ cb.saveState();
+ PdfGState gs1 = new PdfGState();
+ gs1.setFillOpacity(1.0f);
+ cb.setGState(gs1);
+ cb.setColorFill(new BaseColor(Color.red));
+ cb.circle(x + 70, y + 70, 50);
+ cb.fill();
+ cb.restoreState();
+
+ cb.setColorFill(new BaseColor(Color.yellow));
+ cb.circle(x + 100, y + 130, 50);
+ cb.fill();
+ cb.setColorFill(new BaseColor(Color.blue));
+ cb.circle(x + 130, y + 70, 50);
+ cb.fill();
+ }
+
+ private PdfPTable createTable(Map yearToPublicationCount) {
+
+ Font normalContentStyle = FontFactory.getFont(FontFactory.TIMES_ROMAN, 11);
+ Font summaryContentStyle = FontFactory.getFont(FontFactory.TIMES_ROMAN, 11, Font.BOLDITALIC);
+ BaseColor summaryBackgroundColor = new BaseColor(0xEE, 0xEE, 0xEE);
+ BaseColor headerBackgroundColor = new BaseColor(0xC3, 0xD9, 0xFF);
+ BaseColor bodyBackgroundColor = new BaseColor(Color.white);
+
+ PdfPTable table = new PdfPTable(2);
+ table.setWidthPercentage(36.0f);
+
+ table.setHorizontalAlignment(Element.ALIGN_LEFT);
+ table.getDefaultCell().setBorderWidth(0.0f);
+ table.setHeaderRows(2);
+
+ PdfPCell cell;
+ cell = new PdfPCell(new Phrase("Publications per year", normalContentStyle));
+ setTableCaptionStyle(summaryBackgroundColor, cell);
+ table.addCell(cell);
+
+ cell = new PdfPCell(new Phrase("Year", normalContentStyle));
+ setTableHeaderStyle(headerBackgroundColor, cell);
+ table.addCell(cell);
+
+ cell.setPhrase(new Phrase("Publications", normalContentStyle));
+ table.addCell(cell);
+
+
+
+ setTableBodyStyle(bodyBackgroundColor, cell);
+ int totalPublications = 0;
+
+ for (Entry currentEntry : yearToPublicationCount.entrySet()) {
+
+ cell.setPhrase(new Phrase(currentEntry.getKey(), normalContentStyle));
+ table.addCell(cell);
+
+ cell.setPhrase(new Phrase(currentEntry.getValue().toString(), normalContentStyle));
+ table.addCell(cell);
+
+ totalPublications += currentEntry.getValue();
+ }
+
+ setTableFooterStyle(summaryBackgroundColor, cell);
+ cell.setPhrase(new Phrase("Total", summaryContentStyle));
+ table.addCell(cell);
+
+ cell.setPhrase(new Phrase(String.valueOf(totalPublications), summaryContentStyle));
+ table.addCell(cell);
+
+ return table;
+ }
+
+ private void setTableFooterStyle(BaseColor footerBackgroundColor,
+ PdfPCell cell) {
+ cell.setBorderWidth(0.0f);
+ cell.setBackgroundColor(footerBackgroundColor);
+ cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ cell.setPaddingTop(5f);
+ cell.setPaddingRight(10f);
+ cell.setPaddingBottom(5f);
+ cell.setPaddingLeft(10f);
+ }
+
+ private void setTableBodyStyle(BaseColor bodyBackgroundColor,
+ PdfPCell cell) {
+ cell.setBorderWidth(0.0f);
+ cell.setBackgroundColor(bodyBackgroundColor);
+ cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ cell.setPaddingTop(5f);
+ cell.setPaddingRight(10f);
+ cell.setPaddingBottom(5f);
+ cell.setPaddingLeft(10f);
+ }
+
+ private void setTableHeaderStyle(BaseColor headerBackgroundColor,
+ PdfPCell cell) {
+ cell.setBorderWidth(0.0f);
+ cell.setBackgroundColor(headerBackgroundColor);
+ cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ cell.setPaddingTop(5f);
+ cell.setPaddingRight(10f);
+ cell.setPaddingBottom(5f);
+ cell.setPaddingLeft(10f);
+ }
+
+ private void setTableCaptionStyle(BaseColor summaryBackgroundColor,
+ PdfPCell cell) {
+ cell.setBorderWidth(0.0f);
+ cell.setBackgroundColor(summaryBackgroundColor);
+ cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ cell.setPaddingTop(5.0f);
+ cell.setPaddingRight(10.0f);
+ cell.setPaddingBottom(5.0f);
+ cell.setPaddingLeft(10.0f);
+ cell.setColspan(2);
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipGraphMLWriter.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipGraphMLWriter.java
new file mode 100644
index 00000000..7dd5a9a6
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/CoAuthorshipGraphMLWriter.java
@@ -0,0 +1,336 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Map;
+import java.util.Set;
+
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Edge;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
+
+public class CoAuthorshipGraphMLWriter {
+
+ private StringBuilder coAuthorshipGraphMLContent;
+
+ private final String GRAPHML_HEADER = "\n"
+ + " \n\n";
+
+ private final String GRAPHML_FOOTER = " ";
+
+ public CoAuthorshipGraphMLWriter(VisVOContainer visVOContainer) {
+
+ coAuthorshipGraphMLContent = createCoAuthorshipGraphMLContent(visVOContainer);
+
+ }
+
+ public StringBuilder getCoAuthorshipGraphMLContent() {
+ return coAuthorshipGraphMLContent;
+ }
+
+ private StringBuilder createCoAuthorshipGraphMLContent(
+ VisVOContainer visVOContainer) {
+
+ StringBuilder graphMLContent = new StringBuilder();
+
+ graphMLContent.append(GRAPHML_HEADER);
+
+ /*
+ * We are side-effecting "graphMLContent" object in this method since creating
+ * another String object to hold key definition data will be redundant & will
+ * not serve the purpose.
+ * */
+ generateKeyDefinitionContent(visVOContainer, graphMLContent);
+
+ /*
+ * Used to generate graph content. It will contain both the nodes & edge information.
+ * We are side-effecting "graphMLContent".
+ * */
+ generateGraphContent(visVOContainer, graphMLContent);
+
+ graphMLContent.append(GRAPHML_FOOTER);
+
+ return graphMLContent;
+ }
+
+ private void generateGraphContent(VisVOContainer visVOContainer,
+ StringBuilder graphMLContent) {
+
+ graphMLContent.append("\n\n");
+
+ if (visVOContainer.getNodes() != null & visVOContainer.getNodes().size() > 0) {
+ generateNodeSectionContent(visVOContainer, graphMLContent);
+ }
+
+ if (visVOContainer.getEdges() != null & visVOContainer.getEdges().size() > 0) {
+ generateEdgeSectionContent(visVOContainer, graphMLContent);
+ }
+
+ graphMLContent.append(" \n");
+
+
+
+
+ }
+
+ private void generateEdgeSectionContent(VisVOContainer visVOContainer,
+ StringBuilder graphMLContent) {
+
+ graphMLContent.append("\n");
+
+ Set edges = visVOContainer.getEdges();
+
+
+ for (Edge currentEdge : edges) {
+
+ /*
+ * This method actually creates the XML code for a single edge. "graphMLContent"
+ * is being side-effected.
+ * */
+ getEdgeContent(graphMLContent, currentEdge);
+
+ }
+
+ }
+
+ private void getEdgeContent(StringBuilder graphMLContent, Edge currentEdge) {
+
+ graphMLContent.append("\n");
+
+ graphMLContent.append("\t" + currentEdge.getSourceNode().getNodeName() + " \n");
+ graphMLContent.append("\t" + currentEdge.getTargetNode().getNodeName() + " \n");
+
+ graphMLContent.append("\t"
+ + currentEdge.getNumOfCoAuthoredWorks()
+ + " \n");
+
+ if (currentEdge.getEarliestCollaborationYearCount() != null) {
+
+ /*
+ * 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.
+ * I am feeling dirty just about now.
+ * */
+ for (Map.Entry publicationInfo :
+ currentEdge.getEarliestCollaborationYearCount().entrySet()) {
+
+ graphMLContent.append("\t"
+ + publicationInfo.getKey()
+ + " \n");
+
+ graphMLContent.append("\t"
+ + publicationInfo.getValue()
+ + " \n");
+
+
+ }
+
+ }
+
+ if (currentEdge.getLatestCollaborationYearCount() != null) {
+
+ for (Map.Entry publicationInfo :
+ currentEdge.getLatestCollaborationYearCount().entrySet()) {
+
+ graphMLContent.append("\t"
+ + publicationInfo.getKey()
+ + " \n");
+
+ graphMLContent.append("\t"
+ + publicationInfo.getValue()
+ + " \n");
+ }
+
+ }
+
+ if (currentEdge.getUnknownCollaborationYearCount() != null) {
+
+ graphMLContent.append("\t"
+ + currentEdge.getUnknownCollaborationYearCount()
+ + " \n");
+
+ }
+
+ graphMLContent.append(" \n");
+
+
+ }
+
+ private void generateNodeSectionContent(VisVOContainer visVOContainer,
+ StringBuilder graphMLContent) {
+
+ graphMLContent.append("\n");
+
+ Node egoNode = visVOContainer.getEgoNode();
+ Set authorNodes = visVOContainer.getNodes();
+
+ /*
+ * This method actually creates the XML code for a single node. "graphMLContent"
+ * is being side-effected. The egoNode is added first because this is the "requirement"
+ * of the co-author vis. Ego should always come first.
+ *
+ * */
+ getNodeContent(graphMLContent, egoNode);
+
+
+ for (Node currNode : authorNodes) {
+
+ /*
+ * We have already printed the Ego Node info.
+ * */
+ if (currNode != egoNode) {
+
+ getNodeContent(graphMLContent, currNode);
+
+ }
+
+ }
+
+ }
+
+ private void getNodeContent(StringBuilder graphMLContent, Node node) {
+
+ String profileURL = null;
+ try {
+ profileURL = "/individual?"
+ + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ + "=" + URLEncoder.encode(node.getNodeURL(),
+ VisualizationController
+ .URL_ENCODING_SCHEME).toString();
+ } catch (UnsupportedEncodingException e) {
+ System.err.println("URL Encoding ERRor. Move this to use log.error ASAP");
+ }
+
+
+
+ graphMLContent.append("\n");
+ graphMLContent.append("\t" + node.getNodeURL() + " \n");
+ graphMLContent.append("\t" + node.getNodeName() + " \n");
+
+ if (profileURL != null) {
+ graphMLContent.append("\t" + profileURL + " \n");
+ }
+
+
+ graphMLContent.append("\t"
+ + node.getNumOfAuthoredWorks()
+ + " \n");
+
+ if (node.getEarliestPublicationYearCount() != null) {
+
+ /*
+ * 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.
+ * I am feeling dirty just about now.
+ * */
+ for (Map.Entry publicationInfo :
+ node.getEarliestPublicationYearCount().entrySet()) {
+
+ graphMLContent.append("\t"
+ + publicationInfo.getKey()
+ + " \n");
+
+ graphMLContent.append("\t"
+ + publicationInfo.getValue()
+ + " \n");
+
+
+ }
+
+ }
+
+ if (node.getLatestPublicationYearCount() != null) {
+
+ for (Map.Entry publicationInfo :
+ node.getLatestPublicationYearCount().entrySet()) {
+
+ graphMLContent.append("\t"
+ + publicationInfo.getKey()
+ + " \n");
+
+ graphMLContent.append("\t"
+ + publicationInfo.getValue()
+ + " \n");
+
+
+ }
+
+ }
+
+ if (node.getUnknownPublicationYearCount() != null) {
+
+ graphMLContent.append("\t"
+ + node.getUnknownPublicationYearCount()
+ + " \n");
+
+ }
+
+ graphMLContent.append(" \n");
+ }
+
+ private void generateKeyDefinitionContent(VisVOContainer visVOContainer,
+ StringBuilder graphMLContent) {
+
+ /*
+ * Generate the key definition content for node.
+ * */
+ getKeyDefinitionFromSchema(visVOContainer.getNodeSchema(), graphMLContent);
+
+ /*
+ * Generate the key definition content for edge.
+ * */
+ getKeyDefinitionFromSchema(visVOContainer.getEdgeSchema(), graphMLContent);
+
+
+ }
+
+ private void getKeyDefinitionFromSchema(Set> schema,
+ StringBuilder graphMLContent) {
+
+ for (Map currentNodeSchemaAttribute : schema) {
+
+ graphMLContent.append("\n currentAttributeKey : currentNodeSchemaAttribute.entrySet()) {
+
+ graphMLContent.append(currentAttributeKey.getKey()
+ + "=\"" + currentAttributeKey.getValue()
+ + "\" ");
+
+ }
+
+ if (currentNodeSchemaAttribute.containsKey("default")) {
+
+ graphMLContent.append(">\n");
+ graphMLContent.append("");
+ graphMLContent.append(currentNodeSchemaAttribute.get("default"));
+ graphMLContent.append(" \n");
+ graphMLContent.append(" \n");
+
+ } else {
+ graphMLContent.append("/>\n");
+ }
+
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/QueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/QueryHandler.java
new file mode 100644
index 00000000..be3fc699
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/QueryHandler.java
@@ -0,0 +1,461 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.commons.logging.Log;
+
+import com.hp.hpl.jena.iri.IRI;
+import com.hp.hpl.jena.iri.IRIFactory;
+import com.hp.hpl.jena.iri.Violation;
+import com.hp.hpl.jena.query.DataSource;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+import com.hp.hpl.jena.query.QueryFactory;
+import com.hp.hpl.jena.query.QuerySolution;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.query.Syntax;
+import com.hp.hpl.jena.rdf.model.RDFNode;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryFieldLabels;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Edge;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoCollegeOrSchool;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UniqueIDGenerator;
+
+
+
+/**
+ * @author cdtank
+ */
+public class QueryHandler {
+
+ protected static final Syntax SYNTAX = Syntax.syntaxARQ;
+
+ private String egoURLParam, resultFormatParam, rdfResultFormatParam;
+ private Map collegeURLToVO = new HashMap();
+ private DataSource dataSource;
+
+ private Log log;
+
+ private UniqueIDGenerator nodeIDGenerator;
+
+ private UniqueIDGenerator edgeIDGenerator;
+
+ public QueryHandler(String egoURLParam,
+ String resultFormatParam, String rdfResultFormatParam,
+ DataSource dataSource, Log log) {
+
+ this.egoURLParam = egoURLParam;
+ this.resultFormatParam = resultFormatParam;
+ this.rdfResultFormatParam = rdfResultFormatParam;
+ this.dataSource = dataSource;
+ this.log = log;
+
+ this.nodeIDGenerator = new UniqueIDGenerator();
+ this.edgeIDGenerator = new UniqueIDGenerator();
+
+ }
+
+ private VisVOContainer createJavaValueObjects(ResultSet resultSet) {
+
+ Set nodes = new HashSet();
+
+ Map biboDocumentURLToVO = new HashMap();
+ Map> biboDocumentURLToCoAuthors = new HashMap>();
+ Map nodeURLToVO = new HashMap();
+
+ Node egoNode = null;
+
+ Set edges = new HashSet();
+
+ while (resultSet.hasNext()) {
+ QuerySolution solution = resultSet.nextSolution();
+
+
+ /*
+ * We only want to create only ONE ego node.
+ * */
+ RDFNode egoAuthorURLNode = solution.get(QueryFieldLabels.AUTHOR_URL);
+ if (nodeURLToVO.containsKey(egoAuthorURLNode.toString())) {
+
+ egoNode = nodeURLToVO.get(egoAuthorURLNode.toString());
+
+ } else {
+
+ egoNode = new Node(egoAuthorURLNode.toString(), nodeIDGenerator);
+ nodes.add(egoNode);
+ nodeURLToVO.put(egoAuthorURLNode.toString(), egoNode);
+
+ RDFNode authorLabelNode = solution.get(QueryFieldLabels.AUTHOR_LABEL);
+ if (authorLabelNode != null) {
+ egoNode.setNodeName(authorLabelNode.toString());
+ }
+ }
+
+ RDFNode documentNode = solution.get(QueryFieldLabels.DOCUMENT_URL);
+ BiboDocument biboDocument;
+
+ if (biboDocumentURLToVO.containsKey(documentNode.toString())) {
+ biboDocument = biboDocumentURLToVO.get(documentNode.toString());
+ } else {
+ biboDocument = createDocumentVO(solution, documentNode.toString());
+ biboDocumentURLToVO.put(documentNode.toString(), biboDocument);
+ }
+
+ egoNode.addAuthorDocument(biboDocument);
+
+ /*
+ * After some discussion we concluded that for the purpose of this visualization
+ * we do not want a co-author node or edge if the publication has only one
+ * author and that happens to be the ego.
+ * */
+ if (solution.get(QueryFieldLabels.AUTHOR_URL).toString().equalsIgnoreCase(
+ solution.get(QueryFieldLabels.CO_AUTHOR_URL).toString())) {
+ continue;
+ }
+
+ Node coAuthorNode;
+
+ RDFNode coAuthorURLNode = solution.get(QueryFieldLabels.CO_AUTHOR_URL);
+ if (nodeURLToVO.containsKey(coAuthorURLNode.toString())) {
+
+ coAuthorNode = nodeURLToVO.get(coAuthorURLNode.toString());
+
+ } else {
+
+ coAuthorNode = new Node(coAuthorURLNode.toString(), nodeIDGenerator);
+ nodes.add(coAuthorNode);
+ nodeURLToVO.put(coAuthorURLNode.toString(), coAuthorNode);
+
+ RDFNode coAuthorLabelNode = solution.get(QueryFieldLabels.CO_AUTHOR_LABEL);
+ if (coAuthorLabelNode != null) {
+ coAuthorNode.setNodeName(coAuthorLabelNode.toString());
+ }
+ }
+
+ coAuthorNode.addAuthorDocument(biboDocument);
+
+ Set coAuthorsForCurrentBiboDocument;
+
+ if (biboDocumentURLToCoAuthors.containsKey(biboDocument.getDocumentURL())) {
+ coAuthorsForCurrentBiboDocument = biboDocumentURLToCoAuthors.get(biboDocument.getDocumentURL());
+ } else {
+ coAuthorsForCurrentBiboDocument = new HashSet();
+ biboDocumentURLToCoAuthors.put(biboDocument.getDocumentURL(), coAuthorsForCurrentBiboDocument);
+ }
+
+ coAuthorsForCurrentBiboDocument.add(coAuthorNode);
+
+ Edge egoCoAuthorEdge = getExistingEdge(egoNode, coAuthorNode, edges);
+
+ /*
+ * If "egoCoAuthorEdge" is null it means that no edge exists in between the egoNode & current
+ * coAuthorNode. Else create a new edge, add it to the edges set & add the collaborator document
+ * to it.
+ * */
+ if (egoCoAuthorEdge != null) {
+ egoCoAuthorEdge.addCollaboratorDocument(biboDocument);
+ } else {
+ egoCoAuthorEdge = new Edge(egoNode, coAuthorNode, biboDocument, edgeIDGenerator);
+ edges.add(egoCoAuthorEdge);
+ }
+
+
+ }
+
+ /*
+ * 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);
+
+
+/* System.out.println(collegeURLToVO);
+ System.out.println("------------------------------------------------------------");
+ System.out.println(departmentURLToVO);
+ System.out.println("------------------------------------------------------------");
+ System.out.println(employeeURLToVO);
+ System.out.println("------------------------------------------------------------");
+*/
+ return new VisVOContainer(egoNode, nodes, edges);
+ }
+
+ private void createCoAuthorEdges(
+ Map biboDocumentURLToVO,
+ Map> biboDocumentURLToCoAuthors, Set edges) {
+ for (Map.Entry> currentBiboDocumentEntry : biboDocumentURLToCoAuthors.entrySet()) {
+ /*
+ * If there was only one co-author (other than ego) then we dont have to create any edges. so
+ * the below condition will take care of that.
+ * */
+ if (currentBiboDocumentEntry.getValue().size() > 1) {
+
+ /*
+ * In order to leverage the nested "for loop" for making edges between all the co=authors
+ * we need to create a list out of the set first.
+ * */
+ List coAuthorNodes = new ArrayList(currentBiboDocumentEntry.getValue());
+
+ int numOfCoAuthors = coAuthorNodes.size();
+
+ for (int ii = 0; ii < numOfCoAuthors - 1; ii++) {
+ for (int jj = ii + 1; jj < numOfCoAuthors; jj++) {
+
+ Node coAuthor1 = coAuthorNodes.get(ii);
+ Node coAuthor2 = coAuthorNodes.get(jj);
+
+ Edge coAuthor1_2Edge = getExistingEdge(coAuthor1, coAuthor2, edges);
+
+ BiboDocument currentBiboDocument = biboDocumentURLToVO
+ .get(currentBiboDocumentEntry.getKey());
+
+ if (coAuthor1_2Edge != null) {
+ coAuthor1_2Edge.addCollaboratorDocument(currentBiboDocument);
+ } else {
+ coAuthor1_2Edge = new Edge(coAuthor1, coAuthor2, currentBiboDocument, edgeIDGenerator);
+ edges.add(coAuthor1_2Edge);
+ }
+ }
+ }
+
+ }
+
+ }
+ }
+
+ private Edge getExistingEdge(
+ Node collaboratingNode1,
+ Node collaboratingNode2,
+ Set edges) {
+
+ Edge duplicateEdge = null;
+
+ for (Edge currentEdge : edges) {
+
+ /*
+ * We first check if either the source or target node of the current edge is
+ * the collaboratingNode1. If yes then we go on to check if the collaboratingNode2
+ * matches either the source or the target node. We dont care about the directionality
+ * of the edge.
+ * */
+ if (currentEdge.getSourceNode().getNodeID() == collaboratingNode1.getNodeID()
+ || currentEdge.getTargetNode().getNodeID() == collaboratingNode1.getNodeID()) {
+
+ if (currentEdge.getSourceNode().getNodeID() == collaboratingNode2.getNodeID()
+ || currentEdge.getTargetNode().getNodeID() == collaboratingNode2.getNodeID()) {
+
+ duplicateEdge = currentEdge;
+ break;
+ }
+ }
+ }
+
+ return duplicateEdge;
+ }
+
+ public Map getCollegeURLToVO() {
+ return collegeURLToVO;
+ }
+
+ private BiboDocument createDocumentVO(QuerySolution solution, String documentURL) {
+
+ BiboDocument biboDocument = new BiboDocument(documentURL);
+
+ RDFNode documentLabelNode = solution.get(QueryFieldLabels.DOCUMENT_LABEL);
+ if (documentLabelNode != null) {
+ biboDocument.setDocumentLabel(documentLabelNode.toString());
+ }
+
+ RDFNode documentBlurbNode = solution.get(QueryFieldLabels.DOCUMENT_BLURB);
+ if (documentBlurbNode != null) {
+ biboDocument.setDocumentBlurb(documentBlurbNode.toString());
+ }
+
+ RDFNode documentMonikerNode = solution.get(QueryFieldLabels.DOCUMENT_MONIKER);
+ if (documentMonikerNode != null) {
+ biboDocument.setDocumentMoniker(documentMonikerNode.toString());
+ }
+
+ RDFNode publicationYearNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR);
+ if (publicationYearNode != null) {
+ biboDocument.setPublicationYear(publicationYearNode.toString());
+ }
+
+ RDFNode publicationYearMonthNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR_MONTH);
+ if (publicationYearMonthNode != null) {
+ biboDocument.setPublicationYearMonth(publicationYearMonthNode.toString());
+ }
+
+ RDFNode publicationDateNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_DATE);
+ if (publicationDateNode != null) {
+ biboDocument.setPublicationDate(publicationDateNode.toString());
+ }
+
+ return biboDocument;
+ }
+
+ private ResultSet executeQuery(String queryText,
+ String resultFormatParam,
+ String rdfResultFormatParam,
+ DataSource dataSource) {
+
+ QueryExecution queryExecution = null;
+ try{
+ Query query = QueryFactory.create(queryText, SYNTAX);
+
+// QuerySolutionMap qs = new QuerySolutionMap();
+// qs.add("authPerson", queryParam); // bind resource to s
+
+ queryExecution = QueryExecutionFactory.create(query, dataSource);
+
+
+ //remocve this if loop after knowing what is describe & construct sparql stuff.
+ if (query.isSelectType()){
+ return queryExecution.execSelect();
+ }
+ } finally {
+ if(queryExecution != null) {
+ queryExecution.close();
+ }
+
+ }
+ return null;
+ }
+
+ private String generateEgoCoAuthorshipSparqlQuery(String queryURI) {
+// Resource uri1 = ResourceFactory.createResource(queryURI);
+
+ String sparqlQuery = QueryConstants.getSparqlPrefixQuery()
+ + "SELECT "
+ + " (str(<" + queryURI + ">) as ?" + QueryFieldLabels.AUTHOR_URL + ") "
+ + " (str(?authorLabel) as ?" + QueryFieldLabels.AUTHOR_LABEL + ") "
+ + " (str(?coAuthorPerson) as ?" + QueryFieldLabels.CO_AUTHOR_URL + ") "
+ + " (str(?coAuthorPersonLabel) as ?" + QueryFieldLabels.CO_AUTHOR_LABEL + ") "
+ + " (str(?document) as ?" + QueryFieldLabels.DOCUMENT_URL + ") "
+ + " (str(?documentLabel) as ?" + QueryFieldLabels.DOCUMENT_LABEL + ") "
+ + " (str(?documentMoniker) as ?" + QueryFieldLabels.DOCUMENT_MONIKER + ") "
+ + " (str(?documentBlurb) as ?" + QueryFieldLabels.DOCUMENT_BLURB + ") "
+ + " (str(?publicationYear) as ?" + QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR + ") "
+ + " (str(?publicationYearMonth) as ?" + QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR_MONTH + ") "
+ + " (str(?publicationDate) as ?" + QueryFieldLabels.DOCUMENT_PUBLICATION_DATE + ") "
+ + "WHERE { "
+ + "<" + queryURI + "> rdf:type foaf:Person ; rdfs:label ?authorLabel ; core:authorInAuthorship ?authorshipNode . "
+ + "?authorshipNode rdf:type core:Authorship ; core:linkedInformationResource ?document . "
+ + "?document rdf:type bibo:Document . "
+ + "?document rdfs:label ?documentLabel . "
+ + "?document core:informationResourceInAuthorship ?coAuthorshipNode . "
+ + "?coAuthorshipNode core:linkedAuthor ?coAuthorPerson . "
+ + "?coAuthorPerson rdfs:label ?coAuthorPersonLabel . "
+ + "OPTIONAL { ?document core:year ?publicationYear } . "
+ + "OPTIONAL { ?document core:yearMonth ?publicationYearMonth } . "
+ + "OPTIONAL { ?document core:date ?publicationDate } . "
+ + "OPTIONAL { ?document vitro:moniker ?documentMoniker } . "
+ + "OPTIONAL { ?document vitro:blurb ?documentBlurb } . "
+ + "OPTIONAL { ?document vitro:description ?documentDescription } "
+// + "FILTER (<" + queryURI + "> != ?coAuthorPerson ) . "
+ + "}";
+
+// System.out.println(sparqlQuery);
+
+ return sparqlQuery;
+ }
+
+
+ public VisVOContainer getVisualizationJavaValueObjects()
+ throws MalformedQueryParametersException {
+
+ if (this.egoURLParam == null || "".equals(egoURLParam)) {
+ throw new MalformedQueryParametersException("URI parameter is either null or empty.");
+ } else {
+
+ /*
+ * To test for the validity of the URI submitted.
+ * */
+ IRIFactory iRIFactory = IRIFactory.jenaImplementation();
+ IRI iri = iRIFactory.create(this.egoURLParam);
+ if (iri.hasViolation(false)) {
+ String errorMsg = ((Violation)iri.violations(false).next()).getShortMessage()+" ";
+ log.error("Ego Co Authorship Vis Query " + errorMsg);
+ throw new MalformedQueryParametersException("URI provided for an individual is malformed.");
+ }
+ }
+
+ ResultSet resultSet = executeQuery(generateEgoCoAuthorshipSparqlQuery(this.egoURLParam),
+ this.resultFormatParam,
+ this.rdfResultFormatParam,
+ this.dataSource);
+
+ return createJavaValueObjects(resultSet);
+ }
+
+ public Map getYearToPublicationCount(
+ Set authorDocuments) {
+
+ /*
+ * Create a map from the year to number of publications. Use the BiboDocument's
+ * parsedPublicationYear to populate the data.
+ *
+ * I am pushing the logic to check for validity of year in "getPublicationYear" itself
+ * because,
+ * 1. We will be using getPub... multiple times & this will save us duplication of code
+ * 2. If we change the logic of validity of a pub year we would not have to make changes
+ * all throughout the codebase.
+ * 3. We are asking for a publication year & we should get a proper one or NOT at all.
+ * */
+ Map yearToPublicationCount = new TreeMap();
+
+ for (BiboDocument curr : authorDocuments) {
+
+ /*
+ * Increment the count because there is an entry already available for
+ * that particular year.
+ * */
+ String publicationYear;
+ if (curr.getPublicationYear() != null) {
+ publicationYear = curr.getPublicationYear();
+ } else {
+ publicationYear = curr.getParsedPublicationYear();
+ }
+
+ if (yearToPublicationCount.containsKey(publicationYear)) {
+ yearToPublicationCount.put(publicationYear,
+ yearToPublicationCount
+ .get(publicationYear) + 1);
+
+ } else {
+ yearToPublicationCount.put(publicationYear, 1);
+ }
+
+ }
+
+ return yearToPublicationCount;
+ }
+
+
+
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisVOContainer.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisVOContainer.java
new file mode 100644
index 00000000..e39e965f
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisVOContainer.java
@@ -0,0 +1,234 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship;
+
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Edge;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
+
+public class VisVOContainer {
+
+ private Set nodes;
+ private Set edges;
+ private Node egoNode;
+ private Set> NODE_SCHEMA;
+ private Set> EDGE_SCHEMA;
+
+ public VisVOContainer(Node egoNode, Set nodes, Set edges) {
+ this.egoNode = egoNode;
+ this.nodes = nodes;
+ this.edges = edges;
+ }
+
+ public Set getNodes() {
+ return nodes;
+ }
+
+ public Set getEdges() {
+ return edges;
+ }
+
+ public Node getEgoNode() {
+ return egoNode;
+ }
+
+ /*
+ * Node Schema for graphML
+ * */
+ public Set> getNodeSchema() {
+
+ if (NODE_SCHEMA == null) {
+ NODE_SCHEMA = initializeNodeSchema();
+ }
+
+ return NODE_SCHEMA;
+ }
+
+ /*
+ * Edge Schema for graphML
+ * */
+ public Set> getEdgeSchema() {
+
+ if (EDGE_SCHEMA == null) {
+ EDGE_SCHEMA = initializeEdgeSchema();
+ }
+
+ return EDGE_SCHEMA;
+ }
+
+ private Set> initializeEdgeSchema() {
+
+ Set> edgeSchema = new HashSet>();
+
+ Map schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "collaborator1");
+ schemaAttributes.put("for", "edge");
+ schemaAttributes.put("attr.name", "collaborator1");
+ schemaAttributes.put("attr.type", "string");
+
+ edgeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "collaborator2");
+ schemaAttributes.put("for", "edge");
+ schemaAttributes.put("attr.name", "collaborator2");
+ schemaAttributes.put("attr.type", "string");
+
+ edgeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "number_of_coauthored_works");
+ schemaAttributes.put("for", "edge");
+ schemaAttributes.put("attr.name", "number_of_coauthored_works");
+ schemaAttributes.put("attr.type", "int");
+
+ edgeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "earliest_collaboration");
+ schemaAttributes.put("for", "edge");
+ schemaAttributes.put("attr.name", "earliest_collaboration");
+ schemaAttributes.put("attr.type", "int");
+
+ edgeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "num_earliest_collaboration");
+ schemaAttributes.put("for", "edge");
+ schemaAttributes.put("attr.name", "num_earliest_collaboration");
+ schemaAttributes.put("attr.type", "int");
+
+ edgeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "latest_collaboration");
+ schemaAttributes.put("for", "edge");
+ schemaAttributes.put("attr.name", "latest_collaboration");
+ schemaAttributes.put("attr.type", "int");
+
+ edgeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "num_latest_collaboration");
+ schemaAttributes.put("for", "edge");
+ schemaAttributes.put("attr.name", "num_latest_collaboration");
+ schemaAttributes.put("attr.type", "int");
+
+ edgeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "num_unknown_collaboration");
+ schemaAttributes.put("for", "edge");
+ schemaAttributes.put("attr.name", "num_unknown_collaboration");
+ schemaAttributes.put("attr.type", "int");
+
+ edgeSchema.add(schemaAttributes);
+
+ return edgeSchema;
+ }
+
+
+ private Set> initializeNodeSchema() {
+
+ Set> nodeSchema = new HashSet>();
+
+ Map schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "url");
+ schemaAttributes.put("for", "node");
+ schemaAttributes.put("attr.name", "url");
+ schemaAttributes.put("attr.type", "string");
+
+ nodeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "name");
+ schemaAttributes.put("for", "node");
+ schemaAttributes.put("attr.name", "name");
+ schemaAttributes.put("attr.type", "string");
+
+ nodeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "profile_url");
+ schemaAttributes.put("for", "node");
+ schemaAttributes.put("attr.name", "profile_url");
+ schemaAttributes.put("attr.type", "string");
+
+ nodeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "number_of_authored_works");
+ schemaAttributes.put("for", "node");
+ schemaAttributes.put("attr.name", "number_of_authored_works");
+ schemaAttributes.put("attr.type", "int");
+
+ nodeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "earliest_publication");
+ schemaAttributes.put("for", "node");
+ schemaAttributes.put("attr.name", "earliest_publication");
+ schemaAttributes.put("attr.type", "int");
+
+ nodeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "num_earliest_publication");
+ schemaAttributes.put("for", "node");
+ schemaAttributes.put("attr.name", "num_earliest_publication");
+ schemaAttributes.put("attr.type", "int");
+
+ nodeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "latest_publication");
+ schemaAttributes.put("for", "node");
+ schemaAttributes.put("attr.name", "latest_publication");
+ schemaAttributes.put("attr.type", "int");
+
+ nodeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "num_latest_publication");
+ schemaAttributes.put("for", "node");
+ schemaAttributes.put("attr.name", "num_latest_publication");
+ schemaAttributes.put("attr.type", "int");
+
+ nodeSchema.add(schemaAttributes);
+
+ schemaAttributes = new LinkedHashMap();
+
+ schemaAttributes.put("id", "num_unknown_publication");
+ schemaAttributes.put("for", "node");
+ schemaAttributes.put("attr.name", "num_unknown_publication");
+ schemaAttributes.put("attr.type", "int");
+
+ nodeSchema.add(schemaAttributes);
+
+
+ return nodeSchema;
+ }
+
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationCodeGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationCodeGenerator.java
new file mode 100644
index 00000000..2066844b
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationCodeGenerator.java
@@ -0,0 +1,664 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.apache.commons.logging.Log;
+
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer;
+
+
+public class VisualizationCodeGenerator {
+
+ private final static Map visDivNames = new HashMap() {{
+
+ put("SHORT_SPARK", "unique_coauthors_short_sparkline_vis");
+ put("FULL_SPARK", "unique_coauthors_full_sparkline_vis");
+
+ }};
+
+ private static final String visualizationStyleClass = "sparkline_style";
+
+ private static final String defaultVisContainerDivID = "unique_coauthors_vis_container";
+
+ public static final String SHORT_SPARKLINE_MODE_URL_HANDLE = "short";
+
+ public static final String FULL_SPARKLINE_MODE_URL_HANDLE = "full";
+
+ private Map> yearToUniqueCoauthors;
+
+ private Log log;
+
+ private SparklineVOContainer valueObjectContainer;
+
+ private String contextPath;
+
+ private String individualURIParam;
+
+ public VisualizationCodeGenerator(String contextPath,
+ String individualURIParam,
+ String visMode,
+ String visContainer,
+ Map> yearToUniqueCoauthors,
+ SparklineVOContainer valueObjectContainer,
+ Log log) {
+
+ this.contextPath = contextPath;
+ this.individualURIParam = individualURIParam;
+
+ this.yearToUniqueCoauthors = yearToUniqueCoauthors;
+ this.valueObjectContainer = valueObjectContainer;
+
+ this.log = log;
+
+
+ generateVisualizationCode(visMode,
+ visContainer);
+
+
+ }
+
+ private void generateVisualizationCode(String visMode,
+ String visContainer) {
+
+ valueObjectContainer.setSparklineContent(getMainVisualizationCode(visMode,
+ visContainer));
+
+
+ valueObjectContainer.setSparklineContext(getVisualizationContextCode(visMode));
+
+ }
+
+ private String getMainVisualizationCode(String visMode,
+ String providedVisContainerID) {
+
+ int numOfYearsToBeRendered = 0;
+ int currentYear = Calendar.getInstance().get(Calendar.YEAR);
+ int shortSparkMinYear = currentYear - 10 + 1;
+
+ /*
+ * This is required because when deciding the range of years over which the vis
+ * was rendered we dont want to be influenced by the "DEFAULT_PUBLICATION_YEAR".
+ * */
+ Set publishedYears = new HashSet(yearToUniqueCoauthors.keySet());
+ publishedYears.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ * We are setting the default value of minPublishedYear to be 10 years before
+ * the current year (which is suitably represented by the shortSparkMinYear),
+ * this in case we run into invalid set of published years.
+ * */
+ int minPublishedYear = shortSparkMinYear;
+
+ String visContainerID = null;
+
+ StringBuilder visualizationCode = new StringBuilder();
+
+// System.out.println(yearToPublicationCount);
+ if (yearToUniqueCoauthors.size() > 0) {
+ try {
+ minPublishedYear = Integer.parseInt(Collections.min(publishedYears));
+ } catch (NoSuchElementException e1) {
+ log.debug("vis: " + e1.getMessage() + " error occurred for " + yearToUniqueCoauthors.toString());
+ } catch (NumberFormatException e2) {
+ log.debug("vis: " + e2.getMessage() + " error occurred for " + yearToUniqueCoauthors.toString());
+ }
+ }
+
+ int minPubYearConsidered = 0;
+
+ /*
+ * There might be a case that the author has made his first publication within the
+ * last 10 years but we want to make sure that the sparkline is representative of
+ * at least the last 10 years, so we will set the minPubYearConsidered to
+ * "currentYear - 10" which is also given by "shortSparkMinYear".
+ * */
+ if (minPublishedYear > shortSparkMinYear) {
+ minPubYearConsidered = shortSparkMinYear;
+ } else {
+ minPubYearConsidered = minPublishedYear;
+ }
+
+ numOfYearsToBeRendered = currentYear - minPubYearConsidered + 1;
+
+ visualizationCode.append("\n");
+
+// .sparkline {display:inline; margin:0; padding:0; width:600px }
+
+
+
+// td.sparkline-img {margin:0; padding:0; }
+
+
+ visualizationCode.append("\n";
+ }
+
+ private String getVisualizationContextCode(String visMode) {
+
+ String visualizationContextCode = "";
+ if (SHORT_SPARKLINE_MODE_URL_HANDLE.equalsIgnoreCase(visMode)) {
+ visualizationContextCode = generateShortVisContext();
+ } else {
+ visualizationContextCode = generateFullVisContext();
+ }
+
+
+
+
+
+
+// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ log.debug(visualizationContextCode);
+// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+
+ return visualizationContextCode;
+ }
+
+ private String generateFullVisContext() {
+
+ StringBuilder divContextCode = new StringBuilder();
+
+ String csvDownloadURLHref = "";
+
+ if (yearToUniqueCoauthors.size() > 0) {
+
+ try {
+ if (getCSVDownloadURL() != null) {
+
+ csvDownloadURLHref = "Download data as .csv file. ";
+ valueObjectContainer.setDownloadDataLink(getCSVDownloadURL());
+
+ } else {
+
+ csvDownloadURLHref = "";
+
+ }
+
+ } catch (UnsupportedEncodingException e) {
+ csvDownloadURLHref = "";
+ }
+
+
+ } else {
+ csvDownloadURLHref = "No data available to export. ";
+ }
+
+ String tableCode = generateDataTable();
+
+ divContextCode.append("" + tableCode +
+ csvDownloadURLHref + "
");
+
+ valueObjectContainer.setTable(tableCode);
+
+ return divContextCode.toString();
+
+ }
+
+ private String getCSVDownloadURL()
+ throws UnsupportedEncodingException {
+
+ if (yearToUniqueCoauthors.size() > 0) {
+
+ String secondaryContextPath = "";
+ if (!contextPath.contains("/admin/visQuery")) {
+ secondaryContextPath = "/admin/visQuery";
+ }
+
+
+ String downloadURL = contextPath
+ + secondaryContextPath
+ + "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ + "=" + URLEncoder.encode(individualURIParam,
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&" + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE
+ + "=" + URLEncoder.encode(VisualizationController
+ .COAUTHORSHIP_VIS_URL_VALUE,
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&" + VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE
+ + "=" + URLEncoder.encode("sparkline",
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&" + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE
+ + "=" + URLEncoder.encode(VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE,
+ VisualizationController.URL_ENCODING_SCHEME).toString();
+
+// System.out.println(" ----- >>>> " + contextPath + " XX " + individualURIParam + " XX " + downloadURL);
+
+ return downloadURL;
+ } else {
+ return null;
+ }
+
+ }
+
+
+ private String generateShortVisContext() {
+
+ StringBuilder divContextCode = new StringBuilder();
+
+ try {
+
+ String fullTimelineLink;
+ if (yearToUniqueCoauthors.size() > 0) {
+
+ String secondaryContextPath = "";
+ if (!contextPath.contains("/admin/visQuery")) {
+ secondaryContextPath = "/admin/visQuery";
+ }
+
+ String fullTimelineNetworkURL = contextPath
+ + secondaryContextPath
+ + "?"
+ + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ + "=" + URLEncoder.encode(individualURIParam,
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&"
+ + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE
+ + "=" + URLEncoder.encode("person_level",
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&"
+ + VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE
+ + "=" + URLEncoder.encode("ego_sparkline",
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&"
+ + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE
+ + "=" + URLEncoder.encode(VisualizationFrameworkConstants.STANDALONE_RENDER_MODE_URL_VALUE,
+ VisualizationController.URL_ENCODING_SCHEME).toString();
+
+ System.out.println("context parth full n/w " + contextPath);
+
+ fullTimelineLink = "View full timeline and co-author network ";
+
+ valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL);
+
+ } else {
+
+ fullTimelineLink = "No data available to render full timeline. ";
+
+ }
+
+ divContextCode.append("" + fullTimelineLink + "
");
+
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+
+ return divContextCode.toString();
+
+ }
+
+
+ private String generateDataTable() {
+
+ StringBuilder dataTable = new StringBuilder();
+
+ dataTable.append("" +
+ "Unique Co-Authors per year " +
+ "" +
+ "" +
+ "Year " +
+ "Count " +
+ " " +
+ " " +
+ "");
+
+ for (Entry> currentEntry : yearToUniqueCoauthors.entrySet()) {
+ dataTable.append("" +
+ "" + currentEntry.getKey() + " " +
+ "" + currentEntry.getValue().size() + " " +
+ " ");
+ }
+
+ dataTable.append(" \n" +
+// "" +
+// "*DNA - Data not available " +
+// " \n" +
+ "
\n");
+
+
+ return dataTable.toString();
+ }
+
+
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationRequestHandler.java
new file mode 100644
index 00000000..3908067f
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/coauthorship/VisualizationRequestHandler.java
@@ -0,0 +1,340 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+
+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.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
+
+public class VisualizationRequestHandler {
+
+ private VitroRequest vitroRequest;
+ private HttpServletRequest request;
+ private HttpServletResponse response;
+ private Log log;
+
+ public VisualizationRequestHandler(VitroRequest vitroRequest,
+ HttpServletRequest request, HttpServletResponse response, Log log) {
+
+ this.vitroRequest = vitroRequest;
+ this.request = request;
+ this.response = response;
+ this.log = log;
+
+ }
+
+ public void generateVisualization(DataSource dataSource) {
+
+ String resultFormatParam = "RS_TEXT";
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ String egoURIParam = vitroRequest.getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE);
+
+ String renderMode = vitroRequest.getParameter(VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE);
+
+ String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE);
+
+ String visContainer = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE);
+
+ String sparklineVisMode = "sparkline";
+
+ QueryHandler queryManager =
+ new QueryHandler(egoURIParam,
+ resultFormatParam,
+ rdfResultFormatParam,
+ dataSource,
+
+ log);
+
+ try {
+
+ VisVOContainer 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.equalsIgnoreCase(renderMode)) {
+
+ /*
+ * We will be using the same visualization package for both sparkline & coauthorship flash
+ * vis. We will use "VIS_MODE_URL_HANDLE" as a modifier to differentiate between these two.
+ * The defualt will be to render the coauthorship network vis.
+ * */
+
+ if (sparklineVisMode.equalsIgnoreCase(visMode)) {
+ /*
+ * When the csv file is required - based on which sparkline visualization will
+ * be rendered.
+ * */
+ prepareVisualizationQuerySparklineDataResponse(authorNodesAndEdges);
+ return;
+
+ } else {
+ /*
+ * When the graphML file is required - based on which coauthorship network visualization
+ * will be rendered.
+ * */
+ prepareVisualizationQueryNetworkDataResponse(authorNodesAndEdges);
+ return;
+ }
+ }
+
+
+
+ /*
+ * Computations required to generate HTML for the sparklines & related context.
+ * */
+
+ /*
+ * 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".
+ * */
+// publishedYearsForCollege.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ VisualizationCodeGenerator visualizationCodeGenerator =
+ new VisualizationCodeGenerator(yearToPublicationCount, log);
+
+ String visContentCode = visualizationCodeGenerator
+ .getMainVisualizationCode(authorDocuments,
+ publishedYears,
+ visMode,
+ visContainer);
+
+ String visContextCode = visualizationCodeGenerator
+ .getVisualizationContextCode(vitroRequest.getRequestURI(),
+ collegeURIParam,
+ visMode);
+ */
+
+ /*
+ * This is side-effecting because the response of this method is just to redirect to
+ * a page with visualization on it.
+ * */
+
+ RequestDispatcher requestDispatcher = null;
+
+ prepareVisualizationQueryStandaloneResponse(egoURIParam, request, response, vitroRequest);
+
+// requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+ requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp");
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+
+ } catch (MalformedQueryParametersException e) {
+ try {
+ handleMalformedParameters(e.getMessage());
+ } catch (ServletException e1) {
+ log.error(e1.getStackTrace());
+ } catch (IOException e1) {
+ log.error(e1.getStackTrace());
+ }
+ return;
+ }
+
+ }
+
+ private void prepareVisualizationQueryNetworkDataResponse(VisVOContainer authorNodesAndEdges) {
+
+ response.setContentType("text/xml");
+
+ 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(authorNodesAndEdges);
+
+ responseWriter.append(coAuthorShipGraphMLWriter.getCoAuthorshipGraphMLContent());
+
+ responseWriter.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void prepareVisualizationQuerySparklineDataResponse(VisVOContainer authorNodesAndEdges) {
+
+ String outputFileName = "";
+ Map> yearToCoauthors = new TreeMap>();
+
+ if (authorNodesAndEdges.getNodes() == null || authorNodesAndEdges.getNodes().size() < 1 ) {
+
+ outputFileName = "no-coauthors" + ".csv";
+
+ } else {
+
+ outputFileName = UtilityFunctions.slugify(authorNodesAndEdges.getEgoNode().getNodeName())
+ + "-coauthors" + ".csv";
+
+ yearToCoauthors = getCoAuthorsStats(authorNodesAndEdges);
+
+ }
+
+
+
+ response.setContentType("application/octet-stream");
+ response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName);
+
+ try {
+
+ PrintWriter responseWriter = response.getWriter();
+
+ /*
+ * We are side-effecting responseWriter since we are directly manipulating the response
+ * object of the servlet.
+ * */
+ generateCsvFileBuffer(yearToCoauthors,
+ responseWriter);
+
+ responseWriter.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void generateCsvFileBuffer(Map> yearToCoauthors, PrintWriter printWriter) {
+
+ printWriter.append("\"Year\", \"Number of Co-Authors\", \"Co-Author(s)\"\n");
+
+ for (Entry> currentEntry : yearToCoauthors.entrySet()) {
+
+ printWriter.append("\"" + currentEntry.getKey() + "\","
+ + "\"" + currentEntry.getValue().size() + "\","
+ + "\"" + getCoauthorsString(currentEntry.getValue()) + "\"\n"
+ );
+
+
+ }
+
+ printWriter.flush();
+
+ }
+
+ private String getCoauthorsString(Set coAuthors) {
+
+ StringBuilder coAuthorsMerged = new StringBuilder();
+
+ for (Node currCoAuthor : coAuthors) {
+ coAuthorsMerged.append(currCoAuthor.getNodeName() + "; ");
+ }
+
+ return coAuthorsMerged.toString();
+ }
+
+ private Map> getCoAuthorsStats(VisVOContainer authorNodesAndEdges) {
+
+ Map> yearToCoAuthors = new TreeMap>();
+
+ Node egoNode = authorNodesAndEdges.getEgoNode();
+
+ for (Node currNode : authorNodesAndEdges.getNodes()) {
+
+ /*
+ * We have already printed the Ego Node info.
+ * */
+ if (currNode != egoNode) {
+
+ for (String year : currNode.getYearToPublicationCount().keySet()) {
+
+ Set coAuthorNodes;
+
+ if (yearToCoAuthors.containsKey(year)) {
+
+ coAuthorNodes = yearToCoAuthors.get(year);
+ coAuthorNodes.add(currNode);
+
+ } else {
+
+ coAuthorNodes = new HashSet();
+ coAuthorNodes.add(currNode);
+ yearToCoAuthors.put(year, coAuthorNodes);
+ }
+
+ }
+
+ }
+ }
+
+
+ return yearToCoAuthors;
+ }
+
+ private void prepareVisualizationQueryStandaloneResponse(String egoURIParam,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ VitroRequest vreq) {
+
+ Portal portal = vreq.getPortal();
+
+// request.setAttribute("visContentCode", visContentCode);
+// request.setAttribute("visContextCode", visContextCode);
+
+ request.setAttribute("egoURIParam", egoURIParam);
+
+ request.setAttribute("bodyJsp", "/templates/visualization/co_authorship.jsp");
+ request.setAttribute("portalBean", portal);
+// request.setAttribute("title", "Individual Publication Count Visualization");
+// request.setAttribute("scripts", "/templates/visualization/visualization_scripts.jsp");
+
+ }
+
+ private void handleMalformedParameters(String errorMessage)
+ throws ServletException, IOException {
+
+ Portal portal = vitroRequest.getPortal();
+
+ request.setAttribute("error", errorMessage);
+
+ RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+ request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp");
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("title", "Visualization Query Error - Individual Publication Count");
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/QueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/QueryHandler.java
new file mode 100644
index 00000000..0c31a662
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/QueryHandler.java
@@ -0,0 +1,331 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.collegepubcount;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+
+import com.hp.hpl.jena.iri.IRI;
+import com.hp.hpl.jena.iri.IRIFactory;
+import com.hp.hpl.jena.iri.Violation;
+import com.hp.hpl.jena.query.DataSource;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+import com.hp.hpl.jena.query.QueryFactory;
+import com.hp.hpl.jena.query.QuerySolution;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.query.Syntax;
+import com.hp.hpl.jena.rdf.model.RDFNode;
+
+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.VOConstants.EmployeeType;
+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.VivoCollegeOrSchool;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoDepartmentOrDivision;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoEmployee;
+
+
+
+/**
+ * @author cdtank
+ *
+ */
+public class QueryHandler {
+
+ protected static final Syntax SYNTAX = Syntax.syntaxARQ;
+
+ private String collegeURIParam, resultFormatParam, rdfResultFormatParam;
+ private Map collegeURLToVO = new HashMap();
+ private DataSource dataSource;
+
+ private Log log;
+
+ public QueryHandler(String collegeURIParam,
+ String resultFormatParam, String rdfResultFormatParam,
+ DataSource dataSource, Log log) {
+
+ this.collegeURIParam = collegeURIParam;
+ this.resultFormatParam = resultFormatParam;
+ this.rdfResultFormatParam = rdfResultFormatParam;
+ this.dataSource = dataSource;
+ this.log = log;
+
+ }
+
+ private Set createJavaValueObjects(ResultSet resultSet) {
+
+ Set collegeAcademicEmployees = new HashSet();
+
+ Map departmentURLToVO = new HashMap();
+ Map employeeURLToVO = new HashMap();
+
+ while (resultSet.hasNext()) {
+ QuerySolution solution = resultSet.nextSolution();
+
+ String collegeURL = solution.get(QueryFieldLabels.COLLEGE_URL).toString();
+
+ VivoCollegeOrSchool currentCollege;
+
+ if (collegeURLToVO.containsKey(collegeURL)) {
+ currentCollege = collegeURLToVO.get(collegeURL);
+ } else {
+ currentCollege = new VivoCollegeOrSchool(collegeURL);
+ collegeURLToVO.put(collegeURL, currentCollege);
+
+ RDFNode collegeLabelNode = solution.get(QueryFieldLabels.COLLEGE_LABEL);
+ if (collegeLabelNode != null) {
+ currentCollege.setCollegeLabel(collegeLabelNode.toString());
+ }
+ }
+
+ String departmentURL = solution.get(QueryFieldLabels.DEPARTMENT_URL).toString();
+
+ VivoDepartmentOrDivision currentDepartment;
+
+ if (departmentURLToVO.containsKey(departmentURL)) {
+ currentDepartment = departmentURLToVO.get(departmentURL);
+ currentDepartment.addParentCollege(currentCollege);
+ } else {
+ currentDepartment = new VivoDepartmentOrDivision(departmentURL, currentCollege);
+ departmentURLToVO.put(departmentURL, currentDepartment);
+
+ RDFNode departmentLabelNode = solution.get(QueryFieldLabels.DEPARTMENT_LABEL);
+ if (departmentLabelNode != null) {
+ currentDepartment.setDepartmentLabel(departmentLabelNode.toString());
+ }
+ }
+
+ currentCollege.addDepartment(currentDepartment);
+
+ RDFNode employeeNode = solution.get(QueryFieldLabels.ACADEMIC_FACULTY_EMPLOYEE_URL);
+ EmployeeType currentEmployeeType;
+ VivoEmployee currentEmployee;
+
+ if (employeeNode != null) {
+ currentEmployeeType = EmployeeType.ACADEMIC_FACULTY_EMPLOYEE;
+ } else {
+ currentEmployeeType = EmployeeType.ACADEMIC_STAFF_EMPLOYEE;
+ employeeNode = solution.get(QueryFieldLabels.ACADEMIC_STAFF_EMPLOYEE_URL);
+ }
+
+ if (employeeURLToVO.containsKey(employeeNode.toString())) {
+ currentEmployee = employeeURLToVO.get(employeeNode.toString());
+ currentEmployee.addParentDepartment(currentDepartment);
+ } else {
+ currentEmployee = new VivoEmployee(employeeNode.toString(), currentEmployeeType, currentDepartment);
+ RDFNode authorLabelNode = solution.get(QueryFieldLabels.AUTHOR_LABEL);
+ if (authorLabelNode != null) {
+ currentEmployee.setIndividualLabel(authorLabelNode.toString());
+ }
+ employeeURLToVO.put(employeeNode.toString(), currentEmployee);
+ }
+
+ RDFNode documentNode = solution.get(QueryFieldLabels.DOCUMENT_URL);
+ if (documentNode != null) {
+
+ /*
+ * A document can have multiple authors but if the same author serves in multiple departments
+ * then we need to account for "An Authored Document" only once. This check will make sure that
+ * a document by same author is not added twice just because that author serves in 2 distinct
+ * department.
+ * */
+ boolean isNewDocumentAlreadyAdded = testForDuplicateEntryOfDocument(
+ currentEmployee,
+ documentNode);
+
+ if (!isNewDocumentAlreadyAdded) {
+ currentEmployee.addAuthorDocument(createAuthorDocumentsVO(solution, documentNode.toString()));
+ }
+
+ }
+
+ collegeAcademicEmployees.add(currentEmployee);
+ }
+
+
+/* System.out.println(collegeURLToVO);
+ System.out.println("------------------------------------------------------------");
+ System.out.println(departmentURLToVO);
+ System.out.println("------------------------------------------------------------");
+ System.out.println(employeeURLToVO);
+ System.out.println("------------------------------------------------------------");
+*/
+ return collegeAcademicEmployees;
+ }
+
+ private boolean testForDuplicateEntryOfDocument(
+ VivoEmployee currentEmployee, RDFNode documentNode) {
+ boolean isNewDocumentAlreadyAdded = false;
+
+ for (BiboDocument currentAuthoredDocument : currentEmployee.getAuthorDocuments()) {
+ if (currentAuthoredDocument.getDocumentURL().equalsIgnoreCase(documentNode.toString())) {
+ isNewDocumentAlreadyAdded = true;
+ break;
+ }
+ }
+ return isNewDocumentAlreadyAdded;
+ }
+
+ public Map getCollegeURLToVO() {
+ return collegeURLToVO;
+ }
+
+ private BiboDocument createAuthorDocumentsVO(QuerySolution solution, String documentURI) {
+
+ BiboDocument biboDocument = new BiboDocument(documentURI);
+
+ RDFNode documentLabelNode = solution.get(QueryFieldLabels.DOCUMENT_LABEL);
+ if (documentLabelNode != null) {
+ biboDocument.setDocumentLabel(documentLabelNode.toString());
+ }
+
+ RDFNode documentBlurbNode = solution.get(QueryFieldLabels.DOCUMENT_BLURB);
+ if (documentBlurbNode != null) {
+ biboDocument.setDocumentBlurb(documentBlurbNode.toString());
+ }
+
+ RDFNode documentMonikerNode = solution.get(QueryFieldLabels.DOCUMENT_MONIKER);
+ if (documentMonikerNode != null) {
+ biboDocument.setDocumentMoniker(documentMonikerNode.toString());
+ }
+
+ RDFNode documentDescriptionNode = solution.get(QueryFieldLabels.DOCUMENT_DESCRIPTION);
+ if (documentDescriptionNode != null) {
+ biboDocument.setDocumentDescription(documentDescriptionNode.toString());
+ }
+
+ RDFNode publicationYearNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR);
+ if (publicationYearNode != null) {
+ biboDocument.setPublicationYear(publicationYearNode.toString());
+ }
+
+ RDFNode publicationYearMonthNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR_MONTH);
+ if (publicationYearMonthNode != null) {
+ biboDocument.setPublicationYearMonth(publicationYearMonthNode.toString());
+ }
+
+ RDFNode publicationDateNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_DATE);
+ if (publicationDateNode != null) {
+ biboDocument.setPublicationDate(publicationDateNode.toString());
+ }
+
+ return biboDocument;
+ }
+
+ private ResultSet executeQuery(String queryText,
+ String resultFormatParam,
+ String rdfResultFormatParam,
+ DataSource dataSource) {
+
+ QueryExecution queryExecution = null;
+ try{
+ Query query = QueryFactory.create(queryText, SYNTAX);
+
+// QuerySolutionMap qs = new QuerySolutionMap();
+// qs.add("authPerson", queryParam); // bind resource to s
+
+ queryExecution = QueryExecutionFactory.create(query, dataSource);
+
+
+ //remocve this if loop after knowing what is describe & construct sparql stuff.
+ if (query.isSelectType()){
+ return queryExecution.execSelect();
+ }
+ } finally {
+ if(queryExecution != null) {
+ queryExecution.close();
+ }
+
+ }
+ return null;
+ }
+
+ private String generateCollegeEmployeeSparqlQuery(String queryURI) {
+// Resource uri1 = ResourceFactory.createResource(queryURI);
+
+ String sparqlQuery = QueryConstants.getSparqlPrefixQuery()
+ + "SELECT (str(?collegeLabel) as ?" + QueryFieldLabels.COLLEGE_LABEL + ") "
+ + " (str(?department) as ?" + QueryFieldLabels.DEPARTMENT_URL + ") "
+ + " (str(?departmentLabel) as ?" + QueryFieldLabels.DEPARTMENT_LABEL + ") "
+ + " (str(?academicFacultyEmployee) as ?" + QueryFieldLabels.ACADEMIC_FACULTY_EMPLOYEE_URL + ") "
+ + " (str(?academicStaffEmployee) as ?" + QueryFieldLabels.ACADEMIC_STAFF_EMPLOYEE_URL + ") "
+ + " (str(<" + queryURI + ">) as ?" + QueryFieldLabels.COLLEGE_URL + ") "
+ + " (str(?authorLabel) as ?" + QueryFieldLabels.AUTHOR_LABEL + ") "
+ + " (str(?document) as ?" + QueryFieldLabels.DOCUMENT_URL + ") "
+ + " (str(?documentMoniker) as ?" + QueryFieldLabels.DOCUMENT_MONIKER + ") "
+ + " (str(?documentLabel) as ?" + QueryFieldLabels.DOCUMENT_LABEL + ") "
+ + " (str(?documentBlurb) as ?" + QueryFieldLabels.DOCUMENT_BLURB + ") "
+ + " (str(?documentDescription) as ?" + QueryFieldLabels.DOCUMENT_DESCRIPTION + ") "
+ + " (str(?publicationYear) as ?" + QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR + ") "
+ + "WHERE { "
+ + "<" + queryURI + "> rdf:type vivo:CollegeOrSchoolWithinUniversity; " +
+ "rdfs:label ?collegeLabel; " +
+ "vivo:hasAcademicDepartmentOrDivision ?department . "
+ + "?department rdfs:label ?departmentLabel ."
+ + "{ "
+ + getAcademicEmployeePublicationsSparqlQuery("academicFacultyEmployee", "vivo:hasEmployeeAcademicFacultyMember")
+ + " UNION "
+ + getAcademicEmployeePublicationsSparqlQuery("academicStaffEmployee", "vivo:hasEmployeeAcademicStaffMember")
+ + "}"
+ + "}";
+
+// System.out.println(sparqlQuery);
+
+ return sparqlQuery;
+ }
+
+
+ private String getAcademicEmployeePublicationsSparqlQuery(String employeeHandle,
+ String ontologyHandle) {
+
+ String sparqlQuery = " {?department " + ontologyHandle + " ?" + employeeHandle + " . "
+ + "?" + employeeHandle + " rdf:type foaf:Person; rdfs:label ?authorLabel. "
+ + "OPTIONAL { ?" + employeeHandle + " vivo:authorOf ?document ." +
+ " ?document rdf:type bibo:Document ." +
+ " ?document rdfs:label ?documentLabel ." +
+ " OPTIONAL { ?document vitro:moniker ?documentMoniker } ." +
+ " OPTIONAL { ?document vitro:blurb ?documentBlurb } ." +
+ " OPTIONAL { ?document vitro:description ?documentDescription } ." +
+ " OPTIONAL { ?document vivo:publicationYear ?publicationYear } ." +
+ "}" +
+ "} ";
+
+ return sparqlQuery;
+
+ }
+
+ public Set getVisualizationJavaValueObjects()
+ throws MalformedQueryParametersException {
+
+ if (this.collegeURIParam == null || "".equals(collegeURIParam)) {
+ throw new MalformedQueryParametersException("URI parameter is either null or empty.");
+ } else {
+
+ /*
+ * To test for the validity of the URI submitted.
+ * */
+ IRIFactory iRIFactory = IRIFactory.jenaImplementation();
+ IRI iri = iRIFactory.create(this.collegeURIParam);
+ if (iri.hasViolation(false)) {
+ String errorMsg = ((Violation)iri.violations(false).next()).getShortMessage()+" ";
+ log.error("Pub Count Vis Query " + errorMsg);
+ throw new MalformedQueryParametersException("URI provided for an individual is malformed.");
+ }
+ }
+
+ ResultSet resultSet = executeQuery(generateCollegeEmployeeSparqlQuery(this.collegeURIParam),
+ this.resultFormatParam,
+ this.rdfResultFormatParam,
+ this.dataSource);
+
+ return createJavaValueObjects(resultSet);
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/VisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/VisualizationRequestHandler.java
new file mode 100644
index 00000000..58981174
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/VisualizationRequestHandler.java
@@ -0,0 +1,458 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.collegepubcount;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.skife.csv.CSVWriter;
+import org.skife.csv.SimpleWriter;
+
+import com.hp.hpl.jena.query.DataSource;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.pdf.PdfWriter;
+
+import edu.cornell.mannlib.vitro.webapp.beans.Portal;
+import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.PDFDocument;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoCollegeOrSchool;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoDepartmentOrDivision;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoEmployee;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
+
+public class VisualizationRequestHandler {
+
+ private VitroRequest vitroRequest;
+ private HttpServletRequest request;
+ private HttpServletResponse response;
+ private Log log;
+
+
+
+ public VisualizationRequestHandler(VitroRequest vitroRequest,
+ HttpServletRequest request, HttpServletResponse response, Log log) {
+
+ this.vitroRequest = vitroRequest;
+ this.request = request;
+ this.response = response;
+ this.log = log;
+
+ }
+
+ public void generateVisualization(DataSource dataSource) {
+
+ String resultFormatParam = "RS_TEXT";
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ String collegeURIParam = vitroRequest.getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE);
+
+ String renderMode = vitroRequest.getParameter(VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE);
+
+ String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE);
+
+ String visContainer = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE);
+
+ QueryHandler queryManager =
+ new QueryHandler(collegeURIParam,
+ resultFormatParam,
+ rdfResultFormatParam,
+ dataSource,
+ log);
+
+ try {
+
+ Set employees = queryManager.getVisualizationJavaValueObjects();
+
+ Map> departmentToPublicationsOverTime =
+ new HashMap>();
+
+ Set publishedYearsForCollege = new HashSet();
+
+ for (VivoEmployee currentEmployee : employees) {
+
+ Map currentEmployeeYearToPublicationCount =
+ UtilityFunctions.getYearToPublicationCount(currentEmployee.getAuthorDocuments());
+
+ if (currentEmployeeYearToPublicationCount.size() > 0) {
+
+
+ publishedYearsForCollege.addAll(currentEmployeeYearToPublicationCount.keySet());
+
+ for (VivoDepartmentOrDivision currentDepartment : currentEmployee.getParentDepartments()) {
+
+ departmentToPublicationsOverTime.put(currentDepartment,
+ getUpdatedDepartmentPublicationsOverTime(
+ currentEmployeeYearToPublicationCount,
+ departmentToPublicationsOverTime
+ .get(currentDepartment)));
+
+ }
+
+ }
+ }
+
+
+ /*
+ * 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)) {
+ prepareVisualizationQueryDataResponse(
+ departmentToPublicationsOverTime,
+ queryManager.getCollegeURLToVO());
+
+ log.debug(publishedYearsForCollege);
+ return;
+ }
+
+
+
+ /*
+ if (PDF_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) {
+ prepareVisualizationQueryPDFResponse(authorDocuments,
+ yearToPublicationCount);
+ return;
+ }
+ */
+
+ /*
+ * Computations required to generate HTML for the sparklines & related context.
+ * */
+
+ /*
+ * 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".
+ * */
+ publishedYearsForCollege.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ VisualizationCodeGenerator visualizationCodeGenerator =
+ new VisualizationCodeGenerator(yearToPublicationCount, log);
+
+ String visContentCode = visualizationCodeGenerator
+ .getMainVisualizationCode(authorDocuments,
+ publishedYears,
+ visMode,
+ visContainer);
+
+ String visContextCode = visualizationCodeGenerator
+ .getVisualizationContextCode(vitroRequest.getRequestURI(),
+ collegeURIParam,
+ visMode);
+ */
+
+ /*
+ * This is side-effecting because the response of this method is just to redirect to
+ * a page with visualization on it.
+ * */
+
+ /*
+ RequestDispatcher requestDispatcher = null;
+
+ if (DYNAMIC_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) {
+
+ prepareVisualizationQueryDynamicResponse(request, response, vitroRequest,
+ visContentCode, visContextCode);
+ requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp");
+
+ } else {
+ prepareVisualizationQueryStandaloneResponse(request, response, vitroRequest,
+ visContentCode, visContextCode);
+
+ requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+ }
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+
+*/
+ } catch (MalformedQueryParametersException e) {
+ try {
+ handleMalformedParameters(e.getMessage());
+ } catch (ServletException e1) {
+ log.error(e1.getStackTrace());
+ } catch (IOException e1) {
+ log.error(e1.getStackTrace());
+ }
+ return;
+ }
+
+ }
+
+ private Map getUpdatedDepartmentPublicationsOverTime(
+ Map currentEmployeeYearToPublicationCount,
+ Map currentDepartmentYearToPublicationCount) {
+
+ Map departmentYearToPublicationCount;
+
+// System.out.println("inside get updated dept pub obr time");
+
+ /*
+ * In case this is the first time we are consolidating publication counts over time for a department.
+ * */
+ if (currentDepartmentYearToPublicationCount == null) {
+ departmentYearToPublicationCount = new TreeMap();
+
+// System.out.println("new dept yr pub cnt");
+
+ } else {
+ departmentYearToPublicationCount = currentDepartmentYearToPublicationCount;
+ }
+
+
+ Iterator employeePubCountIterator = currentEmployeeYearToPublicationCount.entrySet().iterator();
+
+ while (employeePubCountIterator.hasNext()) {
+ Map.Entry employeePubCountEntry = (Map.Entry) employeePubCountIterator.next();
+
+ String employeePublicationYear = employeePubCountEntry.getKey();
+ Integer employeePublicationCount = employeePubCountEntry.getValue();
+
+ try {
+ if (departmentYearToPublicationCount.containsKey(employeePublicationYear)) {
+ departmentYearToPublicationCount.put(employeePublicationYear,
+ departmentYearToPublicationCount
+ .get(employeePublicationYear)
+ + employeePublicationCount);
+
+ } else {
+ departmentYearToPublicationCount.put(employeePublicationYear, employeePublicationCount);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ return departmentYearToPublicationCount;
+ }
+
+ private void prepareVisualizationQueryPDFResponse(Individual college,
+ List authorDocuments,
+ Map yearToPublicationCount) {
+
+ String authorName = null;
+
+ /*
+ * To protect against cases where there are no author documents associated with the
+ * individual.
+ * */
+ if (authorDocuments.size() > 0) {
+ authorName = college.getIndividualLabel();
+ }
+
+ /*
+ * To make sure that null/empty records for author names do not cause any mischief.
+ * */
+ if (authorName == null) {
+ authorName = "";
+ }
+
+ 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();
+
+ response.setHeader("Expires", "0");
+ response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
+ response.setHeader("Pragma", "public");
+ response.setContentLength(baos.size());
+
+ baos.writeTo(responseOutputStream);
+ responseOutputStream.flush();
+ responseOutputStream.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (DocumentException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void prepareVisualizationQueryDataResponse(
+ Map> departmentToPublicationsOverTime,
+ Map collegeURLToVO) {
+
+ String collegeName = null;
+
+ /*
+ * To protect against cases where there are no author documents associated with the
+ * individual.
+ * */
+// System.out.println(collegeURLToVO);
+ if (collegeURLToVO.size() > 0) {
+ collegeName = ((VivoCollegeOrSchool) collegeURLToVO.values().iterator().next()).getCollegeLabel();
+ }
+
+ /*
+ * To make sure that null/empty records for author names do not cause any mischief.
+ * */
+ if (collegeName == null) {
+ collegeName = "";
+ }
+
+ String outputFileName = UtilityFunctions.slugify(collegeName) + "depts-pub-count" + ".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(departmentToPublicationsOverTime,
+ collegeURLToVO,
+ responseWriter);
+
+ responseWriter.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void generateCsvFileBuffer(
+ Map> departmentToPublicationsOverTime,
+ Map collegeURLToVO, PrintWriter printWriter) {
+
+ CSVWriter csvWriter = new SimpleWriter(printWriter);
+
+ try {
+ csvWriter.append(new String[]{"School", "Department", "Year", "Publications"});
+
+ Iterator collegeIterator = collegeURLToVO.values().iterator();
+
+ while (collegeIterator.hasNext()) {
+ VivoCollegeOrSchool college = collegeIterator.next();
+ String collegeLabel = college.getCollegeLabel();
+ for (VivoDepartmentOrDivision currentDepartment : college.getDepartments()) {
+
+ Map currentDepartmentPublicationsOverTime = departmentToPublicationsOverTime.get(currentDepartment);
+
+ /*
+ * This because many departments might not have any publication.
+ * */
+ if (currentDepartmentPublicationsOverTime != null) {
+
+ for (Entry currentEntry : currentDepartmentPublicationsOverTime.entrySet()) {
+ csvWriter.append(new Object[]{collegeLabel,
+ currentDepartment.getDepartmentLabel(),
+ currentEntry.getKey(),
+ currentEntry.getValue()});
+ }
+
+ }
+
+ }
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ printWriter.flush();
+
+ }
+
+ private void prepareVisualizationQueryStandaloneResponse(HttpServletRequest request,
+ HttpServletResponse response, VitroRequest vreq,
+ String visContentCode, String visContextCode) {
+
+ Portal portal = vreq.getPortal();
+
+ request.setAttribute("visContentCode", visContentCode);
+ request.setAttribute("visContextCode", visContextCode);
+
+ request.setAttribute("bodyJsp", "/templates/visualization/publication_count.jsp");
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("title", "Individual Publication Count Visualization");
+ request.setAttribute("scripts", "/templates/visualization/visualization_scripts.jsp");
+
+ }
+
+ private void prepareVisualizationQueryDynamicResponse(HttpServletRequest request,
+ HttpServletResponse response, VitroRequest vreq,
+ String visContentCode, String visContextCode) {
+
+ Portal portal = vreq.getPortal();
+
+ request.setAttribute("visContentCode", visContentCode);
+ request.setAttribute("visContextCode", visContextCode);
+
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("bodyJsp", "/templates/visualization/ajax_vis_content.jsp");
+
+ }
+
+ private void handleMalformedParameters(String errorMessage)
+ throws ServletException, IOException {
+
+ Portal portal = vitroRequest.getPortal();
+
+ request.setAttribute("error", errorMessage);
+
+ RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+ request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp");
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("title", "Visualization Query Error - Individual Publication Count");
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryConstants.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryConstants.java
new file mode 100644
index 00000000..d66e6876
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryConstants.java
@@ -0,0 +1,62 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.constants;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class QueryConstants {
+
+ public static final Map PREFIX_TO_NAMESPACE = new HashMap() {{
+
+ put("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
+ put("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
+ put("xsd", "http://www.w3.org/2001/XMLSchema#");
+ put("owl", "http://www.w3.org/2002/07/owl#");
+ put("swrl", "http://www.w3.org/2003/11/swrl#");
+ put("swrlb", "http://www.w3.org/2003/11/swrlb#");
+ put("vitro", "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#");
+ put("far", "http://vitro.mannlib.cornell.edu/ns/reporting#");
+ put("ai", "http://vitro.mannlib.cornell.edu/ns/hotel#");
+ put("aktp", "http://www.aktors.org/ontology/portal#");
+ put("akts", "http://www.aktors.org/ontology/support#");
+ put("bibo", "http://purl.org/ontology/bibo/");
+ put("hr", "http://vivo.cornell.edu/ns/hr/0.9/hr.owl#");
+ put("dcterms", "http://purl.org/dc/terms/");
+ put("dcelem", "http://purl.org/dc/elements/1.1/");
+ put("event", "http://purl.org/NET/c4dm/event.owl#");
+ put("foaf", "http://xmlns.com/foaf/0.1/");
+ put("geo", "http://aims.fao.org/aos/geopolitical.owl#");
+ put("mann", "http://vivo.cornell.edu/ns/mannadditions/0.1#");
+ put("pubmed", "http://vitro.mannlib.cornell.edu/ns/pubmed#");
+ put("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
+ put("rdfsyn", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
+ put("skos", "http://www.w3.org/2004/02/skos/core#");
+ put("socsci", "http://vivo.library.cornell.edu/ns/vivo/socsci/0.1#");
+ put("stars", "http://vitro.mannlib.cornell.edu/ns/cornell/stars/classes#");
+ put("temp", "http://vitro.mannlib.cornell.edu/ns/temp#");
+ put("wos", "http://vivo.mannlib.cornell.edu/ns/ThomsonWOS/0.1#");
+ put("core", "http://vivoweb.org/ontology/core#");
+ put("vivo", "http://vivo.library.cornell.edu/ns/0.1#");
+ put("j.1", "http://aims.fao.org/aos/geopolitical.owl#");
+ put("j.2", "http://vitro.mannlib.cornell.edu/ns/vitro/public#");
+
+ }};
+
+ public static String getSparqlPrefixQuery() {
+
+ StringBuilder prefixSection = new StringBuilder();
+
+ for (Map.Entry prefixEntry : PREFIX_TO_NAMESPACE.entrySet()) {
+ prefixSection.append("PREFIX " + prefixEntry.getKey() + ": <" + prefixEntry.getValue() + ">\n");
+ }
+
+
+ return prefixSection.toString();
+
+ }
+
+
+}
+
+
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryFieldLabels.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryFieldLabels.java
new file mode 100644
index 00000000..e35f1bd1
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/QueryFieldLabels.java
@@ -0,0 +1,63 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.constants;
+
+public class QueryFieldLabels {
+
+ /*
+ * Generic Query related field labels
+ * */
+ public static final String PREDICATE = "predicateLit";
+ public static final String OBJECT = "objectLit";
+
+
+ /*
+ * Document related field labels
+ * */
+ public static final String DOCUMENT_URL = "documentLit";
+ public static final String DOCUMENT_MONIKER = "documentMonikerLit";
+ public static final String DOCUMENT_LABEL = "documentLabelLit";
+ public static final String DOCUMENT_BLURB = "documentBlurbLit";
+ public static final String DOCUMENT_DESCRIPTION = "documentDescriptionLit";
+ public static final String DOCUMENT_PUBLICATION_YEAR = "publicationYearLit";
+ public static final String DOCUMENT_PUBLICATION_YEAR_MONTH = "publicationYearMonthLit";
+ public static final String DOCUMENT_PUBLICATION_DATE = "publicationDateLit";
+
+
+ /*
+ * Image related field labels
+ * */
+ public static final String THUMBNAIL_LOCATION_URL = "thumbnailDownloadLocationLit";
+ public static final String THUMBNAIL_FILENAME = "thumbnailFileNameLit";
+
+ /*
+ * Author related field labels
+ * */
+ public static final String AUTHOR_URL = "authPersonLit";
+ public static final String AUTHOR_LABEL = "authorLabelLit";
+
+ /*
+ * Co-Author related field labels
+ * */
+ public static final String CO_AUTHOR_URL = "coAuthPersonLit";
+ public static final String CO_AUTHOR_LABEL = "coAuthPersonLabelLit";
+
+ /*
+ * College related field labels
+ * */
+ public static final String COLLEGE_URL = "collegeLit";
+ public static final String COLLEGE_LABEL = "collegeLabelLit";
+
+ /*
+ * Department related field labels
+ * */
+ public static final String DEPARTMENT_URL = "departmentLit";
+ public static final String DEPARTMENT_LABEL = "departmentLabelLit";
+
+ /*
+ * Employee related field labels
+ * */
+ public static final String ACADEMIC_FACULTY_EMPLOYEE_URL = "academicFacultyEmployeeLit";
+ public static final String ACADEMIC_STAFF_EMPLOYEE_URL = "academicStaffEmployeeLit";
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VOConstants.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VOConstants.java
new file mode 100644
index 00000000..37d8778a
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VOConstants.java
@@ -0,0 +1,18 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.constants;
+
+public class VOConstants {
+
+ public static final String DEFAULT_PUBLICATION_YEAR = "Unknown";
+
+ /*
+ * Employee related constants
+ * */
+ public static enum EmployeeType {
+ ACADEMIC_FACULTY_EMPLOYEE, ACADEMIC_STAFF_EMPLOYEE
+ }
+
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VisConstants.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VisConstants.java
new file mode 100644
index 00000000..d7874de1
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/constants/VisConstants.java
@@ -0,0 +1,10 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.constants;
+
+public class VisConstants {
+
+ public static final int MAX_NAME_TEXT_LENGTH = 10;
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/DocumentFieldNotFoundException.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/DocumentFieldNotFoundException.java
new file mode 100644
index 00000000..2da34434
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/DocumentFieldNotFoundException.java
@@ -0,0 +1,21 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.exceptions;
+
+public class DocumentFieldNotFoundException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public DocumentFieldNotFoundException(String message) {
+ super(message);
+ }
+
+ public DocumentFieldNotFoundException(Exception cause) {
+ super(createMessage(cause), cause);
+ }
+
+ private static String createMessage(Exception cause) {
+ return "Document Field is empty " + cause.getMessage();
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/MalformedQueryParametersException.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/MalformedQueryParametersException.java
new file mode 100644
index 00000000..a721eb13
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/MalformedQueryParametersException.java
@@ -0,0 +1,21 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.exceptions;
+
+public class MalformedQueryParametersException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public MalformedQueryParametersException(String message) {
+ super(message);
+ }
+
+ public MalformedQueryParametersException(Exception cause) {
+ super(createMessage(cause), cause);
+ }
+
+ private static String createMessage(Exception cause) {
+ return "Malformed Query Params " + cause.getMessage();
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/personlevel/VisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/personlevel/VisualizationRequestHandler.java
new file mode 100644
index 00000000..33016494
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personlevel/VisualizationRequestHandler.java
@@ -0,0 +1,426 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.personlevel;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+
+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.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipGraphMLWriter;
+import edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisVOContainer;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationCodeGenerator;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
+
+public class VisualizationRequestHandler {
+
+ private VitroRequest vitroRequest;
+ private HttpServletRequest request;
+ private HttpServletResponse response;
+ private Log log;
+
+ public VisualizationRequestHandler(VitroRequest vitroRequest,
+ HttpServletRequest request, HttpServletResponse response, Log log) {
+
+ this.vitroRequest = vitroRequest;
+ this.request = request;
+ this.response = response;
+ this.log = log;
+
+ }
+
+ public void generateVisualization(DataSource dataSource) {
+
+ String resultFormatParam = "RS_TEXT";
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ String egoURIParam = vitroRequest.getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE);
+
+ String renderMode = vitroRequest.getParameter(VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE);
+
+ String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE);
+
+ String coAuthorsListMode = "coauthors";
+
+ String egoPubSparklineVisContainerID = "ego_pub_sparkline";
+ String uniqueCoauthorsSparklineVisContainerID = "unique_coauthors_sparkline";
+
+ edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.QueryHandler coAuthorshipQueryManager =
+ new edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.QueryHandler(egoURIParam,
+ resultFormatParam,
+ rdfResultFormatParam,
+ dataSource,
+ log);
+
+ edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.QueryHandler publicationQueryManager =
+ new edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.QueryHandler(egoURIParam,
+ resultFormatParam,
+ rdfResultFormatParam,
+ dataSource,
+ log);
+
+ try {
+
+ edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisVOContainer coAuthorshipVO =
+ coAuthorshipQueryManager.getVisualizationJavaValueObjects();
+
+ /*
+ * In order to avoid unneeded computations we have pushed this "if" condition up.
+ * This case arises when the render mode is data. In that case we dont want to generate
+ * HTML code to render sparkline, tables etc. Ideally I would want to avoid this flow.
+ * It is ugly!
+ * */
+ if (VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) {
+
+ /*
+ * We will be using the same visualization package for providing data for both
+ * list of unique coauthors & network of coauthors (used in the flash vis). We will
+ * use "VIS_MODE_URL_HANDLE" as a modifier to differentiate between these two.
+ * The defualt will be to provide data used to render the coauthorship network vis.
+ * */
+
+ if (coAuthorsListMode.equalsIgnoreCase(visMode)) {
+ /*
+ * When the csv file is required - containing the unique co-authors vs how many times
+ * they have co-authored with the ego.
+ * */
+ prepareVisualizationQueryListCoauthorsDataResponse(coAuthorshipVO);
+ return;
+
+ } else {
+ /*
+ * When the graphML file is required - based on which coauthorship network visualization
+ * will be rendered.
+ * */
+ prepareVisualizationQueryNetworkDataResponse(coAuthorshipVO);
+ return;
+ }
+
+
+ }
+
+ List authorDocuments = publicationQueryManager.getVisualizationJavaValueObjects();
+
+ /*
+ * Create a map from the year to number of publications. Use the BiboDocument's
+ * parsedPublicationYear to populate the data.
+ * */
+ Map yearToPublicationCount = publicationQueryManager
+ .getYearToPublicationCount(authorDocuments);
+
+// Map yearToUniqueCoauthorCount = getUniqueCoauthorsCountPerYear(coAuthorshipVO);
+
+
+ /*
+ * Computations required to generate HTML for the sparklines & related context.
+ * */
+
+ SparklineVOContainer publicationSparklineVO = new SparklineVOContainer();
+ SparklineVOContainer uniqueCoauthorsSparklineVO = new SparklineVOContainer();
+
+ edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationCodeGenerator personPubCountVisCodeGenerator =
+ new edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationCodeGenerator(
+ vitroRequest.getRequestURI(),
+ egoURIParam,
+ VisualizationCodeGenerator.FULL_SPARKLINE_MODE_URL_HANDLE,
+ egoPubSparklineVisContainerID,
+ authorDocuments,
+ yearToPublicationCount,
+ publicationSparklineVO,
+ log);
+
+ edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisualizationCodeGenerator uniqueCoauthorsVisCodeGenerator =
+ new edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisualizationCodeGenerator(
+ vitroRequest.getRequestURI(),
+ egoURIParam,
+ VisualizationCodeGenerator.FULL_SPARKLINE_MODE_URL_HANDLE,
+ uniqueCoauthorsSparklineVisContainerID,
+ getUniqueCoAuthorsPerYear(coAuthorshipVO),
+ uniqueCoauthorsSparklineVO,
+ log);
+
+
+ RequestDispatcher requestDispatcher = null;
+
+ prepareVisualizationQueryStandaloneResponse(egoURIParam,
+ publicationSparklineVO,
+ uniqueCoauthorsSparklineVO,
+ coAuthorshipVO,
+ egoPubSparklineVisContainerID,
+ uniqueCoauthorsSparklineVisContainerID,
+ request,
+ response,
+ vitroRequest);
+
+// requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp");
+ requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+
+ } catch (MalformedQueryParametersException e) {
+ try {
+ handleMalformedParameters(e.getMessage());
+ } catch (ServletException e1) {
+ log.error(e1.getStackTrace());
+ } catch (IOException e1) {
+ log.error(e1.getStackTrace());
+ }
+ return;
+ }
+
+ }
+/*
+ private Map getUniqueCoauthorsCountPerYear(
+ edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisVOContainer coAuthorshipVO) {
+ Map yearToUniqueCoauthorCount = new TreeMap();
+
+ Map> yearToUniqueCoauthors = getUniqueCoAuthorsPerYear(coAuthorshipVO);
+
+ for (Entry> currentEntry : yearToUniqueCoauthors.entrySet()) {
+
+ yearToUniqueCoauthorCount.put(currentEntry.getKey(), currentEntry.getValue().size());
+
+ }
+ return yearToUniqueCoauthorCount;
+ }
+ */
+
+ private Map> getUniqueCoAuthorsPerYear(edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.VisVOContainer authorNodesAndEdges) {
+
+ Map> yearToCoAuthors = new TreeMap>();
+
+ Node egoNode = authorNodesAndEdges.getEgoNode();
+
+ for (Node currNode : authorNodesAndEdges.getNodes()) {
+
+ /*
+ * We have already printed the Ego Node info.
+ * */
+ if (currNode != egoNode) {
+
+ for (String year : currNode.getYearToPublicationCount().keySet()) {
+
+ Set coAuthorNodes;
+
+ if (yearToCoAuthors.containsKey(year)) {
+
+ coAuthorNodes = yearToCoAuthors.get(year);
+ coAuthorNodes.add(currNode);
+
+ } else {
+
+ coAuthorNodes = new HashSet();
+ coAuthorNodes.add(currNode);
+ yearToCoAuthors.put(year, coAuthorNodes);
+ }
+
+ }
+
+ }
+ }
+
+
+ return yearToCoAuthors;
+ }
+
+ private void prepareVisualizationQueryNetworkDataResponse(VisVOContainer coAuthorsipVO) {
+
+ String outputFileName = "";
+
+ if (coAuthorsipVO.getNodes() == null || coAuthorsipVO.getNodes().size() < 1) {
+
+ outputFileName = "no-coauthorship-net" + ".csv";
+
+ } else {
+
+ outputFileName = UtilityFunctions.slugify(coAuthorsipVO.getEgoNode().getNodeName())
+ + "-coauthor-net" + ".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(VisVOContainer coAuthorsipVO) {
+
+ String outputFileName = "";
+ Map coAuthorsToCount = new TreeMap();
+
+ if (coAuthorsipVO.getNodes() == null || coAuthorsipVO.getNodes().size() < 1 ) {
+
+ outputFileName = "no-coauthors-list" + ".csv";
+
+ } else {
+
+ outputFileName = UtilityFunctions.slugify(coAuthorsipVO.getEgoNode().getNodeName())
+ + "-coauthors-list" + ".csv";
+
+ coAuthorsToCount = getCoAuthorsList(coAuthorsipVO);
+
+ }
+
+ response.setContentType("application/octet-stream");
+ response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName);
+
+ try {
+
+ PrintWriter responseWriter = response.getWriter();
+
+ /*
+ * We are side-effecting responseWriter since we are directly manipulating the response
+ * object of the servlet.
+ * */
+ generateCsvFileBuffer(coAuthorsToCount,
+ responseWriter);
+
+ responseWriter.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ private Map getCoAuthorsList(VisVOContainer coAuthorsipVO) {
+
+ Map coAuthorsToCount = new TreeMap();
+
+ for (Node currNode : coAuthorsipVO.getNodes()) {
+
+ /*
+ * We have already printed the Ego Node info.
+ * */
+ if (currNode != coAuthorsipVO.getEgoNode()) {
+
+ coAuthorsToCount.put(currNode.getNodeName(), currNode.getNumOfAuthoredWorks());
+
+ }
+
+ }
+
+
+ return coAuthorsToCount;
+ }
+
+ private void generateCsvFileBuffer(Map coAuthorsToCount, PrintWriter printWriter) {
+
+ printWriter.append("\"Co-Author\", \"Count\"\n");
+
+ for (Entry currentEntry : coAuthorsToCount.entrySet()) {
+
+ printWriter.append("\"" + currentEntry.getKey() + "\","
+ + "\"" + currentEntry.getValue() + "\"\n"
+ );
+ }
+
+ printWriter.flush();
+ }
+
+
+ private void prepareVisualizationQueryStandaloneResponse(
+ String egoURIParam,
+ SparklineVOContainer egoPubSparklineVO,
+ SparklineVOContainer uniqueCoauthorsSparklineVO,
+ VisVOContainer coAuthorshipVO,
+ String egoPubSparklineVisContainer,
+ String uniqueCoauthorsSparklineVisContainer,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ VitroRequest vreq) {
+
+ Portal portal = vreq.getPortal();
+
+ request.setAttribute("egoURIParam", egoURIParam);
+
+ if (coAuthorshipVO.getNodes() != null) {
+ request.setAttribute("numOfAuthors", coAuthorshipVO.getNodes().size());
+ }
+
+ if (coAuthorshipVO.getEdges() != null) {
+ request.setAttribute("numOfCoAuthorShips", coAuthorshipVO.getEdges().size());
+ }
+
+
+ request.setAttribute("egoPubSparklineVO", egoPubSparklineVO);
+ request.setAttribute("uniqueCoauthorsSparklineVO", uniqueCoauthorsSparklineVO);
+
+ request.setAttribute("egoPubSparklineContainerID", egoPubSparklineVisContainer);
+ request.setAttribute("uniqueCoauthorsSparklineVisContainerID", uniqueCoauthorsSparklineVisContainer);
+
+ request.setAttribute("title", "Person Level Visualization");
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("scripts", "/templates/visualization/person_level_inject_head.jsp");
+
+ request.setAttribute("bodyJsp", "/templates/visualization/person_level.jsp");
+ }
+
+ private void handleMalformedParameters(String errorMessage)
+ throws ServletException, IOException {
+
+ Portal portal = vitroRequest.getPortal();
+
+ request.setAttribute("error", errorMessage);
+
+ RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+ request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp");
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("title", "Visualization Query Error - Individual Publication Count");
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/QueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/QueryHandler.java
new file mode 100644
index 00000000..555cbf79
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/QueryHandler.java
@@ -0,0 +1,274 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.commons.logging.Log;
+
+import com.hp.hpl.jena.iri.IRI;
+import com.hp.hpl.jena.iri.IRIFactory;
+import com.hp.hpl.jena.iri.Violation;
+import com.hp.hpl.jena.query.DataSource;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+import com.hp.hpl.jena.query.QueryFactory;
+import com.hp.hpl.jena.query.QuerySolution;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.query.Syntax;
+import com.hp.hpl.jena.rdf.model.RDFNode;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryFieldLabels;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual;
+
+
+
+/**
+ * @author cdtank
+ *
+ */
+public class QueryHandler {
+
+ protected static final Syntax SYNTAX = Syntax.syntaxARQ;
+
+ private String queryParam, resultFormatParam, rdfResultFormatParam;
+ private DataSource dataSource;
+
+ private Individual author;
+
+ public Individual getAuthor() {
+ return author;
+ }
+
+ private Log log;
+
+ private static final String SPARQL_QUERY_COMMON_SELECT_CLAUSE = "" +
+ "SELECT (str(?authorLabel) as ?authorLabelLit) " +
+ " (str(?document) as ?documentLit) " +
+ " (str(?documentMoniker) as ?documentMonikerLit) " +
+ " (str(?documentLabel) as ?documentLabelLit) " +
+ " (str(?documentBlurb) as ?documentBlurbLit) " +
+ " (str(?publicationYear) as ?publicationYearLit) " +
+ " (str(?publicationYearMonth) as ?publicationYearMonthLit) " +
+ " (str(?publicationDate) as ?publicationDateLit) " +
+ " (str(?documentDescription) as ?documentDescriptionLit) ";
+
+ private static final String SPARQL_QUERY_COMMON_WHERE_CLAUSE = "" +
+ "?document rdf:type bibo:Document ." +
+ "?document rdfs:label ?documentLabel ." +
+ "OPTIONAL { ?document core:year ?publicationYear } ." +
+ "OPTIONAL { ?document core:yearMonth ?publicationYearMonth } ." +
+ "OPTIONAL { ?document core:date ?publicationDate } ." +
+ "OPTIONAL { ?document vitro:moniker ?documentMoniker } ." +
+ "OPTIONAL { ?document vitro:blurb ?documentBlurb } ." +
+ "OPTIONAL { ?document vitro:description ?documentDescription }";
+
+ public QueryHandler(String queryParam,
+ String resultFormatParam, String rdfResultFormatParam,
+ DataSource dataSource, Log log) {
+
+ this.queryParam = queryParam;
+ this.resultFormatParam = resultFormatParam;
+ this.rdfResultFormatParam = rdfResultFormatParam;
+ this.dataSource = dataSource;
+ this.log = log;
+
+ }
+
+ private List createJavaValueObjects(ResultSet resultSet) {
+ List authorDocuments = new ArrayList();
+
+ while (resultSet.hasNext()) {
+ QuerySolution solution = resultSet.nextSolution();
+
+ BiboDocument biboDocument = new BiboDocument(
+ solution.get(QueryFieldLabels.DOCUMENT_URL)
+ .toString());
+
+ RDFNode documentLabelNode = solution.get(QueryFieldLabels.DOCUMENT_LABEL);
+ if (documentLabelNode != null) {
+ biboDocument.setDocumentLabel(documentLabelNode.toString());
+ }
+
+
+ RDFNode documentBlurbNode = solution.get(QueryFieldLabels.DOCUMENT_BLURB);
+ if (documentBlurbNode != null) {
+ biboDocument.setDocumentBlurb(documentBlurbNode.toString());
+ }
+
+ RDFNode documentmonikerNode = solution.get(QueryFieldLabels.DOCUMENT_MONIKER);
+ if (documentmonikerNode != null) {
+ biboDocument.setDocumentMoniker(documentmonikerNode.toString());
+ }
+
+ RDFNode documentDescriptionNode = solution.get(QueryFieldLabels.DOCUMENT_DESCRIPTION);
+ if (documentDescriptionNode != null) {
+ biboDocument.setDocumentDescription(documentDescriptionNode.toString());
+ }
+
+ RDFNode publicationYearNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR);
+ if (publicationYearNode != null) {
+ biboDocument.setPublicationYear(publicationYearNode.toString());
+ }
+
+ RDFNode publicationYearMonthNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR_MONTH);
+ if (publicationYearMonthNode != null) {
+ biboDocument.setPublicationYearMonth(publicationYearMonthNode.toString());
+ }
+
+ RDFNode publicationDateNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_DATE);
+ if (publicationDateNode != null) {
+ biboDocument.setPublicationDate(publicationDateNode.toString());
+ }
+
+ /*
+ * Since we are getting publication count for just one author at a time we need
+ * to create only one "Individual" instance. We test against the null for "author" to
+ * make sure that it has not already been instantiated.
+ * */
+ RDFNode authorURLNode = solution.get(QueryFieldLabels.AUTHOR_URL);
+ if (authorURLNode != null && author == null) {
+ author = new Individual(authorURLNode.toString());
+ RDFNode authorLabelNode = solution.get(QueryFieldLabels.AUTHOR_LABEL);
+ if (authorLabelNode != null) {
+ author.setIndividualLabel(authorLabelNode.toString());
+ }
+
+ }
+
+ authorDocuments.add(biboDocument);
+ }
+ return authorDocuments;
+ }
+
+ private ResultSet executeQuery(String queryURI,
+ String resultFormatParam, String rdfResultFormatParam, DataSource dataSource) {
+
+ QueryExecution queryExecution = null;
+ try{
+ Query query = QueryFactory.create(generateSparqlQuery(queryURI), SYNTAX);
+
+// QuerySolutionMap qs = new QuerySolutionMap();
+// qs.add("authPerson", queryParam); // bind resource to s
+
+ queryExecution = QueryExecutionFactory.create(query, dataSource);
+
+
+ //remocve this if loop after knowing what is describe & construct sparql stuff.
+ if( query.isSelectType() ){
+ return queryExecution.execSelect();
+ }
+ } finally {
+ if(queryExecution != null) {
+ queryExecution.close();
+ }
+
+ }
+ return null;
+ }
+
+ private String generateSparqlQuery(String queryURI) {
+// Resource uri1 = ResourceFactory.createResource(queryURI);
+
+ String sparqlQuery = QueryConstants.getSparqlPrefixQuery()
+ + SPARQL_QUERY_COMMON_SELECT_CLAUSE
+ + "(str(<" + queryURI + ">) as ?authPersonLit) "
+ + "WHERE { "
+ + "<" + queryURI + "> rdf:type foaf:Person ; rdfs:label ?authorLabel ; core:authorInAuthorship ?authorshipNode . "
+ + " ?authorshipNode rdf:type core:Authorship ; core:linkedInformationResource ?document . "
+ + SPARQL_QUERY_COMMON_WHERE_CLAUSE
+ + "}";
+
+// System.out.println("SPARQL query for person pub count -> \n" + sparqlQuery);
+
+ return sparqlQuery;
+ }
+
+ public List getVisualizationJavaValueObjects()
+ throws MalformedQueryParametersException {
+
+ if(this.queryParam == null || "".equals(queryParam)) {
+ throw new MalformedQueryParametersException("URL parameter is either null or empty.");
+ } else {
+
+ /*
+ * To test for the validity of the URI submitted.
+ * */
+ IRIFactory iRIFactory = IRIFactory.jenaImplementation();
+ IRI iri = iRIFactory.create(this.queryParam);
+ if (iri.hasViolation(false)) {
+ String errorMsg = ((Violation)iri.violations(false).next()).getShortMessage()+" ";
+ log.error("Pub Count vis Query " + errorMsg);
+ throw new MalformedQueryParametersException("URI provided for an individual is malformed.");
+ }
+ }
+
+ ResultSet resultSet = executeQuery(this.queryParam,
+ this.resultFormatParam,
+ this.rdfResultFormatParam,
+ this.dataSource);
+
+ return createJavaValueObjects(resultSet);
+ }
+
+ public Map getYearToPublicationCount(
+ List authorDocuments) {
+
+ //List publishedYears = new ArrayList();
+
+ /*
+ * Create a map from the year to number of publications. Use the BiboDocument's
+ * parsedPublicationYear to populate the data.
+ * */
+ Map yearToPublicationCount = new TreeMap();
+
+ for (BiboDocument curr : authorDocuments) {
+
+ /*
+ * Increment the count because there is an entry already available for
+ * that particular year.
+ *
+ * I am pushing the logic to check for validity of year in "getPublicationYear" itself
+ * because,
+ * 1. We will be using getPub... multiple times & this will save us duplication of code
+ * 2. If we change the logic of validity of a pub year we would not have to make changes
+ * all throughout the codebase.
+ * 3. We are asking for a publication year & we should get a proper one or NOT at all.
+ * */
+ String publicationYear;
+ if (curr.getPublicationYear() != null) {
+ publicationYear = curr.getPublicationYear();
+ } else {
+ publicationYear = curr.getParsedPublicationYear();
+ }
+
+ if (yearToPublicationCount.containsKey(publicationYear)) {
+ yearToPublicationCount.put(publicationYear,
+ yearToPublicationCount
+ .get(publicationYear) + 1);
+
+ } else {
+ yearToPublicationCount.put(publicationYear, 1);
+ }
+
+// if (!parsedPublicationYear.equalsIgnoreCase(BiboDocument.DEFAULT_PUBLICATION_YEAR)) {
+// publishedYears.add(Integer.parseInt(parsedPublicationYear));
+// }
+
+ }
+
+ return yearToPublicationCount;
+ }
+
+
+
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationCodeGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationCodeGenerator.java
new file mode 100644
index 00000000..c8cedd0b
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationCodeGenerator.java
@@ -0,0 +1,676 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.apache.commons.logging.Log;
+
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer;
+
+
+public class VisualizationCodeGenerator {
+
+ private final static Map visDivNames = new HashMap() {{
+
+ put("SHORT_SPARK", "pub_count_short_sparkline_vis");
+ put("FULL_SPARK", "pub_count_full_sparkline_vis");
+
+ }};
+
+ private static final String visualizationStyleClass = "sparkline_style";
+
+ private static final String defaultVisContainerDivID = "pub_count_vis_container";
+
+ public static final String SHORT_SPARKLINE_MODE_URL_HANDLE = "short";
+
+ public static final String FULL_SPARKLINE_MODE_URL_HANDLE = "full";
+
+ private Map yearToPublicationCount;
+
+ private Log log;
+
+ private SparklineVOContainer valueObjectContainer;
+
+ private String contextPath;
+
+ private String individualURIParam;
+
+ public VisualizationCodeGenerator(String contextPath,
+ String individualURIParam,
+ String visMode,
+ String visContainer,
+ List authorDocuments,
+ Map yearToPublicationCount,
+ SparklineVOContainer valueObjectContainer,
+ Log log) {
+
+ this.contextPath = contextPath;
+ this.individualURIParam = individualURIParam;
+
+ this.yearToPublicationCount = yearToPublicationCount;
+ this.valueObjectContainer = valueObjectContainer;
+
+ this.log = log;
+
+
+ generateVisualizationCode(visMode,
+ visContainer,
+ authorDocuments);
+
+
+ }
+
+ private void generateVisualizationCode(String visMode,
+ String visContainer,
+ List authorDocuments) {
+
+ valueObjectContainer.setSparklineContent(getMainVisualizationCode(authorDocuments,
+ visMode,
+ visContainer));
+
+
+ valueObjectContainer.setSparklineContext(getVisualizationContextCode(visMode));
+
+ }
+
+ private String getMainVisualizationCode(List authorDocuments,
+ String visMode,
+ String providedVisContainerID) {
+
+ int numOfYearsToBeRendered = 0;
+ int currentYear = Calendar.getInstance().get(Calendar.YEAR);
+ int shortSparkMinYear = currentYear - 10 + 1;
+
+ /*
+ * This is required because when deciding the range of years over which the vis
+ * was rendered we dont want to be influenced by the "DEFAULT_PUBLICATION_YEAR".
+ * */
+ Set publishedYears = new HashSet(yearToPublicationCount.keySet());
+ publishedYears.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ * We are setting the default value of minPublishedYear to be 10 years before
+ * the current year (which is suitably represented by the shortSparkMinYear),
+ * this in case we run into invalid set of published years.
+ * */
+ int minPublishedYear = shortSparkMinYear;
+
+ String visContainerID = null;
+
+ StringBuilder visualizationCode = new StringBuilder();
+
+// System.out.println(yearToPublicationCount);
+ if (yearToPublicationCount.size() > 0) {
+ try {
+ minPublishedYear = Integer.parseInt(Collections.min(publishedYears));
+ } catch (NoSuchElementException e1) {
+ log.debug("vis: " + e1.getMessage() + " error occurred for " + yearToPublicationCount.toString());
+ } catch (NumberFormatException e2) {
+ log.debug("vis: " + e2.getMessage() + " error occurred for " + yearToPublicationCount.toString());
+ }
+ }
+
+ int minPubYearConsidered = 0;
+
+ /*
+ * There might be a case that the author has made his first publication within the
+ * last 10 years but we want to make sure that the sparkline is representative of
+ * at least the last 10 years, so we will set the minPubYearConsidered to
+ * "currentYear - 10" which is also given by "shortSparkMinYear".
+ * */
+ if (minPublishedYear > shortSparkMinYear) {
+ minPubYearConsidered = shortSparkMinYear;
+ } else {
+ minPubYearConsidered = minPublishedYear;
+ }
+
+ numOfYearsToBeRendered = currentYear - minPubYearConsidered + 1;
+
+ visualizationCode.append("\n");
+
+// .sparkline {display:inline; margin:0; padding:0; width:600px }
+
+
+
+// td.sparkline-img {margin:0; padding:0; }
+
+
+ visualizationCode.append("\n";
+ }
+
+ private String getVisualizationContextCode(String visMode) {
+
+ String visualizationContextCode = "";
+ if (SHORT_SPARKLINE_MODE_URL_HANDLE.equalsIgnoreCase(visMode)) {
+ visualizationContextCode = generateShortVisContext();
+ } else {
+ visualizationContextCode = generateFullVisContext();
+ }
+
+
+
+
+
+
+// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ log.debug(visualizationContextCode);
+// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+
+ return visualizationContextCode;
+ }
+
+ private String generateFullVisContext() {
+
+ StringBuilder divContextCode = new StringBuilder();
+
+ String csvDownloadURLHref = "";
+
+ if (yearToPublicationCount.size() > 0) {
+
+ try {
+ if (getCSVDownloadURL() != null) {
+
+ csvDownloadURLHref = "Download data as .csv file. ";
+ valueObjectContainer.setDownloadDataLink(getCSVDownloadURL());
+
+ } else {
+
+ csvDownloadURLHref = "";
+
+ }
+
+ } catch (UnsupportedEncodingException e) {
+ csvDownloadURLHref = "";
+ }
+
+
+ } else {
+ csvDownloadURLHref = "No data available to export. ";
+ }
+
+ String tableCode = generateDataTable();
+
+ divContextCode.append("" + tableCode +
+ csvDownloadURLHref + "
");
+
+ valueObjectContainer.setTable(tableCode);
+
+ return divContextCode.toString();
+
+ }
+
+ private String getCSVDownloadURL()
+ throws UnsupportedEncodingException {
+
+ if (yearToPublicationCount.size() > 0) {
+
+ String secondaryContextPath = "";
+ if (!contextPath.contains("/admin/visQuery")) {
+ secondaryContextPath = "/admin/visQuery";
+ }
+
+
+ String downloadURL = contextPath
+ + secondaryContextPath
+ + "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ + "=" + URLEncoder.encode(individualURIParam,
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&" + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE
+ + "=" + URLEncoder.encode(VisualizationController
+ .PERSON_PUBLICATION_COUNT_VIS_URL_VALUE,
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&" + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE
+ + "=" + URLEncoder.encode(VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE,
+ VisualizationController.URL_ENCODING_SCHEME).toString();
+// System.out.println(" ----- >>>> " + contextPath + " XX " + individualURIParam + " XX " + downloadURL);
+ return downloadURL;
+ } else {
+ return null;
+ }
+
+ }
+
+
+ private String generateShortVisContext() {
+
+ StringBuilder divContextCode = new StringBuilder();
+
+ try {
+
+ String fullTimelineLink;
+ if (yearToPublicationCount.size() > 0) {
+
+ String secondaryContextPath = "";
+ if (!contextPath.contains("/admin/visQuery")) {
+ secondaryContextPath = "/admin/visQuery";
+ }
+
+ String fullTimelineNetworkURL = contextPath
+ + secondaryContextPath
+ + "?"
+ + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ + "=" + URLEncoder.encode(individualURIParam,
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&"
+ + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE
+ + "=" + URLEncoder.encode("person_level",
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&"
+ + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE
+ + "=" + URLEncoder.encode(VisualizationFrameworkConstants.STANDALONE_RENDER_MODE_URL_VALUE,
+ VisualizationController.URL_ENCODING_SCHEME).toString();
+
+ System.out.println("context parth full n/w " + contextPath);
+
+ fullTimelineLink = "View all publications over career and co-author network ";
+
+ valueObjectContainer.setFullTimelineNetworkLink(fullTimelineNetworkURL);
+
+ } else {
+
+ fullTimelineLink = "No data available to render full timeline. ";
+
+ }
+
+ divContextCode.append("" + fullTimelineLink + " ");
+
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+
+ return divContextCode.toString();
+
+ }
+
+
+ private String generateDataTable() {
+
+ String csvDownloadURLHref = "";
+
+ try {
+ if (getCSVDownloadURL() != null) {
+
+ csvDownloadURLHref = "(.CSV File) ";
+
+ } else {
+
+ csvDownloadURLHref = "";
+
+ }
+
+ } catch (UnsupportedEncodingException e) {
+ csvDownloadURLHref = "";
+ }
+
+ StringBuilder dataTable = new StringBuilder();
+
+ dataTable.append("" +
+ "Publications per year " + csvDownloadURLHref + " " +
+ "" +
+ "" +
+ "Year " +
+ "Publications " +
+ " " +
+ " " +
+ "");
+
+ for (Entry currentEntry : yearToPublicationCount.entrySet()) {
+ dataTable.append("" +
+ "" + currentEntry.getKey() + " " +
+ "" + currentEntry.getValue() + " " +
+ " ");
+ }
+
+ dataTable.append(" \n" +
+ "
\n");
+
+
+ return dataTable.toString();
+ }
+
+
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationRequestHandler.java
new file mode 100644
index 00000000..c5982a26
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationRequestHandler.java
@@ -0,0 +1,338 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.skife.csv.CSVWriter;
+import org.skife.csv.SimpleWriter;
+
+import com.hp.hpl.jena.query.DataSource;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.pdf.PdfWriter;
+
+import edu.cornell.mannlib.vitro.webapp.beans.Portal;
+import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.PDFDocument;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Individual;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineVOContainer;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
+
+public class VisualizationRequestHandler {
+
+ private VitroRequest vitroRequest;
+ private HttpServletRequest request;
+ private HttpServletResponse response;
+ private Log log;
+
+
+
+ public VisualizationRequestHandler(VitroRequest vitroRequest,
+ HttpServletRequest request, HttpServletResponse response, Log log) {
+
+ this.vitroRequest = vitroRequest;
+ this.request = request;
+ this.response = response;
+ this.log = log;
+
+ }
+
+ public void generateVisualization(DataSource dataSource) {
+
+ String resultFormatParam = "RS_TEXT";
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ String individualURIParam = vitroRequest.getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE);
+
+ String renderMode = vitroRequest.getParameter(VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE);
+
+ String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE);
+
+ String visContainer = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE);
+
+ QueryHandler queryManager =
+ new QueryHandler(individualURIParam,
+ resultFormatParam,
+ rdfResultFormatParam,
+ dataSource,
+ log);
+
+ try {
+ List authorDocuments = queryManager.getVisualizationJavaValueObjects();
+
+ /*
+ * Create a map from the year to number of publications. Use the BiboDocument's
+ * parsedPublicationYear to populate the data.
+ * */
+ Map yearToPublicationCount =
+ queryManager.getYearToPublicationCount(authorDocuments);
+
+ /*
+ * In order to avoid unneeded computations we have pushed this "if" condition up.
+ * This case arises when the render mode is data. In that case we dont want to generate
+ * HTML code to render sparkline, tables etc. Ideally I would want to avoid this flow.
+ * It is ugly!
+ * */
+ if (VisualizationFrameworkConstants.DATA_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) {
+ prepareVisualizationQueryDataResponse(queryManager.getAuthor(),
+ authorDocuments,
+ yearToPublicationCount);
+ return;
+ }
+
+
+ if (VisualizationFrameworkConstants.PDF_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) {
+ prepareVisualizationQueryPDFResponse(queryManager.getAuthor(),
+ authorDocuments,
+ yearToPublicationCount);
+ return;
+ }
+
+ /*
+ * Computations required to generate HTML for the sparklines & related context.
+ * */
+
+ SparklineVOContainer valueObjectContainer = new SparklineVOContainer();
+
+ VisualizationCodeGenerator visualizationCodeGenerator =
+ new VisualizationCodeGenerator(vitroRequest.getContextPath(),
+ individualURIParam,
+ visMode,
+ visContainer,
+ authorDocuments,
+ yearToPublicationCount,
+ valueObjectContainer,
+ log);
+
+
+ /*
+ * This is side-effecting because the response of this method is just to redirect to
+ * a page with visualization on it.
+ * */
+ RequestDispatcher requestDispatcher = null;
+
+ if (VisualizationFrameworkConstants.DYNAMIC_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) {
+
+ prepareVisualizationQueryDynamicResponse(request, response, vitroRequest,
+ valueObjectContainer, yearToPublicationCount);
+ requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp");
+
+ } else {
+ prepareVisualizationQueryStandaloneResponse(request, response, vitroRequest,
+ valueObjectContainer);
+
+ requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+ }
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+
+ } catch (MalformedQueryParametersException e) {
+ try {
+ handleMalformedParameters(e.getMessage());
+ } catch (ServletException e1) {
+ log.error(e1.getStackTrace());
+ } catch (IOException e1) {
+ log.error(e1.getStackTrace());
+ }
+ return;
+ }
+
+ }
+
+ private void prepareVisualizationQueryPDFResponse(Individual author, List authorDocuments,
+ Map yearToPublicationCount) {
+
+ String authorName = null;
+
+ /*
+ * To protect against cases where there are no author documents associated with the
+ * individual.
+ * */
+ if (authorDocuments.size() > 0) {
+ authorName = author.getIndividualLabel();
+ }
+
+ /*
+ * To make sure that null/empty records for author names do not cause any mischief.
+ * */
+ if (authorName == null) {
+ authorName = "";
+ }
+
+ 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();
+ }
+ }
+
+ private void prepareVisualizationQueryDataResponse(Individual author, List authorDocuments,
+ Map yearToPublicationCount) {
+
+ String authorName = null;
+
+ /*
+ * To protect against cases where there are no author documents associated with the
+ * individual.
+ * */
+ if (authorDocuments.size() > 0) {
+ authorName = author.getIndividualLabel();
+ }
+
+ /*
+ * To make sure that null/empty records for author names do not cause any mischief.
+ * */
+ if (authorName == null) {
+ authorName = "";
+ }
+
+ String outputFileName = UtilityFunctions.slugify(authorName) + "pub-count-sparkline" + ".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(yearToPublicationCount,
+ responseWriter);
+
+ responseWriter.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void generateCsvFileBuffer(Map yearToPublicationCount,
+ PrintWriter responseWriter) {
+
+ CSVWriter csvWriter = new SimpleWriter(responseWriter);
+
+ try {
+ csvWriter.append(new String[]{"Year", "Publications"});
+ for (Entry currentEntry : yearToPublicationCount.entrySet()) {
+ csvWriter.append(new Object[]{currentEntry.getKey(), currentEntry.getValue()});
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ responseWriter.flush();
+
+ }
+
+ private void prepareVisualizationQueryStandaloneResponse(HttpServletRequest request,
+ HttpServletResponse response, VitroRequest vreq,
+ SparklineVOContainer valueObjectContainer) {
+
+ Portal portal = vreq.getPortal();
+
+ request.setAttribute("sparklineVO", valueObjectContainer);
+
+ request.setAttribute("bodyJsp", "/templates/visualization/publication_count.jsp");
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("title", "Individual Publication Count visualization");
+ request.setAttribute("scripts", "/templates/visualization/visualization_scripts.jsp");
+
+ }
+
+ private void prepareVisualizationQueryDynamicResponse(HttpServletRequest request,
+ HttpServletResponse response, VitroRequest vreq, SparklineVOContainer valueObjectContainer,
+ Map yearToPublicationCount) {
+
+ Portal portal = vreq.getPortal();
+
+ request.setAttribute("sparklineVO", valueObjectContainer);
+
+ if (yearToPublicationCount.size() > 0) {
+ request.setAttribute("shouldVIVOrenderVis", true);
+ } else {
+ request.setAttribute("shouldVIVOrenderVis", false);
+ }
+
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("bodyJsp", "/templates/visualization/ajax_vis_content.jsp");
+
+ }
+
+ private void handleMalformedParameters(String errorMessage)
+ throws ServletException, IOException {
+
+ Portal portal = vitroRequest.getPortal();
+
+ request.setAttribute("error", errorMessage);
+
+ RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+ request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp");
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("title", "Visualization Query Error - Individual Publication Count");
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/utilities/VisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/utilities/VisualizationRequestHandler.java
new file mode 100644
index 00000000..2d5f2032
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/utilities/VisualizationRequestHandler.java
@@ -0,0 +1,291 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.utilities;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+
+import com.google.gson.Gson;
+import com.hp.hpl.jena.query.DataSource;
+import com.hp.hpl.jena.query.QuerySolution;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.rdf.model.RDFNode;
+
+import edu.cornell.mannlib.vitro.webapp.beans.Portal;
+import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.filestorage.FileServingHelper;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryFieldLabels;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.GenericQueryMap;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.AllPropertiesQueryHandler;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.GenericQueryHandler;
+
+public class VisualizationRequestHandler {
+
+ private VitroRequest vitroRequest;
+ private HttpServletRequest request;
+ private HttpServletResponse response;
+ private Log log;
+
+
+
+ public VisualizationRequestHandler(VitroRequest vitroRequest,
+ HttpServletRequest request, HttpServletResponse response, Log log) {
+
+ this.vitroRequest = vitroRequest;
+ this.request = request;
+ this.response = response;
+ this.log = log;
+
+ }
+
+ public void generateVisualization(DataSource dataSource) {
+
+ String individualURIParam = vitroRequest.getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE);
+
+ String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE);
+
+ String profileInfoMode = "PROFILE_INFO";
+ String profileVisMode = "PROFILE_URL";
+ String coAuthorVisMode = "COAUTHORSHIP_URL";
+ String personLevelVisMode = "PERSON_LEVEL_URL";
+ String imageVisMode = "IMAGE_URL";
+
+ String resultFormatParam = "RS_TEXT";
+ String rdfResultFormatParam = "RDF/XML-ABBREV";
+
+ String preparedURL = "";
+
+ try {
+
+ /*
+ * If the info being requested is about a profile which includes the name, moniker
+ * & image url.
+ * */
+ if (profileInfoMode.equalsIgnoreCase(visMode)) {
+
+
+ String filterRule = "?predicate = j.2:mainImage || ?predicate = vitro:moniker || ?predicate = rdfs:label";
+ AllPropertiesQueryHandler profileQueryHandler = new AllPropertiesQueryHandler(individualURIParam,
+ filterRule,
+ resultFormatParam,
+ rdfResultFormatParam,
+ dataSource,
+ log);
+
+ try {
+
+ GenericQueryMap profilePropertiesToValues = profileQueryHandler.getJavaValueObjects();
+
+ profilePropertiesToValues.addEntry("imageContextPath", request.getContextPath());
+
+ Gson profileInformation = new Gson();
+
+ prepareVisualizationQueryResponse(profileInformation.toJson(profilePropertiesToValues));
+
+ return;
+
+
+ } catch (MalformedQueryParametersException e) {
+ try {
+ handleMalformedParameters(e.getMessage());
+ } catch (ServletException e1) {
+ log.error(e1.getStackTrace());
+ } catch (IOException e1) {
+ log.error(e1.getStackTrace());
+ }
+ return;
+ }
+
+
+ } else if (imageVisMode.equalsIgnoreCase(visMode)) {
+ /*
+ * If the url being requested is about a standalone image, which is used when we want
+ * to render an image & other info for a co-author OR ego for that matter.
+ * */
+
+ Map fieldLabelToOutputFieldLabel = new HashMap();
+ fieldLabelToOutputFieldLabel.put("downloadLocation", QueryFieldLabels.THUMBNAIL_LOCATION_URL);
+ fieldLabelToOutputFieldLabel.put("fileName", QueryFieldLabels.THUMBNAIL_FILENAME);
+
+ String whereClause = "<" + individualURIParam + "> j.2:thumbnailImage ?thumbnailImage . "
+ + "?thumbnailImage j.2:downloadLocation ?downloadLocation ; j.2:filename ?fileName .";
+
+
+
+ GenericQueryHandler imageQueryHandler = new GenericQueryHandler(individualURIParam,
+ fieldLabelToOutputFieldLabel,
+ whereClause,
+ resultFormatParam,
+ rdfResultFormatParam,
+ dataSource,
+ log);
+
+ try {
+
+ String thumbnailAccessURL = getThumnailInformation(
+ imageQueryHandler.getResultSet(),
+ fieldLabelToOutputFieldLabel);
+
+ System.out.println("thumnail access URL " + thumbnailAccessURL);
+ prepareVisualizationQueryResponse(thumbnailAccessURL);
+ return;
+
+
+ } catch (MalformedQueryParametersException e) {
+ try {
+ handleMalformedParameters(e.getMessage());
+ } catch (ServletException e1) {
+ log.error(e1.getStackTrace());
+ } catch (IOException e1) {
+ log.error(e1.getStackTrace());
+ }
+ return;
+ }
+
+
+ } else if (coAuthorVisMode.equalsIgnoreCase(visMode)) {
+ /*
+ * By default we will be generating profile url else some specific url like coAuthorShip vis
+ * url for that individual.
+ * */
+
+ preparedURL += request.getContextPath()
+ + "/admin/visQuery"
+ + "?"
+ + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ + "=" + URLEncoder.encode(individualURIParam,
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&"
+ + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE
+ + "=" + URLEncoder.encode("coauthorship",
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&"
+ + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE
+ + "=" + URLEncoder.encode(VisualizationFrameworkConstants.STANDALONE_RENDER_MODE_URL_VALUE,
+ VisualizationController.URL_ENCODING_SCHEME).toString();
+
+
+ prepareVisualizationQueryResponse(preparedURL);
+ return;
+
+ } else if (personLevelVisMode.equalsIgnoreCase(visMode)) {
+ /*
+ * By default we will be generating profile url else some specific url like coAuthorShip vis
+ * url for that individual.
+ * */
+
+ preparedURL += request.getContextPath()
+ + "/admin/visQuery"
+ + "?"
+ + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ + "=" + URLEncoder.encode(individualURIParam,
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&"
+ + VisualizationFrameworkConstants.VIS_TYPE_URL_HANDLE
+ + "=" + URLEncoder.encode("person_level",
+ VisualizationController.URL_ENCODING_SCHEME).toString()
+ + "&"
+ + VisualizationFrameworkConstants.RENDER_MODE_URL_HANDLE
+ + "=" + URLEncoder.encode(VisualizationFrameworkConstants.STANDALONE_RENDER_MODE_URL_VALUE,
+ VisualizationController.URL_ENCODING_SCHEME).toString();
+
+ prepareVisualizationQueryResponse(preparedURL);
+ return;
+
+ } else {
+
+ preparedURL += request.getContextPath()
+ + "/individual"
+ + "?"
+ + VisualizationFrameworkConstants.INDIVIDUAL_URI_URL_HANDLE
+ + "=" + URLEncoder.encode(individualURIParam,
+ VisualizationController.URL_ENCODING_SCHEME).toString();
+
+ prepareVisualizationQueryResponse(preparedURL);
+ return;
+
+ }
+
+ } catch (UnsupportedEncodingException e) {
+ log.error(e.getLocalizedMessage());
+ }
+
+ }
+
+ private String getThumnailInformation(ResultSet resultSet,
+ Map fieldLabelToOutputFieldLabel) {
+
+ String finalThumbNailLocation = "";
+
+ while (resultSet.hasNext()) {
+ QuerySolution solution = resultSet.nextSolution();
+
+
+ RDFNode downloadLocationNode = solution.get(fieldLabelToOutputFieldLabel.get("downloadLocation"));
+ RDFNode fileNameNode = solution.get(fieldLabelToOutputFieldLabel.get("fileName"));
+
+ if (downloadLocationNode != null && fileNameNode != null) {
+ finalThumbNailLocation = FileServingHelper
+ .getBytestreamAliasUrl(downloadLocationNode.toString(),
+ fileNameNode.toString());
+ }
+
+ }
+
+ return finalThumbNailLocation;
+ }
+
+ private void prepareVisualizationQueryResponse(String preparedURL) {
+
+ response.setContentType("text/plain");
+
+ try {
+
+ PrintWriter responseWriter = response.getWriter();
+
+ responseWriter.append(preparedURL);
+
+ responseWriter.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void handleMalformedParameters(String errorMessage)
+ throws ServletException, IOException {
+
+ Portal portal = vitroRequest.getPortal();
+
+ request.setAttribute("error", errorMessage);
+
+ RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
+ request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp");
+ request.setAttribute("portalBean", portal);
+ request.setAttribute("title", "Visualization Query Error - Individual Publication Count");
+
+ try {
+ requestDispatcher.forward(request, response);
+ } catch (Exception e) {
+ log.error("EntityEditController could not forward to view.");
+ log.error(e.getMessage());
+ log.error(e.getStackTrace());
+ }
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java
new file mode 100644
index 00000000..2a1b5b75
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java
@@ -0,0 +1,184 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
+
+import java.util.Calendar;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
+
+/**
+ * @author cdtank
+ *
+ */
+public class BiboDocument extends Individual{
+
+ public static final int MINIMUM_PUBLICATION_YEAR = 1800;
+ private static final int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR);
+
+ private String documentMoniker;
+ private String documentBlurb;
+ private String documentDescription;
+ private String publicationYear;
+ private String publicationYearMonth;
+ private String publicationDate;
+ private String parsedPublicationYear = VOConstants.DEFAULT_PUBLICATION_YEAR;
+
+ public BiboDocument(String documentURL) {
+ super(documentURL);
+ }
+
+ public String getDocumentURL() {
+ return this.getIndividualURL();
+ }
+
+ public String getDocumentMoniker() {
+ return documentMoniker;
+ }
+
+ public void setDocumentMoniker(String documentMoniker) {
+ this.documentMoniker = documentMoniker;
+ }
+
+ public String getDocumentLabel() {
+ return this.getIndividualLabel();
+ }
+
+ public void setDocumentLabel(String documentLabel) {
+ this.setIndividualLabel(documentLabel);
+ }
+
+ public String getDocumentBlurb() {
+ return documentBlurb;
+ }
+
+ public void setDocumentBlurb(String documentBlurb) {
+ this.documentBlurb = documentBlurb;
+
+// if (documentBlurb != null) {
+// this.setParsedPublicationYear(parsePublicationYear(documentBlurb));
+// }
+ }
+
+ private String parsePublicationYear(String documentBlurb) {
+
+ /*
+ * This pattern will match all group of numbers which have only 4 digits
+ * delimited by the word boundary.
+ * */
+// String pattern = "\\b\\d{4}\\b";
+ String pattern = "(?= MINIMUM_PUBLICATION_YEAR) {
+ publishedYear = candidateYearInteger.toString();
+ }
+
+ }
+
+ return publishedYear;
+ }
+
+ public String getDocumentDescription() {
+ return documentDescription;
+ }
+ public void setDocumentDescription(String documentDescription) {
+ this.documentDescription = documentDescription;
+ }
+
+ /**
+ * This method will be called when there is no usable core:year value found
+ * for the bibo:Document. It will first check & parse core:yearMonth failing
+ * which it will try core:date
+ * @return
+ */
+ public String getParsedPublicationYear() {
+
+ /*
+ * We are assuming that core:yearMonth has "YYYY-MM" format. This is based
+ * off of http://www.w3.org/TR/xmlschema-2/#gYearMonth , which is what
+ * core:yearMonth points to internally.
+ * */
+ if (publicationYearMonth != null
+ && publicationYearMonth.length() >= 4
+ && isValidPublicationYear(publicationYearMonth.substring(0, 4))) {
+
+ return publicationYearMonth.substring(0, 4);
+
+ }
+
+ if (publicationDate != null
+ && publicationDate.length() >= 4
+ && isValidPublicationYear(publicationDate.substring(0, 4))) {
+
+ return publicationDate.substring(0, 4);
+ }
+
+ /*
+ * If all else fails return default unknown year identifier
+ * */
+ return VOConstants.DEFAULT_PUBLICATION_YEAR;
+ }
+
+ /*
+ * This publicationYear value is directly from the data supported by the ontology. If this is empty only
+ * then use the parsedPublicationYear.
+ * */
+ public String getPublicationYear() {
+ if (publicationYear != null && isValidPublicationYear(publicationYear)) {
+ return publicationYear;
+ } else {
+ return null;
+ }
+
+ }
+
+ public void setPublicationYear(String publicationYear) {
+ this.publicationYear = publicationYear;
+ }
+
+ public String getPublicationYearMonth() {
+ return publicationYearMonth;
+ }
+
+ public void setPublicationYearMonth(String publicationYearMonth) {
+ this.publicationYearMonth = publicationYearMonth;
+ }
+
+ public String getPublicationDate() {
+ return publicationDate;
+ }
+
+ public void setPublicationDate(String publicationDate) {
+ this.publicationDate = publicationDate;
+ }
+
+ private boolean isValidPublicationYear(String testPublicationYear) {
+
+ if (testPublicationYear.length() != 0
+ && testPublicationYear.trim().length() == 4
+ && testPublicationYear.matches("\\d+")
+ && Integer.parseInt(testPublicationYear) >= MINIMUM_PUBLICATION_YEAR) {
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Edge.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Edge.java
new file mode 100644
index 00000000..8437e5be
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Edge.java
@@ -0,0 +1,149 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UniqueIDGenerator;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
+
+/**
+ *
+ * This is the Value Object for storing edge information mainly for co-author vis.
+ * @author cdtank
+ *
+ */
+public class Edge {
+
+ private int edgeID;
+ private Map yearToPublicationCount;
+ private Set collaboratorDocuments = new HashSet();
+ private Node sourceNode;
+ private Node targetNode;
+
+ public Edge(Node sourceNode, Node targetNode, BiboDocument seedCoAuthoredDocument,
+ UniqueIDGenerator uniqueIDGenerator) {
+ edgeID = uniqueIDGenerator.getNextNumericID();
+ this.sourceNode = sourceNode;
+ this.targetNode = targetNode;
+ this.collaboratorDocuments.add(seedCoAuthoredDocument);
+ }
+
+ public int getEdgeID() {
+ return edgeID;
+ }
+
+ public Node getSourceNode() {
+ return sourceNode;
+ }
+
+ public Node getTargetNode() {
+ return targetNode;
+ }
+
+ public Set getCollaboratorDocuments() {
+ return collaboratorDocuments;
+ }
+
+ public int getNumOfCoAuthoredWorks() {
+ return collaboratorDocuments.size();
+ }
+
+ public void addCollaboratorDocument(BiboDocument authorDocument) {
+ this.collaboratorDocuments.add(authorDocument);
+ }
+
+ /*
+ * 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
+ * incomplete dataset.
+ * */
+ @SuppressWarnings("serial")
+ public Map getEarliestCollaborationYearCount() {
+ if (yearToPublicationCount == null) {
+ yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(collaboratorDocuments);
+ }
+
+ /*
+ * We do not want to consider the default publication year when we are checking
+ * for the min or max publication year.
+ * */
+ Set yearsToBeConsidered = new HashSet(yearToPublicationCount.keySet());
+ yearsToBeConsidered.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ * There can be a case when the only publication the author has no attached year to it
+ * so essentially an "Unknown". In that case Collections.max or min will throw an
+ * NoSuchElementException.
+ *
+ * If there is no maximum year available then we should imply so by returning a "null".
+ * */
+ if (yearsToBeConsidered.size() > 0) {
+ final String earliestYear = Collections.min(yearsToBeConsidered);
+ final Integer earliestYearPubCount = yearToPublicationCount.get(earliestYear);
+
+ return new HashMap(){{
+ put(earliestYear, earliestYearPubCount);
+ }};
+ } else {
+ return null;
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public Map getLatestCollaborationYearCount() {
+ if (yearToPublicationCount == null) {
+ yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(collaboratorDocuments);
+ }
+
+ /*
+ * We do not want to consider the default publication year when we are checking
+ * for the min or max publication year.
+ * */
+ Set yearsToBeConsidered = new HashSet(yearToPublicationCount.keySet());
+ yearsToBeConsidered.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ * There can be a case when the only publication the author has no attached year to it
+ * so essentially an "Unknown". In that case Collections.max or min will throw an
+ * NoSuchElementException.
+ *
+ * If there is no maximum year available then we should imply so by returning a "null".
+ * */
+ if (yearsToBeConsidered.size() > 0) {
+ final String latestYear = Collections.max(yearsToBeConsidered);
+ final Integer latestYearPubCount = yearToPublicationCount.get(latestYear);
+
+ return new HashMap(){{
+ put(latestYear, latestYearPubCount);
+ }};
+ } else {
+ return null;
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public Integer getUnknownCollaborationYearCount() {
+ if (yearToPublicationCount == null) {
+ yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(collaboratorDocuments);
+ }
+
+ Integer unknownYearPubCount = yearToPublicationCount.get(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ * If there is no unknown year available then we should imply so by returning a "null".
+ * */
+ if (unknownYearPubCount != null) {
+ return unknownYearPubCount;
+ } else {
+ return null;
+ }
+ }
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/GenericQueryMap.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/GenericQueryMap.java
new file mode 100644
index 00000000..883fdc93
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/GenericQueryMap.java
@@ -0,0 +1,41 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Right now this is just acting as a hashmap but in future we would want to provide
+ * more detailed info other than just what properties had what values. E.g. we
+ * could parse properties (& its values) to look for what namespaces are used.
+ * @author cdtank
+ *
+ */
+@SuppressWarnings("serial")
+public class GenericQueryMap extends HashMap> {
+
+ public GenericQueryMap() {
+ super();
+ }
+
+ public void addEntry(String property, String value) {
+
+ Set values;
+
+ if (this.containsKey(property)) {
+
+ values = this.get(property);
+ values.add(value);
+
+ } else {
+
+ values = new HashSet();
+ values.add(value);
+ this.put(property, values);
+
+ }
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Individual.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Individual.java
new file mode 100644
index 00000000..f4afa724
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Individual.java
@@ -0,0 +1,32 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
+
+public class Individual {
+
+ private String individualLabel;
+ private String individualURL;
+
+ public Individual(String individualURL, String individualLabel) {
+ this.individualURL = individualURL;
+ this.individualLabel = individualLabel;
+ }
+
+ public Individual(String individualURL) {
+ this(individualURL, "");
+ }
+
+ public String getIndividualLabel() {
+ return individualLabel;
+ }
+
+ public void setIndividualLabel(String individualLabel) {
+ this.individualLabel = individualLabel;
+ }
+
+ public String getIndividualURL() {
+ return individualURL;
+ }
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java
new file mode 100644
index 00000000..f0e27fa3
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/Node.java
@@ -0,0 +1,157 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UniqueIDGenerator;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
+
+/**
+ *
+ * This is the Value Object for storing node information mainly for co-author vis.
+ * @author cdtank
+ *
+ */
+public class Node extends Individual {
+
+ private int nodeID;
+ private Map yearToPublicationCount;
+
+ private Set authorDocuments = new HashSet();
+
+ public Node(String nodeURL,
+ UniqueIDGenerator uniqueIDGenerator) {
+ super(nodeURL);
+ nodeID = uniqueIDGenerator.getNextNumericID();
+ }
+
+ public int getNodeID() {
+ return nodeID;
+ }
+
+ public String getNodeURL() {
+ return this.getIndividualURL();
+ }
+
+ public String getNodeName() {
+ return this.getIndividualLabel();
+ }
+
+ public void setNodeName(String nodeName) {
+ this.setIndividualLabel(nodeName);
+ }
+
+ public Set getAuthorDocuments() {
+ return authorDocuments;
+ }
+
+ public int getNumOfAuthoredWorks() {
+ return authorDocuments.size();
+ }
+
+ public void addAuthorDocument(BiboDocument authorDocument) {
+ this.authorDocuments.add(authorDocument);
+ }
+
+
+ public Map getYearToPublicationCount() {
+ if (yearToPublicationCount == null) {
+ yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments);
+ }
+ return yearToPublicationCount;
+ }
+ /*
+ * getEarliest, Latest & Unknown Publication YearCount should only be used after
+ * the parsing of the entire sparql is done. Else it will give results based on
+ * incomplete dataset.
+ * */
+ @SuppressWarnings("serial")
+ public Map getEarliestPublicationYearCount() {
+ if (yearToPublicationCount == null) {
+ yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments);
+ }
+
+ /*
+ * We do not want to consider the default publication year when we are checking
+ * for the min or max publication year.
+ * */
+ Set yearsToBeConsidered = new HashSet(yearToPublicationCount.keySet());
+ yearsToBeConsidered.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ * There can be a case when the only publication the author has no attached year to it
+ * so essentially an "Unknown". In that case Collections.max or min will throw an
+ * NoSuchElementException.
+ *
+ * If there is no maximum year available then we should imply so by returning a "null".
+ * */
+ if (yearsToBeConsidered.size() > 0) {
+ final String earliestYear = Collections.min(yearsToBeConsidered);
+ final Integer earliestYearPubCount = yearToPublicationCount.get(earliestYear);
+
+ return new HashMap(){{
+ put(earliestYear, earliestYearPubCount);
+ }};
+ } else {
+ return null;
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public Map getLatestPublicationYearCount() {
+ if (yearToPublicationCount == null) {
+ yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments);
+ }
+
+ /*
+ * We do not want to consider the default publication year when we are checking
+ * for the min or max publication year.
+ * */
+ Set yearsToBeConsidered = new HashSet(yearToPublicationCount.keySet());
+ yearsToBeConsidered.remove(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ * There can be a case when the only publication the author has no attached year to it
+ * so essentially an "Unknown". In that case Collections.max or min will throw an
+ * NoSuchElementException.
+ *
+ * If there is no maximum year available then we should imply so by returning a "null".
+ * */
+ if (yearsToBeConsidered.size() > 0) {
+ final String latestYear = Collections.max(yearsToBeConsidered);
+ final Integer latestYearPubCount = yearToPublicationCount.get(latestYear);
+
+ return new HashMap(){{
+ put(latestYear, latestYearPubCount);
+ }};
+ } else {
+ return null;
+ }
+
+ }
+
+ public Integer getUnknownPublicationYearCount() {
+ if (yearToPublicationCount == null) {
+ yearToPublicationCount = UtilityFunctions.getYearToPublicationCount(authorDocuments);
+ }
+
+ Integer unknownYearPubCount = yearToPublicationCount.get(VOConstants.DEFAULT_PUBLICATION_YEAR);
+
+ /*
+ * If there is no unknown year available then we should imply so by returning a "null".
+ * */
+ if (unknownYearPubCount != null) {
+ return unknownYearPubCount;
+ } else {
+ return null;
+ }
+ }
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineVOContainer.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineVOContainer.java
new file mode 100644
index 00000000..f51a7347
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/SparklineVOContainer.java
@@ -0,0 +1,86 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
+
+public class SparklineVOContainer {
+
+ /*
+ * For now sparklineNumPublicationsText & sparklinePublicationRangeText is left
+ * as empty but later on we would want to leverage the granularity that this
+ * provides.
+ * */
+ private String sparklineNumPublicationsText = "";
+ private String sparklinePublicationRangeText = "";
+
+ private Integer earliestRenderedPublicationYear;
+ private Integer latestRenderedPublicationYear;
+
+ private String table = "";
+
+ private String downloadDataLink = "";
+ private String fullTimelineNetworkLink = "";
+
+ private String sparklineContent;
+ private String sparklineContext;
+
+ public String getSparklineNumPublicationsText() {
+ return sparklineNumPublicationsText;
+ }
+ public void setSparklineNumPublicationsText(String sparklineNumPublicationsText) {
+ this.sparklineNumPublicationsText = sparklineNumPublicationsText;
+ }
+ public String getSparklinePublicationRangeText() {
+ return sparklinePublicationRangeText;
+ }
+ public void setSparklinePublicationRangeText(
+ String sparklinePublicationRangeText) {
+ this.sparklinePublicationRangeText = sparklinePublicationRangeText;
+ }
+ public Integer getEarliestRenderedPublicationYear() {
+ return earliestRenderedPublicationYear;
+ }
+ public void setEarliestRenderedPublicationYear(
+ Integer earliestRenderedPublicationYear) {
+ this.earliestRenderedPublicationYear = earliestRenderedPublicationYear;
+ }
+ public Integer getLatestRenderedPublicationYear() {
+ return latestRenderedPublicationYear;
+ }
+ public void setLatestRenderedPublicationYear(
+ Integer latestRenderedPublicationYear) {
+ this.latestRenderedPublicationYear = latestRenderedPublicationYear;
+ }
+ public String getTable() {
+ return table;
+ }
+ public void setTable(String table) {
+ this.table = table;
+ }
+ public String getDownloadDataLink() {
+ return downloadDataLink;
+ }
+ public void setDownloadDataLink(String downloadDataLink) {
+ this.downloadDataLink = downloadDataLink;
+ }
+ public String getFullTimelineNetworkLink() {
+ return fullTimelineNetworkLink;
+ }
+ public void setFullTimelineNetworkLink(String fullTimelineNetworkLink) {
+ this.fullTimelineNetworkLink = fullTimelineNetworkLink;
+ }
+
+ public String getSparklineContent() {
+ return sparklineContent;
+ }
+ public void setSparklineContent(String shortSparklineContent) {
+ this.sparklineContent = shortSparklineContent;
+ }
+
+ public String getSparklineContext() {
+ return sparklineContext;
+ }
+ public void setSparklineContext(String shortSparklineContext) {
+ this.sparklineContext = shortSparklineContext;
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java
new file mode 100644
index 00000000..71b20641
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java
@@ -0,0 +1,42 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * This is the Value Object equivalent for vivo:CollegeOrSchoolWithinUniversity object type.
+ * @author cdtank
+ *
+ */
+public class VivoCollegeOrSchool extends Individual {
+
+ private Set departments = new HashSet();
+
+ public VivoCollegeOrSchool(String collegeURL) {
+ super(collegeURL);
+ }
+
+ public Set getDepartments() {
+ return departments;
+ }
+
+ public void addDepartment(VivoDepartmentOrDivision department) {
+ this.departments.add(department);
+ }
+
+ public String getCollegeURL() {
+ return this.getIndividualURL();
+ }
+
+ public String getCollegeLabel() {
+ return this.getIndividualLabel();
+ }
+
+ public void setCollegeLabel(String collegeLabel) {
+ this.setIndividualLabel(collegeLabel);
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java
new file mode 100644
index 00000000..4e0f21cd
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java
@@ -0,0 +1,43 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * This is the Value Object equivalent for vivo:AcademicDepartmentOrDivision object type.
+ * @author cdtank
+ *
+ */
+public class VivoDepartmentOrDivision extends Individual {
+
+ private Set parentColleges = new HashSet();
+
+ public VivoDepartmentOrDivision(String departmentURL, VivoCollegeOrSchool parentCollege) {
+ super(departmentURL);
+ addParentCollege(parentCollege);
+ }
+
+ public Set getParentCollege() {
+ return parentColleges;
+ }
+
+ public void addParentCollege(VivoCollegeOrSchool parentCollege) {
+ this.parentColleges.add(parentCollege);
+ }
+
+ public String getDepartmentURL() {
+ return this.getIndividualURL();
+ }
+
+ public String getDepartmentLabel() {
+ return this.getIndividualLabel();
+ }
+
+ public void setDepartmentLabel(String departmentLabel) {
+ this.setIndividualLabel(departmentLabel);
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java
new file mode 100644
index 00000000..51d83837
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java
@@ -0,0 +1,62 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants.EmployeeType;
+
+/**
+ *
+ * This is the Value Object equivalent for vivo's Employee object type.
+ * @author cdtank
+ *
+ */
+public class VivoEmployee extends Individual {
+
+ private EmployeeType employeeType;
+ private Set parentDepartments = new HashSet();
+ private Set authorDocuments = new HashSet();
+
+ public VivoEmployee(String employeeURL,
+ EmployeeType employeeType,
+ VivoDepartmentOrDivision parentDepartment) {
+ super(employeeURL);
+ addParentDepartment(parentDepartment);
+ }
+
+ public String getEmployeeURL() {
+ return this.getIndividualURL();
+ }
+
+ public String getEmployeeName() {
+ return this.getIndividualLabel();
+ }
+
+ public EmployeeType getEmployeeType() {
+ return employeeType;
+ }
+
+ public void setEmployeeType(EmployeeType employeeType) {
+ this.employeeType = employeeType;
+ }
+
+ public Set getParentDepartments() {
+ return parentDepartments;
+ }
+
+ public void addParentDepartment(VivoDepartmentOrDivision parentDepartment) {
+ this.parentDepartments.add(parentDepartment);
+ }
+
+ public Set getAuthorDocuments() {
+ return authorDocuments;
+ }
+
+ public void addAuthorDocument(BiboDocument authorDocument) {
+ this.authorDocuments.add(authorDocument);
+ }
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/AllPropertiesQueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/AllPropertiesQueryHandler.java
new file mode 100644
index 00000000..c8179ae6
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/AllPropertiesQueryHandler.java
@@ -0,0 +1,160 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.visutils;
+
+import org.apache.commons.logging.Log;
+
+import com.hp.hpl.jena.iri.IRI;
+import com.hp.hpl.jena.iri.IRIFactory;
+import com.hp.hpl.jena.iri.Violation;
+import com.hp.hpl.jena.query.DataSource;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+import com.hp.hpl.jena.query.QueryFactory;
+import com.hp.hpl.jena.query.QuerySolution;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.query.Syntax;
+import com.hp.hpl.jena.rdf.model.RDFNode;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryFieldLabels;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.GenericQueryMap;
+
+
+
+/**
+ * Very dumb name of the class. change it.
+ * @author cdtank
+ *
+ */
+public class AllPropertiesQueryHandler {
+
+ protected static final Syntax SYNTAX = Syntax.syntaxARQ;
+
+ private String filterRule, individualURLParam, resultFormatParam, rdfResultFormatParam;
+ private DataSource dataSource;
+
+ private Log log;
+
+ public AllPropertiesQueryHandler(String individualURLParam,
+ String filterRule,
+ String resultFormatParam,
+ String rdfResultFormatParam,
+ DataSource dataSource,
+ Log log) {
+
+ this.individualURLParam = individualURLParam;
+ this.filterRule = filterRule;
+ this.resultFormatParam = resultFormatParam;
+ this.rdfResultFormatParam = rdfResultFormatParam;
+ this.dataSource = dataSource;
+ this.log = log;
+
+ }
+
+ private GenericQueryMap createJavaValueObjects(ResultSet resultSet) {
+
+ GenericQueryMap queryResultVO = new GenericQueryMap();
+
+ while (resultSet.hasNext()) {
+ QuerySolution solution = resultSet.nextSolution();
+
+
+ RDFNode predicateNode = solution.get(QueryFieldLabels.PREDICATE);
+ RDFNode objectNode = solution.get(QueryFieldLabels.OBJECT);
+
+ if (predicateNode != null && objectNode != null) {
+ queryResultVO.addEntry(predicateNode.toString(),
+ objectNode.toString());
+ }
+
+ }
+
+ return queryResultVO;
+ }
+
+
+ private ResultSet executeQuery(String queryText,
+ String resultFormatParam,
+ String rdfResultFormatParam,
+ DataSource dataSource) {
+
+ QueryExecution queryExecution = null;
+ try{
+ Query query = QueryFactory.create(queryText, SYNTAX);
+
+// QuerySolutionMap qs = new QuerySolutionMap();
+// qs.add("authPerson", queryParam); // bind resource to s
+
+ queryExecution = QueryExecutionFactory.create(query, dataSource);
+
+
+ //remocve this if loop after knowing what is describe & construct sparql stuff.
+ if (query.isSelectType()){
+ return queryExecution.execSelect();
+ }
+ } finally {
+ if(queryExecution != null) {
+ queryExecution.close();
+ }
+
+ }
+ return null;
+ }
+
+ private String generateGenericSparqlQuery(String queryURI, String filterRule) {
+// Resource uri1 = ResourceFactory.createResource(queryURI);
+ String filterClause;
+
+ if (filterRule == null || filterRule.trim().isEmpty()) {
+ filterClause = "";
+ } else {
+ filterClause = "FILTER ( " + filterRule + " ) . ";
+ }
+
+ String sparqlQuery = QueryConstants.getSparqlPrefixQuery()
+ + "SELECT "
+ + " (str(?predicate) as ?" + QueryFieldLabels.PREDICATE + ") "
+ + " (str(?object) as ?" + QueryFieldLabels.OBJECT + ") "
+ + "WHERE { "
+ + "<" + queryURI + "> ?predicate ?object. "
+ + filterClause
+ + "}";
+
+ System.out.println(sparqlQuery);
+
+ return sparqlQuery;
+ }
+
+
+ public GenericQueryMap getJavaValueObjects()
+ throws MalformedQueryParametersException {
+
+ if (this.individualURLParam == null || "".equals(individualURLParam)) {
+ throw new MalformedQueryParametersException("URI parameter is either null or empty.");
+ } else {
+
+ /*
+ * To test for the validity of the URI submitted.
+ * */
+ IRIFactory iRIFactory = IRIFactory.jenaImplementation();
+ IRI iri = iRIFactory.create(this.individualURLParam);
+ if (iri.hasViolation(false)) {
+ String errorMsg = ((Violation)iri.violations(false).next()).getShortMessage()+" ";
+ log.error("Generic Query " + errorMsg);
+ throw new MalformedQueryParametersException("URI provided for an individual is malformed.");
+ }
+ }
+
+ ResultSet resultSet = executeQuery(generateGenericSparqlQuery(this.individualURLParam, this.filterRule),
+ this.resultFormatParam,
+ this.rdfResultFormatParam,
+ this.dataSource);
+
+ return createJavaValueObjects(resultSet);
+ }
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/GenericQueryHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/GenericQueryHandler.java
new file mode 100644
index 00000000..5e7fb97f
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/GenericQueryHandler.java
@@ -0,0 +1,176 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.visutils;
+
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+
+import com.hp.hpl.jena.iri.IRI;
+import com.hp.hpl.jena.iri.IRIFactory;
+import com.hp.hpl.jena.iri.Violation;
+import com.hp.hpl.jena.query.DataSource;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+import com.hp.hpl.jena.query.QueryFactory;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.query.Syntax;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+
+
+
+/**
+ * @author cdtank
+ *
+ */
+public class GenericQueryHandler {
+
+ protected static final Syntax SYNTAX = Syntax.syntaxARQ;
+
+ private String whereClause, individualURLParam, resultFormatParam, rdfResultFormatParam;
+ private DataSource dataSource;
+
+ private Log log;
+
+ private Map fieldLabelToOutputFieldLabel;
+
+ public GenericQueryHandler(String individualURLParam,
+ Map fieldLabelToOutputFieldLabel,
+ String whereClause,
+ String resultFormatParam,
+ String rdfResultFormatParam,
+ DataSource dataSource,
+ Log log) {
+
+ this.individualURLParam = individualURLParam;
+ this.fieldLabelToOutputFieldLabel = fieldLabelToOutputFieldLabel;
+ this.whereClause = whereClause;
+ this.resultFormatParam = resultFormatParam;
+ this.rdfResultFormatParam = rdfResultFormatParam;
+ this.dataSource = dataSource;
+ this.log = log;
+
+ }
+/*
+ private GenericQueryMap createJavaValueObjects(ResultSet resultSet) {
+
+ GenericQueryMap queryResultVO = new GenericQueryMap();
+
+ while (resultSet.hasNext()) {
+ QuerySolution solution = resultSet.nextSolution();
+
+
+ RDFNode predicateNode = solution.get(QueryFieldLabels.PREDICATE);
+ RDFNode objectNode = solution.get(QueryFieldLabels.OBJECT);
+
+ if (predicateNode != null && objectNode != null) {
+ queryResultVO.addEntry(predicateNode.toString(),
+ objectNode.toString());
+ }
+
+
+ for (String currentOutputFieldLabel : this.fieldLabelToOutputFieldLabel.values()) {
+
+ RDFNode currentFieldNode = solution.get(currentOutputFieldLabel);
+ if (currentFieldNode != null) {
+// biboDocument.setDocumentBlurb(currentFieldNode.toString());
+
+ TupleSet
+ }
+
+ }
+
+ }
+
+ return queryResultVO;
+ }
+
+ */
+ private ResultSet executeQuery(String queryText,
+ String resultFormatParam,
+ String rdfResultFormatParam,
+ DataSource dataSource) {
+
+ QueryExecution queryExecution = null;
+ try{
+ Query query = QueryFactory.create(queryText, SYNTAX);
+
+// QuerySolutionMap qs = new QuerySolutionMap();
+// qs.add("authPerson", queryParam); // bind resource to s
+
+ queryExecution = QueryExecutionFactory.create(query, dataSource);
+
+
+ //remocve this if loop after knowing what is describe & construct sparql stuff.
+ if (query.isSelectType()){
+ return queryExecution.execSelect();
+ }
+ } finally {
+ if(queryExecution != null) {
+ queryExecution.close();
+ }
+
+ }
+ return null;
+ }
+
+ private String generateGenericSparqlQuery() {
+// Resource uri1 = ResourceFactory.createResource(queryURI);
+
+ StringBuilder sparqlQuery = new StringBuilder();
+ sparqlQuery.append(QueryConstants.getSparqlPrefixQuery());
+
+ sparqlQuery.append("SELECT\n");
+
+ for (Map.Entry currentfieldLabelToOutputFieldLabel
+ : this.fieldLabelToOutputFieldLabel.entrySet()) {
+
+ sparqlQuery.append("\t(str(?" + currentfieldLabelToOutputFieldLabel.getKey() + ") as ?"
+ + currentfieldLabelToOutputFieldLabel.getValue() + ")\n");
+
+ }
+
+ sparqlQuery.append("WHERE {\n");
+
+ sparqlQuery.append(this.whereClause);
+
+ sparqlQuery.append("}\n");
+
+ System.out.println("GENERIC QEURY >>>>> " + sparqlQuery);
+
+ return sparqlQuery.toString();
+ }
+
+
+ public ResultSet getResultSet()
+ throws MalformedQueryParametersException {
+
+ if (this.individualURLParam == null || "".equals(individualURLParam)) {
+ throw new MalformedQueryParametersException("URI parameter is either null or empty.");
+ } else {
+
+ /*
+ * To test for the validity of the URI submitted.
+ * */
+ IRIFactory iRIFactory = IRIFactory.jenaImplementation();
+ IRI iri = iRIFactory.create(this.individualURLParam);
+ if (iri.hasViolation(false)) {
+ String errorMsg = ((Violation)iri.violations(false).next()).getShortMessage()+" ";
+ log.error("Generic Query " + errorMsg);
+ throw new MalformedQueryParametersException("URI provided for an individual is malformed.");
+ }
+ }
+
+ ResultSet resultSet = executeQuery(generateGenericSparqlQuery(),
+ this.resultFormatParam,
+ this.rdfResultFormatParam,
+ this.dataSource);
+
+ return resultSet;
+ }
+
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/JavaResearch.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/JavaResearch.java
new file mode 100644
index 00000000..0257f94b
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/JavaResearch.java
@@ -0,0 +1,15 @@
+package edu.cornell.mannlib.vitro.webapp.visualization.visutils;
+
+public class JavaResearch {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+
+ System.out.println(UtilityFunctions.slugify("Yung, R."));
+
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UniqueIDGenerator.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UniqueIDGenerator.java
new file mode 100644
index 00000000..ddfa0b27
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UniqueIDGenerator.java
@@ -0,0 +1,16 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.visutils;
+
+public class UniqueIDGenerator {
+
+ private int nextNumericID = 1;
+
+ public int getNextNumericID() {
+ int nextNumericID = this.nextNumericID;
+ this.nextNumericID++;
+
+ return nextNumericID;
+ }
+
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UtilityFunctions.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UtilityFunctions.java
new file mode 100644
index 00000000..8cedda04
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/visutils/UtilityFunctions.java
@@ -0,0 +1,78 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.visutils;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.commons.lang.StringUtils;
+
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument;
+
+public class UtilityFunctions {
+
+ public static Map getYearToPublicationCount(
+ Set authorDocuments) {
+
+ //List publishedYears = new ArrayList();
+
+ /*
+ * Create a map from the year to number of publications. Use the BiboDocument's
+ * parsedPublicationYear to populate the data.
+ * */
+ Map yearToPublicationCount = new TreeMap();
+
+ for (BiboDocument curr : authorDocuments) {
+
+ /*
+ * Increment the count because there is an entry already available for
+ * that particular year.
+ *
+ * I am pushing the logic to check for validity of year in "getPublicationYear" itself
+ * because,
+ * 1. We will be using getPub... multiple times & this will save us duplication of code
+ * 2. If we change the logic of validity of a pub year we would not have to make changes
+ * all throughout the codebase.
+ * 3. We are asking for a publication year & we should get a proper one or NOT at all.
+ * */
+ String publicationYear;
+ if (curr.getPublicationYear() != null) {
+ publicationYear = curr.getPublicationYear();
+ } else {
+ publicationYear = curr.getParsedPublicationYear();
+ }
+
+ if (yearToPublicationCount.containsKey(publicationYear)) {
+ yearToPublicationCount.put(publicationYear,
+ yearToPublicationCount
+ .get(publicationYear) + 1);
+
+ } else {
+ yearToPublicationCount.put(publicationYear, 1);
+ }
+
+// if (!parsedPublicationYear.equalsIgnoreCase(BiboDocument.DEFAULT_PUBLICATION_YEAR)) {
+// publishedYears.add(Integer.parseInt(parsedPublicationYear));
+// }
+
+ }
+
+ return yearToPublicationCount;
+ }
+
+ /**
+ * Currently the approach for slugifying filenames is naive. In future if there is need,
+ * we can write more sophisticated method.
+ * @param textToBeSlugified
+ * @return
+ */
+ public static String slugify(String textToBeSlugified) {
+ return StringUtils.substring(textToBeSlugified.toLowerCase()
+ .replaceAll("[^a-zA-Z0-9-]+", "-"),
+ 0,
+ VisConstants.MAX_NAME_TEXT_LENGTH);
+ }
+
+}