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());
}
}

View file

@ -31,6 +31,11 @@ public class ModelUtilitiesTestHelper {
createResource(classUri));
}
public static Statement objectProperty(String subjectUri, String propertyUri) {
return createStatement(createResource(subjectUri),
createProperty(propertyUri), createResource());
}
public static Statement objectProperty(String subjectUri,
String propertyUri, String objectUri) {
return createStatement(createResource(subjectUri),

View file

@ -16,7 +16,6 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Level;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
@ -29,7 +28,6 @@ import org.apache.jena.rdf.model.ModelFactory;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ProxyRelationshipSelectionCriteria.ProxyRelationshipView;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ProxyRelationshipSelector.Context;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner;
/**
* TODO

View file

@ -1,92 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils;
import static org.junit.Assert.*;
import static edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.*;
import org.junit.Test;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
/**
* For now, just test the methods that manipulate the query string.
*/
public class SparqlQueryRunnerTest extends AbstractTestClass {
@Test
public void bindValuesNameNotFound() {
String raw = "No such name here";
String expected = raw;
assertEquals(expected, bindValues(raw, uriValue("bogus", "BOGUS")));
}
@Test
public void bindOneUri() {
String raw = "Replace both ?this and ?this also.";
String expected = "Replace both <URI> and <URI> also.";
assertEquals(expected, bindValues(raw, uriValue("this", "URI")));
}
@Test
public void bindTwoUris() {
String raw = "Replace both ?this and ?that also.";
String expected = "Replace both <URI> and <ANOTHER> also.";
assertEquals(
expected,
bindValues(raw, uriValue("this", "URI"),
uriValue("that", "ANOTHER")));
}
@Test
public void honorWordBoundary() {
String raw = "Replace ?this but not ?thistle.";
String expected = "Replace <URI> but not ?thistle.";
assertEquals(expected, bindValues(raw, uriValue("this", "URI")));
}
@Test
public void honorStringLimit() {
String raw = "?this";
String expected = "<URI>";
assertEquals(expected, bindValues(raw, uriValue("this", "URI")));
}
private static final String REAL_WORLD_RAW = "" //
+ "PREFIX : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" //
+ "\n" //
+ "SELECT DISTINCT ?context ?config \n" //
+ "WHERE { \n" //
+ " ?context a :ConfigContext ; \n" //
+ " :configContextFor ?baseUri ; \n" //
+ " :qualifiedByDomain ?domainUri ; \n" //
+ " :qualifiedBy ?rangeUri ; \n" //
+ " :hasConfiguration ?config . \n" //
+ "} \n"; //
private static final String REAL_WORLD_EXPECTED = "" //
+ "PREFIX : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" //
+ "\n" //
+ "SELECT DISTINCT ?context ?config \n" //
+ "WHERE { \n" //
+ " ?context a :ConfigContext ; \n" //
+ " :configContextFor <http://vivoweb.org/ontology/core#relates> ; \n" //
+ " :qualifiedByDomain <http://vivoweb.org/ontology/core#Contract> ; \n" //
+ " :qualifiedBy <http://vivoweb.org/ontology/core#ResearcherRole> ; \n" //
+ " :hasConfiguration ?config . \n" //
+ "} \n"; //
@Test
public void realWorldExample() {
assertEquals(
REAL_WORLD_EXPECTED,
bindValues(
REAL_WORLD_RAW,
uriValue("baseUri",
"http://vivoweb.org/ontology/core#relates"),
uriValue("domainUri",
"http://vivoweb.org/ontology/core#Contract"),
uriValue("rangeUri",
"http://vivoweb.org/ontology/core#ResearcherRole")));
}
}

View file

@ -0,0 +1,155 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner;
import static org.junit.Assert.*;
import org.junit.Test;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
/**
* Check the functionality of QueryHolder.
*/
public class QueryHolderTest extends AbstractTestClass {
private static final String SOME_URI = "http://some.uri/";
private static final String SOME_LITERAL = "abracadabra";
private static final String FIND_ONCE = "SELECT ?s ?p WHERE { ?s ?p ?bindMe }";
private static final String URI_BOUND_ONCE = "SELECT ?s ?p WHERE { ?s ?p <"
+ SOME_URI + "> }";
private static final String LITERAL_BOUND_ONCE = "SELECT ?s ?p WHERE { ?s ?p \""
+ SOME_LITERAL + "\" }";
private static final String FIND_TWICE = "CONSTRUCT { ?s ?p ?find_twice } WHERE { ?s ?p ?find_twice }";
private static final String URI_BOUND_TWICE = "CONSTRUCT { ?s ?p <"
+ SOME_URI + "> } WHERE { ?s ?p <" + SOME_URI + "> }";
private static final String LITERAL_BOUND_TWICE = "CONSTRUCT { ?s ?p \""
+ SOME_LITERAL + "\" } WHERE { ?s ?p \"" + SOME_LITERAL + "\" }";
private static final String SQUEEZED = "CONSTRUCT {?s ?p ?squeeze} WHERE {?s ?p ?squeeze}";
private static final String URI_BOUND_SQUEEZED = "CONSTRUCT {?s ?p <"
+ SOME_URI + ">} WHERE {?s ?p <" + SOME_URI + ">}";
private static final String LITERAL_BOUND_SQUEEZED = "CONSTRUCT {?s ?p \""
+ SOME_LITERAL + "\"} WHERE {?s ?p \"" + SOME_LITERAL + "\"}";
private static final String FIND_IN_SELECT_CLAUSE = "SELECT ?s ?p ?bindMe WHERE { ?s ?p ?bindMe }";
private static final String URI_BOUND_IN_SELECT_CLAUSE = "SELECT ?s ?p ?bindMe WHERE { ?s ?p <"
+ SOME_URI + "> }";
// ----------------------------------------------------------------------
// The tests
// ----------------------------------------------------------------------
@Test
public void hasVariable_findsOne() {
assertTrue(new QueryHolder(FIND_ONCE).hasVariable("bindMe"));
}
@Test
public void hasVariable_findsTwo() {
assertTrue(new QueryHolder(FIND_TWICE).hasVariable("find_twice"));
}
@Test
public void hasVariable_doesntFindOne() {
assertFalse(new QueryHolder(FIND_TWICE).hasVariable("notThere"));
}
@Test
public void hasVariable_notFooledByExtendedName() {
assertFalse(new QueryHolder(FIND_ONCE).hasVariable("bind"));
}
@Test
public void hasVariable_notFooledByPunctuation() {
assertTrue(new QueryHolder(SQUEEZED).hasVariable("squeeze"));
}
@Test
public void bindToUri_notFound_noComplaint() {
bindToUri(FIND_ONCE, "notThere", SOME_URI).yields(FIND_ONCE);
}
@Test
public void bindToUri_findsOne_bindsIt() {
bindToUri(FIND_ONCE, "bindMe", SOME_URI).yields(URI_BOUND_ONCE);
}
@Test
public void bindToUri_findsTwo_bindsBoth() {
bindToUri(FIND_TWICE, "find_twice", SOME_URI).yields(URI_BOUND_TWICE);
}
@Test
public void bindToUri_notFooledByExtendedName() {
bindToUri(FIND_ONCE, "bind", SOME_URI).yields(FIND_ONCE);
}
@Test
public void bindToUri_notFooledByPunctuation() {
bindToUri(SQUEEZED, "squeeze", SOME_URI).yields(URI_BOUND_SQUEEZED);
}
@Test
public void bindToPlainLiteral_notFound_noComplaint() {
bindToLiteral(FIND_ONCE, "notThere", SOME_LITERAL).yields(FIND_ONCE);
}
@Test
public void bindToPlainLiteral_findsOne_bindsIt() {
bindToLiteral(FIND_ONCE, "bindMe", SOME_LITERAL)
.yields(LITERAL_BOUND_ONCE);
}
@Test
public void bindToPlainLiteral_findsTwo_bindsBoth() {
bindToLiteral(FIND_TWICE, "find_twice", SOME_LITERAL)
.yields(LITERAL_BOUND_TWICE);
}
@Test
public void bindToPlainLiteral_notFooledByExtendedName() {
bindToLiteral(FIND_ONCE, "bind", SOME_LITERAL).yields(FIND_ONCE);
}
@Test
public void bindToPlainLiteral_notFooledByPunctuation() {
bindToLiteral(SQUEEZED, "squeeze", SOME_LITERAL)
.yields(LITERAL_BOUND_SQUEEZED);
}
@Test
public void variableInSelectClauseIsLeftAlone() {
bindToUri(FIND_IN_SELECT_CLAUSE, "bindMe", SOME_URI)
.yields(URI_BOUND_IN_SELECT_CLAUSE);
}
// ----------------------------------------------------------------------
// Helper methods and classes
// ----------------------------------------------------------------------
private Yielder bindToUri(String query, String name, String uri) {
QueryHolder holder = new QueryHolder(query);
QueryHolder bound = holder.bindToUri(name, uri);
return new Yielder(bound.getQueryString());
}
private Yielder bindToLiteral(String query, String name, String value) {
QueryHolder holder = new QueryHolder(query);
QueryHolder bound = holder.bindToPlainLiteral(name, value);
return new Yielder(bound.getQueryString());
}
private class Yielder {
private final String actual;
public Yielder(String actual) {
this.actual = actual;
}
void yields(String expected) {
assertEquals(expected, actual);
}
}
}

View file

@ -0,0 +1,331 @@
/* $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.testing.ModelUtilitiesTestHelper.dataProperty;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.model;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.objectProperty;
import static org.apache.jena.datatypes.xsd.XSDDatatype.XSDinteger;
import static org.apache.jena.datatypes.xsd.XSDDatatype.XSDlong;
import static org.junit.Assert.assertEquals;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.log4j.Level;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
public class ResultSetParserTest extends AbstractTestClass {
private static final String NAMESPACE = "http://namespace#";
private static final String SUBJECT = NAMESPACE + "subject";
private static final String PREDICATE_URI = NAMESPACE + "uri";
private static final String OBJECT_URI = NAMESPACE + "objectUri";
private static final String OBJECT_URI_DEFAULT = NAMESPACE
+ "objectUriDefault";
private static final String PREDICATE_ANON = NAMESPACE + "anonymous";
private static final String OBJECT_ANON_DEFAULT = NAMESPACE + "anonDefault";
private static final String PREDICATE_STRING = NAMESPACE + "string";
private static final String OBJECT_STRING = "objectString";
private static final String OBJECT_STRING_DEFAULT = "objectStringDefault";
private static final String PREDICATE_INT = NAMESPACE + "int";
private static final Integer OBJECT_INT = 4;
private static final Integer OBJECT_INT_DEFAULT = -1;
private static final String PREDICATE_LONG = NAMESPACE + "long";
private static final Long OBJECT_LONG = 888L;
private static final Long OBJECT_LONG_DEFAULT = -333L;
private static final Object PARSING_FAILURE = "PARSING_FAILURE";
private static final Object NO_RECORDS_FOUND = "NO_RECORDS_FOUND";
private static final String SELECT_QUERY = "" //
+ "SELECT ?uri ?anonymous ?string ?int ?long \n" //
+ "WHERE { \n" //
+ " ?s <" + PREDICATE_URI + "> ?uri . \n" //
+ " ?s <" + PREDICATE_ANON + "> ?anon . \n" //
+ " ?s <" + PREDICATE_STRING + "> ?string . \n" //
+ " ?s <" + PREDICATE_INT + "> ?int . \n" //
+ " ?s <" + PREDICATE_LONG + "> ?long . \n" //
+ "} \n";
private Model model;
@Before
public void setup() {
setLoggerLevel(ModelSelectQueryContext.class, Level.OFF);
model = model(objectProperty(SUBJECT, PREDICATE_URI, OBJECT_URI),
objectProperty(SUBJECT, PREDICATE_ANON),
dataProperty(SUBJECT, PREDICATE_STRING, OBJECT_STRING),
dataProperty(SUBJECT, PREDICATE_INT, OBJECT_INT, XSDinteger),
dataProperty(SUBJECT, PREDICATE_LONG, OBJECT_LONG, XSDlong));
}
// ----------------------------------------------------------------------
// The tests
// ----------------------------------------------------------------------
@Test
public void errorInParse_yieldsDefaultValue() {
assertParsingResult(PARSING_FAILURE, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
throw new RuntimeException("I refuse to parse this!");
}
});
}
// ----------------------------------------------------------------------
@Test
public void expectedUriFoundUri() {
assertParsingResult(OBJECT_URI, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifResourcePresent(solution, "uri", OBJECT_URI_DEFAULT);
}
});
}
@Test
public void expectedUriFoundNothing_returnsDefault() {
assertParsingResult(OBJECT_URI_DEFAULT, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifResourcePresent(solution, "nothing",
OBJECT_URI_DEFAULT);
}
});
}
/**
* TODO Ignoring because the anonymous node isn't showing up in the
* ResultSet. Why not? Anyway, this behaves like "foundNothing".
*/
@Test
@Ignore
public void expectedUriFoundAnonymous_returnsDefault() {
assertParsingResult(OBJECT_URI_DEFAULT, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifResourcePresent(solution, "anon", OBJECT_URI_DEFAULT);
}
});
}
@Test
public void expectedUriFoundString_returnsDefault() {
assertParsingResult(OBJECT_URI_DEFAULT, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifResourcePresent(solution, "string", OBJECT_URI_DEFAULT);
}
});
}
// ----------------------------------------------------------------------
@Test
public void expectedStringFoundString() {
assertParsingResult(OBJECT_STRING, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifLiteralPresent(solution, "string",
OBJECT_STRING_DEFAULT);
}
});
}
@Test
public void expectedStringFoundNothing_returnsDefault() {
assertParsingResult(OBJECT_STRING_DEFAULT, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifLiteralPresent(solution, "nothing",
OBJECT_STRING_DEFAULT);
}
});
}
@Test
public void expectedStringFoundResource_fails() {
assertParsingResult(PARSING_FAILURE, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifLiteralPresent(solution, "uri", OBJECT_STRING_DEFAULT);
}
});
}
@Test
public void expectedStringFoundInt_returnsStringValueOfInt() {
assertParsingResult(OBJECT_INT.toString(), new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifLiteralPresent(solution, "int", OBJECT_STRING_DEFAULT);
}
});
}
// ----------------------------------------------------------------------
@Test
public void expectedIntFoundInt() {
assertParsingResult(OBJECT_INT, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifIntPresent(solution, "int", OBJECT_INT_DEFAULT);
}
});
}
@Test
public void expectedIntFoundNothing() {
assertParsingResult(OBJECT_INT_DEFAULT, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifIntPresent(solution, "nothing", OBJECT_INT_DEFAULT);
}
});
}
@Test
public void expectedIntFoundResource_fails() {
assertParsingResult(PARSING_FAILURE, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifIntPresent(solution, "uri", OBJECT_INT_DEFAULT);
}
});
}
@Test
public void expectedIntFoundString_fails() {
assertParsingResult(PARSING_FAILURE, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifIntPresent(solution, "string", OBJECT_INT_DEFAULT);
}
});
}
@Test
public void expectedIntFoundLong() {
assertParsingResult(new Integer(OBJECT_LONG.intValue()),
new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifIntPresent(solution, "long",
OBJECT_INT_DEFAULT);
}
});
}
// ----------------------------------------------------------------------
@Test
public void expectedLongFoundLong() {
assertParsingResult(OBJECT_LONG, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifLongPresent(solution, "long", OBJECT_LONG_DEFAULT);
}
});
}
@Test
public void expectedLongFoundNothing() {
assertParsingResult(OBJECT_LONG_DEFAULT, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifLongPresent(solution, "nothing", OBJECT_LONG_DEFAULT);
}
});
}
@Test
public void expectedLongFoundResource_fails() {
assertParsingResult(PARSING_FAILURE, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifLongPresent(solution, "uri", OBJECT_LONG_DEFAULT);
}
});
}
@Test
public void expectedLongFoundString_fails() {
assertParsingResult(PARSING_FAILURE, new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifLongPresent(solution, "string", OBJECT_LONG_DEFAULT);
}
});
}
@Test
public void expectedLongFoundInt() {
assertParsingResult(new Long(OBJECT_INT), new BaseParser() {
@Override
Object parseOneLine(QuerySolution solution) {
return ifLongPresent(solution, "int", OBJECT_LONG_DEFAULT);
}
});
}
/**
* <pre>
* ifLongPresent, return value or default.
* present, absent
* </pre>
*/
// ----------------------------------------------------------------------
// Helper methods
// ----------------------------------------------------------------------
private void assertParsingResult(Object expected, BaseParser parser) {
Object actual = SparqlQueryRunner
.createSelectQueryContext(model, SELECT_QUERY).execute()
.parse(parser);
assertEquals(expected, actual);
}
private abstract static class BaseParser extends ResultSetParser<Object> {
@Override
protected Object defaultValue() {
return PARSING_FAILURE;
}
@Override
protected Object parseResults(String queryStr, ResultSet results) {
if (results.hasNext()) {
return parseOneLine(results.next());
} else {
return NO_RECORDS_FOUND;
}
}
abstract Object parseOneLine(QuerySolution solution);
}
// private String dumpSolution(QuerySolution solution) {
// Map<String, Object> fields = new HashMap<>();
// Iterator<String> names = solution.varNames();
// while (names.hasNext()) {
// String name = names.next();
// fields.put(name, solution.get(name));
// }
// return fields.toString();
// }
//
}

View file

@ -0,0 +1,170 @@
/* $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.testing.ModelUtilitiesTestHelper.dataProperty;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.model;
import static edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.createConstructQueryContext;
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.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;
import org.apache.jena.atlas.json.JSON;
import org.apache.jena.atlas.json.JsonObject;
import org.apache.jena.rdf.model.Model;
import org.junit.Before;
import org.junit.Test;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel;
/**
* Top-level smoke tests for the SparqlQueryRunnerTest. Exercise all of the
* methods that create contexts, and show that we can do the simplest of
* operations against them.
*/
public class SparqlQueryRunnerTest extends AbstractTestClass {
private static final String SUBJECT_URI = "http://namespace/subject_uri";
private static final String PREDICATE_URI = "http://namespace/predicate_uri";
private static final String OBJECT_VALUE = "object_value";
private static final String SELECT_QUERY = "SELECT ?s ?p ?o WHERE { ?s ?p ?o . }";
private static final JsonObject EXPECTED_SELECT_RESULTS = JSON.parse(""
+ "{ " //
+ " 'head' : { " //
+ " 'vars' : [ 's', 'p', 'o' ] " //
+ " } , " //
+ " 'results' : { " //
+ " 'bindings' : [ " //
+ " { " //
+ " 'p' : { " //
+ " 'type' : 'uri' , " //
+ " 'value' : 'http://namespace/predicate_uri' " //
+ " } , " //
+ " 'o' : { " //
+ " 'type' : 'literal' , " //
+ " 'value' : 'object_value' " //
+ " } , " //
+ " 's' : { " //
+ " 'type' : 'uri' , " //
+ " 'value' : 'http://namespace/subject_uri' " //
+ " } " //
+ " } " //
+ " ] " //
+ " } " //
+ "} ");
private static final String CONSTRUCT_QUERY = "CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }";
private Model model;
private RDFService rdfService;
private ByteArrayOutputStream buffer;
private Model constructed;
@Before
public void setup() {
model = model(dataProperty(SUBJECT_URI, PREDICATE_URI, OBJECT_VALUE));
rdfService = new RDFServiceModel(model);
buffer = new ByteArrayOutputStream();
}
// ----------------------------------------------------------------------
// SELECT tests
// ----------------------------------------------------------------------
@Test
public void selectQueryAgainstModel() {
createSelectQueryContext(model, SELECT_QUERY).execute().writeToOutput(
buffer);
assertExpectedSelectResults();
}
@Test
public void selectQueryHolderAgainstModel() {
createSelectQueryContext(model, queryHolder(SELECT_QUERY)).execute()
.writeToOutput(buffer);
assertExpectedSelectResults();
}
@Test
public void selectQueryAgainstRDFService() {
createSelectQueryContext(rdfService, SELECT_QUERY).execute()
.writeToOutput(buffer);
assertExpectedSelectResults();
}
@Test
public void selectQueryHolderAgainstRDFService() {
createSelectQueryContext(rdfService, queryHolder(SELECT_QUERY))
.execute().writeToOutput(buffer);
assertExpectedSelectResults();
}
/**
* We've shown that all select contexts work. It should suffice that one of
* them can convert to string fields.
*/
@Test
public void selectToStringFields() {
List<String> objectValues = createSelectQueryContext(model,
SELECT_QUERY).execute().toStringFields("o").flatten();
assertEquals(Arrays.asList(OBJECT_VALUE), objectValues);
}
// ----------------------------------------------------------------------
// CONSTRUCT tests
// ----------------------------------------------------------------------
@Test
public void constructQueryAgainstModel() {
constructed = createConstructQueryContext(model, CONSTRUCT_QUERY)
.execute().toModel();
assertExpectedConstructResults();
}
@Test
public void constructQueryHolderAgainstModel() {
constructed = createConstructQueryContext(model,
queryHolder(CONSTRUCT_QUERY)).execute().toModel();
assertExpectedConstructResults();
}
@Test
public void constructQueryAgainstRDFService() {
constructed = createConstructQueryContext(rdfService, CONSTRUCT_QUERY)
.execute().toModel();
assertExpectedConstructResults();
}
@Test
public void constructQueryHolderAgainstRDFService() {
constructed = createConstructQueryContext(rdfService,
queryHolder(CONSTRUCT_QUERY)).execute().toModel();
assertExpectedConstructResults();
}
// ----------------------------------------------------------------------
// Helper methods
// ----------------------------------------------------------------------
private void assertExpectedSelectResults() {
try {
JsonObject actual = JSON.parse(buffer.toString("UTF-8"));
assertEquals(EXPECTED_SELECT_RESULTS, actual);
} catch (UnsupportedEncodingException e) {
fail(e.toString());
}
}
private void assertExpectedConstructResults() {
assertEquals(model.listStatements().toSet(), constructed
.listStatements().toSet());
}
}

View file

@ -0,0 +1,140 @@
/* $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.testing.ModelUtilitiesTestHelper.dataProperty;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.model;
import static edu.cornell.mannlib.vitro.webapp.utils.sparqlrunner.SparqlQueryRunner.createSelectQueryContext;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.apache.jena.rdf.model.Model;
import org.junit.Before;
import org.junit.Test;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
public class StringResultsMappingTest extends AbstractTestClass {
private static final String SUBJECT_URI_1 = "http://namespace/subject_uri_1";
private static final String PREDICATE_URI_1 = "http://namespace/predicate_uri_1";
private static final String OBJECT_VALUE_1 = "object_value_1";
private static final String SUBJECT_URI_2 = "http://namespace/subject_uri_2";
private static final String PREDICATE_URI_2 = "http://namespace/predicate_uri_2";
private static final String OBJECT_VALUE_2 = "object_value_2";
private static final String SELECT_QUERY = "SELECT ?s ?p ?o WHERE { ?s ?p ?o . }";
private static final List<Map<String, String>> LIST_ALL_FIELDS = list(
map(entry("s", SUBJECT_URI_1), entry("p", PREDICATE_URI_1),
entry("o", OBJECT_VALUE_1)),
map(entry("s", SUBJECT_URI_2), entry("p", PREDICATE_URI_2),
entry("o", OBJECT_VALUE_2)));
private static final List<Map<String, String>> LIST_ONE_FIELD = list(
map(entry("o", OBJECT_VALUE_1)), map(entry("o", OBJECT_VALUE_2)));
private static final List<String> FLATTEN_ALL_FIELDS = list(SUBJECT_URI_1,
PREDICATE_URI_1, OBJECT_VALUE_1, SUBJECT_URI_2, PREDICATE_URI_2,
OBJECT_VALUE_2);
private static final List<String> FLATTEN_ONE_FIELD = list(OBJECT_VALUE_1,
OBJECT_VALUE_2);
private Model model;
@Before
public void setup() {
model = model(
dataProperty(SUBJECT_URI_1, PREDICATE_URI_1, OBJECT_VALUE_1),
dataProperty(SUBJECT_URI_2, PREDICATE_URI_2, OBJECT_VALUE_2));
}
@Test
public void checkMapsOfAllFields() {
assertEquivalentUnorderedLists(LIST_ALL_FIELDS,
createSelectQueryContext(model, SELECT_QUERY).execute()
.toStringFields().getListOfMaps());
}
@Test
public void checkMapsOfOneField() {
assertEquivalentUnorderedLists(LIST_ONE_FIELD,
createSelectQueryContext(model, SELECT_QUERY).execute()
.toStringFields("o").getListOfMaps());
}
@Test
public void checkFlattenAllFields() {
assertEquivalentUnorderedLists(FLATTEN_ALL_FIELDS,
createSelectQueryContext(model, SELECT_QUERY).execute()
.toStringFields().flatten());
}
@Test
public void checkFlattenOneField() {
assertEquivalentUnorderedLists(FLATTEN_ONE_FIELD,
createSelectQueryContext(model, SELECT_QUERY).execute()
.toStringFields("o").flatten());
}
@Test
public void checkFlattenToSet() {
assertEquals(new HashSet<>(FLATTEN_ONE_FIELD),
createSelectQueryContext(model, SELECT_QUERY).execute()
.toStringFields("o").flattenToSet());
}
// ----------------------------------------------------------------------
// Helper methods
// ----------------------------------------------------------------------
private <T> void assertEquivalentUnorderedLists(List<T> list1, List<T> list2) {
Collections.sort(list1, new ArbitraryOrder<>());
Collections.sort(list2, new ArbitraryOrder<>());
assertEquals(list1, list2);
}
private static class ArbitraryOrder<T> implements Comparator<T> {
@Override
public int compare(T t1, T t2) {
return t1.hashCode() - t2.hashCode();
}
}
@SafeVarargs
private static <T> List<T> list(T... items) {
List<T> l = new ArrayList<>();
for (T item : items) {
l.add(item);
}
return l;
}
private static Map<String, String> map(Entry... entries) {
Map<String, String> m = new HashMap<>();
for (Entry entry : entries) {
m.put(entry.key, entry.value);
}
return m;
}
private static Entry entry(String key, String value) {
return new Entry(key, value);
}
private static class Entry {
final String key;
final String value;
Entry(String key, String value) {
this.key = key;
this.value = value;
}
}
}