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:
parent
546e27c15a
commit
61eb57ca5d
9 changed files with 137 additions and 3 deletions
|
@ -24,4 +24,7 @@ public interface TripleSource extends Application.Module{
|
||||||
|
|
||||||
OntModelCache getShortTermOntModels(RDFService shortTermRdfService,
|
OntModelCache getShortTermOntModels(RDFService shortTermRdfService,
|
||||||
OntModelCache longTermOntModelCache);
|
OntModelCache longTermOntModelCache);
|
||||||
|
|
||||||
|
/** Ways in which this TripleSource behaves oddly. */
|
||||||
|
TripleStoreQuirks getQuirks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -218,12 +218,15 @@ public class FileGraphSetup implements ServletContextListener {
|
||||||
path.getFileName(), dbModel.size(), fileModel.size()));
|
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()) {
|
if (dbModel.isEmpty() && !fileModel.isEmpty()) {
|
||||||
dbModel.add(fileModel);
|
dbModel.add(fileModel);
|
||||||
modelChanged = true;
|
modelChanged = true;
|
||||||
} else if (!isIsomorphic) {
|
} else if (isChanged) {
|
||||||
log.info("Updating " + path + " because graphs are not isomorphic");
|
log.info("Updating " + path + " because graphs are not isomorphic");
|
||||||
log.info("dbModel: " + dbModel.size() + " ; fileModel: " + fileModel.size());
|
log.info("dbModel: " + dbModel.size() + " ; fileModel: " + fileModel.size());
|
||||||
dbModel.removeAll();
|
dbModel.removeAll();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.Application;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
|
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.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.RDFService;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory;
|
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.jena.sdb.RDFServiceFactorySDB;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.logging.LoggingRDFServiceFactory;
|
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.servlet.setup.JenaDataSourceSetupBase;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.triplesource.impl.DefaultTripleStoreQuirks;
|
||||||
import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
|
import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,6 +79,8 @@ public class ContentTripleSourceSDB extends ContentTripleSource {
|
||||||
static final boolean DEFAULT_TESTONBORROW = true;
|
static final boolean DEFAULT_TESTONBORROW = true;
|
||||||
static final boolean DEFAULT_TESTONRETURN = true;
|
static final boolean DEFAULT_TESTONRETURN = true;
|
||||||
|
|
||||||
|
private final TripleStoreQuirks quirks = new DefaultTripleStoreQuirks();
|
||||||
|
|
||||||
private ServletContext ctx;
|
private ServletContext ctx;
|
||||||
private ComboPooledDataSource ds;
|
private ComboPooledDataSource ds;
|
||||||
private RDFServiceFactory rdfServiceFactory;
|
private RDFServiceFactory rdfServiceFactory;
|
||||||
|
@ -205,6 +209,11 @@ public class ContentTripleSourceSDB extends ContentTripleSource {
|
||||||
return new UnionModelsOntModelsCache(combinedCache, CONTENT_UNIONS);
|
return new UnionModelsOntModelsCache(combinedCache, CONTENT_UNIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TripleStoreQuirks getQuirks() {
|
||||||
|
return quirks;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ContentTripleSourceSDB[" + ToString.hashHex(this) + "]";
|
return "ContentTripleSourceSDB[" + ToString.hashHex(this) + "]";
|
||||||
|
|
|
@ -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.Application;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
|
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.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.RDFService;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory;
|
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.RDFServiceFactorySingle;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.logging.LoggingRDFServiceFactory;
|
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.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.Property;
|
||||||
import edu.cornell.mannlib.vitro.webapp.utils.configuration.Validation;
|
import edu.cornell.mannlib.vitro.webapp.utils.configuration.Validation;
|
||||||
import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
|
import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
|
||||||
|
@ -36,6 +38,8 @@ public class ContentTripleSourceSPARQL extends ContentTripleSource {
|
||||||
private String endpointURI;
|
private String endpointURI;
|
||||||
private String updateEndpointURI; // Optional
|
private String updateEndpointURI; // Optional
|
||||||
|
|
||||||
|
private final TripleStoreQuirks quirks = new DefaultTripleStoreQuirks();
|
||||||
|
|
||||||
private RDFService rdfService;
|
private RDFService rdfService;
|
||||||
private RDFServiceFactory rdfServiceFactory;
|
private RDFServiceFactory rdfServiceFactory;
|
||||||
private Dataset dataset;
|
private Dataset dataset;
|
||||||
|
@ -132,6 +136,11 @@ public class ContentTripleSourceSPARQL extends ContentTripleSource {
|
||||||
return longTermOntModelCache;
|
return longTermOntModelCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TripleStoreQuirks getQuirks() {
|
||||||
|
return quirks;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ContentTripleSourceSPARQL[" + ToString.hashHex(this)
|
return "ContentTripleSourceSPARQL[" + ToString.hashHex(this)
|
||||||
|
|
|
@ -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.Application;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
|
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.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.RDFService;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory;
|
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.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.
|
* Memory-map all of the configuration models, and add the standard decorators.
|
||||||
*/
|
*/
|
||||||
public class ConfigurationTripleSourceTDB extends ConfigurationTripleSource {
|
public class ConfigurationTripleSourceTDB extends ConfigurationTripleSource {
|
||||||
|
|
||||||
private static final String DIRECTORY_TDB = "tdbModels";
|
private static final String DIRECTORY_TDB = "tdbModels";
|
||||||
|
|
||||||
|
private final TripleStoreQuirks quirks = new TDBTripleStoreQuirks();
|
||||||
|
|
||||||
private volatile RDFService rdfService;
|
private volatile RDFService rdfService;
|
||||||
private RDFServiceFactory rdfServiceFactory;
|
private RDFServiceFactory rdfServiceFactory;
|
||||||
private RDFService unclosableRdfService;
|
private RDFService unclosableRdfService;
|
||||||
|
@ -112,6 +114,11 @@ public class ConfigurationTripleSourceTDB extends ConfigurationTripleSource {
|
||||||
return longTermOntModelCache;
|
return longTermOntModelCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TripleStoreQuirks getQuirks() {
|
||||||
|
return quirks;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ConfigurationTripleSourceTDB[" + ToString.hashHex(this) + "]";
|
return "ConfigurationTripleSourceTDB[" + ToString.hashHex(this) + "]";
|
||||||
|
|
|
@ -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.Application;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
|
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.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.RDFService;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory;
|
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.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.
|
* Memory-map the small content models, and add the standard decorators.
|
||||||
*/
|
*/
|
||||||
public class ContentTripleSourceTDB extends ContentTripleSource {
|
public class ContentTripleSourceTDB extends ContentTripleSource {
|
||||||
|
private final TripleStoreQuirks quirks = new TDBTripleStoreQuirks();
|
||||||
|
|
||||||
private String tdbPath;
|
private String tdbPath;
|
||||||
|
|
||||||
private volatile RDFService rdfService;
|
private volatile RDFService rdfService;
|
||||||
|
@ -124,6 +127,11 @@ public class ContentTripleSourceTDB extends ContentTripleSource {
|
||||||
return longTermOntModelCache;
|
return longTermOntModelCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TripleStoreQuirks getQuirks() {
|
||||||
|
return quirks;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ContentTripleSourceTDB[" + ToString.hashHex(this) + "]";
|
return "ContentTripleSourceTDB[" + ToString.hashHex(this) + "]";
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue