VIVO-907 Create the TripleStoreQuirks interface

Use it to handle the odd behavior that a particular triple store might have.
In this case, the odd behavior is that TDB mangles XMLSchema#nonNegativeInteger to XMLSchema#integer in literal types.
This commit is contained in:
Jim Blake 2014-11-17 13:21:36 -05:00
parent 546e27c15a
commit 61eb57ca5d
9 changed files with 137 additions and 3 deletions

View file

@ -24,4 +24,7 @@ public interface TripleSource extends Application.Module{
OntModelCache getShortTermOntModels(RDFService shortTermRdfService,
OntModelCache longTermOntModelCache);
/** Ways in which this TripleSource behaves oddly. */
TripleStoreQuirks getQuirks();
}

View file

@ -0,0 +1,18 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.modules.tripleSource;
import com.hp.hpl.jena.rdf.model.Model;
/**
* TODO
*/
public interface TripleStoreQuirks {
/**
* Test to see whether the FileGraph must be updated to reflect the current
* state of the file.
*/
boolean hasFileGraphChanged(Model fromFile, Model previous, String graphURI);
}

View file

@ -218,12 +218,15 @@ public class FileGraphSetup implements ServletContextListener {
path.getFileName(), dbModel.size(), fileModel.size()));
boolean isIsomorphic = dbModel.isIsomorphicWith(fileModel);
// Isomorphism has some quirky issues with TDB, and perhaps also with Virtuoso.
boolean isChanged = ApplicationUtils.instance()
.getContentTripleSource().getQuirks()
.hasFileGraphChanged(fileModel, dbModel, graphURI);
if (dbModel.isEmpty() && !fileModel.isEmpty()) {
dbModel.add(fileModel);
modelChanged = true;
} else if (!isIsomorphic) {
} else if (isChanged) {
log.info("Updating " + path + " because graphs are not isomorphic");
log.info("dbModel: " + dbModel.size() + " ; fileModel: " + fileModel.size());
dbModel.removeAll();

View file

@ -0,0 +1,19 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.triplesource.impl;
import com.hp.hpl.jena.rdf.model.Model;
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.TripleStoreQuirks;
/**
* The behavior for non-quirky TripleSource implementations.
*/
public class DefaultTripleStoreQuirks implements TripleStoreQuirks {
@Override
public boolean hasFileGraphChanged(Model fromFile, Model previous, String graphURI) {
return !fromFile.isIsomorphicWith(previous);
}
}

View file

@ -38,11 +38,13 @@ import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.UnionModelsOntMode
import edu.cornell.mannlib.vitro.webapp.modules.Application;
import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource;
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.TripleStoreQuirks;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.sdb.RDFServiceFactorySDB;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.logging.LoggingRDFServiceFactory;
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase;
import edu.cornell.mannlib.vitro.webapp.triplesource.impl.DefaultTripleStoreQuirks;
import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
/**
@ -76,6 +78,8 @@ public class ContentTripleSourceSDB extends ContentTripleSource {
static final boolean DEFAULT_TESTONBORROW = true;
static final boolean DEFAULT_TESTONRETURN = true;
private final TripleStoreQuirks quirks = new DefaultTripleStoreQuirks();
private ServletContext ctx;
private ComboPooledDataSource ds;
@ -205,6 +209,11 @@ public class ContentTripleSourceSDB extends ContentTripleSource {
return new UnionModelsOntModelsCache(combinedCache, CONTENT_UNIONS);
}
@Override
public TripleStoreQuirks getQuirks() {
return quirks;
}
@Override
public String toString() {
return "ContentTripleSourceSDB[" + ToString.hashHex(this) + "]";

View file

@ -13,11 +13,13 @@ import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.OntModelCache;
import edu.cornell.mannlib.vitro.webapp.modules.Application;
import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource;
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.TripleStoreQuirks;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceFactorySingle;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.logging.LoggingRDFServiceFactory;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.sparql.RDFServiceSparql;
import edu.cornell.mannlib.vitro.webapp.triplesource.impl.DefaultTripleStoreQuirks;
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.logging.ToString;
@ -35,6 +37,8 @@ import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
public class ContentTripleSourceSPARQL extends ContentTripleSource {
private String endpointURI;
private String updateEndpointURI; // Optional
private final TripleStoreQuirks quirks = new DefaultTripleStoreQuirks();
private RDFService rdfService;
private RDFServiceFactory rdfServiceFactory;
@ -132,6 +136,11 @@ public class ContentTripleSourceSPARQL extends ContentTripleSource {
return longTermOntModelCache;
}
@Override
public TripleStoreQuirks getQuirks() {
return quirks;
}
@Override
public String toString() {
return "ContentTripleSourceSPARQL[" + ToString.hashHex(this)

View file

@ -18,6 +18,7 @@ import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.OntModelCache;
import edu.cornell.mannlib.vitro.webapp.modules.Application;
import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource;
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.TripleStoreQuirks;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceFactorySingle;
@ -39,9 +40,10 @@ import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
* Memory-map all of the configuration models, and add the standard decorators.
*/
public class ConfigurationTripleSourceTDB extends ConfigurationTripleSource {
private static final String DIRECTORY_TDB = "tdbModels";
private final TripleStoreQuirks quirks = new TDBTripleStoreQuirks();
private volatile RDFService rdfService;
private RDFServiceFactory rdfServiceFactory;
private RDFService unclosableRdfService;
@ -112,6 +114,11 @@ public class ConfigurationTripleSourceTDB extends ConfigurationTripleSource {
return longTermOntModelCache;
}
@Override
public TripleStoreQuirks getQuirks() {
return quirks;
}
@Override
public String toString() {
return "ConfigurationTripleSourceTDB[" + ToString.hashHex(this) + "]";

View file

@ -16,6 +16,7 @@ import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.OntModelCache;
import edu.cornell.mannlib.vitro.webapp.modules.Application;
import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource;
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.TripleStoreQuirks;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory;
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceFactorySingle;
@ -39,6 +40,8 @@ import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
* Memory-map the small content models, and add the standard decorators.
*/
public class ContentTripleSourceTDB extends ContentTripleSource {
private final TripleStoreQuirks quirks = new TDBTripleStoreQuirks();
private String tdbPath;
private volatile RDFService rdfService;
@ -124,6 +127,11 @@ public class ContentTripleSourceTDB extends ContentTripleSource {
return longTermOntModelCache;
}
@Override
public TripleStoreQuirks getQuirks() {
return quirks;
}
@Override
public String toString() {
return "ContentTripleSourceTDB[" + ToString.hashHex(this) + "]";

View file

@ -0,0 +1,58 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.triplesource.impl.tdb;
import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDinteger;
import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDnonNegativeInteger;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import edu.cornell.mannlib.vitro.webapp.triplesource.impl.DefaultTripleStoreQuirks;
/**
* TDB has some odd behaviors to deal with.
*/
public class TDBTripleStoreQuirks extends DefaultTripleStoreQuirks {
private static final Log log = LogFactory
.getLog(TDBTripleStoreQuirks.class);
/**
* When the file graph was previously written to the TDB store, TDB mangled
* some of the literal types: any type of XMLSchema#nonNegativeInteger was
* changed to XMLSchema#integer.
*
* We need to mangle our new model in the same way before comparing to the
* previous one.
*/
@Override
public boolean hasFileGraphChanged(Model fromFile, Model previous,
String graphURI) {
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
fromFile.write(buffer, "N-TRIPLE");
String fromString = buffer.toString("UTF-8");
String mangleString = fromString.replace(
XSDnonNegativeInteger.getURI(), XSDinteger.getURI());
InputStream mangleStream = new ByteArrayInputStream(
mangleString.getBytes("UTF-8"));
Model mangled = ModelFactory.createDefaultModel();
mangled.read(mangleStream, null, "N-TRIPLE");
return !mangled.isIsomorphicWith(previous);
} catch (Exception e) {
log.warn("Failed to test for changes in filegraph. "
+ "Change assumed.", e);
return true;
}
}
}