1. Changed vis architecture to serve 3 type of responses from 3 corresponding url patterns (standard, ajax, data).
2. Removed debug statements from publication sparkline ftl. 3. Reworked publication sparkline & utilities visualziation to ahere to new architecture. 4. Started work on co-authorship freemarkerization. 5. Removed FileResponseValues type per talks with Rebecca Y. & Nick C. 6. Temporarily disabled person grant count visualization (freemarker version).
This commit is contained in:
parent
b8e8a81171
commit
06523d402e
26 changed files with 2565 additions and 558 deletions
|
@ -12,13 +12,15 @@
|
||||||
<bean id="person_pub_count"
|
<bean id="person_pub_count"
|
||||||
class="edu.cornell.mannlib.vitro.webapp.visualization.freemarker.personpubcount.PersonPublicationCountRequestHandler" />
|
class="edu.cornell.mannlib.vitro.webapp.visualization.freemarker.personpubcount.PersonPublicationCountRequestHandler" />
|
||||||
|
|
||||||
|
<bean id="utilities"
|
||||||
|
class="edu.cornell.mannlib.vitro.webapp.visualization.freemarker.utilities.UtilitiesRequestHandler" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<bean id="coauthorship"
|
<bean id="coauthorship"
|
||||||
class="edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipRequestHandler" />
|
class="edu.cornell.mannlib.vitro.webapp.visualization.coauthorship.CoAuthorshipRequestHandler" />
|
||||||
<bean id="person_level"
|
<bean id="person_level"
|
||||||
class="edu.cornell.mannlib.vitro.webapp.visualization.personlevel.PersonLevelRequestHandler" />
|
class="edu.cornell.mannlib.vitro.webapp.visualization.personlevel.PersonLevelRequestHandler" />
|
||||||
<bean id="utilities"
|
|
||||||
class="edu.cornell.mannlib.vitro.webapp.visualization.utilities.UtilitiesRequestHandler" />
|
|
||||||
<bean id="entity_comparison"
|
<bean id="entity_comparison"
|
||||||
class="edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison.EntityPublicationCountRequestHandler" />
|
class="edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison.EntityPublicationCountRequestHandler" />
|
||||||
<bean id="coprincipalinvestigator"
|
<bean id="coprincipalinvestigator"
|
||||||
|
@ -33,6 +35,9 @@
|
||||||
<ref bean="person_pub_count"></ref>
|
<ref bean="person_pub_count"></ref>
|
||||||
</entry>
|
</entry>
|
||||||
|
|
||||||
|
<entry key="utilities">
|
||||||
|
<ref bean="utilities"></ref>
|
||||||
|
</entry>
|
||||||
<!--
|
<!--
|
||||||
<entry key="coauthorship">
|
<entry key="coauthorship">
|
||||||
<ref bean="coauthorship"></ref>
|
<ref bean="coauthorship"></ref>
|
||||||
|
@ -40,9 +45,6 @@
|
||||||
<entry key="person_level">
|
<entry key="person_level">
|
||||||
<ref bean="person_level"></ref>
|
<ref bean="person_level"></ref>
|
||||||
</entry>
|
</entry>
|
||||||
<entry key="utilities">
|
|
||||||
<ref bean="utilities"></ref>
|
|
||||||
</entry>
|
|
||||||
<entry key="entity_comparison">
|
<entry key="entity_comparison">
|
||||||
<ref bean="entity_comparison"></ref>
|
<ref bean="entity_comparison"></ref>
|
||||||
</entry>
|
</entry>
|
||||||
|
|
|
@ -495,6 +495,7 @@
|
||||||
<url-pattern>/csv2rdf</url-pattern>
|
<url-pattern>/csv2rdf</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>JenaExportController</servlet-name>
|
<servlet-name>JenaExportController</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.jena.JenaExportController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.jena.JenaExportController</servlet-class>
|
||||||
|
@ -1248,16 +1249,6 @@
|
||||||
<url-pattern>/admin/sparqlquery</url-pattern>
|
<url-pattern>/admin/sparqlquery</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<servlet-name>DummyVisClientFM</servlet-name>
|
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.DummyVisClientController</servlet-class>
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>DummyVisClientFM</servlet-name>
|
|
||||||
<url-pattern>/admin/dummyVisClientfm</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>DummyVisClient</servlet-name>
|
<servlet-name>DummyVisClient</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.DummyVisClientController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.DummyVisClientController</servlet-class>
|
||||||
|
@ -1267,6 +1258,16 @@
|
||||||
<servlet-name>DummyVisClient</servlet-name>
|
<servlet-name>DummyVisClient</servlet-name>
|
||||||
<url-pattern>/admin/dummyVisClient</url-pattern>
|
<url-pattern>/admin/dummyVisClient</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>DummyVisClientFM</servlet-name>
|
||||||
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.DummyVisClientController</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>DummyVisClientFM</servlet-name>
|
||||||
|
<url-pattern>/admin/dummyVisClientfm</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>VisualizationController</servlet-name>
|
<servlet-name>VisualizationController</servlet-name>
|
||||||
|
@ -1279,15 +1280,34 @@
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>VisualizationControllerFM</servlet-name>
|
<servlet-name>StandardVisualizationController</servlet-name>
|
||||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.VisualizationController</servlet-class>
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.StandardVisualizationController</servlet-class>
|
||||||
</servlet>
|
</servlet>
|
||||||
|
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>VisualizationControllerFM</servlet-name>
|
<servlet-name>StandardVisualizationController</servlet-name>
|
||||||
<url-pattern>/visualizationfm</url-pattern>
|
<url-pattern>/visualizationfm</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>AjaxVisualizationController</servlet-name>
|
||||||
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.AjaxVisualizationController</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>AjaxVisualizationController</servlet-name>
|
||||||
|
<url-pattern>/visualizationAjax</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>DataVisualizationController</servlet-name>
|
||||||
|
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.DataVisualizationController</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>DataVisualizationController</servlet-name>
|
||||||
|
<url-pattern>/visualizationData</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>authtest</servlet-name>
|
<servlet-name>authtest</servlet-name>
|
||||||
|
|
|
@ -26,6 +26,6 @@ var visualization = {
|
||||||
};
|
};
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
visualizationUrl = visualizationUrl.replace("/visualization", "/visualizationfm");
|
visualizationUrl = visualizationUrl.replace("/visualization", "/visualizationAjax");
|
||||||
visualization.render(visualizationUrl);
|
visualization.render(visualizationUrl);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#assign visualizationURLRoot ="/visualization">
|
||||||
|
|
||||||
|
<#assign egoURI ="${egoURIParam?url}">
|
||||||
|
|
||||||
|
<#assign egoCoAuthorshipDataFeederURL = '${urls.base}${visualizationURLRoot}?vis=coauthorship&uri=${egoURI}&render_mode=data&labelField=label'>
|
||||||
|
|
||||||
|
<#assign egoCoPIDataFeederURL = '${urls.base}${visualizationURLRoot}?vis=coprincipalinvestigator&uri=${egoURI}&render_mode=data&labelField=label'>
|
||||||
|
|
||||||
|
<#assign egoCoAuthorsListDataFileURL = '${urls.base}${visualizationURLRoot}?vis=person_level&uri=${egoURI}&render_mode=data&vis_mode=coauthors'>
|
||||||
|
|
||||||
|
<#assign swfLink = '${urls.images}/visualization/coauthorship/EgoCentric.swf'>
|
||||||
|
|
||||||
|
<c:url var="adobeFlashDetector" value="/js/visualization/coauthorship/AC_OETags.js" />
|
||||||
|
<c:url var="googleVisualizationAPI" value="http://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22visualization%22%2C%22version%22%3A%221%22%2C%22packages%22%3A%5B%22areachart%22%2C%22imagesparkline%22%5D%7D%5D%7D"/>
|
||||||
|
<c:url var="coAuthorShipJavaScript" value="/js/visualization/personlevel/person_level.js" />
|
|
@ -69,8 +69,6 @@
|
||||||
|
|
||||||
<#if sparklineVO.shortVisMode>
|
<#if sparklineVO.shortVisMode>
|
||||||
|
|
||||||
console.log("Yay! Short Vis Mode!");
|
|
||||||
|
|
||||||
<#-- For the short view we only want the last 10 year's view of publication count, hence we filter
|
<#-- For the short view we only want the last 10 year's view of publication count, hence we filter
|
||||||
the data we actually want to use for render. -->
|
the data we actually want to use for render. -->
|
||||||
|
|
||||||
|
@ -85,8 +83,6 @@
|
||||||
|
|
||||||
<#else>
|
<#else>
|
||||||
|
|
||||||
console.log("Yay! Full Vis Mode!");
|
|
||||||
|
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,8 +171,6 @@
|
||||||
|
|
||||||
row.append(sparklineImgTD);
|
row.append(sparklineImgTD);
|
||||||
|
|
||||||
console.log(sparklineImgTD);
|
|
||||||
|
|
||||||
var sparklineNumberTD = $('<td>');
|
var sparklineNumberTD = $('<td>');
|
||||||
sparklineNumberTD.attr('width', '30');
|
sparklineNumberTD.attr('width', '30');
|
||||||
sparklineNumberTD.attr('align', 'right');
|
sparklineNumberTD.attr('align', 'right');
|
||||||
|
@ -191,8 +185,6 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(sparklineImgTD);
|
|
||||||
|
|
||||||
drawPubCountVisualization(sparklineImgTD);
|
drawPubCountVisualization(sparklineImgTD);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -25,6 +25,8 @@ public class VisualizationFrameworkConstants {
|
||||||
*/
|
*/
|
||||||
public static final String VISUALIZATION_URL_PREFIX = "/visualization";
|
public static final String VISUALIZATION_URL_PREFIX = "/visualization";
|
||||||
public static final String FREEMARKERIZED_VISUALIZATION_URL_PREFIX = "/visualizationfm";
|
public static final String FREEMARKERIZED_VISUALIZATION_URL_PREFIX = "/visualizationfm";
|
||||||
|
public static final String AJAX_VISUALIZATION_SERVICE_URL_PREFIX = "/visualizationAjax";
|
||||||
|
public static final String DATA_VISUALIZATION_SERVICE_URL_PREFIX = "/visualizationData";
|
||||||
|
|
||||||
public static final String INDIVIDUAL_URL_PREFIX = "/individual";
|
public static final String INDIVIDUAL_URL_PREFIX = "/individual";
|
||||||
|
|
||||||
|
@ -85,6 +87,5 @@ public class VisualizationFrameworkConstants {
|
||||||
public static final String ENTITY_COMPARISON_VIS = "entity_comparison";
|
public static final String ENTITY_COMPARISON_VIS = "entity_comparison";
|
||||||
public static final String CO_PI_VIS = "coprincipalinvestigator";
|
public static final String CO_PI_VIS = "coprincipalinvestigator";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,8 @@ import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|
||||||
|
|
||||||
import com.hp.hpl.jena.query.DataSource;
|
import com.hp.hpl.jena.query.DataSource;
|
||||||
import com.hp.hpl.jena.query.DatasetFactory;
|
import com.hp.hpl.jena.query.DatasetFactory;
|
||||||
|
@ -28,6 +24,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Res
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
|
@ -39,75 +36,34 @@ import freemarker.template.Configuration;
|
||||||
* @author cdtank
|
* @author cdtank
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class VisualizationController extends FreemarkerHttpServlet {
|
public class AjaxVisualizationController extends FreemarkerHttpServlet {
|
||||||
|
|
||||||
private Map<String, VisualizationRequestHandler> visualizationIDsToClass;
|
|
||||||
|
|
||||||
public static final String URL_ENCODING_SCHEME = "UTF-8";
|
public static final String URL_ENCODING_SCHEME = "UTF-8";
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog(VisualizationController.class.getName());
|
private static final Log log = LogFactory.getLog(AjaxVisualizationController.class.getName());
|
||||||
|
|
||||||
protected static final Syntax SYNTAX = Syntax.syntaxARQ;
|
protected static final Syntax SYNTAX = Syntax.syntaxARQ;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
|
|
||||||
VitroRequest vreq = new VitroRequest(request);
|
VitroRequest vreq = new VitroRequest(request);
|
||||||
|
|
||||||
String renderMode = vreq.getParameter(VisualizationFrameworkConstants
|
Object ajaxResponse = processAjaxRequest(vreq);
|
||||||
.RENDER_MODE_KEY);
|
|
||||||
|
if (ajaxResponse instanceof TemplateResponseValues) {
|
||||||
if (StringUtils.equalsIgnoreCase(renderMode, VisualizationFrameworkConstants.DYNAMIC_RENDER_MODE)) {
|
|
||||||
|
|
||||||
Configuration config = getConfig(vreq);
|
|
||||||
TemplateResponseValues trv = (TemplateResponseValues) processRequest(vreq);
|
|
||||||
writeTemplate(trv.getTemplateName(), trv.getMap(), config, request, response);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
super.doGet(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This method is overridden to inject vis dependencies i.e. the vis algorithms that are
|
|
||||||
* being implemented into the vis controller. Modified Dependency Injection pattern is
|
|
||||||
* used here. XML file containing the location of all the vis is saved in accessible folder.
|
|
||||||
* @see javax.servlet.GenericServlet#init()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void init() throws ServletException {
|
|
||||||
super.init();
|
|
||||||
try {
|
|
||||||
|
|
||||||
String resourcePath =
|
Configuration config = getConfig(vreq);
|
||||||
getServletContext()
|
TemplateResponseValues trv = (TemplateResponseValues) ajaxResponse;
|
||||||
.getRealPath(VisualizationFrameworkConstants
|
writeTemplate(trv.getTemplateName(), trv.getMap(), config, request, response);
|
||||||
.RELATIVE_LOCATION_OF_FM_VISUALIZATIONS_BEAN);
|
|
||||||
|
|
||||||
ApplicationContext context = new ClassPathXmlApplicationContext(
|
} else {
|
||||||
"file:" + resourcePath);
|
response.getWriter().write(ajaxResponse.toString());
|
||||||
|
|
||||||
BeanFactory factory = context;
|
|
||||||
|
|
||||||
VisualizationInjector visualizationInjector =
|
|
||||||
(VisualizationInjector) factory.getBean("visualizationInjector");
|
|
||||||
|
|
||||||
visualizationIDsToClass = visualizationInjector.getVisualizationIDToClass();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object processAjaxRequest(VitroRequest vreq) {
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ResponseValues processRequest(VitroRequest vreq) {
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Based on the query parameters passed via URI get the appropriate visualization
|
* Based on the query parameters passed via URI get the appropriate visualization
|
||||||
* request handler.
|
* request handler.
|
||||||
|
@ -131,12 +87,10 @@ public class VisualizationController extends FreemarkerHttpServlet {
|
||||||
vreq);
|
vreq);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private ResponseValues renderVisualization(VitroRequest vitroRequest,
|
private Object renderVisualization(VitroRequest vitroRequest,
|
||||||
VisualizationRequestHandler visRequestHandler) {
|
VisualizationRequestHandler visRequestHandler) {
|
||||||
|
|
||||||
Model model = vitroRequest.getJenaOntModel(); // getModel()
|
Model model = vitroRequest.getJenaOntModel(); // getModel()
|
||||||
|
@ -158,9 +112,17 @@ public class VisualizationController extends FreemarkerHttpServlet {
|
||||||
|
|
||||||
if (dataSource != null && visRequestHandler != null) {
|
if (dataSource != null && visRequestHandler != null) {
|
||||||
|
|
||||||
return visRequestHandler.generateVisualization(vitroRequest,
|
try {
|
||||||
log,
|
return visRequestHandler.generateAjaxVisualization(vitroRequest,
|
||||||
dataSource);
|
log,
|
||||||
|
dataSource);
|
||||||
|
} catch (MalformedQueryParametersException e) {
|
||||||
|
return UtilityFunctions.handleMalformedParameters(
|
||||||
|
"Ajax Visualization Query Error - Individual Publication Count",
|
||||||
|
e.getMessage(),
|
||||||
|
vitroRequest);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -184,10 +146,10 @@ public class VisualizationController extends FreemarkerHttpServlet {
|
||||||
.VIS_TYPE_KEY);
|
.VIS_TYPE_KEY);
|
||||||
VisualizationRequestHandler visRequestHandler = null;
|
VisualizationRequestHandler visRequestHandler = null;
|
||||||
|
|
||||||
System.out.println(visType + " --> " + visualizationIDsToClass);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
visRequestHandler = visualizationIDsToClass.get(visType);
|
visRequestHandler = VisualizationsDependencyInjector
|
||||||
|
.getVisualizationIDsToClassMap(getServletContext()).get(visType);
|
||||||
|
|
||||||
} catch (NullPointerException nullKeyException) {
|
} catch (NullPointerException nullKeyException) {
|
||||||
|
|
||||||
return null;
|
return null;
|
|
@ -0,0 +1,178 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
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 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 edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services a visualization request. This will return a simple error message and a 501 if
|
||||||
|
* there is no jena Model.
|
||||||
|
*
|
||||||
|
* @author cdtank
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class DataVisualizationController extends VitroHttpServlet {
|
||||||
|
|
||||||
|
public static final String URL_ENCODING_SCHEME = "UTF-8";
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(DataVisualizationController.class.getName());
|
||||||
|
|
||||||
|
protected static final Syntax SYNTAX = Syntax.syntaxARQ;
|
||||||
|
|
||||||
|
public static final String FILE_CONTENT_TYPE_KEY = "fileContentType";
|
||||||
|
public static final String FILE_CONTENT_KEY = "fileContent";
|
||||||
|
public static final String FILE_NAME_KEY = "fileName";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
|
||||||
|
VitroRequest vreq = new VitroRequest(request);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Based on the query parameters passed via URI get the appropriate visualization
|
||||||
|
* request handler.
|
||||||
|
* */
|
||||||
|
VisualizationRequestHandler visRequestHandler =
|
||||||
|
getVisualizationRequestHandler(vreq);
|
||||||
|
|
||||||
|
if (visRequestHandler != null) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pass the query to the selected visualization request handler & render the visualization.
|
||||||
|
* Since the visualization content is directly added to the response object we are side-
|
||||||
|
* effecting this method.
|
||||||
|
* */
|
||||||
|
try {
|
||||||
|
|
||||||
|
Map<String, String> dataResponse = renderVisualization(vreq, visRequestHandler);
|
||||||
|
|
||||||
|
response.setContentType(dataResponse.get(FILE_CONTENT_TYPE_KEY));
|
||||||
|
|
||||||
|
if (dataResponse.containsKey(FILE_NAME_KEY)) {
|
||||||
|
response.setHeader("Content-Disposition",
|
||||||
|
"attachment;filename=" + dataResponse.get(FILE_NAME_KEY));
|
||||||
|
}
|
||||||
|
|
||||||
|
response.getWriter().write(dataResponse.get(FILE_CONTENT_KEY));
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
} catch (MalformedQueryParametersException e) {
|
||||||
|
|
||||||
|
UtilityFunctions.handleMalformedParameters("Visualization Query Error",
|
||||||
|
e.getMessage(),
|
||||||
|
vreq,
|
||||||
|
request,
|
||||||
|
response,
|
||||||
|
log);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
UtilityFunctions.handleMalformedParameters("Visualization Query Error",
|
||||||
|
"Inappropriate query parameters were submitted.",
|
||||||
|
vreq,
|
||||||
|
request,
|
||||||
|
response,
|
||||||
|
log);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Map<String, String> renderVisualization(
|
||||||
|
VitroRequest vitroRequest,
|
||||||
|
VisualizationRequestHandler visRequestHandler)
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
|
||||||
|
Model model = vitroRequest.getJenaOntModel(); // getModel()
|
||||||
|
if (model == null) {
|
||||||
|
|
||||||
|
String errorMessage = "This service is not supporeted by the current "
|
||||||
|
+ "webapp configuration. A jena model is required in the "
|
||||||
|
+ "servlet context.";
|
||||||
|
|
||||||
|
log.error(errorMessage);
|
||||||
|
|
||||||
|
throw new MalformedQueryParametersException(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSource dataSource = setupJENADataSource(model, vitroRequest);
|
||||||
|
|
||||||
|
if (dataSource != null && visRequestHandler != null) {
|
||||||
|
return visRequestHandler.generateDataVisualization(vitroRequest,
|
||||||
|
log,
|
||||||
|
dataSource);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
String errorMessage = "Data Model Empty &/or Inappropriate "
|
||||||
|
+ "query parameters were submitted. ";
|
||||||
|
|
||||||
|
throw new MalformedQueryParametersException(errorMessage);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private VisualizationRequestHandler getVisualizationRequestHandler(
|
||||||
|
VitroRequest vitroRequest) {
|
||||||
|
|
||||||
|
String visType = vitroRequest.getParameter(VisualizationFrameworkConstants
|
||||||
|
.VIS_TYPE_KEY);
|
||||||
|
VisualizationRequestHandler visRequestHandler = null;
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
visRequestHandler = VisualizationsDependencyInjector
|
||||||
|
.getVisualizationIDsToClassMap(getServletContext())
|
||||||
|
.get(visType);
|
||||||
|
} catch (NullPointerException nullKeyException) {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return visRequestHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataSource setupJENADataSource(Model model, VitroRequest vreq) {
|
||||||
|
|
||||||
|
log.debug("rdfResultFormat was: " + VisConstants.RDF_RESULT_FORMAT_PARAM);
|
||||||
|
|
||||||
|
DataSource dataSource = DatasetFactory.create();
|
||||||
|
ModelMaker maker = (ModelMaker) getServletContext().getAttribute("vitroJenaModelMaker");
|
||||||
|
|
||||||
|
dataSource.setDefaultModel(model);
|
||||||
|
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker;
|
||||||
|
|
||||||
|
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 edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services a standard visualization request, which involves templates. This will return a simple error message and a 501 if
|
||||||
|
* there is no jena Model.
|
||||||
|
*
|
||||||
|
* @author cdtank
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class StandardVisualizationController extends FreemarkerHttpServlet {
|
||||||
|
|
||||||
|
public static final String URL_ENCODING_SCHEME = "UTF-8";
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(StandardVisualizationController.class.getName());
|
||||||
|
|
||||||
|
protected static final Syntax SYNTAX = Syntax.syntaxARQ;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ResponseValues processRequest(VitroRequest vreq) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Based on the query parameters passed via URI get the appropriate visualization
|
||||||
|
* request handler.
|
||||||
|
* */
|
||||||
|
VisualizationRequestHandler visRequestHandler =
|
||||||
|
getVisualizationRequestHandler(vreq);
|
||||||
|
|
||||||
|
if (visRequestHandler != null) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pass the query to the selected visualization request handler & render the visualization.
|
||||||
|
* Since the visualization content is directly added to the response object we are side-
|
||||||
|
* effecting this method.
|
||||||
|
* */
|
||||||
|
return renderVisualization(vreq, visRequestHandler);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return UtilityFunctions.handleMalformedParameters("Visualization Query Error",
|
||||||
|
"Inappropriate query parameters were submitted.",
|
||||||
|
vreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ResponseValues renderVisualization(VitroRequest vitroRequest,
|
||||||
|
VisualizationRequestHandler visRequestHandler) {
|
||||||
|
|
||||||
|
Model model = vitroRequest.getJenaOntModel(); // getModel()
|
||||||
|
if (model == null) {
|
||||||
|
|
||||||
|
String errorMessage = "This service is not supporeted by the current "
|
||||||
|
+ "webapp configuration. A jena model is required in the "
|
||||||
|
+ "servlet context.";
|
||||||
|
|
||||||
|
log.error(errorMessage);
|
||||||
|
|
||||||
|
return UtilityFunctions.handleMalformedParameters("Visualization Query Error",
|
||||||
|
errorMessage,
|
||||||
|
vitroRequest);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSource dataSource = setupJENADataSource(model, vitroRequest);
|
||||||
|
|
||||||
|
if (dataSource != null && visRequestHandler != null) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return visRequestHandler.generateStandardVisualization(vitroRequest,
|
||||||
|
log,
|
||||||
|
dataSource);
|
||||||
|
} catch (MalformedQueryParametersException e) {
|
||||||
|
return UtilityFunctions.handleMalformedParameters(
|
||||||
|
"Standard Visualization Query Error - Individual Publication Count",
|
||||||
|
e.getMessage(),
|
||||||
|
vitroRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
String errorMessage = "Data Model Empty &/or Inappropriate "
|
||||||
|
+ "query parameters were submitted. ";
|
||||||
|
|
||||||
|
log.error(errorMessage);
|
||||||
|
|
||||||
|
return UtilityFunctions.handleMalformedParameters("Visualization Query Error",
|
||||||
|
errorMessage,
|
||||||
|
vitroRequest);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private VisualizationRequestHandler getVisualizationRequestHandler(
|
||||||
|
VitroRequest vitroRequest) {
|
||||||
|
|
||||||
|
String visType = vitroRequest.getParameter(VisualizationFrameworkConstants
|
||||||
|
.VIS_TYPE_KEY);
|
||||||
|
VisualizationRequestHandler visRequestHandler = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
visRequestHandler = VisualizationsDependencyInjector
|
||||||
|
.getVisualizationIDsToClassMap(getServletContext())
|
||||||
|
.get(visType);
|
||||||
|
} catch (NullPointerException nullKeyException) {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return visRequestHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataSource setupJENADataSource(Model model, VitroRequest vreq) {
|
||||||
|
|
||||||
|
log.debug("rdfResultFormat was: " + VisConstants.RDF_RESULT_FORMAT_PARAM);
|
||||||
|
|
||||||
|
DataSource dataSource = DatasetFactory.create();
|
||||||
|
ModelMaker maker = (ModelMaker) getServletContext().getAttribute("vitroJenaModelMaker");
|
||||||
|
|
||||||
|
dataSource.setDefaultModel(model);
|
||||||
|
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
||||||
|
|
||||||
|
public class VisualizationsDependencyInjector {
|
||||||
|
|
||||||
|
private static Map<String, VisualizationRequestHandler> visualizationIDsToClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to inject vis dependencies i.e. the vis algorithms that are
|
||||||
|
* being implemented into the vis controller. Modified Dependency Injection pattern is
|
||||||
|
* used here. XML file containing the location of all the vis is saved in accessible folder.
|
||||||
|
* @param servletContext
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private synchronized static Map<String, VisualizationRequestHandler> initVisualizations(
|
||||||
|
ServletContext servletContext) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A visualization request has already been made causing the visualizationIDsToClass to be
|
||||||
|
* initiated & populated with visualization ids to its request handlers.
|
||||||
|
* */
|
||||||
|
if (visualizationIDsToClass != null) {
|
||||||
|
return visualizationIDsToClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
String resourcePath =
|
||||||
|
servletContext
|
||||||
|
.getRealPath(VisualizationFrameworkConstants
|
||||||
|
.RELATIVE_LOCATION_OF_FM_VISUALIZATIONS_BEAN);
|
||||||
|
|
||||||
|
ApplicationContext context = new ClassPathXmlApplicationContext(
|
||||||
|
"file:" + resourcePath);
|
||||||
|
|
||||||
|
BeanFactory factory = context;
|
||||||
|
|
||||||
|
VisualizationInjector visualizationInjector =
|
||||||
|
(VisualizationInjector) factory.getBean("visualizationInjector");
|
||||||
|
|
||||||
|
visualizationIDsToClass = visualizationInjector.getVisualizationIDToClass();
|
||||||
|
|
||||||
|
|
||||||
|
return visualizationIDsToClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, VisualizationRequestHandler> getVisualizationIDsToClassMap(
|
||||||
|
ServletContext servletContext) {
|
||||||
|
if (visualizationIDsToClass != null) {
|
||||||
|
return visualizationIDsToClass;
|
||||||
|
} else {
|
||||||
|
return initVisualizations(servletContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,332 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.coauthorship;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.StandardVisualizationController;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.CoAuthorshipData;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Edge;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Node;
|
||||||
|
|
||||||
|
public class CoAuthorshipGraphMLWriter {
|
||||||
|
|
||||||
|
private StringBuilder coAuthorshipGraphMLContent;
|
||||||
|
|
||||||
|
private final String GRAPHML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
+ " <graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\"\n"
|
||||||
|
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
|
||||||
|
+ " xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns\n"
|
||||||
|
+ " http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n\n";
|
||||||
|
|
||||||
|
private final String GRAPHML_FOOTER = "</graphml>";
|
||||||
|
|
||||||
|
public CoAuthorshipGraphMLWriter(CoAuthorshipData visVOContainer) {
|
||||||
|
|
||||||
|
coAuthorshipGraphMLContent = createCoAuthorshipGraphMLContent(visVOContainer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilder getCoAuthorshipGraphMLContent() {
|
||||||
|
return coAuthorshipGraphMLContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder createCoAuthorshipGraphMLContent(
|
||||||
|
CoAuthorshipData coAuthorshipData) {
|
||||||
|
|
||||||
|
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(coAuthorshipData, graphMLContent);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to generate graph content. It will contain both the nodes & edge information.
|
||||||
|
* We are side-effecting "graphMLContent".
|
||||||
|
* */
|
||||||
|
generateGraphContent(coAuthorshipData, graphMLContent);
|
||||||
|
|
||||||
|
graphMLContent.append(GRAPHML_FOOTER);
|
||||||
|
|
||||||
|
return graphMLContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateGraphContent(CoAuthorshipData coAuthorshipData,
|
||||||
|
StringBuilder graphMLContent) {
|
||||||
|
|
||||||
|
graphMLContent.append("\n<graph edgedefault=\"undirected\">\n");
|
||||||
|
|
||||||
|
if (coAuthorshipData.getNodes() != null & coAuthorshipData.getNodes().size() > 0) {
|
||||||
|
generateNodeSectionContent(coAuthorshipData, graphMLContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coAuthorshipData.getEdges() != null & coAuthorshipData.getEdges().size() > 0) {
|
||||||
|
generateEdgeSectionContent(coAuthorshipData, graphMLContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
graphMLContent.append("</graph>\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateEdgeSectionContent(CoAuthorshipData coAuthorshipData,
|
||||||
|
StringBuilder graphMLContent) {
|
||||||
|
|
||||||
|
graphMLContent.append("<!-- edges -->\n");
|
||||||
|
|
||||||
|
Set<Edge> edges = coAuthorshipData.getEdges();
|
||||||
|
|
||||||
|
List<Edge> orderedEdges = new ArrayList<Edge>(edges);
|
||||||
|
|
||||||
|
Collections.sort(orderedEdges, new EdgeComparator());
|
||||||
|
|
||||||
|
for (Edge currentEdge : orderedEdges) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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("<edge "
|
||||||
|
+ "id=\"" + currentEdge.getEdgeID() + "\" "
|
||||||
|
+ "source=\"" + currentEdge.getSourceNode().getNodeID() + "\" "
|
||||||
|
+ "target=\"" + currentEdge.getTargetNode().getNodeID() + "\" "
|
||||||
|
+ ">\n");
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"collaborator1\">"
|
||||||
|
+ currentEdge.getSourceNode().getNodeName()
|
||||||
|
+ "</data>\n");
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"collaborator2\">"
|
||||||
|
+ currentEdge.getTargetNode().getNodeName()
|
||||||
|
+ "</data>\n");
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"number_of_coauthored_works\">"
|
||||||
|
+ currentEdge.getNumOfCoAuthoredWorks()
|
||||||
|
+ "</data>\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.
|
||||||
|
* */
|
||||||
|
for (Map.Entry<String, Integer> publicationInfo
|
||||||
|
: currentEdge.getEarliestCollaborationYearCount().entrySet()) {
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"earliest_collaboration\">"
|
||||||
|
+ publicationInfo.getKey()
|
||||||
|
+ "</data>\n");
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"num_earliest_collaboration\">"
|
||||||
|
+ publicationInfo.getValue()
|
||||||
|
+ "</data>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentEdge.getLatestCollaborationYearCount() != null) {
|
||||||
|
|
||||||
|
for (Map.Entry<String, Integer> publicationInfo
|
||||||
|
: currentEdge.getLatestCollaborationYearCount().entrySet()) {
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"latest_collaboration\">"
|
||||||
|
+ publicationInfo.getKey()
|
||||||
|
+ "</data>\n");
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"num_latest_collaboration\">"
|
||||||
|
+ publicationInfo.getValue()
|
||||||
|
+ "</data>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentEdge.getUnknownCollaborationYearCount() != null) {
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"num_unknown_collaboration\">"
|
||||||
|
+ currentEdge.getUnknownCollaborationYearCount()
|
||||||
|
+ "</data>\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
graphMLContent.append("</edge>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateNodeSectionContent(CoAuthorshipData coAuthorshipData,
|
||||||
|
StringBuilder graphMLContent) {
|
||||||
|
|
||||||
|
graphMLContent.append("<!-- nodes -->\n");
|
||||||
|
|
||||||
|
Node egoNode = coAuthorshipData.getEgoNode();
|
||||||
|
Set<Node> authorNodes = coAuthorshipData.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);
|
||||||
|
|
||||||
|
List<Node> orderedAuthorNodes = new ArrayList<Node>(authorNodes);
|
||||||
|
orderedAuthorNodes.remove(egoNode);
|
||||||
|
|
||||||
|
Collections.sort(orderedAuthorNodes, new NodeComparator());
|
||||||
|
|
||||||
|
|
||||||
|
for (Node currNode : orderedAuthorNodes) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 = VisualizationFrameworkConstants.INDIVIDUAL_URL_PREFIX + "?"
|
||||||
|
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
|
||||||
|
+ "=" + URLEncoder.encode(node.getNodeURI(),
|
||||||
|
StandardVisualizationController
|
||||||
|
.URL_ENCODING_SCHEME).toString();
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
System.err.println("URL Encoding ERRor. Move this to use log.error ASAP");
|
||||||
|
}
|
||||||
|
|
||||||
|
graphMLContent.append("<node id=\"" + node.getNodeID() + "\">\n");
|
||||||
|
graphMLContent.append("\t<data key=\"url\">" + node.getNodeURI() + "</data>\n");
|
||||||
|
graphMLContent.append("\t<data key=\"label\">" + node.getNodeName() + "</data>\n");
|
||||||
|
|
||||||
|
if (profileURL != null) {
|
||||||
|
graphMLContent.append("\t<data key=\"profile_url\">" + profileURL + "</data>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"number_of_authored_works\">"
|
||||||
|
+ node.getNumOfAuthoredWorks()
|
||||||
|
+ "</data>\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<String, Integer> publicationInfo
|
||||||
|
: node.getEarliestPublicationYearCount().entrySet()) {
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"earliest_publication\">"
|
||||||
|
+ publicationInfo.getKey()
|
||||||
|
+ "</data>\n");
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"num_earliest_publication\">"
|
||||||
|
+ publicationInfo.getValue()
|
||||||
|
+ "</data>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.getLatestPublicationYearCount() != null) {
|
||||||
|
|
||||||
|
for (Map.Entry<String, Integer> publicationInfo
|
||||||
|
: node.getLatestPublicationYearCount().entrySet()) {
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"latest_publication\">"
|
||||||
|
+ publicationInfo.getKey()
|
||||||
|
+ "</data>\n");
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"num_latest_publication\">"
|
||||||
|
+ publicationInfo.getValue()
|
||||||
|
+ "</data>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.getUnknownPublicationYearCount() != null) {
|
||||||
|
|
||||||
|
graphMLContent.append("\t<data key=\"num_unknown_publication\">"
|
||||||
|
+ node.getUnknownPublicationYearCount()
|
||||||
|
+ "</data>\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
graphMLContent.append("</node>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateKeyDefinitionContent(CoAuthorshipData 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<Map<String, String>> schema,
|
||||||
|
StringBuilder graphMLContent) {
|
||||||
|
|
||||||
|
for (Map<String, String> currentNodeSchemaAttribute : schema) {
|
||||||
|
|
||||||
|
graphMLContent.append("\n<key ");
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> currentAttributeKey
|
||||||
|
: currentNodeSchemaAttribute.entrySet()) {
|
||||||
|
|
||||||
|
graphMLContent.append(currentAttributeKey.getKey()
|
||||||
|
+ "=\"" + currentAttributeKey.getValue()
|
||||||
|
+ "\" ");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentNodeSchemaAttribute.containsKey("default")) {
|
||||||
|
|
||||||
|
graphMLContent.append(">\n");
|
||||||
|
graphMLContent.append("<default>");
|
||||||
|
graphMLContent.append(currentNodeSchemaAttribute.get("default"));
|
||||||
|
graphMLContent.append("</default>\n");
|
||||||
|
graphMLContent.append("</key>\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
graphMLContent.append("/>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,488 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.coauthorship;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
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.freemarker.valueobjects.BiboDocument;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.CoAuthorshipData;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Edge;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Node;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.QueryRunner;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UniqueIDGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This query runner is used to execute a sparql query to get all the publications
|
||||||
|
* for a particular individual. It will also fetch all the authors that worked
|
||||||
|
* on that particular publication.
|
||||||
|
*
|
||||||
|
* @author cdtank
|
||||||
|
*/
|
||||||
|
public class CoAuthorshipQueryRunner implements QueryRunner<CoAuthorshipData> {
|
||||||
|
|
||||||
|
private static final int MAX_AUTHORS_PER_PAPER_ALLOWED = 100;
|
||||||
|
|
||||||
|
protected static final Syntax SYNTAX = Syntax.syntaxARQ;
|
||||||
|
|
||||||
|
private String egoURI;
|
||||||
|
|
||||||
|
private DataSource dataSource;
|
||||||
|
|
||||||
|
private Log log;
|
||||||
|
|
||||||
|
private UniqueIDGenerator nodeIDGenerator;
|
||||||
|
|
||||||
|
private UniqueIDGenerator edgeIDGenerator;
|
||||||
|
|
||||||
|
public CoAuthorshipQueryRunner(String egoURI,
|
||||||
|
DataSource dataSource, Log log) {
|
||||||
|
|
||||||
|
this.egoURI = egoURI;
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
this.log = log;
|
||||||
|
|
||||||
|
this.nodeIDGenerator = new UniqueIDGenerator();
|
||||||
|
this.edgeIDGenerator = new UniqueIDGenerator();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private CoAuthorshipData createQueryResult(ResultSet resultSet) {
|
||||||
|
|
||||||
|
Set<Node> nodes = new HashSet<Node>();
|
||||||
|
|
||||||
|
Map<String, BiboDocument> biboDocumentURLToVO = new HashMap<String, BiboDocument>();
|
||||||
|
Map<String, Set<Node>> biboDocumentURLToCoAuthors = new HashMap<String, Set<Node>>();
|
||||||
|
Map<String, Node> nodeURLToVO = new HashMap<String, Node>();
|
||||||
|
Map<String, Edge> edgeUniqueIdentifierToVO = new HashMap<String, Edge>();
|
||||||
|
|
||||||
|
Node egoNode = null;
|
||||||
|
|
||||||
|
Set<Edge> edges = new HashSet<Edge>();
|
||||||
|
|
||||||
|
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<Node> coAuthorsForCurrentBiboDocument;
|
||||||
|
|
||||||
|
if (biboDocumentURLToCoAuthors.containsKey(biboDocument.getDocumentURL())) {
|
||||||
|
coAuthorsForCurrentBiboDocument = biboDocumentURLToCoAuthors
|
||||||
|
.get(biboDocument.getDocumentURL());
|
||||||
|
} else {
|
||||||
|
coAuthorsForCurrentBiboDocument = new HashSet<Node>();
|
||||||
|
biboDocumentURLToCoAuthors.put(biboDocument.getDocumentURL(),
|
||||||
|
coAuthorsForCurrentBiboDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
coAuthorsForCurrentBiboDocument.add(coAuthorNode);
|
||||||
|
|
||||||
|
Edge egoCoAuthorEdge = getExistingEdge(egoNode, coAuthorNode, edgeUniqueIdentifierToVO);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
edgeUniqueIdentifierToVO.put(
|
||||||
|
getEdgeUniqueIdentifier(egoNode.getNodeID(),
|
||||||
|
coAuthorNode.getNodeID()),
|
||||||
|
egoCoAuthorEdge);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method takes out all the authors & edges between authors that belong to documents
|
||||||
|
* that have more than 100 authors. We conjecture that these papers do not provide much
|
||||||
|
* insight. However, we have left the documents be.
|
||||||
|
*
|
||||||
|
* This method side-effects "nodes" & "edges".
|
||||||
|
* */
|
||||||
|
removeLowQualityNodesAndEdges(nodes,
|
||||||
|
biboDocumentURLToVO,
|
||||||
|
biboDocumentURLToCoAuthors,
|
||||||
|
edges);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to create edges between 2 co-authors. E.g. On a paper there were 3 authors
|
||||||
|
* ego, A & B then we have already created edges like,
|
||||||
|
* ego - A
|
||||||
|
* ego - B
|
||||||
|
* The below sub-routine will take care of,
|
||||||
|
* A - B
|
||||||
|
*
|
||||||
|
* We are side-effecting "edges" here. The only reason to do this is because we are adding
|
||||||
|
* edges en masse for all the co-authors on all the publications considered so far. The
|
||||||
|
* other reason being we dont want to compare against 2 sets of edges (edges created before
|
||||||
|
* & co-author edges created during the course of this method) when we are creating a new
|
||||||
|
* edge.
|
||||||
|
* */
|
||||||
|
createCoAuthorEdges(biboDocumentURLToVO,
|
||||||
|
biboDocumentURLToCoAuthors,
|
||||||
|
edges,
|
||||||
|
edgeUniqueIdentifierToVO);
|
||||||
|
|
||||||
|
|
||||||
|
return new CoAuthorshipData(egoNode, nodes, edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeLowQualityNodesAndEdges(Set<Node> nodes,
|
||||||
|
Map<String, BiboDocument> biboDocumentURLToVO,
|
||||||
|
Map<String, Set<Node>> biboDocumentURLToCoAuthors,
|
||||||
|
Set<Edge> edges) {
|
||||||
|
|
||||||
|
Set<Node> nodesToBeRemoved = new HashSet<Node>();
|
||||||
|
for (Map.Entry<String, Set<Node>> currentBiboDocumentEntry
|
||||||
|
: biboDocumentURLToCoAuthors.entrySet()) {
|
||||||
|
|
||||||
|
if (currentBiboDocumentEntry.getValue().size() > MAX_AUTHORS_PER_PAPER_ALLOWED) {
|
||||||
|
|
||||||
|
BiboDocument currentBiboDocument = biboDocumentURLToVO
|
||||||
|
.get(currentBiboDocumentEntry.getKey());
|
||||||
|
|
||||||
|
Set<Edge> edgesToBeRemoved = new HashSet<Edge>();
|
||||||
|
|
||||||
|
for (Edge currentEdge : edges) {
|
||||||
|
Set<BiboDocument> currentCollaboratorDocuments =
|
||||||
|
currentEdge.getCollaboratorDocuments();
|
||||||
|
|
||||||
|
if (currentCollaboratorDocuments.contains(currentBiboDocument)) {
|
||||||
|
currentCollaboratorDocuments.remove(currentBiboDocument);
|
||||||
|
if (currentCollaboratorDocuments.isEmpty()) {
|
||||||
|
edgesToBeRemoved.add(currentEdge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
edges.removeAll(edgesToBeRemoved);
|
||||||
|
|
||||||
|
for (Node currentCoAuthor : currentBiboDocumentEntry.getValue()) {
|
||||||
|
currentCoAuthor.getAuthorDocuments().remove(currentBiboDocument);
|
||||||
|
if (currentCoAuthor.getAuthorDocuments().isEmpty()) {
|
||||||
|
nodesToBeRemoved.add(currentCoAuthor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes.removeAll(nodesToBeRemoved);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createCoAuthorEdges(
|
||||||
|
Map<String, BiboDocument> biboDocumentURLToVO,
|
||||||
|
Map<String, Set<Node>> biboDocumentURLToCoAuthors, Set<Edge> edges,
|
||||||
|
Map<String, Edge> edgeUniqueIdentifierToVO) {
|
||||||
|
|
||||||
|
for (Map.Entry<String, Set<Node>> 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.
|
||||||
|
*
|
||||||
|
* We are restricting edges between co-author if a particular document has more than
|
||||||
|
* 100 co-authors. Our conjecture is that such edges do not provide any good insight
|
||||||
|
* & causes unnecessary computations causing the server to time-out.
|
||||||
|
* */
|
||||||
|
if (currentBiboDocumentEntry.getValue().size() > 1
|
||||||
|
&& currentBiboDocumentEntry.getValue().size()
|
||||||
|
<= MAX_AUTHORS_PER_PAPER_ALLOWED) {
|
||||||
|
|
||||||
|
|
||||||
|
Set<Edge> newlyAddedEdges = new HashSet<Edge>();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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<Node> coAuthorNodes = new ArrayList<Node>(currentBiboDocumentEntry.getValue());
|
||||||
|
Collections.sort(coAuthorNodes, new NodeComparator());
|
||||||
|
|
||||||
|
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,
|
||||||
|
edgeUniqueIdentifierToVO);
|
||||||
|
|
||||||
|
BiboDocument currentBiboDocument = biboDocumentURLToVO
|
||||||
|
.get(currentBiboDocumentEntry
|
||||||
|
.getKey());
|
||||||
|
|
||||||
|
if (coAuthor1_2Edge != null) {
|
||||||
|
coAuthor1_2Edge.addCollaboratorDocument(currentBiboDocument);
|
||||||
|
} else {
|
||||||
|
coAuthor1_2Edge = new Edge(coAuthor1,
|
||||||
|
coAuthor2,
|
||||||
|
currentBiboDocument,
|
||||||
|
edgeIDGenerator);
|
||||||
|
newlyAddedEdges.add(coAuthor1_2Edge);
|
||||||
|
edgeUniqueIdentifierToVO.put(
|
||||||
|
getEdgeUniqueIdentifier(coAuthor1.getNodeID(),
|
||||||
|
coAuthor2.getNodeID()),
|
||||||
|
coAuthor1_2Edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
edges.addAll(newlyAddedEdges);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Edge getExistingEdge(
|
||||||
|
Node collaboratingNode1,
|
||||||
|
Node collaboratingNode2,
|
||||||
|
Map<String, Edge> edgeUniqueIdentifierToVO) {
|
||||||
|
|
||||||
|
String edgeUniqueIdentifier = getEdgeUniqueIdentifier(collaboratingNode1.getNodeID(),
|
||||||
|
collaboratingNode2.getNodeID());
|
||||||
|
|
||||||
|
return edgeUniqueIdentifierToVO.get(edgeUniqueIdentifier);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getEdgeUniqueIdentifier(int nodeID1, int nodeID2) {
|
||||||
|
|
||||||
|
String separator = "*";
|
||||||
|
|
||||||
|
if (nodeID1 < nodeID2) {
|
||||||
|
return nodeID1 + separator + nodeID2;
|
||||||
|
} else {
|
||||||
|
return nodeID2 + separator + nodeID1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// public Map<String, VivoCollegeOrSchool> 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,
|
||||||
|
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);
|
||||||
|
System.out.println("\n\nquery.isSelectType() is "+ query.isSelectType()+ " \n\n");
|
||||||
|
// 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 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 } "
|
||||||
|
+ "} "
|
||||||
|
+ "ORDER BY ?document ?coAuthorPerson";
|
||||||
|
|
||||||
|
// System.out.println("COAUTHORSHIP QUERY - " + sparqlQuery);
|
||||||
|
|
||||||
|
return sparqlQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public CoAuthorshipData getQueryResult()
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(this.egoURI)) {
|
||||||
|
/*
|
||||||
|
* To test for the validity of the URI submitted.
|
||||||
|
* */
|
||||||
|
IRIFactory iRIFactory = IRIFactory.jenaImplementation();
|
||||||
|
IRI iri = iRIFactory.create(this.egoURI);
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new MalformedQueryParametersException("URI parameter is either null or empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultSet resultSet = executeQuery(generateEgoCoAuthorshipSparqlQuery(this.egoURI),
|
||||||
|
this.dataSource);
|
||||||
|
return createQueryResult(resultSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,243 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.coauthorship;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringEscapeUtils;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
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.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.DataVisualizationController;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.CoAuthorshipData;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Node;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.QueryRunner;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This request handler is used when information related to co-authorship network
|
||||||
|
* for an individual is requested. It currently provides 2 outputs,
|
||||||
|
* 1. Graphml content representing the individual's co-authorship network
|
||||||
|
* 1. CSV file containing the list(& count) of unique co-authors with which
|
||||||
|
* the individual has worked over the years. This data powers the related sparkline.
|
||||||
|
*
|
||||||
|
* @author cdtank
|
||||||
|
*/
|
||||||
|
public class CoAuthorshipRequestHandler implements VisualizationRequestHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateAjaxVisualization(VitroRequest vitroRequest, Log log,
|
||||||
|
DataSource dataSource) throws MalformedQueryParametersException {
|
||||||
|
throw new UnsupportedOperationException("CoAuthorship does not provide Ajax Response.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> generateDataVisualization(
|
||||||
|
VitroRequest vitroRequest, Log log, DataSource dataSource)
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
|
||||||
|
|
||||||
|
String egoURI = vitroRequest.getParameter(
|
||||||
|
VisualizationFrameworkConstants
|
||||||
|
.INDIVIDUAL_URI_KEY);
|
||||||
|
|
||||||
|
String visMode = vitroRequest.getParameter(
|
||||||
|
VisualizationFrameworkConstants
|
||||||
|
.VIS_MODE_KEY);
|
||||||
|
|
||||||
|
QueryRunner<CoAuthorshipData> queryManager =
|
||||||
|
new CoAuthorshipQueryRunner(egoURI, dataSource, log);
|
||||||
|
|
||||||
|
CoAuthorshipData authorNodesAndEdges =
|
||||||
|
queryManager.getQueryResult();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We will be using the same visualization package for both sparkline & coauthorship
|
||||||
|
* flash vis. We will use "VIS_MODE_KEY" as a modifier to differentiate
|
||||||
|
* between these two. The default will be to render the coauthorship network vis.
|
||||||
|
* */
|
||||||
|
if (VisualizationFrameworkConstants.SPARKLINE_VIS_MODE
|
||||||
|
.equalsIgnoreCase(visMode)) {
|
||||||
|
/*
|
||||||
|
* When the csv file is required - based on which sparkline visualization will
|
||||||
|
* be rendered.
|
||||||
|
* */
|
||||||
|
return prepareSparklineDataResponse(authorNodesAndEdges);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* When the graphML file is required - based on which coauthorship network
|
||||||
|
* visualization will be rendered.
|
||||||
|
* */
|
||||||
|
return prepareNetworkDataResponse(authorNodesAndEdges);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseValues generateStandardVisualization(VitroRequest vitroRequest,
|
||||||
|
Log log,
|
||||||
|
DataSource dataSource)
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
|
||||||
|
String egoURI = vitroRequest.getParameter(
|
||||||
|
VisualizationFrameworkConstants
|
||||||
|
.INDIVIDUAL_URI_KEY);
|
||||||
|
|
||||||
|
QueryRunner<CoAuthorshipData> queryManager =
|
||||||
|
new CoAuthorshipQueryRunner(egoURI, dataSource, log);
|
||||||
|
|
||||||
|
CoAuthorshipData authorNodesAndEdges =
|
||||||
|
queryManager.getQueryResult();
|
||||||
|
|
||||||
|
|
||||||
|
return prepareStandaloneResponse(egoURI,
|
||||||
|
authorNodesAndEdges,
|
||||||
|
vitroRequest);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCoauthorsPerYearCSVContent(Map<String, Set<Node>> yearToCoauthors) {
|
||||||
|
|
||||||
|
StringBuilder csvFileContent = new StringBuilder();
|
||||||
|
|
||||||
|
csvFileContent.append("Year, Count, Co-Author(s)\n");
|
||||||
|
|
||||||
|
for (Entry<String, Set<Node>> currentEntry : yearToCoauthors.entrySet()) {
|
||||||
|
csvFileContent.append(StringEscapeUtils.escapeCsv(currentEntry.getKey()));
|
||||||
|
csvFileContent.append(",");
|
||||||
|
csvFileContent.append(currentEntry.getValue().size());
|
||||||
|
csvFileContent.append(",");
|
||||||
|
csvFileContent.append(StringEscapeUtils.escapeCsv(getCoauthorNamesAsString(currentEntry.getValue())));
|
||||||
|
csvFileContent.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return csvFileContent.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCoauthorNamesAsString(Set<Node> coAuthors) {
|
||||||
|
|
||||||
|
StringBuilder coAuthorsMerged = new StringBuilder();
|
||||||
|
|
||||||
|
String coAuthorSeparator = "; ";
|
||||||
|
for (Node currCoAuthor : coAuthors) {
|
||||||
|
coAuthorsMerged.append(currCoAuthor.getNodeName() + coAuthorSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringUtils.removeEnd(coAuthorsMerged.toString(), coAuthorSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides response when a csv file containing number & names of unique co-authors per
|
||||||
|
* year is requested.
|
||||||
|
* @param authorNodesAndEdges
|
||||||
|
* @param response
|
||||||
|
*/
|
||||||
|
private Map<String, String> prepareSparklineDataResponse(CoAuthorshipData authorNodesAndEdges) {
|
||||||
|
|
||||||
|
String outputFileName;
|
||||||
|
Map<String, Set<Node>> yearToCoauthors = new TreeMap<String, Set<Node>>();
|
||||||
|
|
||||||
|
if (authorNodesAndEdges.getNodes() != null && authorNodesAndEdges.getNodes().size() > 0) {
|
||||||
|
|
||||||
|
outputFileName = UtilityFunctions.slugify(authorNodesAndEdges
|
||||||
|
.getEgoNode().getNodeName())
|
||||||
|
+ "_coauthors-per-year" + ".csv";
|
||||||
|
|
||||||
|
yearToCoauthors = UtilityFunctions.getPublicationYearToCoAuthors(authorNodesAndEdges);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
outputFileName = "no_coauthors-per-year" + ".csv";
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> fileData = new HashMap<String, String>();
|
||||||
|
fileData.put(DataVisualizationController.FILE_NAME_KEY,
|
||||||
|
outputFileName);
|
||||||
|
fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
|
||||||
|
"application/octet-stream");
|
||||||
|
fileData.put(DataVisualizationController.FILE_CONTENT_KEY,
|
||||||
|
getCoauthorsPerYearCSVContent(yearToCoauthors));
|
||||||
|
|
||||||
|
return fileData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a response when graphml formatted co-authorship network is requested, typically by
|
||||||
|
* the flash vis.
|
||||||
|
* @param authorNodesAndEdges
|
||||||
|
* @param response
|
||||||
|
*/
|
||||||
|
private Map<String, String> prepareNetworkDataResponse(CoAuthorshipData authorNodesAndEdges) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are side-effecting responseWriter since we are directly manipulating the response
|
||||||
|
* object of the servlet.
|
||||||
|
* */
|
||||||
|
CoAuthorshipGraphMLWriter coAuthorshipGraphMLWriter =
|
||||||
|
new CoAuthorshipGraphMLWriter(authorNodesAndEdges);
|
||||||
|
|
||||||
|
Map<String, String> fileData = new HashMap<String, String>();
|
||||||
|
fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
|
||||||
|
"text/xml");
|
||||||
|
fileData.put(DataVisualizationController.FILE_CONTENT_KEY,
|
||||||
|
coAuthorshipGraphMLWriter.getCoAuthorshipGraphMLContent().toString());
|
||||||
|
|
||||||
|
return fileData;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the page for person level visualization is requested.
|
||||||
|
* @param egoURI
|
||||||
|
* @param coAuthorshipVO
|
||||||
|
* @param vitroRequest
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private TemplateResponseValues prepareStandaloneResponse(
|
||||||
|
String egoURI,
|
||||||
|
CoAuthorshipData coAuthorshipVO,
|
||||||
|
VitroRequest vitroRequest) {
|
||||||
|
|
||||||
|
Portal portal = vitroRequest.getPortal();
|
||||||
|
|
||||||
|
String title = "";
|
||||||
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
if (coAuthorshipVO.getNodes() != null && coAuthorshipVO.getNodes().size() > 0) {
|
||||||
|
title = coAuthorshipVO.getEgoNode().getNodeName() + " - ";
|
||||||
|
body.put("numOfAuthors", coAuthorshipVO.getNodes().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coAuthorshipVO.getEdges() != null && coAuthorshipVO.getEdges().size() > 0) {
|
||||||
|
body.put("numOfCoAuthorShips", coAuthorshipVO.getEdges().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//request.setAttribute("scripts", "/templates/visualization/person_level_inject_head.jsp");
|
||||||
|
|
||||||
|
String standaloneTemplate = "/visualization/coauthorship/coAuthorship.ftl";
|
||||||
|
|
||||||
|
|
||||||
|
body.put("portalBean", portal);
|
||||||
|
body.put("egoURIParam", egoURI);
|
||||||
|
body.put("title", title + "Co-Authorship Visualization");
|
||||||
|
|
||||||
|
return new TemplateResponseValues(standaloneTemplate, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,580 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.coauthorship;
|
||||||
|
|
||||||
|
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.freemarker.UrlBuilder;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SparklineData;
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class CoAuthorshipVisCodeGenerator {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are 2 modes of sparkline that are available via this visualization.
|
||||||
|
* 1. Short Sparkline - This sparkline will render all the data points (or sparks),
|
||||||
|
* which in this case are the coauthors over the years, from the last 10 years.
|
||||||
|
*
|
||||||
|
* 2. Full Sparkline - This sparkline will render all the data points (or sparks)
|
||||||
|
* spanning the career of the person & last 10 years at the minimum, in case if
|
||||||
|
* the person started his career in the last 10 yeras.
|
||||||
|
* */
|
||||||
|
private static final Map<String, String> VIS_DIV_NAMES = new HashMap<String, String>() { {
|
||||||
|
|
||||||
|
put("SHORT_SPARK", "unique_coauthors_short_sparkline_vis");
|
||||||
|
put("FULL_SPARK", "unique_coauthors_full_sparkline_vis");
|
||||||
|
|
||||||
|
} };
|
||||||
|
|
||||||
|
private static final String VISUALIZATION_STYLE_CLASS = "sparkline_style";
|
||||||
|
|
||||||
|
private static final String DEFAULT_VISCONTAINER_DIV_ID = "unique_coauthors_vis_container";
|
||||||
|
|
||||||
|
private Map<String, Set<Node>> yearToUniqueCoauthors;
|
||||||
|
|
||||||
|
private Log log;
|
||||||
|
|
||||||
|
private SparklineData sparklineData;
|
||||||
|
|
||||||
|
private String individualURI;
|
||||||
|
|
||||||
|
public CoAuthorshipVisCodeGenerator(String individualURI,
|
||||||
|
String visMode,
|
||||||
|
String visContainer,
|
||||||
|
Map<String, Set<Node>> yearToUniqueCoauthors,
|
||||||
|
Log log) {
|
||||||
|
|
||||||
|
this.individualURI = individualURI;
|
||||||
|
|
||||||
|
this.yearToUniqueCoauthors = yearToUniqueCoauthors;
|
||||||
|
this.sparklineData = new SparklineData();
|
||||||
|
|
||||||
|
this.log = log;
|
||||||
|
|
||||||
|
generateVisualizationCode(visMode, visContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to generate the visualization code (HMTL, CSS & JavaScript).
|
||||||
|
* There 2 parts to it - 1. Actual Content Code & 2. Context Code.
|
||||||
|
* 1. Actual Content code in this case is the sparkline image, text related to
|
||||||
|
* data and the wrapping tables. This is generated via call to google vis API through
|
||||||
|
* JavaScript.
|
||||||
|
* 2. Context code is generally optional but contains code pertaining to tabulated
|
||||||
|
* data & links to download files etc.
|
||||||
|
* @param visMode
|
||||||
|
* @param visContainer
|
||||||
|
*/
|
||||||
|
private void generateVisualizationCode(String visMode,
|
||||||
|
String visContainer) {
|
||||||
|
|
||||||
|
sparklineData.setSparklineContent(getMainVisualizationCode(visMode,
|
||||||
|
visContainer));
|
||||||
|
|
||||||
|
sparklineData.setSparklineContext(getVisualizationContextCode(visMode));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMainVisualizationCode(String visMode,
|
||||||
|
String providedVisContainerID) {
|
||||||
|
|
||||||
|
int numOfYearsToBeRendered = 0;
|
||||||
|
int currentYear = Calendar.getInstance().get(Calendar.YEAR);
|
||||||
|
int shortSparkMinYear = currentYear
|
||||||
|
- VisConstants.MINIMUM_YEARS_CONSIDERED_FOR_SPARKLINE
|
||||||
|
+ 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is required because when deciding the range of years over which the vis
|
||||||
|
* was rendered we dont want to be influenced by the "DEFAULT_PUBLICATION_YEAR".
|
||||||
|
* */
|
||||||
|
Set<String> publishedYears = new HashSet<String>(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();
|
||||||
|
|
||||||
|
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("<style type='text/css'>"
|
||||||
|
+ "." + VISUALIZATION_STYLE_CLASS + " table{"
|
||||||
|
+ " margin: 0;"
|
||||||
|
+ " padding: 0;"
|
||||||
|
+ " width: auto;"
|
||||||
|
+ " border-collapse: collapse;"
|
||||||
|
+ " border-spacing: 0;"
|
||||||
|
+ " vertical-align: inherit;"
|
||||||
|
+ "}"
|
||||||
|
+ ".incomplete-data-holder {"
|
||||||
|
+ ""
|
||||||
|
+ "}"
|
||||||
|
+ "td.sparkline_number { text-align:right; "
|
||||||
|
+ "padding-right:5px; }"
|
||||||
|
+ "td.sparkline_text {text-align:left;}"
|
||||||
|
+ "</style>\n");
|
||||||
|
|
||||||
|
visualizationCode.append("<script type=\"text/javascript\">\n"
|
||||||
|
+ "function drawUniqueCoauthorCountVisualization(providedSparklineImgTD) {\n"
|
||||||
|
+ "var data = new google.visualization.DataTable();\n"
|
||||||
|
+ "data.addColumn('string', 'Year');\n"
|
||||||
|
+ "data.addColumn('number', 'Unique co-authors');\n"
|
||||||
|
+ "data.addRows(" + numOfYearsToBeRendered + ");\n");
|
||||||
|
|
||||||
|
int uniqueCoAuthorCounter = 0;
|
||||||
|
int renderedFullSparks = 0;
|
||||||
|
Set<Node> allCoAuthorsWithKnownAuthorshipYears = new HashSet<Node>();
|
||||||
|
|
||||||
|
for (int publicationYear = minPubYearConsidered;
|
||||||
|
publicationYear <= currentYear;
|
||||||
|
publicationYear++) {
|
||||||
|
|
||||||
|
String publicationYearAsString = String.valueOf(publicationYear);
|
||||||
|
Set<Node> currentCoAuthors = yearToUniqueCoauthors.get(publicationYearAsString);
|
||||||
|
|
||||||
|
Integer currentUniqueCoAuthors = null;
|
||||||
|
|
||||||
|
if (currentCoAuthors != null) {
|
||||||
|
currentUniqueCoAuthors = currentCoAuthors.size();
|
||||||
|
allCoAuthorsWithKnownAuthorshipYears.addAll(currentCoAuthors);
|
||||||
|
} else {
|
||||||
|
currentUniqueCoAuthors = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
visualizationCode.append("data.setValue("
|
||||||
|
+ uniqueCoAuthorCounter
|
||||||
|
+ ", 0, '"
|
||||||
|
+ publicationYearAsString
|
||||||
|
+ "');\n");
|
||||||
|
|
||||||
|
visualizationCode.append("data.setValue("
|
||||||
|
+ uniqueCoAuthorCounter
|
||||||
|
+ ", 1, "
|
||||||
|
+ currentUniqueCoAuthors
|
||||||
|
+ ");\n");
|
||||||
|
uniqueCoAuthorCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the purpose of this visualization I have come up with a term "Sparks" which
|
||||||
|
* essentially means data points.
|
||||||
|
* Sparks that will be rendered in full mode will always be the one's which have any year
|
||||||
|
* associated with it. Hence.
|
||||||
|
* */
|
||||||
|
renderedFullSparks = allCoAuthorsWithKnownAuthorshipYears.size();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Total publications will also consider publications that have no year associated with
|
||||||
|
* them. Hence.
|
||||||
|
* */
|
||||||
|
Integer unknownYearCoauthors = 0;
|
||||||
|
if (yearToUniqueCoauthors.get(VOConstants.DEFAULT_PUBLICATION_YEAR) != null) {
|
||||||
|
unknownYearCoauthors = yearToUniqueCoauthors
|
||||||
|
.get(VOConstants.DEFAULT_PUBLICATION_YEAR).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String sparklineDisplayOptions = "{width: 65, height: 30, showAxisLines: false, "
|
||||||
|
+ "showValueLabels: false, labelPosition: 'none'}";
|
||||||
|
|
||||||
|
if (providedVisContainerID != null) {
|
||||||
|
visContainerID = providedVisContainerID;
|
||||||
|
} else {
|
||||||
|
visContainerID = DEFAULT_VISCONTAINER_DIV_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default these represents the range of the rendered sparks. Only in case of
|
||||||
|
* "short" sparkline mode we will set the Earliest RenderedPublication year to
|
||||||
|
* "currentYear - 10".
|
||||||
|
* */
|
||||||
|
sparklineData.setEarliestRenderedPublicationYear(minPublishedYear);
|
||||||
|
sparklineData.setLatestRenderedPublicationYear(currentYear);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Full Sparkline will be rendered by default. Only if the url has specific mention of
|
||||||
|
* SHORT_SPARKLINE_MODE_KEY then we render the short sparkline and not otherwise.
|
||||||
|
* */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since building StringBuilder objects (which is being used to store the vis code) is
|
||||||
|
* essentially a side-effecting process, we have both the activators method as
|
||||||
|
* side-effecting. They both side-effect "visualizationCode"
|
||||||
|
* */
|
||||||
|
if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE.equalsIgnoreCase(visMode)) {
|
||||||
|
|
||||||
|
sparklineData.setEarliestRenderedPublicationYear(shortSparkMinYear);
|
||||||
|
generateShortSparklineVisualizationContent(currentYear,
|
||||||
|
shortSparkMinYear,
|
||||||
|
visContainerID,
|
||||||
|
visualizationCode,
|
||||||
|
unknownYearCoauthors,
|
||||||
|
sparklineDisplayOptions);
|
||||||
|
} else {
|
||||||
|
generateFullSparklineVisualizationContent(currentYear,
|
||||||
|
minPubYearConsidered,
|
||||||
|
visContainerID,
|
||||||
|
visualizationCode,
|
||||||
|
unknownYearCoauthors,
|
||||||
|
renderedFullSparks,
|
||||||
|
sparklineDisplayOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(visualizationCode);
|
||||||
|
|
||||||
|
return visualizationCode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateShortSparklineVisualizationContent(int currentYear,
|
||||||
|
int shortSparkMinYear,
|
||||||
|
String visContainerID,
|
||||||
|
StringBuilder visualizationCode,
|
||||||
|
int unknownYearCoauthors,
|
||||||
|
String sparklineDisplayOptions) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a view of the data containing only the column pertaining to publication count.
|
||||||
|
* */
|
||||||
|
visualizationCode.append("var shortSparklineView = "
|
||||||
|
+ "new google.visualization.DataView(data);\n"
|
||||||
|
+ "shortSparklineView.setColumns([1]);\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the short view we only want the last 10 year's view of publication count,
|
||||||
|
* hence we filter the data we actually want to use for render.
|
||||||
|
* */
|
||||||
|
visualizationCode.append("shortSparklineView.setRows("
|
||||||
|
+ "data.getFilteredRows([{column: 0, "
|
||||||
|
+ "minValue: '" + shortSparkMinYear + "', "
|
||||||
|
+ "maxValue: '" + currentYear + "'}])"
|
||||||
|
+ ");\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the vis object and draw it in the div pertaining to short-sparkline.
|
||||||
|
* */
|
||||||
|
visualizationCode.append("var short_spark = new google.visualization.ImageSparkLine("
|
||||||
|
+ "providedSparklineImgTD[0]"
|
||||||
|
+ ");\n"
|
||||||
|
+ "short_spark.draw(shortSparklineView, "
|
||||||
|
+ sparklineDisplayOptions + ");\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We want to display how many publication counts were considered, so this is used
|
||||||
|
* to calculate this.
|
||||||
|
* */
|
||||||
|
visualizationCode.append("var shortSparkRows = shortSparklineView.getViewRows();\n"
|
||||||
|
+ "var renderedShortSparks = 0;\n"
|
||||||
|
+ "$.each(shortSparkRows, function(index, value) {"
|
||||||
|
+ "renderedShortSparks += data.getValue(value, 1);"
|
||||||
|
+ "});\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate the text introducing the vis.
|
||||||
|
* */
|
||||||
|
|
||||||
|
String imcompleteDataText = "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.";
|
||||||
|
|
||||||
|
|
||||||
|
visualizationCode.append("$('#" + VIS_DIV_NAMES.get("SHORT_SPARK")
|
||||||
|
+ " td.sparkline_number')" + ".text("
|
||||||
|
+ "parseInt(renderedShortSparks) + "
|
||||||
|
+ "parseInt(" + unknownYearCoauthors + "));");
|
||||||
|
|
||||||
|
visualizationCode.append("var shortSparksText = ''"
|
||||||
|
+ "+ ' co-author(s) within the last 10 years '"
|
||||||
|
+ "<span class=\"incomplete-data-holder\" title=\""
|
||||||
|
+ imcompleteDataText + "\">incomplete data</span>'"
|
||||||
|
+ "+ '';"
|
||||||
|
+ "$('#" + VIS_DIV_NAMES.get("SHORT_SPARK")
|
||||||
|
+ " td.sparkline_text').html(shortSparksText);");
|
||||||
|
|
||||||
|
visualizationCode.append("}\n ");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate the code that will activate the visualization. It takes care of creating div
|
||||||
|
* elements to hold the actual sparkline image and then calling the
|
||||||
|
* drawUniqueCoauthorCountVisualization function.
|
||||||
|
* */
|
||||||
|
visualizationCode.append(generateVisualizationActivator(VIS_DIV_NAMES.get("SHORT_SPARK"),
|
||||||
|
visContainerID));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateFullSparklineVisualizationContent(int currentYear,
|
||||||
|
int minPubYearConsidered,
|
||||||
|
String visContainerID,
|
||||||
|
StringBuilder visualizationCode,
|
||||||
|
int unknownYearCoauthors,
|
||||||
|
int renderedFullSparks,
|
||||||
|
String sparklineDisplayOptions) {
|
||||||
|
|
||||||
|
String csvDownloadURLHref = "";
|
||||||
|
|
||||||
|
if (getCSVDownloadURL() != null) {
|
||||||
|
csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL()
|
||||||
|
+ "\" class=\"inline_href\">(.CSV File)</a>";
|
||||||
|
} else {
|
||||||
|
csvDownloadURLHref = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
visualizationCode.append("var fullSparklineView = "
|
||||||
|
+ "new google.visualization.DataView(data);\n"
|
||||||
|
+ "fullSparklineView.setColumns([1]);\n");
|
||||||
|
|
||||||
|
visualizationCode.append("var full_spark = new google.visualization.ImageSparkLine("
|
||||||
|
+ "providedSparklineImgTD[0]"
|
||||||
|
+ ");\n"
|
||||||
|
+ "full_spark.draw(fullSparklineView, "
|
||||||
|
+ sparklineDisplayOptions + ");\n");
|
||||||
|
|
||||||
|
visualizationCode.append("$('#" + VIS_DIV_NAMES.get("FULL_SPARK")
|
||||||
|
+ " td.sparkline_number')"
|
||||||
|
+ ".text('" + (renderedFullSparks
|
||||||
|
+ unknownYearCoauthors) + "');");
|
||||||
|
|
||||||
|
visualizationCode.append("var allSparksText = ''"
|
||||||
|
+ "+ ' co-author(s) from '"
|
||||||
|
+ "+ ' <span class=\"sparkline_range\">"
|
||||||
|
+ "" + minPubYearConsidered + " to " + currentYear + ""
|
||||||
|
+ "</span> '"
|
||||||
|
+ "+ ' " + csvDownloadURLHref + " ';"
|
||||||
|
+ "$('#" + VIS_DIV_NAMES.get("FULL_SPARK")
|
||||||
|
+ " td.sparkline_text').html(allSparksText);");
|
||||||
|
|
||||||
|
visualizationCode.append("}\n ");
|
||||||
|
|
||||||
|
visualizationCode.append(generateVisualizationActivator(VIS_DIV_NAMES.get("FULL_SPARK"),
|
||||||
|
visContainerID));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateVisualizationActivator(String sparklineID, String visContainerID) {
|
||||||
|
|
||||||
|
String sparklineTableWrapper = "\n"
|
||||||
|
+ "var table = $('<table>');"
|
||||||
|
+ "table.attr('class', 'sparkline_wrapper_table');"
|
||||||
|
+ "var row = $('<tr>');"
|
||||||
|
+ "sparklineImgTD = $('<td>');"
|
||||||
|
+ "sparklineImgTD.attr('id', '" + sparklineID + "_img');"
|
||||||
|
+ "sparklineImgTD.attr('width', '65');"
|
||||||
|
+ "sparklineImgTD.attr('align', 'right');"
|
||||||
|
+ "sparklineImgTD.attr('class', '" + VISUALIZATION_STYLE_CLASS + "');"
|
||||||
|
+ "row.append(sparklineImgTD);"
|
||||||
|
+ "var sparklineNumberTD = $('<td>');"
|
||||||
|
+ "sparklineNumberTD.attr('width', '30');"
|
||||||
|
+ "sparklineNumberTD.attr('align', 'right');"
|
||||||
|
+ "sparklineNumberTD.attr('class', 'sparkline_number');"
|
||||||
|
+ "row.append(sparklineNumberTD);"
|
||||||
|
+ "var sparklineTextTD = $('<td>');"
|
||||||
|
+ "sparklineTextTD.attr('width', '350');"
|
||||||
|
+ "sparklineTextTD.attr('class', 'sparkline_text');"
|
||||||
|
+ "row.append(sparklineTextTD);"
|
||||||
|
+ "table.append(row);"
|
||||||
|
+ "table.prependTo('#" + sparklineID + "');\n";
|
||||||
|
|
||||||
|
return "$(document).ready(function() {"
|
||||||
|
+ "var sparklineImgTD; "
|
||||||
|
/*
|
||||||
|
* This is a nuclear option (creating the container in which everything goes)
|
||||||
|
* the only reason this will be ever used is the API user never submitted a
|
||||||
|
* container ID in which everything goes. The alternative was to let the
|
||||||
|
* vis not appear in the calling page at all. So now atleast vis appears but
|
||||||
|
* appended at the bottom of the body.
|
||||||
|
* */
|
||||||
|
+ "if ($('#" + visContainerID + "').length === 0) {"
|
||||||
|
+ " $('<div/>', {'id': '" + visContainerID + "'"
|
||||||
|
+ " }).appendTo('body');"
|
||||||
|
+ "}"
|
||||||
|
+ "if ($('#" + sparklineID + "').length === 0) {"
|
||||||
|
+ "$('<div/>', {'id': '" + sparklineID + "',"
|
||||||
|
+ "'class': '" + VISUALIZATION_STYLE_CLASS + "'"
|
||||||
|
+ "}).prependTo('#" + visContainerID + "');"
|
||||||
|
+ sparklineTableWrapper
|
||||||
|
+ "}"
|
||||||
|
+ "drawUniqueCoauthorCountVisualization(sparklineImgTD);"
|
||||||
|
+ "});"
|
||||||
|
+ "</script>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getVisualizationContextCode(String visMode) {
|
||||||
|
|
||||||
|
String visualizationContextCode = "";
|
||||||
|
if (VisualizationFrameworkConstants.SHORT_SPARKLINE_VIS_MODE.equalsIgnoreCase(visMode)) {
|
||||||
|
visualizationContextCode = generateShortVisContext();
|
||||||
|
} else {
|
||||||
|
visualizationContextCode = generateFullVisContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(visualizationContextCode);
|
||||||
|
|
||||||
|
return visualizationContextCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateFullVisContext() {
|
||||||
|
|
||||||
|
StringBuilder divContextCode = new StringBuilder();
|
||||||
|
|
||||||
|
String csvDownloadURLHref = "";
|
||||||
|
|
||||||
|
if (yearToUniqueCoauthors.size() > 0) {
|
||||||
|
|
||||||
|
if (getCSVDownloadURL() != null) {
|
||||||
|
|
||||||
|
csvDownloadURLHref = "Download data as <a href='"
|
||||||
|
+ getCSVDownloadURL() + "'>.csv</a> file.<br />";
|
||||||
|
sparklineData.setDownloadDataLink(getCSVDownloadURL());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
csvDownloadURLHref = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
csvDownloadURLHref = "No data available to export.<br />";
|
||||||
|
}
|
||||||
|
|
||||||
|
String tableCode = generateDataTable();
|
||||||
|
|
||||||
|
divContextCode.append("<p>" + tableCode + csvDownloadURLHref + "</p>");
|
||||||
|
|
||||||
|
sparklineData.setTable(tableCode);
|
||||||
|
|
||||||
|
return divContextCode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCSVDownloadURL(){
|
||||||
|
|
||||||
|
if (yearToUniqueCoauthors.size() > 0) {
|
||||||
|
|
||||||
|
ParamMap CSVDownloadURLParams = new ParamMap(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY,
|
||||||
|
individualURI,
|
||||||
|
VisualizationFrameworkConstants.VIS_TYPE_KEY,
|
||||||
|
VisualizationFrameworkConstants.COAUTHORSHIP_VIS,
|
||||||
|
VisualizationFrameworkConstants.VIS_MODE_KEY,
|
||||||
|
VisualizationFrameworkConstants.SPARKLINE_VIS_MODE);
|
||||||
|
|
||||||
|
return UrlBuilder.getUrl(VisualizationFrameworkConstants.DATA_VISUALIZATION_SERVICE_URL_PREFIX,
|
||||||
|
CSVDownloadURLParams);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateShortVisContext() {
|
||||||
|
|
||||||
|
StringBuilder divContextCode = new StringBuilder();
|
||||||
|
|
||||||
|
String fullTimelineLink;
|
||||||
|
if (yearToUniqueCoauthors.size() > 0) {
|
||||||
|
|
||||||
|
ParamMap fullTimelineNetworkURLParams = new ParamMap(
|
||||||
|
VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY,
|
||||||
|
individualURI,
|
||||||
|
VisualizationFrameworkConstants.VIS_TYPE_KEY,
|
||||||
|
VisualizationFrameworkConstants.PERSON_LEVEL_VIS,
|
||||||
|
VisualizationFrameworkConstants.VIS_CONTAINER_KEY,
|
||||||
|
"ego_sparkline");
|
||||||
|
|
||||||
|
String fullTimelineNetworkURL = UrlBuilder.getUrl(
|
||||||
|
VisualizationFrameworkConstants.FREEMARKERIZED_VISUALIZATION_URL_PREFIX,
|
||||||
|
fullTimelineNetworkURLParams);
|
||||||
|
|
||||||
|
fullTimelineLink = "<a href='" + fullTimelineNetworkURL
|
||||||
|
+ "'>View full timeline and co-author network.</a>";
|
||||||
|
|
||||||
|
sparklineData.setFullTimelineNetworkLink(fullTimelineNetworkURL);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fullTimelineLink = "No data available to render full timeline.<br />";
|
||||||
|
}
|
||||||
|
|
||||||
|
divContextCode.append("<p>" + fullTimelineLink + "</p>");
|
||||||
|
|
||||||
|
return divContextCode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String generateDataTable() {
|
||||||
|
|
||||||
|
StringBuilder dataTable = new StringBuilder();
|
||||||
|
|
||||||
|
dataTable.append("<table id='sparkline_data_table'>"
|
||||||
|
+ "<caption>Unique Co-Authors per year</caption>"
|
||||||
|
+ "<thead>"
|
||||||
|
+ "<tr>"
|
||||||
|
+ "<th>Year</th>"
|
||||||
|
+ "<th>Count</th>"
|
||||||
|
+ "</tr>"
|
||||||
|
+ "</thead>"
|
||||||
|
+ "<tbody>");
|
||||||
|
|
||||||
|
for (Entry<String, Set<Node>> currentEntry : yearToUniqueCoauthors.entrySet()) {
|
||||||
|
dataTable.append("<tr>"
|
||||||
|
+ "<td>" + currentEntry.getKey() + "</td>"
|
||||||
|
+ "<td>" + currentEntry.getValue().size() + "</td>"
|
||||||
|
+ "</tr>");
|
||||||
|
}
|
||||||
|
|
||||||
|
dataTable.append("</tbody>\n </table>\n");
|
||||||
|
|
||||||
|
return dataTable.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SparklineData getValueObjectContainer() {
|
||||||
|
return sparklineData;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.coauthorship;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Edge;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Comparator is used to sort the edges based on their IDs in ascending order.
|
||||||
|
* @author cdtank
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class EdgeComparator implements Comparator<Edge> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(Edge arg0, Edge arg1) {
|
||||||
|
return arg0.getEdgeID() - arg1.getEdgeID();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.freemarker.coauthorship;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Node;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Comparator is used to sort the nodes based on their IDs in ascending order.
|
||||||
|
* @author cdtank
|
||||||
|
*/
|
||||||
|
public class NodeComparator implements Comparator<Node> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(Node arg0, Node arg1) {
|
||||||
|
return arg0.getNodeID() - arg1.getNodeID();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,20 +24,17 @@ import com.itextpdf.text.pdf.PdfWriter;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
|
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.FileResponseValues;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Grant;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Grant;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Individual;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Individual;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.SparklineData;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.SparklineData;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument;
|
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
|
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
|
||||||
import edu.cornell.mannlib.vitro.webapp.web.ContentType;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,9 +86,12 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
|
||||||
if (VisualizationFrameworkConstants.DATA_RENDER_MODE
|
if (VisualizationFrameworkConstants.DATA_RENDER_MODE
|
||||||
.equalsIgnoreCase(renderMode)) {
|
.equalsIgnoreCase(renderMode)) {
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
return prepareDataResponse(investigator,
|
return prepareDataResponse(investigator,
|
||||||
piGrants,
|
piGrants,
|
||||||
yearToGrantCount);
|
yearToGrantCount);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -173,7 +173,7 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
|
||||||
* @param yearToGrantCount
|
* @param yearToGrantCount
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private FileResponseValues prepareDataResponse(
|
private Map<String, String> prepareDataResponse(
|
||||||
Individual investigator,
|
Individual investigator,
|
||||||
Set<Grant> piGrants,
|
Set<Grant> piGrants,
|
||||||
Map<String, Integer> yearToGrantCount) {
|
Map<String, Integer> yearToGrantCount) {
|
||||||
|
@ -203,7 +203,9 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
|
||||||
Map<String, Object> fileContents = new HashMap<String, Object>();
|
Map<String, Object> fileContents = new HashMap<String, Object>();
|
||||||
fileContents.put("fileContent", getGrantsOverTimeCSVContent(yearToGrantCount));
|
fileContents.put("fileContent", getGrantsOverTimeCSVContent(yearToGrantCount));
|
||||||
|
|
||||||
return new FileResponseValues(new ContentType(), outputFileName, fileContents);
|
// return new FileResponseValues(new ContentType(), outputFileName, fileContents);
|
||||||
|
|
||||||
|
return new HashMap<String, String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -329,47 +331,27 @@ public class PersonGrantCountRequestHandler implements VisualizationRequestHandl
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateAjaxVisualization(VitroRequest vitroRequest, Log log,
|
||||||
|
DataSource dataSource) throws MalformedQueryParametersException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> generateDataVisualization(
|
||||||
|
VitroRequest vitroRequest, Log log, DataSource dataSource)
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseValues generateStandardVisualization(
|
||||||
|
VitroRequest vitroRequest, Log log, DataSource dataSource)
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.VisualizationController;
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.StandardVisualizationController;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
||||||
|
@ -547,18 +547,18 @@ public class PersonGrantCountVisCodeGenerator {
|
||||||
+ secondaryContextPath
|
+ secondaryContextPath
|
||||||
+ "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
|
+ "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
|
||||||
+ "=" + URLEncoder.encode(individualURI,
|
+ "=" + URLEncoder.encode(individualURI,
|
||||||
VisualizationController.URL_ENCODING_SCHEME)
|
StandardVisualizationController.URL_ENCODING_SCHEME)
|
||||||
.toString()
|
.toString()
|
||||||
+ "&" + VisualizationFrameworkConstants.VIS_TYPE_KEY
|
+ "&" + VisualizationFrameworkConstants.VIS_TYPE_KEY
|
||||||
+ "=" + URLEncoder.encode(
|
+ "=" + URLEncoder.encode(
|
||||||
VisualizationFrameworkConstants
|
VisualizationFrameworkConstants
|
||||||
.PERSON_GRANT_COUNT_VIS,
|
.PERSON_GRANT_COUNT_VIS,
|
||||||
VisualizationController.URL_ENCODING_SCHEME)
|
StandardVisualizationController.URL_ENCODING_SCHEME)
|
||||||
.toString()
|
.toString()
|
||||||
+ "&" + VisualizationFrameworkConstants.RENDER_MODE_KEY
|
+ "&" + VisualizationFrameworkConstants.RENDER_MODE_KEY
|
||||||
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
|
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
|
||||||
.DATA_RENDER_MODE,
|
.DATA_RENDER_MODE,
|
||||||
VisualizationController.URL_ENCODING_SCHEME)
|
StandardVisualizationController.URL_ENCODING_SCHEME)
|
||||||
.toString();
|
.toString();
|
||||||
return downloadURL;
|
return downloadURL;
|
||||||
} else {
|
} else {
|
||||||
|
@ -586,16 +586,16 @@ public class PersonGrantCountVisCodeGenerator {
|
||||||
+ "?"
|
+ "?"
|
||||||
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
|
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
|
||||||
+ "=" + URLEncoder.encode(individualURI,
|
+ "=" + URLEncoder.encode(individualURI,
|
||||||
VisualizationController.URL_ENCODING_SCHEME).toString()
|
StandardVisualizationController.URL_ENCODING_SCHEME).toString()
|
||||||
+ "&"
|
+ "&"
|
||||||
+ VisualizationFrameworkConstants.VIS_TYPE_KEY
|
+ VisualizationFrameworkConstants.VIS_TYPE_KEY
|
||||||
+ "=" + URLEncoder.encode("person_level",
|
+ "=" + URLEncoder.encode("person_level",
|
||||||
VisualizationController.URL_ENCODING_SCHEME).toString()
|
StandardVisualizationController.URL_ENCODING_SCHEME).toString()
|
||||||
+ "&"
|
+ "&"
|
||||||
+ VisualizationFrameworkConstants.RENDER_MODE_KEY
|
+ VisualizationFrameworkConstants.RENDER_MODE_KEY
|
||||||
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
|
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
|
||||||
.STANDALONE_RENDER_MODE,
|
.STANDALONE_RENDER_MODE,
|
||||||
VisualizationController.URL_ENCODING_SCHEME).toString();
|
StandardVisualizationController.URL_ENCODING_SCHEME).toString();
|
||||||
|
|
||||||
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View all VIVO "
|
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View all VIVO "
|
||||||
+ "grants and corresponding co-pi network.</a>";
|
+ "grants and corresponding co-pi network.</a>";
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import javax.servlet.RequestDispatcher;
|
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@ -24,145 +23,176 @@ import com.itextpdf.text.pdf.PdfWriter;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
|
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.FileResponseValues;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.DataVisualizationController;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.BiboDocument;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.BiboDocument;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Individual;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.Individual;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.SparklineData;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.valueobjects.SparklineData;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument;
|
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.PDFDocument;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
|
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.QueryRunner;
|
||||||
import edu.cornell.mannlib.vitro.webapp.web.ContentType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* This request handler is used to serve the content related to an individual's
|
* This request handler is used to serve the content related to an individual's
|
||||||
* publications over the years like,
|
* publications over the years like, 1. Sprakline representing this 2. An entire
|
||||||
* 1. Sprakline representing this
|
* page dedicated to the sparkline vis which will also have links to download
|
||||||
* 2. An entire page dedicated to the sparkline vis which will also have links to
|
* the data using which the sparkline was rendered & its tabular representation
|
||||||
* download the data using which the sparkline was rendered & its tabular representation etc.
|
* etc. 3. Downloadable CSV file containing number of publications over the
|
||||||
* 3. Downloadable CSV file containing number of publications over the years.
|
* years. 4. Downloadable PDf file containing the publications content, among
|
||||||
* 4. Downloadable PDf file containing the publications content, among other things.
|
* other things. Currently this is disabled because the feature is half-baked.
|
||||||
* Currently this is disabled because the feature is half-baked. We plan to activate this in
|
* We plan to activate this in the next major release.
|
||||||
* the next major release.
|
|
||||||
*
|
*
|
||||||
* @author cdtank
|
* @author cdtank
|
||||||
*/
|
*/
|
||||||
public class PersonPublicationCountRequestHandler implements VisualizationRequestHandler {
|
public class PersonPublicationCountRequestHandler implements
|
||||||
|
VisualizationRequestHandler {
|
||||||
public ResponseValues generateVisualization(VitroRequest vitroRequest,
|
|
||||||
Log log,
|
|
||||||
DataSource dataSource) {
|
|
||||||
|
|
||||||
String peronURI = vitroRequest.getParameter(
|
|
||||||
VisualizationFrameworkConstants
|
|
||||||
.INDIVIDUAL_URI_KEY);
|
|
||||||
|
|
||||||
String renderMode = vitroRequest.getParameter(
|
@Override
|
||||||
VisualizationFrameworkConstants
|
public Object generateAjaxVisualization(VitroRequest vitroRequest, Log log,
|
||||||
.RENDER_MODE_KEY);
|
DataSource dataSource) throws MalformedQueryParametersException {
|
||||||
|
|
||||||
String visMode = vitroRequest.getParameter(
|
|
||||||
VisualizationFrameworkConstants
|
|
||||||
.VIS_MODE_KEY);
|
|
||||||
|
|
||||||
String visContainer = vitroRequest.getParameter(
|
String personURI = vitroRequest
|
||||||
VisualizationFrameworkConstants
|
.getParameter(
|
||||||
.VIS_CONTAINER_KEY);
|
VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
|
||||||
|
|
||||||
QueryRunner<Set<BiboDocument>> queryManager =
|
String visMode = vitroRequest
|
||||||
new PersonPublicationCountQueryRunner(peronURI, dataSource, log);
|
.getParameter(
|
||||||
|
VisualizationFrameworkConstants.VIS_MODE_KEY);
|
||||||
|
|
||||||
try {
|
String visContainer = vitroRequest
|
||||||
Set<BiboDocument> authorDocuments = queryManager.getQueryResult();
|
.getParameter(
|
||||||
|
VisualizationFrameworkConstants.VIS_CONTAINER_KEY);
|
||||||
|
|
||||||
/*
|
QueryRunner<Set<BiboDocument>> queryManager = new PersonPublicationCountQueryRunner(
|
||||||
* Create a map from the year to number of publications. Use the BiboDocument's
|
personURI,
|
||||||
* parsedPublicationYear to populate the data.
|
dataSource,
|
||||||
* */
|
log);
|
||||||
Map<String, Integer> yearToPublicationCount =
|
|
||||||
UtilityFunctions.getYearToPublicationCount(authorDocuments);
|
|
||||||
|
|
||||||
Individual author = ((PersonPublicationCountQueryRunner) queryManager).getAuthor();
|
|
||||||
|
|
||||||
if (VisualizationFrameworkConstants.DATA_RENDER_MODE
|
Set<BiboDocument> authorDocuments = queryManager.getQueryResult();
|
||||||
.equalsIgnoreCase(renderMode)) {
|
|
||||||
|
|
||||||
return prepareDataResponse(author,
|
|
||||||
authorDocuments,
|
|
||||||
yearToPublicationCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For now we are disabling the capability to render pdf file.
|
|
||||||
* */
|
|
||||||
/*
|
|
||||||
if (VisualizationFrameworkConstants.PDF_RENDER_MODE
|
|
||||||
.equalsIgnoreCase(renderMode)) {
|
|
||||||
|
|
||||||
preparePDFResponse(author,
|
|
||||||
authorDocuments,
|
|
||||||
yearToPublicationCount,
|
|
||||||
response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Computations required to generate HTML for the sparkline & related context.
|
|
||||||
* */
|
|
||||||
PersonPublicationCountVisCodeGenerator visualizationCodeGenerator =
|
|
||||||
new PersonPublicationCountVisCodeGenerator(vitroRequest.getContextPath(),
|
|
||||||
peronURI,
|
|
||||||
visMode,
|
|
||||||
visContainer,
|
|
||||||
authorDocuments,
|
|
||||||
yearToPublicationCount,
|
|
||||||
log);
|
|
||||||
|
|
||||||
SparklineData sparklineData = visualizationCodeGenerator
|
|
||||||
.getValueObjectContainer();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
.equalsIgnoreCase(renderMode)) {
|
|
||||||
|
|
||||||
return prepareDynamicResponse(vitroRequest,
|
/*
|
||||||
sparklineData,
|
* Create a map from the year to number of publications. Use the
|
||||||
yearToPublicationCount);
|
* BiboDocument's parsedPublicationYear to populate the data.
|
||||||
|
*/
|
||||||
} else {
|
Map<String, Integer> yearToPublicationCount =
|
||||||
return prepareStandaloneResponse(vitroRequest,
|
UtilityFunctions.getYearToPublicationCount(authorDocuments);
|
||||||
sparklineData);
|
|
||||||
}
|
boolean shouldVIVOrenderVis =
|
||||||
|
yearToPublicationCount.size() > 0 ? true : false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Computations required to generate HTML for the sparkline & related
|
||||||
|
* context.
|
||||||
|
*/
|
||||||
|
PersonPublicationCountVisCodeGenerator visualizationCodeGenerator =
|
||||||
|
new PersonPublicationCountVisCodeGenerator(
|
||||||
|
personURI,
|
||||||
|
visMode,
|
||||||
|
visContainer,
|
||||||
|
authorDocuments,
|
||||||
|
yearToPublicationCount,
|
||||||
|
log);
|
||||||
|
|
||||||
|
SparklineData sparklineData = visualizationCodeGenerator
|
||||||
|
.getValueObjectContainer();
|
||||||
|
|
||||||
|
return prepareDynamicResponse(vitroRequest, sparklineData,
|
||||||
|
shouldVIVOrenderVis);
|
||||||
|
|
||||||
} catch (MalformedQueryParametersException e) {
|
|
||||||
return UtilityFunctions.handleMalformedParameters(
|
|
||||||
"Visualization Query Error - Individual Publication Count",
|
|
||||||
e.getMessage(),
|
|
||||||
vitroRequest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPublicationsOverTimeCSVContent(Map<String, Integer> yearToPublicationCount) {
|
@Override
|
||||||
|
public Map<String, String> generateDataVisualization(VitroRequest vitroRequest, Log log,
|
||||||
|
DataSource dataSource) throws MalformedQueryParametersException {
|
||||||
|
|
||||||
|
String personURI = vitroRequest
|
||||||
|
.getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
|
||||||
|
|
||||||
|
QueryRunner<Set<BiboDocument>> queryManager = new PersonPublicationCountQueryRunner(
|
||||||
|
personURI,
|
||||||
|
dataSource,
|
||||||
|
log);
|
||||||
|
|
||||||
|
Set<BiboDocument> authorDocuments = queryManager.getQueryResult();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a map from the year to number of publications. Use the
|
||||||
|
* BiboDocument's parsedPublicationYear to populate the data.
|
||||||
|
*/
|
||||||
|
Map<String, Integer> yearToPublicationCount =
|
||||||
|
UtilityFunctions.getYearToPublicationCount(authorDocuments);
|
||||||
|
|
||||||
|
Individual author = ((PersonPublicationCountQueryRunner) queryManager).getAuthor();
|
||||||
|
|
||||||
|
return prepareDataResponse(author,
|
||||||
|
authorDocuments,
|
||||||
|
yearToPublicationCount);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseValues generateStandardVisualization(
|
||||||
|
VitroRequest vitroRequest, Log log, DataSource dataSource)
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
|
||||||
|
String personURI = vitroRequest.getParameter(
|
||||||
|
VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
|
||||||
|
|
||||||
|
String visMode = vitroRequest.getParameter(
|
||||||
|
VisualizationFrameworkConstants.VIS_MODE_KEY);
|
||||||
|
|
||||||
|
String visContainer = vitroRequest.getParameter(
|
||||||
|
VisualizationFrameworkConstants.VIS_CONTAINER_KEY);
|
||||||
|
|
||||||
|
QueryRunner<Set<BiboDocument>> queryManager = new PersonPublicationCountQueryRunner(
|
||||||
|
personURI,
|
||||||
|
dataSource,
|
||||||
|
log);
|
||||||
|
|
||||||
|
Set<BiboDocument> authorDocuments = queryManager.getQueryResult();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a map from the year to number of publications. Use the
|
||||||
|
* BiboDocument's parsedPublicationYear to populate the data.
|
||||||
|
*/
|
||||||
|
Map<String, Integer> yearToPublicationCount =
|
||||||
|
UtilityFunctions.getYearToPublicationCount(authorDocuments);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Computations required to generate HTML for the sparkline & related
|
||||||
|
* context.
|
||||||
|
*/
|
||||||
|
PersonPublicationCountVisCodeGenerator visualizationCodeGenerator =
|
||||||
|
new PersonPublicationCountVisCodeGenerator(
|
||||||
|
personURI,
|
||||||
|
visMode,
|
||||||
|
visContainer,
|
||||||
|
authorDocuments,
|
||||||
|
yearToPublicationCount,
|
||||||
|
log);
|
||||||
|
|
||||||
|
SparklineData sparklineData =
|
||||||
|
visualizationCodeGenerator.getValueObjectContainer();
|
||||||
|
|
||||||
|
return prepareStandaloneResponse(vitroRequest, sparklineData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPublicationsOverTimeCSVContent(
|
||||||
|
Map<String, Integer> yearToPublicationCount) {
|
||||||
|
|
||||||
StringBuilder csvFileContent = new StringBuilder();
|
StringBuilder csvFileContent = new StringBuilder();
|
||||||
|
|
||||||
csvFileContent.append("Year, Publications\n");
|
csvFileContent.append("Year, Publications\n");
|
||||||
|
|
||||||
for (Entry<String, Integer> currentEntry : yearToPublicationCount.entrySet()) {
|
for (Entry<String, Integer> currentEntry : yearToPublicationCount
|
||||||
csvFileContent.append(StringEscapeUtils.escapeCsv(currentEntry.getKey()));
|
.entrySet()) {
|
||||||
|
csvFileContent.append(StringEscapeUtils.escapeCsv(currentEntry
|
||||||
|
.getKey()));
|
||||||
csvFileContent.append(",");
|
csvFileContent.append(",");
|
||||||
csvFileContent.append(currentEntry.getValue());
|
csvFileContent.append(currentEntry.getValue());
|
||||||
csvFileContent.append("\n");
|
csvFileContent.append("\n");
|
||||||
|
@ -172,169 +202,156 @@ public class PersonPublicationCountRequestHandler implements VisualizationReques
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides response when csv file containing the publication count over the years
|
* Provides response when csv file containing the publication count over the
|
||||||
* is requested.
|
* years is requested.
|
||||||
|
*
|
||||||
* @param author
|
* @param author
|
||||||
* @param authorDocuments
|
* @param authorDocuments
|
||||||
* @param yearToPublicationCount
|
* @param yearToPublicationCount
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private FileResponseValues prepareDataResponse(
|
private Map<String, String> prepareDataResponse(Individual author,
|
||||||
Individual author,
|
Set<BiboDocument> authorDocuments,
|
||||||
Set<BiboDocument> authorDocuments,
|
Map<String, Integer> yearToPublicationCount) {
|
||||||
Map<String, Integer> 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 (StringUtils.isBlank(authorName)) {
|
|
||||||
authorName = "no-author";
|
|
||||||
}
|
|
||||||
|
|
||||||
String outputFileName = UtilityFunctions.slugify(authorName)
|
|
||||||
+ "_publications-per-year" + ".csv";
|
|
||||||
|
|
||||||
|
String authorName = null;
|
||||||
Map<String, Object> fileContents = new HashMap<String, Object>();
|
|
||||||
fileContents.put("fileContent", getPublicationsOverTimeCSVContent(yearToPublicationCount));
|
/*
|
||||||
|
* To protect against cases where there are no author documents
|
||||||
return new FileResponseValues(new ContentType(), outputFileName, fileContents);
|
* associated with the individual.
|
||||||
|
*/
|
||||||
|
if (authorDocuments.size() > 0) {
|
||||||
|
authorName = author.getIndividualLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To make sure that null/empty records for author names do not cause
|
||||||
|
* any mischief.
|
||||||
|
*/
|
||||||
|
if (StringUtils.isBlank(authorName)) {
|
||||||
|
authorName = "no-author";
|
||||||
|
}
|
||||||
|
|
||||||
|
String outputFileName = UtilityFunctions.slugify(authorName)
|
||||||
|
+ "_publications-per-year" + ".csv";
|
||||||
|
|
||||||
|
Map<String, String> fileData = new HashMap<String, String>();
|
||||||
|
fileData.put(DataVisualizationController.FILE_NAME_KEY,
|
||||||
|
outputFileName);
|
||||||
|
fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
|
||||||
|
"application/octet-stream");
|
||||||
|
fileData.put(DataVisualizationController.FILE_CONTENT_KEY,
|
||||||
|
getPublicationsOverTimeCSVContent(yearToPublicationCount));
|
||||||
|
|
||||||
|
return fileData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides response when an entire page dedicated to publication sparkline is requested.
|
* Provides response when an entire page dedicated to publication sparkline
|
||||||
|
* is requested.
|
||||||
|
*
|
||||||
* @param vreq
|
* @param vreq
|
||||||
* @param valueObjectContainer
|
* @param valueObjectContainer
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private TemplateResponseValues prepareStandaloneResponse(VitroRequest vreq,
|
private TemplateResponseValues prepareStandaloneResponse(VitroRequest vreq,
|
||||||
SparklineData valueObjectContainer) {
|
SparklineData valueObjectContainer) {
|
||||||
|
|
||||||
Portal portal = vreq.getPortal();
|
Portal portal = vreq.getPortal();
|
||||||
|
|
||||||
String standaloneTemplate = "/visualization/publicationCount.ftl";
|
|
||||||
|
|
||||||
Map<String, Object> body = new HashMap<String, Object>();
|
String standaloneTemplate = "/visualization/publicationCount.ftl";
|
||||||
body.put("portalBean", portal);
|
|
||||||
body.put("title", "Individual Publication Count visualization");
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
body.put("sparklineVO", valueObjectContainer);
|
body.put("portalBean", portal);
|
||||||
|
body.put("title", "Individual Publication Count visualization");
|
||||||
|
body.put("sparklineVO", valueObjectContainer);
|
||||||
|
|
||||||
|
return new TemplateResponseValues(standaloneTemplate, body);
|
||||||
|
|
||||||
/*
|
|
||||||
* DO NOT DO THIS HERE. Set stylesheets/scripts in the *.ftl instead using $(scripts.add)
|
|
||||||
* */
|
|
||||||
// body.put("scripts", "/templates/visualization/visualization_scripts.jsp");
|
|
||||||
|
|
||||||
return new TemplateResponseValues(standaloneTemplate, body);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides response when the publication sparkline has to be rendered in already existing
|
* Provides response when the publication sparkline has to be rendered in
|
||||||
* page, e.g. profile page.
|
* already existing page, e.g. profile page.
|
||||||
|
*
|
||||||
* @param vreq
|
* @param vreq
|
||||||
* @param valueObjectContainer
|
* @param valueObjectContainer
|
||||||
* @param yearToPublicationCount
|
* @param yearToPublicationCount
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private TemplateResponseValues prepareDynamicResponse(
|
private TemplateResponseValues prepareDynamicResponse(VitroRequest vreq,
|
||||||
VitroRequest vreq,
|
SparklineData valueObjectContainer, boolean shouldVIVOrenderVis) {
|
||||||
SparklineData valueObjectContainer,
|
|
||||||
Map<String, Integer> yearToPublicationCount) {
|
|
||||||
|
|
||||||
Portal portal = vreq.getPortal();
|
Portal portal = vreq.getPortal();
|
||||||
|
|
||||||
|
String dynamicTemplate = "/visualization/sparklineAjaxVisContent.ftl";
|
||||||
|
|
||||||
String dynamicTemplate = "/visualization/sparklineAjaxVisContent.ftl";
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
body.put("portalBean", portal);
|
||||||
|
body.put("sparklineVO", valueObjectContainer);
|
||||||
|
body.put("shouldVIVOrenderVis", shouldVIVOrenderVis);
|
||||||
|
|
||||||
Map<String, Object> body = new HashMap<String, Object>();
|
return new TemplateResponseValues(dynamicTemplate, body);
|
||||||
body.put("portalBean", portal);
|
|
||||||
body.put("sparklineVO", valueObjectContainer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DO NOT DO THIS HERE. Set stylesheets/scripts in the *.ftl instead using $(scripts.add)
|
|
||||||
* */
|
|
||||||
// body.put("scripts", "/templates/visualization/visualization_scripts.jsp");
|
|
||||||
|
|
||||||
if (yearToPublicationCount.size() > 0) {
|
|
||||||
body.put("shouldVIVOrenderVis", true);
|
|
||||||
} else {
|
|
||||||
body.put("shouldVIVOrenderVis", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TemplateResponseValues(dynamicTemplate, body);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preparePDFResponse(
|
private void preparePDFResponse(Individual author,
|
||||||
Individual author,
|
Set<BiboDocument> authorDocuments,
|
||||||
Set<BiboDocument> authorDocuments,
|
Map<String, Integer> yearToPublicationCount,
|
||||||
Map<String, Integer> yearToPublicationCount,
|
HttpServletResponse response) {
|
||||||
HttpServletResponse response) {
|
|
||||||
|
String authorName = null;
|
||||||
String authorName = null;
|
|
||||||
|
// To protect against cases where there are no author documents
|
||||||
// To protect against cases where there are no author documents associated with the
|
// associated with the
|
||||||
// / individual.
|
// / individual.
|
||||||
if (authorDocuments.size() > 0) {
|
if (authorDocuments.size() > 0) {
|
||||||
authorName = author.getIndividualLabel();
|
authorName = author.getIndividualLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
//To make sure that null/empty records for author names do not cause any mischief.
|
// To make sure that null/empty records for author names do not cause
|
||||||
|
// any mischief.
|
||||||
if (StringUtils.isBlank(authorName)) {
|
if (StringUtils.isBlank(authorName)) {
|
||||||
authorName = "no-author";
|
authorName = "no-author";
|
||||||
}
|
}
|
||||||
|
|
||||||
String outputFileName = UtilityFunctions.slugify(authorName) + "_report" + ".pdf";
|
String outputFileName = UtilityFunctions.slugify(authorName)
|
||||||
|
+ "_report" + ".pdf";
|
||||||
|
|
||||||
response.setContentType("application/pdf");
|
response.setContentType("application/pdf");
|
||||||
response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName);
|
response.setHeader("Content-Disposition", "attachment;filename="
|
||||||
|
+ outputFileName);
|
||||||
ServletOutputStream responseOutputStream;
|
|
||||||
try {
|
ServletOutputStream responseOutputStream;
|
||||||
responseOutputStream = response.getOutputStream();
|
try {
|
||||||
|
responseOutputStream = response.getOutputStream();
|
||||||
|
|
||||||
Document document = new Document();
|
Document document = new Document();
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
|
PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
|
||||||
document.open();
|
document.open();
|
||||||
|
|
||||||
PDFDocument pdfDocument = new PDFDocument(authorName,
|
PDFDocument pdfDocument = new PDFDocument(authorName,
|
||||||
yearToPublicationCount,
|
yearToPublicationCount, document, pdfWriter);
|
||||||
document,
|
|
||||||
pdfWriter);
|
document.close();
|
||||||
|
|
||||||
document.close();
|
// setting some response headers & content type
|
||||||
|
response.setHeader("Expires", "0");
|
||||||
// setting some response headers & content type
|
response.setHeader("Cache-Control",
|
||||||
response.setHeader("Expires", "0");
|
"must-revalidate, post-check=0, pre-check=0");
|
||||||
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
|
response.setHeader("Pragma", "public");
|
||||||
response.setHeader("Pragma", "public");
|
response.setContentLength(baos.size());
|
||||||
response.setContentLength(baos.size());
|
// write ByteArrayOutputStream to the ServletOutputStream
|
||||||
// write ByteArrayOutputStream to the ServletOutputStream
|
baos.writeTo(responseOutputStream);
|
||||||
baos.writeTo(responseOutputStream);
|
responseOutputStream.flush();
|
||||||
responseOutputStream.flush();
|
responseOutputStream.close();
|
||||||
responseOutputStream.close();
|
|
||||||
|
} catch (IOException e) {
|
||||||
} catch (IOException e) {
|
e.printStackTrace();
|
||||||
e.printStackTrace();
|
} catch (DocumentException e) {
|
||||||
} catch (DocumentException e) {
|
e.printStackTrace();
|
||||||
e.printStackTrace();
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.personpubcount;
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.personpubcount;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -17,7 +15,8 @@ import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.VisualizationController;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
|
||||||
|
@ -55,19 +54,15 @@ public class PersonPublicationCountVisCodeGenerator {
|
||||||
|
|
||||||
private SparklineData sparklineData;
|
private SparklineData sparklineData;
|
||||||
|
|
||||||
private String contextPath;
|
|
||||||
|
|
||||||
private String individualURI;
|
private String individualURI;
|
||||||
|
|
||||||
public PersonPublicationCountVisCodeGenerator(String contextPath,
|
public PersonPublicationCountVisCodeGenerator(String individualURIParam,
|
||||||
String individualURIParam,
|
|
||||||
String visMode,
|
String visMode,
|
||||||
String visContainer,
|
String visContainer,
|
||||||
Set<BiboDocument> authorDocuments,
|
Set<BiboDocument> authorDocuments,
|
||||||
Map<String, Integer> yearToPublicationCount,
|
Map<String, Integer> yearToPublicationCount,
|
||||||
Log log) {
|
Log log) {
|
||||||
|
|
||||||
this.contextPath = contextPath;
|
|
||||||
this.individualURI = individualURIParam;
|
this.individualURI = individualURIParam;
|
||||||
|
|
||||||
this.yearToPublicationCount = yearToPublicationCount;
|
this.yearToPublicationCount = yearToPublicationCount;
|
||||||
|
@ -407,17 +402,12 @@ public class PersonPublicationCountVisCodeGenerator {
|
||||||
|
|
||||||
String csvDownloadURLHref = "";
|
String csvDownloadURLHref = "";
|
||||||
|
|
||||||
try {
|
if (getCSVDownloadURL() != null) {
|
||||||
if (getCSVDownloadURL() != null) {
|
|
||||||
|
csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL()
|
||||||
csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL()
|
+ "\" class=\"inline_href\">(.CSV File)</a>";
|
||||||
+ "\" class=\"inline_href\">(.CSV File)</a>";
|
|
||||||
|
} else {
|
||||||
} else {
|
|
||||||
csvDownloadURLHref = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
csvDownloadURLHref = "";
|
csvDownloadURLHref = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,18 +515,13 @@ public class PersonPublicationCountVisCodeGenerator {
|
||||||
|
|
||||||
if (yearToPublicationCount.size() > 0) {
|
if (yearToPublicationCount.size() > 0) {
|
||||||
|
|
||||||
try {
|
if (getCSVDownloadURL() != null) {
|
||||||
if (getCSVDownloadURL() != null) {
|
|
||||||
|
csvDownloadURLHref = "Download data as <a href='"
|
||||||
csvDownloadURLHref = "Download data as <a href='"
|
+ getCSVDownloadURL() + "'>.csv</a> file.<br />";
|
||||||
+ getCSVDownloadURL() + "'>.csv</a> file.<br />";
|
sparklineData.setDownloadDataLink(getCSVDownloadURL());
|
||||||
sparklineData.setDownloadDataLink(getCSVDownloadURL());
|
|
||||||
|
} else {
|
||||||
} else {
|
|
||||||
csvDownloadURLHref = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
csvDownloadURLHref = "";
|
csvDownloadURLHref = "";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -552,34 +537,18 @@ public class PersonPublicationCountVisCodeGenerator {
|
||||||
return divContextCode.toString();
|
return divContextCode.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getCSVDownloadURL()
|
private String getCSVDownloadURL() {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
|
|
||||||
if (yearToPublicationCount.size() > 0) {
|
if (yearToPublicationCount.size() > 0) {
|
||||||
|
|
||||||
String secondaryContextPath = "";
|
ParamMap CSVDownloadURLParams = new ParamMap(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY,
|
||||||
if (!contextPath.contains(VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX)) {
|
individualURI,
|
||||||
secondaryContextPath = VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX;
|
VisualizationFrameworkConstants.VIS_TYPE_KEY,
|
||||||
}
|
VisualizationFrameworkConstants.PERSON_PUBLICATION_COUNT_VIS);
|
||||||
|
|
||||||
String downloadURL = contextPath
|
return UrlBuilder.getUrl(VisualizationFrameworkConstants.DATA_VISUALIZATION_SERVICE_URL_PREFIX,
|
||||||
+ secondaryContextPath
|
CSVDownloadURLParams);
|
||||||
+ "?" + VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
|
|
||||||
+ "=" + URLEncoder.encode(individualURI,
|
|
||||||
VisualizationController.URL_ENCODING_SCHEME)
|
|
||||||
.toString()
|
|
||||||
+ "&" + VisualizationFrameworkConstants.VIS_TYPE_KEY
|
|
||||||
+ "=" + URLEncoder.encode(
|
|
||||||
VisualizationFrameworkConstants
|
|
||||||
.PERSON_PUBLICATION_COUNT_VIS,
|
|
||||||
VisualizationController.URL_ENCODING_SCHEME)
|
|
||||||
.toString()
|
|
||||||
+ "&" + VisualizationFrameworkConstants.RENDER_MODE_KEY
|
|
||||||
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
|
|
||||||
.DATA_RENDER_MODE,
|
|
||||||
VisualizationController.URL_ENCODING_SCHEME)
|
|
||||||
.toString();
|
|
||||||
return downloadURL;
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -589,31 +558,18 @@ public class PersonPublicationCountVisCodeGenerator {
|
||||||
|
|
||||||
StringBuilder divContextCode = new StringBuilder();
|
StringBuilder divContextCode = new StringBuilder();
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
String fullTimelineLink;
|
String fullTimelineLink;
|
||||||
if (yearToPublicationCount.size() > 0) {
|
if (yearToPublicationCount.size() > 0) {
|
||||||
|
|
||||||
String secondaryContextPath = "";
|
ParamMap fullTimelineNetworkURLParams = new ParamMap(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY,
|
||||||
if (!contextPath.contains(VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX)) {
|
individualURI,
|
||||||
secondaryContextPath = VisualizationFrameworkConstants.VISUALIZATION_URL_PREFIX;
|
VisualizationFrameworkConstants.VIS_TYPE_KEY,
|
||||||
}
|
VisualizationFrameworkConstants.PERSON_LEVEL_VIS);
|
||||||
|
|
||||||
String fullTimelineNetworkURL = contextPath
|
String fullTimelineNetworkURL = UrlBuilder.getUrl(
|
||||||
+ secondaryContextPath
|
VisualizationFrameworkConstants.FREEMARKERIZED_VISUALIZATION_URL_PREFIX,
|
||||||
+ "?"
|
fullTimelineNetworkURLParams);
|
||||||
+ VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY
|
|
||||||
+ "=" + URLEncoder.encode(individualURI,
|
|
||||||
VisualizationController.URL_ENCODING_SCHEME).toString()
|
|
||||||
+ "&"
|
|
||||||
+ VisualizationFrameworkConstants.VIS_TYPE_KEY
|
|
||||||
+ "=" + URLEncoder.encode("person_level",
|
|
||||||
VisualizationController.URL_ENCODING_SCHEME).toString()
|
|
||||||
+ "&"
|
|
||||||
+ VisualizationFrameworkConstants.RENDER_MODE_KEY
|
|
||||||
+ "=" + URLEncoder.encode(VisualizationFrameworkConstants
|
|
||||||
.STANDALONE_RENDER_MODE,
|
|
||||||
VisualizationController.URL_ENCODING_SCHEME).toString();
|
|
||||||
|
|
||||||
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View all VIVO "
|
fullTimelineLink = "<a href='" + fullTimelineNetworkURL + "'>View all VIVO "
|
||||||
+ "publications and corresponding co-author network.</a>";
|
+ "publications and corresponding co-author network.</a>";
|
||||||
|
@ -625,10 +581,6 @@ public class PersonPublicationCountVisCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
divContextCode.append("<span class=\"vis_link\">" + fullTimelineLink + "</span>");
|
divContextCode.append("<span class=\"vis_link\">" + fullTimelineLink + "</span>");
|
||||||
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
log.error(e);
|
|
||||||
}
|
|
||||||
return divContextCode.toString();
|
return divContextCode.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,13 +588,9 @@ public class PersonPublicationCountVisCodeGenerator {
|
||||||
|
|
||||||
String csvDownloadURLHref = "";
|
String csvDownloadURLHref = "";
|
||||||
|
|
||||||
try {
|
if (getCSVDownloadURL() != null) {
|
||||||
if (getCSVDownloadURL() != null) {
|
csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL() + "\">(.CSV File)</a>";
|
||||||
csvDownloadURLHref = "<a href=\"" + getCSVDownloadURL() + "\">(.CSV File)</a>";
|
} else {
|
||||||
} else {
|
|
||||||
csvDownloadURLHref = "";
|
|
||||||
}
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
csvDownloadURLHref = "";
|
csvDownloadURLHref = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,9 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.utilities;
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.utilities;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
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.Log;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
@ -21,23 +13,19 @@ import com.hp.hpl.jena.query.QuerySolution;
|
||||||
import com.hp.hpl.jena.query.ResultSet;
|
import com.hp.hpl.jena.query.ResultSet;
|
||||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.visualization.freemarker.VisualizationController;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
|
||||||
import edu.cornell.mannlib.vitro.webapp.filestorage.FileServingHelper;
|
import edu.cornell.mannlib.vitro.webapp.filestorage.FileServingHelper;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryFieldLabels;
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryFieldLabels;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.GenericQueryMap;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.AllPropertiesQueryRunner;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.AllPropertiesQueryRunner;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.GenericQueryRunner;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.GenericQueryRunner;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.QueryRunner;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.QueryRunner;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.VisualizationRequestHandler;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.GenericQueryMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This request handler is used when you need helpful information to add more context
|
* This request handler is used when you need helpful information to add more context
|
||||||
|
@ -51,9 +39,10 @@ import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.Visual
|
||||||
*/
|
*/
|
||||||
public class UtilitiesRequestHandler implements VisualizationRequestHandler {
|
public class UtilitiesRequestHandler implements VisualizationRequestHandler {
|
||||||
|
|
||||||
public ResponseValues generateVisualization(VitroRequest vitroRequest,
|
public Object generateAjaxVisualization(VitroRequest vitroRequest,
|
||||||
Log log,
|
Log log,
|
||||||
DataSource dataSource) {
|
DataSource dataSource)
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
|
||||||
String individualURI = vitroRequest.getParameter(
|
String individualURI = vitroRequest.getParameter(
|
||||||
VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
|
VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
|
||||||
|
@ -61,10 +50,6 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
|
||||||
String visMode = vitroRequest.getParameter(
|
String visMode = vitroRequest.getParameter(
|
||||||
VisualizationFrameworkConstants.VIS_MODE_KEY);
|
VisualizationFrameworkConstants.VIS_MODE_KEY);
|
||||||
|
|
||||||
String preparedURL = "";
|
|
||||||
|
|
||||||
UrlBuilder urlBuilder = new UrlBuilder(vitroRequest.getPortal());
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the info being requested is about a profile which includes the name, moniker
|
* If the info being requested is about a profile which includes the name, moniker
|
||||||
* & image url.
|
* & image url.
|
||||||
|
@ -83,28 +68,14 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
|
||||||
dataSource,
|
dataSource,
|
||||||
log);
|
log);
|
||||||
|
|
||||||
try {
|
GenericQueryMap profilePropertiesToValues =
|
||||||
|
profileQueryHandler.getQueryResult();
|
||||||
GenericQueryMap profilePropertiesToValues =
|
|
||||||
profileQueryHandler.getQueryResult();
|
Gson profileInformation = new Gson();
|
||||||
|
|
||||||
profilePropertiesToValues.addEntry("imageContextPath",
|
return profileInformation.toJson(profilePropertiesToValues);
|
||||||
urlBuilder.getBaseUrl());
|
|
||||||
|
|
||||||
Gson profileInformation = new Gson();
|
|
||||||
|
|
||||||
return prepareUtilitiesResponse(
|
|
||||||
profileInformation.toJson(profilePropertiesToValues),
|
|
||||||
vitroRequest);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (MalformedQueryParametersException e) {
|
|
||||||
return UtilityFunctions.handleMalformedParameters(
|
|
||||||
"Visualization Query Error - Utilities Profile Info",
|
|
||||||
e.getMessage(),
|
|
||||||
vitroRequest);
|
|
||||||
}
|
|
||||||
} else if (VisualizationFrameworkConstants.IMAGE_UTILS_VIS_MODE
|
} else if (VisualizationFrameworkConstants.IMAGE_UTILS_VIS_MODE
|
||||||
.equalsIgnoreCase(visMode)) {
|
.equalsIgnoreCase(visMode)) {
|
||||||
/*
|
/*
|
||||||
|
@ -131,21 +102,9 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
|
||||||
dataSource,
|
dataSource,
|
||||||
log);
|
log);
|
||||||
|
|
||||||
try {
|
return getThumbnailInformation(imageQueryHandler.getQueryResult(),
|
||||||
|
fieldLabelToOutputFieldLabel);
|
||||||
String thumbnailAccessURL =
|
|
||||||
getThumbnailInformation(
|
|
||||||
imageQueryHandler.getQueryResult(),
|
|
||||||
fieldLabelToOutputFieldLabel);
|
|
||||||
|
|
||||||
return prepareUtilitiesResponse(thumbnailAccessURL, vitroRequest);
|
|
||||||
|
|
||||||
} catch (MalformedQueryParametersException e) {
|
|
||||||
return UtilityFunctions.handleMalformedParameters(
|
|
||||||
"Visualization Query Error - Utilities Image Info",
|
|
||||||
e.getMessage(),
|
|
||||||
vitroRequest);
|
|
||||||
}
|
|
||||||
} else if (VisualizationFrameworkConstants.COAUTHOR_UTILS_VIS_MODE
|
} else if (VisualizationFrameworkConstants.COAUTHOR_UTILS_VIS_MODE
|
||||||
.equalsIgnoreCase(visMode)) {
|
.equalsIgnoreCase(visMode)) {
|
||||||
|
|
||||||
|
@ -160,12 +119,9 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
|
||||||
VisualizationFrameworkConstants.RENDER_MODE_KEY,
|
VisualizationFrameworkConstants.RENDER_MODE_KEY,
|
||||||
VisualizationFrameworkConstants.STANDALONE_RENDER_MODE);
|
VisualizationFrameworkConstants.STANDALONE_RENDER_MODE);
|
||||||
|
|
||||||
preparedURL = UrlBuilder.getUrl(VisualizationFrameworkConstants.FREEMARKERIZED_VISUALIZATION_URL_PREFIX,
|
return UrlBuilder.getUrl(VisualizationFrameworkConstants.FREEMARKERIZED_VISUALIZATION_URL_PREFIX,
|
||||||
coAuthorProfileURLParams);
|
coAuthorProfileURLParams);
|
||||||
|
|
||||||
|
|
||||||
return prepareUtilitiesResponse(preparedURL, vitroRequest);
|
|
||||||
|
|
||||||
} else if (VisualizationFrameworkConstants.PERSON_LEVEL_UTILS_VIS_MODE
|
} else if (VisualizationFrameworkConstants.PERSON_LEVEL_UTILS_VIS_MODE
|
||||||
.equalsIgnoreCase(visMode)) {
|
.equalsIgnoreCase(visMode)) {
|
||||||
/*
|
/*
|
||||||
|
@ -179,19 +135,16 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
|
||||||
VisualizationFrameworkConstants.RENDER_MODE_KEY,
|
VisualizationFrameworkConstants.RENDER_MODE_KEY,
|
||||||
VisualizationFrameworkConstants.STANDALONE_RENDER_MODE);
|
VisualizationFrameworkConstants.STANDALONE_RENDER_MODE);
|
||||||
|
|
||||||
preparedURL = UrlBuilder.getUrl(VisualizationFrameworkConstants.FREEMARKERIZED_VISUALIZATION_URL_PREFIX,
|
return UrlBuilder.getUrl(VisualizationFrameworkConstants.FREEMARKERIZED_VISUALIZATION_URL_PREFIX,
|
||||||
personLevelURLParams);
|
personLevelURLParams);
|
||||||
|
|
||||||
return prepareUtilitiesResponse(preparedURL, vitroRequest);
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
ParamMap individualProfileURLParams = new ParamMap(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY,
|
ParamMap individualProfileURLParams = new ParamMap(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY,
|
||||||
individualURI);
|
individualURI);
|
||||||
|
|
||||||
preparedURL = UrlBuilder.getUrl(VisualizationFrameworkConstants.INDIVIDUAL_URL_PREFIX,
|
return UrlBuilder.getUrl(VisualizationFrameworkConstants.INDIVIDUAL_URL_PREFIX,
|
||||||
individualProfileURLParams);
|
individualProfileURLParams);
|
||||||
|
|
||||||
return prepareUtilitiesResponse(preparedURL, vitroRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -219,6 +172,7 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
|
||||||
}
|
}
|
||||||
return finalThumbNailLocation;
|
return finalThumbNailLocation;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
private TemplateResponseValues prepareUtilitiesResponse(String preparedContent, VitroRequest vreq) {
|
private TemplateResponseValues prepareUtilitiesResponse(String preparedContent, VitroRequest vreq) {
|
||||||
|
|
||||||
|
@ -231,6 +185,20 @@ public class UtilitiesRequestHandler implements VisualizationRequestHandler {
|
||||||
|
|
||||||
return new TemplateResponseValues(utilitiesTemplate, body);
|
return new TemplateResponseValues(utilitiesTemplate, body);
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> generateDataVisualization(
|
||||||
|
VitroRequest vitroRequest, Log log, DataSource dataSource)
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
throw new UnsupportedOperationException("Utilities does not provide Data Response.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseValues generateStandardVisualization(
|
||||||
|
VitroRequest vitroRequest, Log log, DataSource dataSource)
|
||||||
|
throws MalformedQueryParametersException {
|
||||||
|
throw new UnsupportedOperationException("Utilities does not provide Standard Response.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UniqueIDGenerator;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UniqueIDGenerator;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,7 +9,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UniqueIDGenerator;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UniqueIDGenerator;
|
||||||
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
import edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils.UtilityFunctions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,15 +2,23 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils;
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import javax.servlet.RequestDispatcher;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
|
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||||
|
@ -127,7 +135,9 @@ public class UtilityFunctions {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static ResponseValues handleMalformedParameters(String errorPageTitle, String errorMessage, VitroRequest vitroRequest) {
|
public static ResponseValues handleMalformedParameters(String errorPageTitle,
|
||||||
|
String errorMessage,
|
||||||
|
VitroRequest vitroRequest) {
|
||||||
|
|
||||||
Portal portal = vitroRequest.getPortal();
|
Portal portal = vitroRequest.getPortal();
|
||||||
|
|
||||||
|
@ -139,23 +149,23 @@ public class UtilityFunctions {
|
||||||
return new TemplateResponseValues(VisualizationFrameworkConstants.ERROR_TEMPLATE, body);
|
return new TemplateResponseValues(VisualizationFrameworkConstants.ERROR_TEMPLATE, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* public static void handleMalformedParameters(String errorMessage,
|
public static void handleMalformedParameters(String errorPageTitle,
|
||||||
String errorPageTitle,
|
String errorMessage,
|
||||||
VitroRequest vitroRequest,
|
VitroRequest vitroRequest,
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
Log log)
|
Log log)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
|
||||||
Portal portal = vitroRequest.getPortal();
|
Portal portal = vitroRequest.getPortal();
|
||||||
|
|
||||||
request.setAttribute("error", errorMessage);
|
request.setAttribute("error", errorMessage);
|
||||||
|
|
||||||
RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
|
RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP);
|
||||||
request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp");
|
request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp");
|
||||||
request.setAttribute("portalBean", portal);
|
request.setAttribute("portalBean", portal);
|
||||||
request.setAttribute("title", errorPageTitle);
|
request.setAttribute("title", errorPageTitle);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
requestDispatcher.forward(request, response);
|
requestDispatcher.forward(request, response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -163,8 +173,8 @@ public class UtilityFunctions {
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
log.error(e.getStackTrace());
|
log.error(e.getStackTrace());
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
public static Map<String, Set<CoPINode>> getGrantYearToCoPI(
|
public static Map<String, Set<CoPINode>> getGrantYearToCoPI(
|
||||||
CoPIData pINodesAndEdges) {
|
CoPIData pINodesAndEdges) {
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils;
|
package edu.cornell.mannlib.vitro.webapp.visualization.freemarker.visutils;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import com.hp.hpl.jena.query.DataSource;
|
import com.hp.hpl.jena.query.DataSource;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface is being implemented by all the visualization request handlers like
|
* This interface is being implemented by all the visualization request handlers like
|
||||||
|
@ -20,8 +23,16 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Res
|
||||||
*/
|
*/
|
||||||
public interface VisualizationRequestHandler{
|
public interface VisualizationRequestHandler{
|
||||||
|
|
||||||
ResponseValues generateVisualization(VitroRequest vitroRequest,
|
ResponseValues generateStandardVisualization(VitroRequest vitroRequest,
|
||||||
Log log,
|
Log log,
|
||||||
DataSource dataSource);
|
DataSource dataSource) throws MalformedQueryParametersException;
|
||||||
|
|
||||||
|
Object generateAjaxVisualization(VitroRequest vitroRequest,
|
||||||
|
Log log,
|
||||||
|
DataSource dataSource) throws MalformedQueryParametersException;
|
||||||
|
|
||||||
|
Map<String, String> generateDataVisualization(VitroRequest vitroRequest,
|
||||||
|
Log log,
|
||||||
|
DataSource dataSource) throws MalformedQueryParametersException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue