Adding object property statement consideration to search index updating NIHVIVO-2910

This commit is contained in:
briancaruso 2011-07-15 15:04:31 +00:00
parent 8fadbbb01a
commit d34f951ef0
3 changed files with 247 additions and 0 deletions

View file

@ -0,0 +1,144 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.search.indexing;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
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.search.beans.AdditionalURIsToIndex;
/**
* For a given statement, return the URIs that may need to be updated in
* the search index because of their object property relations to the resources
* in the statement.
*
* Context nodes are not handled here. They are taken care of in AdditionalURIsForContextNodex.
*/
public class AdditionalURIsForObjectProperties implements AdditionalURIsToIndex {
protected static final Log log = LogFactory.getLog(AdditionalURIsForObjectProperties.class);
protected Model model;
public AdditionalURIsForObjectProperties( Model model){
this.model = model;
}
@Override
public List<String> findAdditionalURIsToIndex(Statement stmt) {
if( stmt == null )
return Collections.emptyList();
if( stmt.getObject().isLiteral() )
return doDataPropertyStmt( stmt );
else
return doObjectPropertyStmt( stmt );
}
protected List<String> doObjectPropertyStmt(Statement stmt) {
// Only need to consider the object since the subject
// will already be updated in search index as part of
// SearchReindexingListener.
// Also, context nodes are not handled here. They are
// taken care of in AdditionalURIsForContextNodex.
if( stmt.getObject().isURIResource() )
return Collections.singletonList( stmt.getObject().as(Resource.class).getURI() );
else
return Collections.emptyList();
}
protected List<String> doDataPropertyStmt(Statement stmt) {
if( RDFS.label.equals( stmt.getPredicate() )){
// If the property is rdfs:labe then we need to update
// all the individuals related by object properties. This
// does not need to account for context nodes as that
// is handled in AdditionalURIsForContextNodex.
if( stmt.getSubject().isURIResource() ){
return allIndividualsRelatedByObjectPropertyStmts( stmt.getSubject().getURI() );
}else{
log.debug("ignored bnode");
return Collections.emptyList();
}
}else{
// This class does not need to account for context nodes because that
// is handled in AdditionalURIsForContextNodex.
return Collections.emptyList();
}
}
protected List<String> allIndividualsRelatedByObjectPropertyStmts( String uri ) {
List<String> additionalUris = new ArrayList<String>();
QuerySolutionMap initialBinding = new QuerySolutionMap();
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<String> 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");
}
}
}
}catch(Throwable t){
log.error(t,t);
} finally{
qExec.close();
}
}finally{
model.getLock().leaveCriticalSection();
}
return additionalUris;
}
protected static final String prefixs =
"prefix owl: <http://www.w3.org/2002/07/owl#> \n" +
"prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n" +
"prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n";
protected final String QUERY_FOR_RELATED =
prefixs +
"SELECT ?related WHERE { \n" +
" ?uri ?p ?related \n " +
" filter( isURI( ?related ) && ?p != rdf:type ) \n" +
"}" ;
}

View file

@ -36,6 +36,7 @@ import edu.cornell.mannlib.vitro.webapp.search.beans.FileBasedProhibitedFromSear
import edu.cornell.mannlib.vitro.webapp.search.beans.IndividualProhibitedFromSearchImpl; import edu.cornell.mannlib.vitro.webapp.search.beans.IndividualProhibitedFromSearchImpl;
import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch; import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch;
import edu.cornell.mannlib.vitro.webapp.search.indexing.AdditionalURIsForContextNodes; import edu.cornell.mannlib.vitro.webapp.search.indexing.AdditionalURIsForContextNodes;
import edu.cornell.mannlib.vitro.webapp.search.indexing.AdditionalURIsForObjectProperties;
import edu.cornell.mannlib.vitro.webapp.search.indexing.IndexBuilder; import edu.cornell.mannlib.vitro.webapp.search.indexing.IndexBuilder;
import edu.cornell.mannlib.vitro.webapp.search.indexing.SearchReindexingListener; import edu.cornell.mannlib.vitro.webapp.search.indexing.SearchReindexingListener;
import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup; import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup;
@ -113,6 +114,7 @@ public class SolrSetup implements javax.servlet.ServletContextListener{
//make objects that will find additional URIs for context nodes etc //make objects that will find additional URIs for context nodes etc
List<AdditionalURIsToIndex> uriFinders = new ArrayList<AdditionalURIsToIndex>(); List<AdditionalURIsToIndex> uriFinders = new ArrayList<AdditionalURIsToIndex>();
uriFinders.add( new AdditionalURIsForObjectProperties(jenaOntModel) );
uriFinders.add( new AdditionalURIsForContextNodes(jenaOntModel) ); uriFinders.add( new AdditionalURIsForContextNodes(jenaOntModel) );
// set up listeners so search index builder is notified of changes to model // set up listeners so search index builder is notified of changes to model

View file

@ -0,0 +1,101 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.search.indexing;
import java.io.StringReader;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDFS;
public class AdditionalURIsForObjectPropertiesTest {
Model model;
String testNS = "http://example.com/test#";
String n3 = "" +
"@prefix owl: <http://www.w3.org/2002/07/owl#> .\n" +
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . \n" +
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . \n" +
"@prefix test: <"+ testNS + "> . \n" +
"\n" +
"test:bob rdfs:label \"Mr Bob\" . \n" +
"test:bob test:hatsize \"8 1/2 inches\" . \n" +
"test:bob test:likes test:icecream . \n" +
"test:bob test:likes test:onions . \n" +
"test:bob test:likes test:cheese . \n" +
"test:bob a test:Person . \n" +
"test:bob a owl:Thing . \n" +
"test:bob test:likes [ rdfs:label \"this is a blank node\" ] . ";
@Before
public void setUp() throws Exception {
model = ModelFactory.createDefaultModel();
model.read(new StringReader(n3 ), null , "N3");
}
@Test
public void testChangeOfRdfsLabel() {
AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(model);
List<String> uris = aufop.findAdditionalURIsToIndex(
ResourceFactory.createStatement(
ResourceFactory.createResource(testNS + "bob"),
RDFS.label,
ResourceFactory.createPlainLiteral("Some new label for bob")));
Assert.assertNotNull(uris);
Assert.assertTrue("uris was empty", uris.size() > 0 );
Assert.assertTrue("uris didn't not contain test:onions", uris.contains(testNS+"onions"));
Assert.assertTrue("uris didn't not contain test:cheese", uris.contains(testNS+"cheese"));
Assert.assertTrue("uris didn't not contain test:icecream", uris.contains(testNS+"icecream"));
Assert.assertTrue("uris contained test:Person", !uris.contains(testNS+"Person"));
Assert.assertTrue("uris contained owl:Thing", !uris.contains( OWL.Thing.getURI() ));
Assert.assertEquals(3, uris.size());
}
@Test
public void testChangeOfObjPropStmt() {
AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(model);
List<String> uris = aufop.findAdditionalURIsToIndex(
ResourceFactory.createStatement(
ResourceFactory.createResource(testNS + "bob"),
ResourceFactory.createProperty(testNS+"likes"),
ResourceFactory.createResource(testNS+"cheese")));
Assert.assertNotNull(uris);
Assert.assertTrue("uris was empty", uris.size() > 0 );
Assert.assertTrue("uris didn't not contain test:cheese", uris.contains(testNS+"cheese"));
Assert.assertTrue("uris contained test:Person", !uris.contains(testNS+"Person"));
Assert.assertTrue("uris contained owl:Thing", !uris.contains( OWL.Thing.getURI() ));
Assert.assertTrue("uris contained test:onions", !uris.contains(testNS+"onions"));
Assert.assertTrue("uris contained test:icecream", !uris.contains(testNS+"icecream"));
Assert.assertEquals(1, uris.size());
}
@Test
public void testOfDataPropChange() {
AdditionalURIsForObjectProperties aufop = new AdditionalURIsForObjectProperties(model);
List<String> uris = aufop.findAdditionalURIsToIndex(
ResourceFactory.createStatement(
ResourceFactory.createResource(testNS + "bob"),
ResourceFactory.createProperty(testNS+"hatsize"),
ResourceFactory.createPlainLiteral("Some new hat size for bob")));
Assert.assertNotNull(uris);
Assert.assertTrue("uris was not empty", uris.size() == 0 );
}
}