Adding object property statement consideration to search index updating NIHVIVO-2910
This commit is contained in:
parent
8fadbbb01a
commit
d34f951ef0
3 changed files with 247 additions and 0 deletions
|
@ -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" +
|
||||
"}" ;
|
||||
}
|
|
@ -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.ProhibitedFromSearch;
|
||||
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.SearchReindexingListener;
|
||||
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
|
||||
List<AdditionalURIsToIndex> uriFinders = new ArrayList<AdditionalURIsToIndex>();
|
||||
uriFinders.add( new AdditionalURIsForObjectProperties(jenaOntModel) );
|
||||
uriFinders.add( new AdditionalURIsForContextNodes(jenaOntModel) );
|
||||
|
||||
// set up listeners so search index builder is notified of changes to model
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue