VIVO-1248 extend SparqlQueryRunner, and combine with older attempts. (#45)

* Ignore artifacts that Eclipse creates.

* VIVO-1248 Create the utils.sparqlrunner package.

This is a merge of most of the edu.cornell.mannlib.vitro.webapp.utils.sparql package with
edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner

Remove the references to those classes.

* VIVO-1248 extend SparqlQueryRunner, and combine with older attempts.
This commit is contained in:
Jim Blake 2017-01-03 13:16:22 -05:00 committed by GitHub
parent a8ec633f71
commit 9cd5a1329a
31 changed files with 1799 additions and 438 deletions

View file

@ -20,9 +20,9 @@ import org.apache.jena.rdf.model.Resource;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Field;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.QueryParser;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.ResultSetParser;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner;
/**
* Pull some UserAccounts from the model, based on a set of criteria.
@ -111,8 +111,9 @@ public class UserAccountsSelector {
.replace("%offset%", offset());
log.debug("main query: " + qString);
List<UserAccount> accounts = new SparqlQueryRunner(model)
.executeSelect(new MainQueryParser(), qString);
List<UserAccount> accounts = SparqlQueryRunner
.createSelectQueryContext(model, qString).execute()
.parse(new MainQueryParser());
log.debug("query returns: " + accounts);
return accounts;
}
@ -126,8 +127,8 @@ public class UserAccountsSelector {
.replace("%filterClauses%", filterClauses());
log.debug("count query: " + qString);
int count = new SparqlQueryRunner(model).executeSelect(
new CountQueryParser(), qString);
int count = SparqlQueryRunner.createSelectQueryContext(model, qString)
.execute().parse(new CountQueryParser());
log.debug("result count: " + count);
return count;
}
@ -139,8 +140,9 @@ public class UserAccountsSelector {
PREFIX_LINES).replace("%uri%", uri);
log.debug("permissions query: " + qString);
Set<String> permissions = new SparqlQueryRunner(model)
.executeSelect(new PermissionsQueryParser(), qString);
Set<String> permissions = SparqlQueryRunner
.createSelectQueryContext(model, qString).execute()
.parse(new PermissionsQueryParser());
log.debug("permissions for '" + uri + "': " + permissions);
account.setPermissionSetUris(permissions);
}
@ -214,7 +216,8 @@ public class UserAccountsSelector {
return String.valueOf(offset);
}
private static class MainQueryParser extends QueryParser<List<UserAccount>> {
private static class MainQueryParser extends
ResultSetParser<List<UserAccount>> {
@Override
protected List<UserAccount> defaultValue() {
return Collections.emptyList();
@ -274,7 +277,7 @@ public class UserAccountsSelector {
}
}
private static class CountQueryParser extends QueryParser<Integer> {
private static class CountQueryParser extends ResultSetParser<Integer> {
@Override
protected Integer defaultValue() {
return 0;
@ -299,7 +302,7 @@ public class UserAccountsSelector {
}
private static class PermissionsQueryParser extends
QueryParser<Set<String>> {
ResultSetParser<Set<String>> {
@Override
protected Set<String> defaultValue() {
return Collections.emptySet();

View file

@ -16,9 +16,9 @@ import org.apache.jena.query.ResultSet;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ProxyRelationshipSelectionBuilder.ItemInfo;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ProxyRelationshipSelectionBuilder.Relationship;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ProxyRelationshipSelectionCriteria.ProxyRelationshipView;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.QueryParser;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.ResultSetParser;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner;
/**
* A class which will accept a ProxyRelationshipSelectionCriteria and produce a
@ -94,8 +94,9 @@ public class ProxyRelationshipSelector {
PREFIX_LINES);
qString = replaceFilterClauses(qString);
int count = new SparqlQueryRunner(context.userAccountsModel)
.executeSelect(new CountQueryParser(), qString);
int count = SparqlQueryRunner
.createSelectQueryContext(context.userAccountsModel, qString)
.execute().parse(new CountQueryParser());
log.debug("result count: " + count);
builder.count = count;
@ -136,9 +137,9 @@ public class ProxyRelationshipSelector {
.replace("%offset%", offset());
qString = replaceFilterClauses(qString);
List<Relationship> relationships = new SparqlQueryRunner(
context.userAccountsModel).executeSelect(
new ProxyBasicsParser(), qString);
List<Relationship> relationships = SparqlQueryRunner
.createSelectQueryContext(context.userAccountsModel, qString)
.execute().parse(new ProxyBasicsParser());
log.debug("getProxyBasics returns: " + relationships);
builder.relationships.addAll(relationships);
}
@ -177,8 +178,9 @@ public class ProxyRelationshipSelector {
.replace("%matchingProperty%", context.matchingProperty)
.replace("%externalAuthId%", proxy.externalAuthId);
ItemInfo expansion = new SparqlQueryRunner(context.unionModel)
.executeSelect(new ExpandProxyParser(), qString);
ItemInfo expansion = SparqlQueryRunner
.createSelectQueryContext(context.unionModel, qString)
.execute().parse(new ExpandProxyParser());
proxy.classLabel = expansion.classLabel;
proxy.imageUrl = expansion.imageUrl;
}
@ -199,9 +201,10 @@ public class ProxyRelationshipSelector {
String qString = QUERY_RELATIONSHIPS.replace("%prefixes%",
PREFIX_LINES).replace("%proxyUri%", proxy.uri);
List<String> profileUris = new SparqlQueryRunner(
context.userAccountsModel).executeSelect(
new RelationshipsParser(), qString);
List<String> profileUris = SparqlQueryRunner
.createSelectQueryContext(context.userAccountsModel,
qString).execute()
.parse(new RelationshipsParser());
for (String profileUri : profileUris) {
r.profileInfos
@ -235,8 +238,9 @@ public class ProxyRelationshipSelector {
String qString = QUERY_EXPAND_PROFILE.replace("%prefixes%",
PREFIX_LINES).replace("%profileUri%", profile.uri);
ItemInfo expansion = new SparqlQueryRunner(context.unionModel)
.executeSelect(new ExpandProfileParser(), qString);
ItemInfo expansion = SparqlQueryRunner
.createSelectQueryContext(context.unionModel, qString)
.execute().parse(new ExpandProfileParser());
profile.label = expansion.label;
profile.classLabel = expansion.classLabel;
profile.imageUrl = expansion.imageUrl;
@ -285,7 +289,7 @@ public class ProxyRelationshipSelector {
// ----------------------------------------------------------------------
private static class ProxyBasicsParser extends
QueryParser<List<Relationship>> {
ResultSetParser<List<Relationship>> {
@Override
protected List<Relationship> defaultValue() {
return Collections.emptyList();
@ -318,7 +322,7 @@ public class ProxyRelationshipSelector {
}
}
private static class CountQueryParser extends QueryParser<Integer> {
private static class CountQueryParser extends ResultSetParser<Integer> {
@Override
protected Integer defaultValue() {
return 0;
@ -342,7 +346,7 @@ public class ProxyRelationshipSelector {
}
}
private static class ExpandProxyParser extends QueryParser<ItemInfo> {
private static class ExpandProxyParser extends ResultSetParser<ItemInfo> {
@Override
protected ItemInfo defaultValue() {
return new ItemInfo();
@ -367,7 +371,8 @@ public class ProxyRelationshipSelector {
}
}
private static class RelationshipsParser extends QueryParser<List<String>> {
private static class RelationshipsParser extends
ResultSetParser<List<String>> {
@Override
protected List<String> defaultValue() {
return Collections.emptyList();
@ -388,7 +393,7 @@ public class ProxyRelationshipSelector {
}
}
private static class ExpandProfileParser extends QueryParser<ItemInfo> {
private static class ExpandProfileParser extends ResultSetParser<ItemInfo> {
@Override
protected ItemInfo defaultValue() {
return new ItemInfo();

View file

@ -24,8 +24,8 @@ import edu.cornell.mannlib.vitro.webapp.controller.ajax.AbstractAjaxResponder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner;
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
/**
@ -76,10 +76,10 @@ public class BasicProxiesGetter extends AbstractAjaxResponder {
String cleanTerm = SparqlQueryUtils.escapeForRegex(term);
String queryStr = QUERY_BASIC_PROXIES.replace("%term%", cleanTerm);
JSONArray jsonArray = new SparqlQueryRunner(userAccountsModel)
.executeSelect(
new BasicProxyInfoParser(placeholderImageUrl),
queryStr);
JSONArray jsonArray = SparqlQueryRunner
.createSelectQueryContext(userAccountsModel, queryStr)
.execute()
.parse(new BasicProxyInfoParser(placeholderImageUrl));
String response = jsonArray.toString();
log.debug(response);

View file

@ -36,9 +36,9 @@ import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.http.AcceptHeaderParsingException;
import edu.cornell.mannlib.vitro.webapp.utils.http.NotAcceptableException;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SparqlQueryUtils;
/**
* Present the SPARQL Query form, and execute the queries.

View file

@ -24,7 +24,7 @@ import org.apache.jena.query.ResultSet;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.ResultSetParser;
/**
* A base class for AJAX responder objects, to be instantiated and invoked by
@ -82,7 +82,7 @@ public abstract class AbstractAjaxResponder {
*/
protected String assembleJsonResponse(List<Map<String, String>> maps) {
JSONArray jsonArray = new JSONArray();
for (Map<String, String> map: maps) {
for (Map<String, String> map : maps) {
jsonArray.put(map);
}
return jsonArray.toString();
@ -93,7 +93,7 @@ public abstract class AbstractAjaxResponder {
* implement "parseSolutionRow()"
*/
protected abstract static class JsonArrayParser extends
SparqlQueryRunner.QueryParser<JSONArray> {
ResultSetParser<JSONArray> {
@Override
protected JSONArray defaultValue() {
return new JSONArray();

View file

@ -10,9 +10,9 @@ import org.apache.jena.query.QueryParseException;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.http.AcceptHeaderParsingException;
import edu.cornell.mannlib.vitro.webapp.utils.http.NotAcceptableException;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SparqlQueryUtils;
/**
* The base class for the SPARQL query API.

View file

@ -73,12 +73,12 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
import edu.cornell.mannlib.vitro.webapp.rdfservice.adapters.VitroModelFactory;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestUtils;
import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestUtils.MergeResult;
import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestWorkflowProcessor;
import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaOutputUtils;
import edu.cornell.mannlib.vitro.webapp.utils.jena.WorkflowOntology;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SparqlQueryUtils;
public class JenaIngestController extends BaseEditController {
private static final Log log = LogFactory.getLog(JenaIngestController.class);

View file

@ -2,9 +2,9 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena;
import static edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.createSelectQueryContext;
import static edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.queryHolder;
import static org.apache.jena.rdf.model.ResourceFactory.createResource;
import static edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.bindValues;
import static edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.uriValue;
import java.util.ArrayList;
import java.util.Collection;
@ -16,7 +16,6 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.ontology.ObjectProperty;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.ontology.OntModelSpec;
@ -33,11 +32,11 @@ import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.QueryParser;
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModel;
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModelSelector;
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedOntModel;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.QueryHolder;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.ResultSetParser;
/**
* TODO
@ -522,7 +521,7 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
+ "} \n"; //
private static class ParserLocateConfigContext extends
QueryParser<Set<ConfigContext>> {
ResultSetParser<Set<ConfigContext>> {
private final String domainUri;
private final String baseUri;
private final String rangeUri;
@ -561,30 +560,29 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao
LockableOntModel lockableDisplayModel, String domainUri,
String baseUri, String rangeUri) {
try (LockedOntModel displayModel = lockableDisplayModel.read()) {
String queryString;
QueryHolder qHolder;
if (domainUri == null || domainUri.trim().isEmpty()
|| domainUri.equals(OWL.Thing.getURI())) {
queryString = bindValues(
QUERY_LOCATE_CONFIG_CONTEXT_WITH_NO_DOMAIN,
uriValue("baseUri", baseUri),
uriValue("rangeUri", rangeUri));
qHolder = queryHolder(
QUERY_LOCATE_CONFIG_CONTEXT_WITH_NO_DOMAIN)
.bindToUri("baseUri", baseUri).bindToUri(
"rangeUri", rangeUri);
} else {
queryString = bindValues(
QUERY_LOCATE_CONFIG_CONTEXT_WITH_DOMAIN,
uriValue("baseUri", baseUri),
uriValue("rangeUri", rangeUri),
uriValue("domainUri", domainUri));
qHolder = queryHolder(
QUERY_LOCATE_CONFIG_CONTEXT_WITH_DOMAIN)
.bindToUri("baseUri", baseUri)
.bindToUri("rangeUri", rangeUri)
.bindToUri("domainUri", domainUri);
}
if (log.isDebugEnabled()) {
log.debug("domainUri=" + domainUri + ", baseUri=" + baseUri
+ ", rangeUri=" + rangeUri + ", queryString="
+ queryString);
+ ", rangeUri=" + rangeUri + ", qHolder=" + qHolder);
}
ParserLocateConfigContext parser = new ParserLocateConfigContext(
domainUri, baseUri, rangeUri);
Set<ConfigContext> contexts = new SparqlQueryRunner(
displayModel).executeSelect(parser, queryString);
Set<ConfigContext> contexts = createSelectQueryContext(
displayModel, qHolder).execute().parse(parser);
log.debug("found " + contexts.size() + " contexts: " + contexts);
return contexts;

View file

@ -5,7 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.searchindex.documentBuilding;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.WhichService.CONTENT;
import static edu.cornell.mannlib.vitro.webapp.search.VitroSearchTermNames.ALLTEXT;
import static edu.cornell.mannlib.vitro.webapp.search.VitroSearchTermNames.ALLTEXTUNSTEMMED;
import static edu.cornell.mannlib.vitro.webapp.utils.sparql.SelectQueryRunner.createQueryContext;
import static edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.createSelectQueryContext;
import java.util.ArrayList;
import java.util.Collections;
@ -24,7 +24,7 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.ContextModelsUser;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.Property;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.Validation;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SelectQueryHolder;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.QueryHolder;
/**
* Modify the document, adding the results of one or more select queries.
@ -151,10 +151,10 @@ public class SelectQueryDocumentModifier implements DocumentModifier,
private List<String> getTextForQuery(String query, Individual ind) {
try {
SelectQueryHolder queryHolder = new SelectQueryHolder(query)
.bindToUri("uri", ind.getURI());
List<String> list = createQueryContext(rdfService, queryHolder)
.execute().getStringFields().flatten();
QueryHolder queryHolder = new QueryHolder(query).bindToUri("uri",
ind.getURI());
List<String> list = createSelectQueryContext(rdfService,
queryHolder).execute().toStringFields().flatten();
log.debug(label + " - query: '" + query + "' returns " + list);
return list;
} catch (Throwable t) {

View file

@ -3,8 +3,8 @@
package edu.cornell.mannlib.vitro.webapp.searchindex.indexing;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.WhichService.CONTENT;
import static edu.cornell.mannlib.vitro.webapp.utils.sparql.SelectQueryRunner.createQueryContext;
import static edu.cornell.mannlib.vitro.webapp.utils.sparql.SelectQueryRunner.selectQuery;
import static edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.createSelectQueryContext;
import static edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.queryHolder;
import java.util.ArrayList;
import java.util.Collections;
@ -23,7 +23,7 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.ContextModelsUser;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.Property;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.Validation;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SelectQueryHolder;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.QueryHolder;
/**
* Find URIs based on one or more select queries.
@ -118,7 +118,7 @@ public class SelectQueryUriFinder implements IndexingUriFinder,
}
private List<String> getUrisForQuery(Statement stmt, String queryString) {
SelectQueryHolder query = selectQuery(queryString);
QueryHolder query = queryHolder(queryString);
query = query.bindToUri("predicate", stmt.getPredicate().getURI());
query = tryToBindUri(query, "subject", stmt.getSubject());
@ -127,12 +127,12 @@ public class SelectQueryUriFinder implements IndexingUriFinder,
return Collections.emptyList();
}
return createQueryContext(rdfService, query).execute()
.getStringFields().flatten();
return createSelectQueryContext(rdfService, query).execute()
.toStringFields().flatten();
}
private SelectQueryHolder tryToBindUri(SelectQueryHolder query,
String name, RDFNode node) {
private QueryHolder tryToBindUri(QueryHolder query, String name,
RDFNode node) {
if (query == null) {
return null;
}

View file

@ -1,125 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparql;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.RDFNode;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SelectQueryRunner.ExecutingSelectQueryContext;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SelectQueryRunner.SelectQueryContext;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SelectQueryRunner.StringResultsMapping;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SelectQueryRunner.StringResultsMappingImpl;
/**
* An implementation of QueryContext based on an RDFService.
*
* Package access. Instances should be created only by SelectQueryRunner, or by
* a method on this class.
*/
class RdfServiceQueryContext implements SelectQueryContext {
private static final Log log = LogFactory
.getLog(RdfServiceQueryContext.class);
private final RDFService rdfService;
private final SelectQueryHolder query;
RdfServiceQueryContext(RDFService rdfService, SelectQueryHolder query) {
this.rdfService = rdfService;
this.query = query;
}
@Override
public RdfServiceQueryContext bindVariableToUri(String name, String uri) {
return new RdfServiceQueryContext(rdfService,
query.bindToUri(name, uri));
}
@Override
public ExecutingSelectQueryContext execute() {
return new RdfServiceExecutingQueryContext(rdfService, query);
}
private static class RdfServiceExecutingQueryContext implements
ExecutingSelectQueryContext {
private final RDFService rdfService;
private final SelectQueryHolder query;
public RdfServiceExecutingQueryContext(RDFService rdfService,
SelectQueryHolder query) {
this.rdfService = rdfService;
this.query = query;
}
@Override
public StringResultsMapping getStringFields(String... names) {
Set<String> fieldNames = new HashSet<>(Arrays.asList(names));
StringResultsMappingImpl mapping = new StringResultsMappingImpl();
try {
ResultSet results = RDFServiceUtils.sparqlSelectQuery(
query.getQueryString(), rdfService);
return mapResultsForQuery(results, fieldNames);
} catch (Exception e) {
log.error(
"problem while running query '"
+ query.getQueryString() + "'", e);
}
return mapping;
}
private StringResultsMapping mapResultsForQuery(ResultSet results,
Set<String> fieldNames) {
StringResultsMappingImpl mapping = new StringResultsMappingImpl();
while (results.hasNext()) {
Map<String, String> rowMapping = mapResultsForRow(
results.nextSolution(), fieldNames);
if (!rowMapping.isEmpty()) {
mapping.add(rowMapping);
}
}
return mapping;
}
private Map<String, String> mapResultsForRow(QuerySolution row,
Set<String> fieldNames) {
Map<String, String> map = new HashMap<>();
for (Iterator<String> names = row.varNames(); names.hasNext();) {
String name = names.next();
RDFNode node = row.get(name);
String text = getTextForNode(node);
if (StringUtils.isNotBlank(text)) {
map.put(name, text);
}
}
if (!fieldNames.isEmpty()) {
map.keySet().retainAll(fieldNames);
}
return map;
}
private String getTextForNode(RDFNode node) {
if (node == null) {
return "";
} else if (node.isLiteral()) {
return node.asLiteral().getString().trim();
} else {
return node.toString().trim();
}
}
}
}

View file

@ -1,36 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparql;
import java.util.regex.Pattern;
/**
* Holds the text of a SPARQL Select query, and allows you to perform some lexical
* operations on it.
*
* This is immutable, so don't forget to get the result of the operations.
*/
public class SelectQueryHolder {
private final String queryString;
public SelectQueryHolder(String queryString) {
this.queryString = queryString;
}
public String getQueryString() {
return queryString;
}
public boolean hasVariable(String name) {
String regex = "\\?" + name + "\\b";
return Pattern.compile(regex).matcher(queryString).find();
}
public SelectQueryHolder bindToUri(String name, String uri) {
String regex = "\\?" + name + "\\b";
String replacement = "<" + uri + ">";
String bound = queryString.replaceAll(regex, replacement);
return new SelectQueryHolder(bound);
}
}

View file

@ -1,104 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparql;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
/**
* A conversational tool for handling SPARQL queries.
*
* {@code
* Examples:
* List<String> values = createQueryContext(rdfService, queryString)
* .bindVariableToUri("uri", uri)
* .execute()
* .getStringFields("partner")
* .flatten();
*
* SelectQueryHolder q = selectQuery(queryString)
* .bindToUri("uri", uri));
* List<Map<String, String> map = createQueryContext(rdfService, q)
* .execute()
* .getStringFields();
* }
*
* The execute() method does not actually execute the query: it merely sets it
* up syntactically.
*
* If you don't supply any field names to getStringFields(), you get all of
* them.
*
* Any string value that returns a blank or empty string is omitted from the
* results. Any row that returns no values is omitted from the results.
*/
public final class SelectQueryRunner {
private static final Log log = LogFactory.getLog(SelectQueryRunner.class);
private SelectQueryRunner() {
// No need to create an instance.
}
public static SelectQueryHolder selectQuery(String queryString) {
return new SelectQueryHolder(queryString);
}
public static SelectQueryContext createQueryContext(RDFService rdfService,
String queryString) {
return createQueryContext(rdfService, selectQuery(queryString));
}
public static SelectQueryContext createQueryContext(RDFService rdfService,
SelectQueryHolder query) {
return new RdfServiceQueryContext(rdfService, query);
}
public static interface SelectQueryContext {
public SelectQueryContext bindVariableToUri(String name, String uri);
public ExecutingSelectQueryContext execute();
}
public static interface ExecutingSelectQueryContext {
public StringResultsMapping getStringFields(String... fieldNames);
}
public static interface StringResultsMapping extends
List<Map<String, String>> {
public List<String> flatten();
public Set<String> flattenToSet();
}
// ----------------------------------------------------------------------
// Helper classes
// ----------------------------------------------------------------------
static class StringResultsMappingImpl extends
ArrayList<Map<String, String>> implements StringResultsMapping {
@Override
public List<String> flatten() {
List<String> flat = new ArrayList<>();
for (Map<String, String> map : this) {
flat.addAll(map.values());
}
return flat;
}
@Override
public Set<String> flattenToSet() {
return new HashSet<>(flatten());
}
}
}

View file

@ -1,6 +1,6 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils;
package edu.cornell.mannlib.vitro.webapp.utils.sparql;
import java.util.Arrays;
import java.util.Iterator;

View file

@ -0,0 +1,87 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.Syntax;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.ConstructQueryContext;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.ExecutingConstructQueryContext;
/**
* TODO
*/
public class ModelConstructQueryContext implements ConstructQueryContext {
private static final Log log = LogFactory
.getLog(ModelConstructQueryContext.class);
private static final Syntax SYNTAX = Syntax.syntaxARQ;
private final Model model;
private final QueryHolder query;
public ModelConstructQueryContext(Model model, QueryHolder query) {
this.model = model;
this.query = query;
}
@Override
public ConstructQueryContext bindVariableToUri(String name, String uri) {
return new ModelConstructQueryContext(model, query.bindToUri(name, uri));
}
@Override
public ConstructQueryContext bindVariableToPlainLiteral(String name,
String value) {
return new ModelConstructQueryContext(model, query.bindToPlainLiteral(
name, value));
}
@Override
public String toString() {
return "ModelConstructQueryContext[query=" + query + "]";
}
@Override
public ExecutingConstructQueryContext execute() {
return new ModelExecutingConstructQueryContext(model, query);
}
private static class ModelExecutingConstructQueryContext implements
ExecutingConstructQueryContext {
private final Model model;
private final QueryHolder query;
public ModelExecutingConstructQueryContext(Model model, QueryHolder query) {
this.model = model;
this.query = query;
}
@Override
public Model toModel() {
QueryExecution qe = null;
try {
Query q = QueryFactory.create(query.getQueryString(), SYNTAX);
qe = QueryExecutionFactory.create(q, model);
return qe.execConstruct();
} catch (Exception e) {
log.error(
"problem while running query '"
+ query.getQueryString() + "'", e);
return ModelFactory.createDefaultModel();
} finally {
if (qe != null) {
qe.close();
}
}
}
}
}

View file

@ -0,0 +1,129 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.ResultSet;
import org.apache.jena.query.ResultSetFormatter;
import org.apache.jena.query.Syntax;
import org.apache.jena.rdf.model.Model;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.ExecutingSelectQueryContext;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.SelectQueryContext;
/**
* An implementation of QueryContext based on a Model.
*
* Package access. Instances should be created only by SparqlQueryRunner, or by
* a method on this class.
*/
class ModelSelectQueryContext implements SelectQueryContext {
private static final Log log = LogFactory
.getLog(ModelSelectQueryContext.class);
private static final Syntax SYNTAX = Syntax.syntaxARQ;
private final Model model;
private final QueryHolder query;
public ModelSelectQueryContext(Model model, QueryHolder query) {
this.model = model;
this.query = query;
}
@Override
public ModelSelectQueryContext bindVariableToUri(String name, String uri) {
return new ModelSelectQueryContext(model, query.bindToUri(name, uri));
}
@Override
public ModelSelectQueryContext bindVariableToPlainLiteral(String name,
String value) {
return new ModelSelectQueryContext(model, query.bindToPlainLiteral(
name, value));
}
@Override
public String toString() {
return "ModelSelectQueryContext[query=" + query + "]";
}
@Override
public ExecutingSelectQueryContext execute() {
return new ModelExecutingQueryContext(model, query);
}
private static class ModelExecutingQueryContext implements
ExecutingSelectQueryContext {
private final Model model;
private final QueryHolder query;
public ModelExecutingQueryContext(Model model, QueryHolder query) {
this.model = model;
this.query = query;
}
@Override
public StringResultsMapping toStringFields(String... names) {
String qString = query.getQueryString();
Set<String> fieldNames = new HashSet<>(Arrays.asList(names));
try {
Query q = QueryFactory.create(qString, SYNTAX);
QueryExecution qexec = QueryExecutionFactory.create(q, model);
try {
ResultSet results = qexec.execSelect();
return new StringResultsMapping(results, fieldNames);
} finally {
qexec.close();
}
} catch (Exception e) {
log.error("problem while running query '" + qString + "'", e);
return StringResultsMapping.EMPTY;
}
}
@Override
public <T> T parse(ResultSetParser<T> parser) {
String qString = query.getQueryString();
try {
Query q = QueryFactory.create(qString, SYNTAX);
QueryExecution qexec = QueryExecutionFactory.create(q, model);
try {
return parser.parseResults(qString, qexec.execSelect());
} finally {
qexec.close();
}
} catch (Exception e) {
log.error("problem while running query '" + qString + "'", e);
return parser.defaultValue();
}
}
@Override
public void writeToOutput(OutputStream output) {
String qString = query.getQueryString();
try {
Query q = QueryFactory.create(qString, SYNTAX);
QueryExecution qexec = QueryExecutionFactory.create(q, model);
try {
ResultSetFormatter.outputAsJSON(output, qexec.execSelect());
} finally {
qexec.close();
}
} catch (Exception e) {
log.error("problem while running query '" + qString + "'", e);
}
}
}
}

View file

@ -0,0 +1,79 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner;
import java.util.Objects;
import java.util.regex.Pattern;
/**
* Holds the text of a SPARQL query, and allows you to perform some lexical
* operations on it.
*
* This is immutable, so don't forget to get the result of the operations.
*/
public class QueryHolder {
private final String queryString;
public QueryHolder(String queryString) {
this.queryString = Objects.requireNonNull(queryString);
}
public String getQueryString() {
return queryString;
}
public boolean hasVariable(String name) {
String regex = "\\?" + name + "\\b";
return Pattern.compile(regex).matcher(queryString).find();
}
public QueryHolder bindToUri(String name, String uri) {
String regex = "\\?" + name + "\\b";
String replacement = "<" + uri + ">";
String bound = replaceWithinBraces(regex, replacement);
return new QueryHolder(bound);
}
public QueryHolder bindToPlainLiteral(String name, String value) {
String regex = "\\?" + name + "\\b";
String replacement = '"' + value + '"';
String bound = replaceWithinBraces(regex, replacement);
return new QueryHolder(bound);
}
private String replaceWithinBraces(String regex, String replacement) {
int openBrace = queryString.indexOf('{');
int closeBrace = queryString.lastIndexOf('}');
if (openBrace == -1 || closeBrace == -1) {
return queryString;
} else {
String prefix = queryString.substring(0, openBrace);
String suffix = queryString.substring(closeBrace);
String patterns = queryString.substring(openBrace, closeBrace);
return prefix + patterns.replaceAll(regex, replacement) + suffix;
}
}
@Override
public int hashCode() {
return queryString.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (obj == null) {
return false;
} else if (getClass() != obj.getClass()) {
return false;
}
QueryHolder that = (QueryHolder) obj;
return Objects.equals(this.queryString, that.queryString);
}
@Override
public String toString() {
return "QueryHolder[" + queryString + "]";
}
}

View file

@ -0,0 +1,130 @@
# A conversational API for running SPARQL queries
`edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner` provides a syntactically simple
way to manipulate and execute SPARQL queries. The query may be run against a Jena `Model`
or a Vitro `RDFService`.
The API supports the most common tasks:
+ bind URI values to variables in the query.
+ bind plain literal values to variables in the query.
+ execute a CONSTRUCT query and return a Jena model.
+ execute a SELECT query and return the results in a variety of formats:
+ a List of String values
+ a Set of String values
+ a List of Maps of String values
+ a JSON-formatted output stream
+ the output of a custom parser class.
The API could reasonably be extended to perform other operations, or to produce
additional forms of output. It currently provides only the functionality that
was immediately useful at the time of writing.
## Usage Examples
In general, the usage pattern is to
+ create the query context
+ optionally bind values to variables in the query
+ execute
+ transform the results
### SELECT to a List of Strings
Run a SELECT query, binding a value to the variable `?uri` and returning
a List of the values that are returned for the variable `?partner`.
List<String> values = createSelectQueryContext(rdfService, queryString)
.bindVariableToUri("uri", uri)
.execute()
.toStringFields("partner")
.flatten();
### SELECT to a List of Maps
Example: Run a SELECT query, returning a list of maps of strings. Each map
represents a record in the ResultSet, with variable names mapped to the
value in that record, translated to a String.
List<Map<String, String>> maps = createSelectQueryContext(model, queryString)
.execute()
.toStringFields()
.getListOfMaps();
>_Note: Null or empty values are omitted from the maps; empty maps are omitted from the list._
### SELECT to a Parser
MyQueryResult mqr = createSelectQueryContext(model, queryString)
.bindVariableToUri("uri", uri)
.bindVariableToPlainLiteral("id", "PW-4250")
.execute()
.parse(new MyQueryParser());
### CONSTRUCT to a Model
Model m = createConstructQueryContext(rdfService, queryString)
.execute()
.toModel();
## Using the QueryHolder
The `QueryHolder` class can be useful in itself, for manipulating a query string.
### Bind variables in a query
String boundQuery = queryHolder(rawQuery)
.bindToUri("uri", uri)
.getQueryString();
### Inquire about unbound variables
boolean foundIt = queryHolder(rawQuery)
.hasVariable("name");
### Prepare a query in advance of executing it.
QueryHolder qh = queryHolder(queryString)
.bindToUri("uri", uri));
.bindVariableToPlainLiteral("id", "PW-4250")
List<Map<String, String> map = createSelectQueryContext(model, qh)
.execute()
.toStringFields()
.getListOfMaps();
## Parsing a ResultSet
By writing a parser, you can translate the `ResultSet` from a SPARQL query
into any object, according to the translation algorithm you specify. You must
provide the parser with both a parsing method and a default value. The parser
will return the default value if the parsing method fails for any reason. In
this way, you are assured that the parser will not throw an exception.
Here is an example of a simple parser. It inspects the first record in the
result set and builds an `ItemInfo` object.
private static class ExpandProfileParser extends ResultSetParser<ItemInfo> {
@Override
protected ItemInfo defaultValue() {
return new ItemInfo();
}
@Override
protected ItemInfo parseResults(String queryStr, ResultSet results) {
ItemInfo item = new ItemInfo();
if (results.hasNext()) {
QuerySolution solution = results.next();
item.label = ifLiteralPresent(solution, "label", "");
item.classLabel = ifLiteralPresent(solution, "classLabel", "");
item.imageUrl = ifLiteralPresent(solution, "imageUrl", "");
}
return item;
}
}
This parser would be used in this way:
ItemInfo info = createSelectQueryContext(model, queryString)
.execute()
.parse(new ExpandProfileParser());

View file

@ -0,0 +1,88 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner;
import static edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService.ModelSerializationFormat.NTRIPLE;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.ConstructQueryContext;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.ExecutingConstructQueryContext;
/**
* TODO
*/
public class RdfServiceConstructQueryContext implements ConstructQueryContext {
private static final Log log = LogFactory
.getLog(RdfServiceConstructQueryContext.class);
private final RDFService rdfService;
private final QueryHolder query;
public RdfServiceConstructQueryContext(RDFService rdfService,
QueryHolder query) {
this.rdfService = rdfService;
this.query = query;
}
@Override
public ConstructQueryContext bindVariableToUri(String name, String uri) {
return new RdfServiceConstructQueryContext(rdfService, query.bindToUri(
name, uri));
}
@Override
public ConstructQueryContext bindVariableToPlainLiteral(String name,
String value) {
return new RdfServiceConstructQueryContext(rdfService,
query.bindToPlainLiteral(name, value));
}
@Override
public ExecutingConstructQueryContext execute() {
return new RdfServiceExecutingConstructQueryContext(rdfService, query);
}
@Override
public String toString() {
return "RdfServiceConstructQueryContext[query=" + query + "]";
}
private static class RdfServiceExecutingConstructQueryContext implements
ExecutingConstructQueryContext {
private final RDFService rdfService;
private final QueryHolder query;
public RdfServiceExecutingConstructQueryContext(RDFService rdfService,
QueryHolder query) {
this.rdfService = rdfService;
this.query = query;
}
@Override
public Model toModel() {
QueryExecution qe = null;
try {
return RDFServiceUtils.parseModel(rdfService
.sparqlConstructQuery(query.getQueryString(), NTRIPLE),
NTRIPLE);
} catch (Exception e) {
log.error(
"problem while running query '"
+ query.getQueryString() + "'", e);
return ModelFactory.createDefaultModel();
} finally {
if (qe != null) {
qe.close();
}
}
}
}
}

View file

@ -0,0 +1,116 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner;
import static edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService.ResultFormat.JSON;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.query.ResultSet;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.ExecutingSelectQueryContext;
import edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.SelectQueryContext;
/**
* An implementation of QueryContext based on an RDFService.
*
* Package access. Instances should be created only by SparqlQueryRunner, or by
* a method on this class.
*/
class RdfServiceSelectQueryContext implements SelectQueryContext {
private static final Log log = LogFactory
.getLog(RdfServiceSelectQueryContext.class);
private final RDFService rdfService;
private final QueryHolder query;
RdfServiceSelectQueryContext(RDFService rdfService, QueryHolder query) {
this.rdfService = rdfService;
this.query = query;
}
@Override
public RdfServiceSelectQueryContext bindVariableToUri(String name,
String uri) {
return new RdfServiceSelectQueryContext(rdfService, query.bindToUri(
name, uri));
}
@Override
public RdfServiceSelectQueryContext bindVariableToPlainLiteral(String name,
String value) {
return new RdfServiceSelectQueryContext(rdfService,
query.bindToPlainLiteral(name, value));
}
@Override
public String toString() {
return "RdfServiceSelectQueryContext[query=" + query + "]";
}
@Override
public ExecutingSelectQueryContext execute() {
return new RdfServiceExecutingQueryContext(rdfService, query);
}
private static class RdfServiceExecutingQueryContext implements
ExecutingSelectQueryContext {
private final RDFService rdfService;
private final QueryHolder query;
public RdfServiceExecutingQueryContext(RDFService rdfService,
QueryHolder query) {
this.rdfService = rdfService;
this.query = query;
}
@Override
public StringResultsMapping toStringFields(String... names) {
Set<String> fieldNames = new HashSet<>(Arrays.asList(names));
try {
ResultSet results = RDFServiceUtils.sparqlSelectQuery(
query.getQueryString(), rdfService);
return new StringResultsMapping(results, fieldNames);
} catch (Exception e) {
log.error(
"problem while running query '"
+ query.getQueryString() + "'", e);
return StringResultsMapping.EMPTY;
}
}
@Override
public <T> T parse(ResultSetParser<T> parser) {
String qString = query.getQueryString();
try {
return parser.parseResults(qString,
RDFServiceUtils.sparqlSelectQuery(qString, rdfService));
} catch (Exception e) {
log.error("problem while running query '" + qString + "'", e);
return parser.defaultValue();
}
}
@Override
public void writeToOutput(OutputStream output) {
try {
InputStream resultStream = rdfService.sparqlSelectQuery(
query.getQueryString(), JSON);
IOUtils.copy(resultStream, output);
} catch (Exception e) {
log.error(
"problem while running query '"
+ query.getQueryString() + "'", e);
}
}
}
}

View file

@ -0,0 +1,57 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.RDFNode;
/**
* Define the interface for parsing a result set, and provide some helpful
* methods as well.
*/
public abstract class ResultSetParser<T> {
protected abstract T parseResults(String queryStr, ResultSet results);
protected abstract T defaultValue();
protected String ifResourcePresent(QuerySolution solution,
String variableName, String defaultValue) {
RDFNode node = solution.get(variableName);
if (node == null || !node.isURIResource()) {
return defaultValue;
}
return node.asResource().getURI();
}
protected String ifLiteralPresent(QuerySolution solution,
String variableName, String defaultValue) {
Literal literal = solution.getLiteral(variableName);
if (literal == null) {
return defaultValue;
} else {
return literal.getString();
}
}
protected long ifLongPresent(QuerySolution solution, String variableName,
long defaultValue) {
Literal literal = solution.getLiteral(variableName);
if (literal == null) {
return defaultValue;
} else {
return literal.getLong();
}
}
protected int ifIntPresent(QuerySolution solution, String variableName,
int defaultValue) {
Literal literal = solution.getLiteral(variableName);
if (literal == null) {
return defaultValue;
} else {
return literal.getInt();
}
}
}

View file

@ -0,0 +1,127 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner;
import java.io.OutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.rdf.model.Model;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
/**
* A conversational tool for handling SPARQL queries.
*
* <pre>
* Examples:
* List<String> values = createSelectQueryContext(rdfService, queryString)
* .bindVariableToUri("uri", uri)
* .execute()
* .toStringFields("partner")
* .flatten();
*
* QueryHolder qh = queryHolder(queryString)
* .bindToUri("uri", uri));
* List<Map<String, String> map = createSelectQueryContext(model, qh)
* .execute()
* .toStringFields();
* </pre>
*
* The query context can come from either an RDFService or a Model.
*
* The execute() method does not actually execute the query: it merely sets it
* up syntactically.
*
* If you don't supply any field names to toStringFields(), you get all of
* them.
*
* Any string value that returns a blank or empty string is omitted from the
* results. Any row that returns no values is omitted from the results.
*/
public final class SparqlQueryRunner {
private static final Log log = LogFactory.getLog(SparqlQueryRunner.class);
private SparqlQueryRunner() {
// No need to create an instance.
}
public static QueryHolder queryHolder(String queryString) {
return new QueryHolder(queryString);
}
// ------------- SELECT ----------- //
public static SelectQueryContext createSelectQueryContext(RDFService rdfService,
String queryString) {
return createSelectQueryContext(rdfService, queryHolder(queryString));
}
public static SelectQueryContext createSelectQueryContext(RDFService rdfService,
QueryHolder query) {
return new RdfServiceSelectQueryContext(rdfService, query);
}
public static SelectQueryContext createSelectQueryContext(Model model,
String queryString) {
return createSelectQueryContext(model, queryHolder(queryString));
}
public static SelectQueryContext createSelectQueryContext(Model model,
QueryHolder query) {
return new ModelSelectQueryContext(model, query);
}
public static interface SelectQueryContext {
public SelectQueryContext bindVariableToUri(String name, String uri);
public SelectQueryContext bindVariableToPlainLiteral(String name,
String value);
public ExecutingSelectQueryContext execute();
}
public static interface ExecutingSelectQueryContext {
public StringResultsMapping toStringFields(String... fieldNames);
public <T> T parse(ResultSetParser<T> parser);
public void writeToOutput(OutputStream output);
}
// ------------- CONSTRUCT ----------- //
public static ConstructQueryContext createConstructQueryContext(RDFService rdfService,
String queryString) {
return createConstructQueryContext(rdfService, queryHolder(queryString));
}
public static ConstructQueryContext createConstructQueryContext(RDFService rdfService,
QueryHolder query) {
return new RdfServiceConstructQueryContext(rdfService, query);
}
public static ConstructQueryContext createConstructQueryContext(Model model,
String queryString) {
return createConstructQueryContext(model, queryHolder(queryString));
}
public static ConstructQueryContext createConstructQueryContext(Model model,
QueryHolder query) {
return new ModelConstructQueryContext(model, query);
}
public static interface ConstructQueryContext{
public ConstructQueryContext bindVariableToUri(String name, String uri);
public ConstructQueryContext bindVariableToPlainLiteral(String name,
String value);
public ExecutingConstructQueryContext execute();
}
public static interface ExecutingConstructQueryContext {
public Model toModel();
}
}

View file

@ -0,0 +1,95 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.RDFNode;
/**
* Parse the set of fieldNames against the results of the query, and make the
* extracted values available.
*/
public class StringResultsMapping {
public static final StringResultsMapping EMPTY = new StringResultsMapping();
private final List<Map<String, String>> listOfMaps;
public StringResultsMapping() {
this.listOfMaps = Collections.emptyList();
}
public StringResultsMapping(ResultSet results, Set<String> fieldNames) {
this.listOfMaps = mapResultsForQuery(results, fieldNames);
}
private List<Map<String, String>> mapResultsForQuery(ResultSet results,
Set<String> fieldNames) {
List<Map<String, String>> mapping = new ArrayList<>();
while (results.hasNext()) {
Map<String, String> rowMapping = mapResultsForRow(
results.nextSolution(), fieldNames);
if (!rowMapping.isEmpty()) {
mapping.add(rowMapping);
}
}
return mapping;
}
private Map<String, String> mapResultsForRow(QuerySolution row,
Set<String> fieldNames) {
Map<String, String> map = new HashMap<>();
for (Iterator<String> names = row.varNames(); names.hasNext();) {
String name = names.next();
RDFNode node = row.get(name);
String text = getTextForNode(node);
if (StringUtils.isNotBlank(text)) {
map.put(name, text);
}
}
if (!fieldNames.isEmpty()) {
map.keySet().retainAll(fieldNames);
}
return map;
}
private String getTextForNode(RDFNode node) {
if (node == null) {
return "";
} else if (node.isLiteral()) {
return node.asLiteral().getString().trim();
} else {
return node.toString().trim();
}
}
public List<Map<String, String>> getListOfMaps() {
List<Map<String, String>> list = new ArrayList<>();
for (Map<String, String> map: listOfMaps) {
list.add(new HashMap<>(map));
}
return list;
}
public List<String> flatten() {
List<String> flat = new ArrayList<>();
for (Map<String, String> map : listOfMaps) {
flat.addAll(map.values());
}
return flat;
}
public Set<String> flattenToSet() {
return new HashSet<>(flatten());
}
}