From 5d19e746e111ecb5e19758ff7b5b204c54635fba Mon Sep 17 00:00:00 2001 From: j2blake Date: Thu, 7 Nov 2013 12:36:05 -0500 Subject: [PATCH] VIVO-469 run the URL Finders from an RDFService, not an OntModel --- .../vitro/webapp/dao/jena/QueryUtils.java | 41 ++++++++++- .../AdditionalURIsForObjectProperties.java | 69 ++++++++----------- .../search/indexing/AdditionalUriFinders.java | 7 +- .../vitro/webapp/search/solr/SolrSetup.java | 4 +- .../vitro/webapp/dao/jena/QueryUtilsTest.java | 65 +++++++++++++++++ ...AdditionalURIsForObjectPropertiesTest.java | 16 +++-- 6 files changed, 149 insertions(+), 53 deletions(-) create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtilsTest.java diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtils.java index f2c686657..c056a28ec 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtils.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -116,7 +117,11 @@ public class QueryUtils { return getQueryResults(queryStr, vreq.getRDFService()); } - public static ResultSet getLanguageNeutralQueryResults(String queryStr, VitroRequest vreq) { + public static ResultSet getQueryResults(String queryStr, QuerySolution initialBindings, RDFService rdfService) { + return getQueryResults(bindVariables(queryStr, initialBindings), rdfService); + } + + public static ResultSet getLanguageNeutralQueryResults(String queryStr, VitroRequest vreq) { return getQueryResults(queryStr, vreq.getUnfilteredRDFService()); } @@ -130,4 +135,38 @@ public class QueryUtils { } } + /** + * The RDFService interface doesn't support initial bindings, so do text + * substitutions instead. + */ + public static String bindVariables(String queryStr, + QuerySolution initialBindings) { + String bound = queryStr; + for (Iterator it = initialBindings.varNames(); it.hasNext();) { + String name = it.next(); + RDFNode node = initialBindings.get(name); + if (node.isLiteral()) { + bound = bound.replace('?' + name, literalToString(node.asLiteral())); + } else if (node.isURIResource()) { + bound = bound.replace('?' + name, '<'+node.asResource().getURI()+ '>'); + }else { + log.warn("Failed to bind anonymous resource variable '" + name + + "' to query '" + bound + "'"); + } + } + return bound; + } + + private static String literalToString(Literal l) { + StringBuilder buffer = new StringBuilder(); + buffer.append('"').append(l.getLexicalForm()).append('"'); + if (l.getDatatypeURI() != null) { + buffer.append("^^<").append(l.getDatatypeURI()).append(">"); + } else if (StringUtils.isNotEmpty(l.getLanguage())) { + buffer.append("@").append(l.getLanguage()); + } + return buffer.toString(); + } + + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalURIsForObjectProperties.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalURIsForObjectProperties.java index ba6d6d1e8..38fdf1ea7 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalURIsForObjectProperties.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalURIsForObjectProperties.java @@ -10,22 +10,17 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.hp.hpl.jena.query.Query; -import com.hp.hpl.jena.query.QueryExecution; -import com.hp.hpl.jena.query.QueryExecutionFactory; -import com.hp.hpl.jena.query.QueryFactory; import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.QuerySolutionMap; import com.hp.hpl.jena.query.ResultSet; -import com.hp.hpl.jena.query.Syntax; -import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.rdf.model.Statement; -import com.hp.hpl.jena.shared.Lock; import com.hp.hpl.jena.vocabulary.RDFS; +import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.search.beans.StatementToURIsToUpdate; /** @@ -38,13 +33,13 @@ import edu.cornell.mannlib.vitro.webapp.search.beans.StatementToURIsToUpdate; public class AdditionalURIsForObjectProperties implements StatementToURIsToUpdate { protected static final Log log = LogFactory.getLog(AdditionalURIsForObjectProperties.class); - protected Model model; + protected final RDFService rdfService; - public AdditionalURIsForObjectProperties( Model model){ - this.model = model; - } - - @Override + public AdditionalURIsForObjectProperties(RDFService rdfService) { + this.rdfService = rdfService; + } + + @Override public List findAdditionalURIsToIndex(Statement stmt) { if( stmt == null ) return Collections.emptyList(); @@ -102,37 +97,27 @@ public class AdditionalURIsForObjectProperties implements StatementToURIsToUpdat Resource uriResource = ResourceFactory.createResource(uri); initialBinding.add("uri", uriResource); - Query sparqlQuery = QueryFactory.create( QUERY_FOR_RELATED ); - model.getLock().enterCriticalSection(Lock.READ); - try{ - QueryExecution qExec = QueryExecutionFactory.create(sparqlQuery, model, initialBinding); - try{ - ResultSet results = qExec.execSelect(); - while(results.hasNext()){ - QuerySolution soln = results.nextSolution(); - Iterator iter = soln.varNames() ; - while( iter.hasNext()){ - String name = iter.next(); - RDFNode node = soln.get( name ); - if( node != null ){ - if( node.isURIResource() ){ - additionalUris.add( node.as( Resource.class ).getURI() ); - }else{ - log.warn( "value from query for var " + name + " was not a URIResource, it was " + node); - } - }else{ - log.warn("value for query for var " + name + " was null"); - } + ResultSet results = QueryUtils.getQueryResults(QUERY_FOR_RELATED, + initialBinding, rdfService); + + while(results.hasNext()){ + QuerySolution soln = results.nextSolution(); + Iterator iter = soln.varNames() ; + while( iter.hasNext()){ + String name = iter.next(); + RDFNode node = soln.get( name ); + if( node != null ){ + if( node.isURIResource() ){ + additionalUris.add( node.as( Resource.class ).getURI() ); + }else{ + log.warn( "value from query for var " + name + " was not a URIResource, it was " + node); } - } - }catch(Throwable t){ - log.error(t,t); - } finally{ - qExec.close(); - } - }finally{ - model.getLock().leaveCriticalSection(); + }else{ + log.warn("value for query for var " + name + " was null"); + } + } } + return additionalUris; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalUriFinders.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalUriFinders.java index 498d74334..4758de021 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalUriFinders.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalUriFinders.java @@ -5,9 +5,8 @@ package edu.cornell.mannlib.vitro.webapp.search.indexing; import java.util.ArrayList; import java.util.List; -import com.hp.hpl.jena.ontology.OntModel; - import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.search.beans.StatementToURIsToUpdate; /** @@ -16,12 +15,12 @@ import edu.cornell.mannlib.vitro.webapp.search.beans.StatementToURIsToUpdate; */ public class AdditionalUriFinders { - public static List getList(OntModel jenaOntModel, + public static List getList(RDFService rdfService, IndividualDao indDao) { // TODO How many of these are only relevant to VIVO? List uriFinders = new ArrayList<>(); uriFinders.add(new AdditionalURIsForDataProperties()); - uriFinders.add(new AdditionalURIsForObjectProperties(jenaOntModel)); + uriFinders.add(new AdditionalURIsForObjectProperties(rdfService)); uriFinders.add(new AdditionalURIsForTypeStatements()); uriFinders.add(new URIsForClassGroupChange(indDao)); return uriFinders; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SolrSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SolrSetup.java index 04ae6971d..883418cee 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SolrSetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/SolrSetup.java @@ -23,6 +23,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.filtering.WebappDaoFactoryFiltering; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilterUtils; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters; import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils; import edu.cornell.mannlib.vitro.webapp.search.beans.StatementToURIsToUpdate; @@ -133,7 +134,8 @@ public class SolrSetup implements javax.servlet.ServletContextListener{ wadf = new WebappDaoFactoryFiltering(wadf, vf); // make objects that will find additional URIs for context nodes etc - List uriFinders = AdditionalUriFinders.getList(jenaOntModel,wadf.getIndividualDao()); + RDFService rdfService = RDFServiceUtils.getRDFServiceFactory(context).getRDFService(); + List uriFinders = AdditionalUriFinders.getList(rdfService,wadf.getIndividualDao()); // Make the IndexBuilder IndexBuilder builder = new IndexBuilder( solrIndexer, wadf, uriFinders ); diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtilsTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtilsTest.java new file mode 100644 index 000000000..837c5cf50 --- /dev/null +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/QueryUtilsTest.java @@ -0,0 +1,65 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.dao.jena; + +import static org.junit.Assert.*; + +import org.junit.Ignore; +import org.junit.Test; + +import com.hp.hpl.jena.query.QuerySolutionMap; +import com.hp.hpl.jena.rdf.model.Literal; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.ResourceFactory; + +import edu.cornell.mannlib.vitro.testing.AbstractTestClass; + +/** + * TODO + */ +public class QueryUtilsTest extends AbstractTestClass { + private QuerySolutionMap bindings = new QuerySolutionMap(); + + @Test + public void bindResource() { + bindings.add("uri", ResourceFactory.createResource("http://my.uri")); + assertBoundQueryEquals("a resource ?uri", "a resource "); + } + + @Test + public void bindPlainLiteral() { + bindings.add("plain", ResourceFactory.createPlainLiteral("too easy")); + assertBoundQueryEquals("This is ?plain ?plain", + "This is \"too easy\" \"too easy\""); + } + + @Test + public void bindTypedLiteral() { + bindings.add("typed", ResourceFactory.createTypedLiteral(100L)); + assertBoundQueryEquals("take this ?typed number", + "take this \"100\"^^ number"); + } + + @Test + public void bindLanguageLiteral() { + Literal l = ModelFactory.createDefaultModel().createLiteral("Spanish", + "es-ES"); + bindings.add("lang", l); + assertBoundQueryEquals("speak my ?lang?", "speak my \"Spanish\"@es-ES?"); + } + + @Ignore + @Test + public void bindAnon() { + fail("bindAnon not implemented"); + } + + // ---------------------------------------------------------------------- + // Helper methods + // ---------------------------------------------------------------------- + + private void assertBoundQueryEquals(String template, String expected) { + String actual = QueryUtils.bindVariables(template, bindings); + assertEquals("bounding results", expected, actual); + } +} diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalURIsForObjectPropertiesTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalURIsForObjectPropertiesTest.java index eeacf0e6f..5b91a3816 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalURIsForObjectPropertiesTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/search/indexing/AdditionalURIsForObjectPropertiesTest.java @@ -15,9 +15,13 @@ import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDFS; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; +import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel; + public class AdditionalURIsForObjectPropertiesTest { Model model; + RDFService rdfService; String testNS = "http://example.com/test#"; String n3 = "" + @@ -39,11 +43,12 @@ public class AdditionalURIsForObjectPropertiesTest { public void setUp() throws Exception { model = ModelFactory.createDefaultModel(); model.read(new StringReader(n3 ), null , "N3"); + rdfService = new RDFServiceModel(model); } @Test public void testChangeOfRdfsLabel() { - AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(model); + AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(rdfService); List uris = aufop.findAdditionalURIsToIndex( ResourceFactory.createStatement( ResourceFactory.createResource(testNS + "bob"), @@ -66,7 +71,7 @@ public class AdditionalURIsForObjectPropertiesTest { @Test public void testChangeOfObjPropStmt() { - AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(model); + AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(rdfService); List uris = aufop.findAdditionalURIsToIndex( ResourceFactory.createStatement( ResourceFactory.createResource(testNS + "bob"), @@ -88,7 +93,7 @@ public class AdditionalURIsForObjectPropertiesTest { @Test public void testOfDataPropChange() { - AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(model); + AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(rdfService); List uris = aufop.findAdditionalURIsToIndex( ResourceFactory.createStatement( ResourceFactory.createResource(testNS + "bob"), @@ -107,8 +112,9 @@ public class AdditionalURIsForObjectPropertiesTest { Model model = ModelFactory.createDefaultModel(); model.read(new StringReader( n3ForNIHVIVO_2902 ), null , "N3"); - - AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(model); + RDFService rdfService = new RDFServiceModel(model); + + AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(rdfService); List uris = aufop.findAdditionalURIsToIndex( ResourceFactory.createStatement( ResourceFactory.createResource("http://caruso-laptop.mannlib.cornell.edu:8090/vivo/individual/n2241"),