Visualisation caching improvements
This commit is contained in:
parent
835b05af0c
commit
403ee2fb48
17 changed files with 333 additions and 138 deletions
|
@ -23,9 +23,6 @@ span.incomplete-data-holder,
|
|||
margin-top: 1.6em;
|
||||
font-size: 1em;
|
||||
}
|
||||
#incomplete-data-small {
|
||||
margin-top: 1.6em;
|
||||
}
|
||||
.collaboratorship-icon {
|
||||
float: left;
|
||||
padding-right: 8px;
|
||||
|
@ -90,6 +87,21 @@ span.incomplete-data-holder,
|
|||
.infoIcon {
|
||||
padding-right:30px;
|
||||
}
|
||||
.cache-info-small {
|
||||
padding: 5px;
|
||||
font-size: .8em;
|
||||
color: #444;
|
||||
border: dotted 1px #eee;
|
||||
background-color: #ffb;
|
||||
float: right;
|
||||
}
|
||||
.cache-info-vis {
|
||||
padding: 5px;
|
||||
color: #444;
|
||||
border: dotted 1px #eee;
|
||||
background-color: #ffb;
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* ---------------------------*/
|
||||
/* Visualization Tools -------*/
|
||||
|
|
|
@ -46,6 +46,9 @@ $(document).ready(function () {
|
|||
<#assign currentParameterObject = grantParameter>
|
||||
|
||||
<div id="temporal-graph-response">
|
||||
<#if (builtFromCacheTime??) >
|
||||
<div class="cache-info-small">${i18n().using_cache_time} ${builtFromCacheTime?time} (${builtFromCacheTime?date?string("MMM dd yyyy")})</div>
|
||||
</#if>
|
||||
|
||||
<#include "entityComparisonBody.ftl">
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@ $(document).ready(function () {
|
|||
<#assign currentParameterObject = publicationParameter>
|
||||
|
||||
<div id="temporal-graph-response">
|
||||
<#if (builtFromCacheTime??) >
|
||||
<div class="cache-info-small">${i18n().using_cache_time} ${builtFromCacheTime?time} (${builtFromCacheTime?date?string("MMM dd yyyy")})</div>
|
||||
</#if>
|
||||
|
||||
<#include "entityComparisonBody.ftl">
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@ corresponding changes in the included Templates. -->
|
|||
<#include "mapOfScienceSetup.ftl">
|
||||
|
||||
<div id="map-of-science-response">
|
||||
<#if (builtFromCacheTime??) >
|
||||
<div class="cache-info-vis">${i18n().using_cache_time} ${builtFromCacheTime?time} (${builtFromCacheTime?date?string("MMM dd yyyy")})</div>
|
||||
</#if>
|
||||
|
||||
<#--
|
||||
<div id="subject-parent-entity" class="hide-dom-on-init">
|
||||
|
@ -84,3 +87,5 @@ corresponding changes in the included Templates. -->
|
|||
</div>
|
||||
|
||||
${headScripts.add('<script type="text/javascript" src="${urls.base}/js/jquery_plugins/qtip/jquery.qtip-1.0.0-rc3.min.js"></script>')}
|
||||
|
||||
${stylesheets.add('<link rel="stylesheet" type="text/css" href="${urls.base}/css/visualization/visualization.css" />')}
|
||||
|
|
|
@ -151,6 +151,9 @@ $(document).ready(function(){
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<#if (builtFromCacheTime??) >
|
||||
<div class="cache-info-small">${i18n().using_cache_time} ${builtFromCacheTime?time} (${builtFromCacheTime?date?string("MMM dd yyyy")})</div>
|
||||
</#if>
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
<#if (numOfAuthors?? && numOfAuthors > 0) >
|
||||
|
|
|
@ -266,6 +266,9 @@ $(document).ready(function(){
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<#if (builtFromCacheTime??) >
|
||||
<div class="cache-info-small">${i18n().using_cache_time} ${builtFromCacheTime?time} (${builtFromCacheTime?date?string("MMM dd yyyy")})</div>
|
||||
</#if>
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
<#if (numOfAuthors?? && numOfAuthors > 0) >
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.visualization.coauthorship;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
@ -15,14 +14,12 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import com.hp.hpl.jena.query.QueryExecution;
|
||||
import com.hp.hpl.jena.query.QueryExecutionFactory;
|
||||
import com.hp.hpl.jena.query.ResultSet;
|
||||
import com.hp.hpl.jena.query.ResultSetFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer;
|
||||
import net.sf.jga.algorithms.Unique;
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.utilities.VisualizationCaches;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.jena.iri.IRI;
|
||||
|
@ -34,7 +31,6 @@ import com.hp.hpl.jena.query.Syntax;
|
|||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.collaborationutils.CoAuthorshipData;
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.collaborationutils.CollaborationData;
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.collaborationutils.CollaboratorComparator;
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryConstants;
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.constants.QueryFieldLabels;
|
||||
|
@ -58,6 +54,8 @@ public class CoAuthorshipQueryRunner implements QueryRunner<CoAuthorshipData> {
|
|||
|
||||
protected static final Syntax SYNTAX = Syntax.syntaxARQ;
|
||||
|
||||
private static boolean preferCaches = false;
|
||||
|
||||
private String egoURI;
|
||||
|
||||
private RDFService rdfService;
|
||||
|
@ -90,34 +88,46 @@ public class CoAuthorshipQueryRunner implements QueryRunner<CoAuthorshipData> {
|
|||
|
||||
@Override
|
||||
protected void processQuerySolution(QuerySolution qs) {
|
||||
RDFNode egoAuthorURLNode = qs.get(QueryFieldLabels.AUTHOR_URL);
|
||||
RDFNode authorLabelNode = qs.get(QueryFieldLabels.AUTHOR_LABEL);
|
||||
RDFNode documentNode = qs.get(QueryFieldLabels.DOCUMENT_URL);
|
||||
RDFNode coAuthorURLNode = qs.get(QueryFieldLabels.CO_AUTHOR_URL);
|
||||
RDFNode coAuthorLabelNode = qs.get(QueryFieldLabels.CO_AUTHOR_LABEL);
|
||||
RDFNode publicationDateNode = qs.get(QueryFieldLabels.DOCUMENT_PUBLICATION_DATE);
|
||||
|
||||
String authorURI = egoAuthorURLNode == null ? null : egoAuthorURLNode.asLiteral().getString();
|
||||
String authorName = authorLabelNode == null ? null : authorLabelNode.asLiteral().getString();
|
||||
String documentURI = documentNode == null ? null : documentNode.asLiteral().getString();
|
||||
String documentDate = publicationDateNode == null ? null : publicationDateNode.asLiteral().getString();
|
||||
String coAuthorURI = coAuthorURLNode == null ? null : coAuthorURLNode.asLiteral().getString();
|
||||
String coAuthorName = coAuthorLabelNode == null ? null : coAuthorLabelNode.asLiteral().getString();
|
||||
|
||||
processEntry(authorURI, authorName, documentURI, documentDate, coAuthorURI, coAuthorName);
|
||||
}
|
||||
|
||||
public void processEntry(String authorURI, String authorName, String documentURI, String documentDate, String coAuthorURI, String coAuthorName) {
|
||||
/*
|
||||
* We only want to create only ONE ego node.
|
||||
* */
|
||||
RDFNode egoAuthorURLNode = qs.get(QueryFieldLabels.AUTHOR_URL);
|
||||
if (nodeURLToVO.containsKey(egoAuthorURLNode.toString())) {
|
||||
|
||||
egoNode = nodeURLToVO.get(egoAuthorURLNode.toString());
|
||||
|
||||
if (nodeURLToVO.containsKey(authorURI)) {
|
||||
egoNode = nodeURLToVO.get(authorURI);
|
||||
} else {
|
||||
|
||||
egoNode = new Collaborator(egoAuthorURLNode.toString(), nodeIDGenerator);
|
||||
egoNode = new Collaborator(authorURI, nodeIDGenerator);
|
||||
nodes.add(egoNode);
|
||||
nodeURLToVO.put(egoAuthorURLNode.toString(), egoNode);
|
||||
nodeURLToVO.put(authorURI, egoNode);
|
||||
|
||||
RDFNode authorLabelNode = qs.get(QueryFieldLabels.AUTHOR_LABEL);
|
||||
if (authorLabelNode != null) {
|
||||
egoNode.setCollaboratorName(authorLabelNode.toString());
|
||||
if (authorName != null) {
|
||||
egoNode.setCollaboratorName(authorName);
|
||||
}
|
||||
}
|
||||
|
||||
RDFNode documentNode = qs.get(QueryFieldLabels.DOCUMENT_URL);
|
||||
Activity biboDocument;
|
||||
|
||||
if (biboDocumentURLToVO.containsKey(documentNode.toString())) {
|
||||
biboDocument = biboDocumentURLToVO.get(documentNode.toString());
|
||||
if (biboDocumentURLToVO.containsKey(documentURI)) {
|
||||
biboDocument = biboDocumentURLToVO.get(documentURI);
|
||||
} else {
|
||||
biboDocument = createDocumentVO(qs, documentNode.toString());
|
||||
biboDocumentURLToVO.put(documentNode.toString(), biboDocument);
|
||||
biboDocument = createDocumentVO(documentURI, documentDate);
|
||||
biboDocumentURLToVO.put(documentURI, biboDocument);
|
||||
}
|
||||
|
||||
egoNode.addActivity(biboDocument);
|
||||
|
@ -127,27 +137,21 @@ public class CoAuthorshipQueryRunner implements QueryRunner<CoAuthorshipData> {
|
|||
* we do not want a co-author node or Collaboration if the publication has only one
|
||||
* author and that happens to be the ego.
|
||||
* */
|
||||
if (qs.get(QueryFieldLabels.AUTHOR_URL).toString().equalsIgnoreCase(
|
||||
qs.get(QueryFieldLabels.CO_AUTHOR_URL).toString())) {
|
||||
if (authorURI.equalsIgnoreCase(coAuthorURI)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Collaborator coAuthorNode;
|
||||
|
||||
RDFNode coAuthorURLNode = qs.get(QueryFieldLabels.CO_AUTHOR_URL);
|
||||
if (nodeURLToVO.containsKey(coAuthorURLNode.toString())) {
|
||||
|
||||
coAuthorNode = nodeURLToVO.get(coAuthorURLNode.toString());
|
||||
|
||||
if (nodeURLToVO.containsKey(coAuthorURI)) {
|
||||
coAuthorNode = nodeURLToVO.get(coAuthorURI);
|
||||
} else {
|
||||
|
||||
coAuthorNode = new Collaborator(coAuthorURLNode.toString(), nodeIDGenerator);
|
||||
coAuthorNode = new Collaborator(coAuthorURI, nodeIDGenerator);
|
||||
nodes.add(coAuthorNode);
|
||||
nodeURLToVO.put(coAuthorURLNode.toString(), coAuthorNode);
|
||||
nodeURLToVO.put(coAuthorURI, coAuthorNode);
|
||||
|
||||
RDFNode coAuthorLabelNode = qs.get(QueryFieldLabels.CO_AUTHOR_LABEL);
|
||||
if (coAuthorLabelNode != null) {
|
||||
coAuthorNode.setCollaboratorName(coAuthorLabelNode.toString());
|
||||
if (coAuthorName != null) {
|
||||
coAuthorNode.setCollaboratorName(coAuthorName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,13 +229,12 @@ public class CoAuthorshipQueryRunner implements QueryRunner<CoAuthorshipData> {
|
|||
return new CoAuthorshipData(egoNode, nodes, edges, biboDocumentURLToVO);
|
||||
}
|
||||
|
||||
private Activity createDocumentVO(QuerySolution solution, String documentURL) {
|
||||
private Activity createDocumentVO(String documentURL, String documentDate) {
|
||||
|
||||
Activity biboDocument = new Activity(documentURL);
|
||||
|
||||
RDFNode publicationDateNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_DATE);
|
||||
if (publicationDateNode != null) {
|
||||
biboDocument.setActivityDate(publicationDateNode.toString());
|
||||
if (documentDate != null) {
|
||||
biboDocument.setActivityDate(documentDate);
|
||||
}
|
||||
|
||||
return biboDocument;
|
||||
|
@ -413,17 +416,17 @@ public class CoAuthorshipQueryRunner implements QueryRunner<CoAuthorshipData> {
|
|||
+ "WHERE\n"
|
||||
+ "{\n"
|
||||
+ " {\n"
|
||||
+ " <" + queryURI + "> rdf:type foaf:Person ;"
|
||||
+ " rdfs:label ?authorLabel ;"
|
||||
+ " core:relatedBy ?authorshipNode . \n"
|
||||
+ " ?authorshipNode rdf:type core:Authorship ;"
|
||||
+ " core:relates ?document . \n"
|
||||
+ " ?document rdf:type <http://purl.obolibrary.org/obo/IAO_0000030> ; \n"
|
||||
+ " core:relatedBy ?coAuthorshipNode . \n"
|
||||
+ " ?coAuthorshipNode rdf:type core:Authorship ; \n"
|
||||
+ " core:relates ?coAuthorPerson . \n"
|
||||
+ " ?coAuthorPerson rdf:type foaf:Person ; \n"
|
||||
+ " rdfs:label ?coAuthorPersonLabel . \n"
|
||||
+ " <" + queryURI + "> rdf:type foaf:Person ;"
|
||||
+ " rdfs:label ?authorLabel ;"
|
||||
+ " core:relatedBy ?authorshipNode . \n"
|
||||
+ " ?authorshipNode rdf:type core:Authorship ;"
|
||||
+ " core:relates ?document . \n"
|
||||
+ " ?document rdf:type <http://purl.obolibrary.org/obo/IAO_0000030> ; \n"
|
||||
+ " core:relatedBy ?coAuthorshipNode . \n"
|
||||
+ " ?coAuthorshipNode rdf:type core:Authorship ; \n"
|
||||
+ " core:relates ?coAuthorPerson . \n"
|
||||
+ " ?coAuthorPerson rdf:type foaf:Person ; \n"
|
||||
+ " rdfs:label ?coAuthorPersonLabel . \n"
|
||||
+ " }\n"
|
||||
+ " UNION\n"
|
||||
+ " {\n"
|
||||
|
@ -487,20 +490,60 @@ public class CoAuthorshipQueryRunner implements QueryRunner<CoAuthorshipData> {
|
|||
throw new MalformedQueryParametersException("URI parameter is either null or empty.");
|
||||
}
|
||||
|
||||
try {
|
||||
Model constructedModel = ModelFactory.createDefaultModel();
|
||||
rdfService.sparqlConstructQuery(generateEgoCoAuthorshipSparqlConstruct(this.egoURI), constructedModel);
|
||||
QueryResultConsumer consumer = new QueryResultConsumer();
|
||||
QueryExecution qe = QueryExecutionFactory.create(generateEgoCoAuthorshipSparqlQuery(this.egoURI), constructedModel);
|
||||
try {
|
||||
consumer.processResultSet(qe.execSelect());
|
||||
} finally {
|
||||
qe.close();
|
||||
}
|
||||
data = consumer.getCollaborationData();
|
||||
} catch (RDFServiceException e) {
|
||||
log.error("Unable to execute query", e);
|
||||
throw new RuntimeException(e);
|
||||
Date cacheTime = null;
|
||||
QueryResultConsumer consumer = new QueryResultConsumer();
|
||||
|
||||
// If we've had long running queries (preferCaches), and the caches are available, use the cache
|
||||
if (preferCaches && VisualizationCaches.personToPublication.isCached()) {
|
||||
cacheTime = VisualizationCaches.personToPublication.cachedWhen();
|
||||
|
||||
Map<String, String> personLabelsMap = VisualizationCaches.personLabels.get(rdfService);
|
||||
Map<String, Set<String>> personToPublicationMap = VisualizationCaches.personToPublication.get(rdfService).personToPublication;
|
||||
Map<String, Set<String>> publicationToPersonMap = VisualizationCaches.personToPublication.get(rdfService).publicationToPerson;
|
||||
Map<String, String> publicationToYearMap = VisualizationCaches.publicationToYear.get(rdfService);
|
||||
|
||||
String authorURI = this.egoURI;
|
||||
String authorName = personLabelsMap.get(authorURI);
|
||||
for (String documentURI : personToPublicationMap.get(authorURI)) {
|
||||
String documentDate = publicationToYearMap.get(documentURI);
|
||||
for (String coAuthorURI : publicationToPersonMap.get(documentURI)) {
|
||||
String coAuthorName = personLabelsMap.get(coAuthorURI);
|
||||
consumer.processEntry(authorURI, authorName, documentURI, documentDate, coAuthorURI, coAuthorName);
|
||||
}
|
||||
}
|
||||
consumer.endProcessing();
|
||||
} else {
|
||||
// Not use the caches, so query the triple store - recording the time it took
|
||||
long queryStart = System.currentTimeMillis();
|
||||
try {
|
||||
Model constructedModel = ModelFactory.createDefaultModel();
|
||||
rdfService.sparqlConstructQuery(generateEgoCoAuthorshipSparqlConstruct(this.egoURI), constructedModel);
|
||||
QueryExecution qe = QueryExecutionFactory.create(generateEgoCoAuthorshipSparqlQuery(this.egoURI), constructedModel);
|
||||
try {
|
||||
consumer.processResultSet(qe.execSelect());
|
||||
} finally {
|
||||
qe.close();
|
||||
}
|
||||
} catch (RDFServiceException e) {
|
||||
log.error("Unable to execute query", e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
// If the query took more than 5 seconds, start using the caches
|
||||
if (System.currentTimeMillis() - queryStart > 5000) {
|
||||
// If the caches haven't already been built, request a rebuild
|
||||
if (!preferCaches && !VisualizationCaches.personToPublication.isCached()) {
|
||||
VisualizationCaches.rebuildAll();
|
||||
}
|
||||
|
||||
// Attempt to use caches next time
|
||||
preferCaches = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data = consumer.getCollaborationData();
|
||||
if (cacheTime != null) {
|
||||
data.setBuiltFromCacheTime(cacheTime);
|
||||
}
|
||||
|
||||
CollaborationDataCacheEntry newEntry = new CollaborationDataCacheEntry();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.visualization.collaborationutils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -16,6 +17,8 @@ public abstract class CollaborationData {
|
|||
private Set<Map<String, String>> NODE_SCHEMA;
|
||||
private Set<Map<String, String>> EDGE_SCHEMA;
|
||||
|
||||
private Date builtFromCacheTime = null;
|
||||
|
||||
public CollaborationData(Collaborator egoCollaborator,
|
||||
Set<Collaborator> collaborators,
|
||||
Set<Collaboration> collaborations) {
|
||||
|
@ -24,6 +27,8 @@ public abstract class CollaborationData {
|
|||
this.collaborations = collaborations;
|
||||
}
|
||||
|
||||
public Date getBuiltFromCacheTime() { return builtFromCacheTime; }
|
||||
|
||||
public Set<Collaborator> getCollaborators() {
|
||||
return collaborators;
|
||||
}
|
||||
|
@ -60,6 +65,8 @@ public abstract class CollaborationData {
|
|||
return EDGE_SCHEMA;
|
||||
}
|
||||
|
||||
public void setBuiltFromCacheTime(Date time) { this.builtFromCacheTime = time; }
|
||||
|
||||
abstract Set<Map<String, String>> initializeEdgeSchema();
|
||||
|
||||
abstract Set<Map<String, String>> initializeNodeSchema();
|
||||
|
|
|
@ -90,7 +90,7 @@ public class MapOfScienceVisualizationRequestHandler implements VisualizationReq
|
|||
|
||||
private Set<String> getPublicationsForPerson(RDFService rdfService, String personUri) {
|
||||
if (preferCachesForPersonMap() && VisualizationCaches.personToPublication.isCached()) {
|
||||
Map<String, Set<String>> personToPublicationMap = VisualizationCaches.personToPublication.get(rdfService);
|
||||
Map<String, Set<String>> personToPublicationMap = VisualizationCaches.personToPublication.get(rdfService).personToPublication;
|
||||
return personToPublicationMap.get(personUri);
|
||||
} else {
|
||||
final Set<String> queryResults = new HashSet<String>();
|
||||
|
@ -253,7 +253,7 @@ public class MapOfScienceVisualizationRequestHandler implements VisualizationReq
|
|||
|
||||
Map<String, Set<String>> subOrgMap = VisualizationCaches.organizationSubOrgs.get(rdfService);
|
||||
Map<String, Set<String>> organisationToPeopleMap = VisualizationCaches.organisationToPeopleMap.get(rdfService);
|
||||
Map<String, Set<String>> personToPublicationMap = VisualizationCaches.personToPublication.get(rdfService);
|
||||
Map<String, Set<String>> personToPublicationMap = VisualizationCaches.personToPublication.get(rdfService).personToPublication;
|
||||
Map<String, String> publicationToJournalMap = VisualizationCaches.publicationToJournal.get(rdfService);
|
||||
|
||||
Set<String> orgPublications = new HashSet<String>();
|
||||
|
@ -397,22 +397,22 @@ public class MapOfScienceVisualizationRequestHandler implements VisualizationReq
|
|||
.getIndividualDao()
|
||||
.getIndividualByURI(entityURI);
|
||||
|
||||
if (individual != null && individual.isVClass("http://xmlns.com/foaf/0.1/Person")) {
|
||||
|
||||
return getSubjectPersonEntityAndGenerateDataResponse(
|
||||
vitroRequest,
|
||||
entityURI,
|
||||
individual != null ? individual.getDataValue("http://www.w3.org/2000/01/rdf-schema#label") : "",
|
||||
currentDataVisMode);
|
||||
|
||||
} else {
|
||||
|
||||
return getSubjectEntityAndGenerateDataResponse(
|
||||
vitroRequest,
|
||||
entityURI,
|
||||
individual != null ? individual.getDataValue("http://www.w3.org/2000/01/rdf-schema#label") : "",
|
||||
currentDataVisMode);
|
||||
|
||||
try {
|
||||
if (individual != null && individual.isVClass("http://xmlns.com/foaf/0.1/Person")) {
|
||||
return getSubjectPersonEntityAndGenerateDataResponse(
|
||||
vitroRequest,
|
||||
entityURI,
|
||||
individual != null ? individual.getDataValue("http://www.w3.org/2000/01/rdf-schema#label") : "",
|
||||
currentDataVisMode);
|
||||
} else {
|
||||
return getSubjectEntityAndGenerateDataResponse(
|
||||
vitroRequest,
|
||||
entityURI,
|
||||
individual != null ? individual.getDataValue("http://www.w3.org/2000/01/rdf-schema#label") : "",
|
||||
currentDataVisMode);
|
||||
}
|
||||
} finally {
|
||||
VisualizationCaches.buildMissing();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,11 +437,17 @@ public class MapOfScienceVisualizationRequestHandler implements VisualizationReq
|
|||
|
||||
if (UtilityFunctions.isEntityAPerson(vreq, entityURI)) {
|
||||
body.put("entityType", "PERSON");
|
||||
|
||||
if (preferCachesForPersonMap() && VisualizationCaches.personToPublication.isCached()) {
|
||||
body.put("builtFromCacheTime", VisualizationCaches.personToPublication.cachedWhen());
|
||||
}
|
||||
} else {
|
||||
body.put("entityType", "ORGANIZATION");
|
||||
if (VisualizationCaches.personToPublication.isCached()) {
|
||||
body.put("builtFromCacheTime", VisualizationCaches.personToPublication.cachedWhen());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
body.put("vivoDefaultNamespace", vreq.getWebappDaoFactory().getDefaultNamespace());
|
||||
|
||||
return new TemplateResponseValues(standaloneTemplate, body);
|
||||
|
|
|
@ -254,6 +254,10 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
|
|||
body.put("egoPubSparklineVO", egoPubSparklineVO);
|
||||
body.put("uniqueCoauthorsSparklineVO", uniqueCoauthorsSparklineVO);
|
||||
|
||||
if (coAuthorshipVO.getBuiltFromCacheTime() != null) {
|
||||
body.put("builtFromCacheTime", coAuthorshipVO.getBuiltFromCacheTime());
|
||||
}
|
||||
|
||||
body.put("title", title + "Person Level Visualization");
|
||||
|
||||
return new TemplateResponseValues(standaloneTemplate, body);
|
||||
|
|
|
@ -103,13 +103,16 @@ public class TemporalGrantVisualizationRequestHandler implements
|
|||
|
||||
}
|
||||
|
||||
return getSubjectEntityAndGenerateDataResponse(
|
||||
vitroRequest,
|
||||
log,
|
||||
dataset,
|
||||
entityURI,
|
||||
currentDataMode);
|
||||
|
||||
try {
|
||||
return getSubjectEntityAndGenerateDataResponse(
|
||||
vitroRequest,
|
||||
log,
|
||||
dataset,
|
||||
entityURI,
|
||||
currentDataMode);
|
||||
} finally {
|
||||
VisualizationCaches.buildMissing();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> prepareDataErrorResponse() {
|
||||
|
@ -290,6 +293,10 @@ public class TemporalGrantVisualizationRequestHandler implements
|
|||
body.put("vivoDefaultNamespace", vreq.getWebappDaoFactory().getDefaultNamespace());
|
||||
body.put("organizationLabel", organizationLabel);
|
||||
|
||||
if (VisualizationCaches.personToGrant.isCached()) {
|
||||
body.put("builtFromCacheTime", VisualizationCaches.personToGrant.cachedWhen());
|
||||
}
|
||||
|
||||
return new TemplateResponseValues(standaloneTemplate, body);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ public class TemporalPublicationVisualizationRequestHandler implements
|
|||
Map<String, String> orgMostSpecificLabelMap = VisualizationCaches.organizationToMostSpecificLabel.get(rdfService);
|
||||
Map<String, String> personMostSpecificLabelMap = VisualizationCaches.personToMostSpecificLabel.get(rdfService);
|
||||
Map<String, Set<String>> organisationToPeopleMap = VisualizationCaches.organisationToPeopleMap.get(rdfService);
|
||||
Map<String, Set<String>> personToPublicationMap = VisualizationCaches.personToPublication.get(rdfService);
|
||||
Map<String, Set<String>> personToPublicationMap = VisualizationCaches.personToPublication.get(rdfService).personToPublication;
|
||||
Map<String, String> publicationToYearMap = VisualizationCaches.publicationToYear.get(rdfService);
|
||||
|
||||
Set<String> orgPublications = new HashSet<String>();
|
||||
|
@ -250,13 +250,16 @@ public class TemporalPublicationVisualizationRequestHandler implements
|
|||
|
||||
}
|
||||
|
||||
return getSubjectEntityAndGenerateDataResponse(
|
||||
vitroRequest,
|
||||
log,
|
||||
dataset,
|
||||
entityURI,
|
||||
currentDataMode);
|
||||
|
||||
try {
|
||||
return getSubjectEntityAndGenerateDataResponse(
|
||||
vitroRequest,
|
||||
log,
|
||||
dataset,
|
||||
entityURI,
|
||||
currentDataMode);
|
||||
} finally {
|
||||
VisualizationCaches.buildMissing();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -276,6 +279,10 @@ public class TemporalPublicationVisualizationRequestHandler implements
|
|||
body.put("vivoDefaultNamespace", vreq.getWebappDaoFactory().getDefaultNamespace());
|
||||
body.put("organizationLabel", organizationLabel);
|
||||
|
||||
if (VisualizationCaches.personToPublication.isCached()) {
|
||||
body.put("builtFromCacheTime", VisualizationCaches.personToPublication.cachedWhen());
|
||||
}
|
||||
|
||||
return new TemplateResponseValues(standaloneTemplate, body);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
|||
import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
@ -35,6 +36,7 @@ public class CachingRDFServiceExecutor<T> {
|
|||
* Background task tracker
|
||||
*/
|
||||
private FutureTask<T> backgroundTask = null;
|
||||
private Thread backgroundCompletion = null;
|
||||
private long backgroundTaskStartTime = -1;
|
||||
|
||||
/**
|
||||
|
@ -50,6 +52,8 @@ public class CachingRDFServiceExecutor<T> {
|
|||
return cachedResults != null;
|
||||
}
|
||||
|
||||
public Date cachedWhen() { return new Date(lastCacheTime); }
|
||||
|
||||
/**
|
||||
* Return the cached results if present, or start the task.
|
||||
* Will wait for completion if the cache is not already populated, otherwise the refresh will happen in the background.
|
||||
|
@ -100,19 +104,32 @@ public class CachingRDFServiceExecutor<T> {
|
|||
*
|
||||
* @param rdfService an RDF service to use, if the background RDF service is not set
|
||||
*/
|
||||
public synchronized void build(RDFService rdfService) {
|
||||
public void build(RDFService rdfService) {
|
||||
// First, check if there are results from the previous background task, and update the cache
|
||||
if (backgroundTask != null && backgroundTask.isDone()) {
|
||||
buildComplete();
|
||||
} else if (backgroundTask == null) {
|
||||
buildStart(rdfService);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void buildComplete() {
|
||||
if (backgroundTask != null && backgroundTask.isDone()) {
|
||||
completeBackgroundTask();
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a background RDF service, we can launch the task in the background and leave it
|
||||
if (backgroundRDFService != null) {
|
||||
startBackgroundTask(backgroundRDFService);
|
||||
} else if (rdfService != null) {
|
||||
// No background service, so use the paassed RDF service, and wait for completion
|
||||
startBackgroundTask(backgroundRDFService);
|
||||
completeBackgroundTask();
|
||||
private synchronized void buildStart(RDFService rdfService) {
|
||||
if (backgroundTask == null) {
|
||||
// If we have a background RDF service, we can launch the task in the background and leave it
|
||||
if (backgroundRDFService != null) {
|
||||
startBackgroundTask(backgroundRDFService);
|
||||
completeBackgroundTaskAsync();
|
||||
} else if (rdfService != null) {
|
||||
// No background service, so use the paassed RDF service, and wait for completion
|
||||
startBackgroundTask(backgroundRDFService);
|
||||
completeBackgroundTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,6 +203,26 @@ public class CachingRDFServiceExecutor<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the background task
|
||||
*/
|
||||
private synchronized void completeBackgroundTaskAsync() {
|
||||
if (backgroundCompletion == null) {
|
||||
backgroundCompletion = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
completeBackgroundTask(-1);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
backgroundCompletion.setDaemon(true);
|
||||
backgroundCompletion.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the background task
|
||||
*/
|
||||
|
@ -215,6 +252,7 @@ public class CachingRDFServiceExecutor<T> {
|
|||
// Clear the background task information
|
||||
backgroundTask = null;
|
||||
backgroundTaskStartTime = -1;
|
||||
backgroundCompletion = null;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// Task was interrupted, so abort it
|
||||
|
@ -307,7 +345,6 @@ public class CachingRDFServiceExecutor<T> {
|
|||
affinity.complete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
package edu.cornell.mannlib.vitro.webapp.visualization.utilities;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class PersonPublicationMaps {
|
||||
public Map<String, Set<String>> personToPublication = new HashMap<String, Set<String>>();
|
||||
public Map<String, Set<String>> publicationToPerson = new HashMap<String, Set<String>>();
|
||||
|
||||
public void put(String person, String document) {
|
||||
Set<String> documentSet = personToPublication.get(person);
|
||||
if (documentSet == null) {
|
||||
documentSet = new HashSet<String>();
|
||||
documentSet.add(document);
|
||||
personToPublication.put(person, documentSet);
|
||||
} else {
|
||||
documentSet.add(document);
|
||||
}
|
||||
|
||||
Set<String> personSet = publicationToPerson.get(document);
|
||||
if (personSet == null) {
|
||||
personSet = new HashSet<String>();
|
||||
personSet.add(person);
|
||||
publicationToPerson.put(document, personSet);
|
||||
} else {
|
||||
personSet.add(person);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,32 @@ final public class VisualizationCaches {
|
|||
grantToYear.build(rdfService);
|
||||
}
|
||||
|
||||
public static void buildMissing() {
|
||||
if (!organizationLabels.isCached()) { organizationLabels.build(null); }
|
||||
if (!organizationSubOrgs.isCached()) { organizationSubOrgs.build(null); }
|
||||
if (!organizationToMostSpecificLabel.isCached()) { organizationToMostSpecificLabel.build(null); }
|
||||
if (!organisationToPeopleMap.isCached()) { organisationToPeopleMap.build(null); }
|
||||
if (!personLabels.isCached()) { personLabels.build(null); }
|
||||
if (!personToMostSpecificLabel.isCached()) { personToMostSpecificLabel.build(null); }
|
||||
if (!personToPublication.isCached()) { personToPublication.build(null); }
|
||||
if (!publicationToJournal.isCached()) { publicationToJournal.build(null); }
|
||||
if (!publicationToYear.isCached()) { publicationToYear.build(null); }
|
||||
if (!personToGrant.isCached()) { personToGrant.build(null); }
|
||||
if (!grantToYear.isCached()) { grantToYear.build(null); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the specifield caches
|
||||
* @param executors
|
||||
*/
|
||||
public static void rebuild(CachingRDFServiceExecutor... executors) {
|
||||
if (executors != null) {
|
||||
for (CachingRDFServiceExecutor e : executors) {
|
||||
e.build(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache of organization labels (uri -> label)
|
||||
*/
|
||||
|
@ -263,11 +289,11 @@ final public class VisualizationCaches {
|
|||
/**
|
||||
* Person to publication Map (person uri -> list of publication uri)
|
||||
*/
|
||||
public static final CachingRDFServiceExecutor<Map<String, Set<String>>> personToPublication =
|
||||
new CachingRDFServiceExecutor<Map<String, Set<String>>>(
|
||||
new CachingRDFServiceExecutor.RDFServiceCallable<Map<String, Set<String>>>(visualizationAffinity) {
|
||||
public static final CachingRDFServiceExecutor<PersonPublicationMaps> personToPublication =
|
||||
new CachingRDFServiceExecutor<PersonPublicationMaps>(
|
||||
new CachingRDFServiceExecutor.RDFServiceCallable<PersonPublicationMaps>(visualizationAffinity) {
|
||||
@Override
|
||||
protected Map<String, Set<String>> callWithService(RDFService rdfService) throws Exception {
|
||||
protected PersonPublicationMaps callWithService(RDFService rdfService) throws Exception {
|
||||
String query = QueryConstants.getSparqlPrefixQuery() +
|
||||
"SELECT ?person ?document\n" +
|
||||
"WHERE\n" +
|
||||
|
@ -276,10 +302,10 @@ final public class VisualizationCaches {
|
|||
" ?person core:relatedBy ?authorship .\n" +
|
||||
" ?authorship a core:Authorship .\n" +
|
||||
" ?authorship core:relates ?document .\n" +
|
||||
" ?document a bibo:Document .\n" +
|
||||
" ?document a <http://purl.obolibrary.org/obo/IAO_0000030> .\n" +
|
||||
"}\n";
|
||||
|
||||
final Map<String, Set<String>> map = new HashMap<String, Set<String>>();
|
||||
final PersonPublicationMaps map = new PersonPublicationMaps();
|
||||
|
||||
rdfService.sparqlSelectQuery(query, new ResultSetConsumer() {
|
||||
@Override
|
||||
|
@ -289,15 +315,9 @@ final public class VisualizationCaches {
|
|||
|
||||
if (person != null && document != null) {
|
||||
String personURI = person.getURI();
|
||||
String documentURI = document.getURI();
|
||||
|
||||
Set<String> documents = map.get(personURI);
|
||||
if (documents == null) {
|
||||
documents = new HashSet<String>();
|
||||
documents.add(document.getURI());
|
||||
map.put(personURI, documents);
|
||||
} else {
|
||||
documents.add(document.getURI());
|
||||
}
|
||||
map.put(personURI, documentURI);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -319,7 +339,7 @@ final public class VisualizationCaches {
|
|||
"SELECT ?document ?journalLabel\n" +
|
||||
"WHERE\n" +
|
||||
"{\n" +
|
||||
" ?document a bibo:Document .\n" +
|
||||
" ?document a <http://purl.obolibrary.org/obo/IAO_0000030> .\n" +
|
||||
" ?document core:hasPublicationVenue ?journal . \n" +
|
||||
" ?journal rdfs:label ?journalLabel . \n" +
|
||||
"}\n";
|
||||
|
@ -353,7 +373,7 @@ final public class VisualizationCaches {
|
|||
"SELECT ?document ?publicationDate\n" +
|
||||
"WHERE\n" +
|
||||
"{\n" +
|
||||
" ?document a bibo:Document .\n" +
|
||||
" ?document a <http://purl.obolibrary.org/obo/IAO_0000030> .\n" +
|
||||
" ?document core:dateTimeValue ?dateTimeValue . \n" +
|
||||
" ?dateTimeValue core:dateTime ?publicationDate . \n" +
|
||||
"}\n";
|
||||
|
|
|
@ -885,3 +885,5 @@ researcher_role = Researcher Role
|
|||
search_service_btn = Search Service
|
||||
through_today = Publications through today's date
|
||||
doi_link=Digital Object Identifier (DOI)
|
||||
|
||||
using_cache_time=Using information cached at
|
||||
|
|
Loading…
Add table
Reference in a new issue