diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java index bce1c4fa4..f098bab9a 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/RDFService.java @@ -195,7 +195,18 @@ public interface RDFService { */ public boolean isEquivalentGraph(String graphURI, InputStream serializedGraph, ModelSerializationFormat serializationFormat) throws RDFServiceException; - + + /** + * Tests to see whether the supplied serialization is equivalent to the + * named graph, as it exists in the store. Equivalence means that if this + * serialization were written to the store, the resulting graph would be + * isomorphic to the existing named graph. + * + * @param graphURI - the URI of the graph to test against. May not be null. + * @param graph - the contents to be compared with the existing graph. May not be null. + */ + public boolean isEquivalentGraph(String graphURI, Model graph) throws RDFServiceException; + /** * Registers a listener to listen to changes in any graph in * the RDF store. diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringRDFService.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringRDFService.java index 2c85d7ad1..145e57c9a 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringRDFService.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/LanguageFilteringRDFService.java @@ -431,7 +431,13 @@ public class LanguageFilteringRDFService implements RDFService { return s.isEquivalentGraph(graphURI, serializedGraph, serializationFormat); } - @Override + @Override + public boolean isEquivalentGraph(String graphURI, + Model graph) throws RDFServiceException { + return s.isEquivalentGraph(graphURI, graph); + } + + @Override public void registerListener(ChangeListener changeListener) throws RDFServiceException { // TODO Auto-generated method stub diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/SameAsFilteringRDFServiceFactory.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/SameAsFilteringRDFServiceFactory.java index e611aa278..5f473ad0e 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/SameAsFilteringRDFServiceFactory.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/filter/SameAsFilteringRDFServiceFactory.java @@ -289,6 +289,12 @@ public class SameAsFilteringRDFServiceFactory implements RDFServiceFactory { return s.isEquivalentGraph(graphURI, serializedGraph, serializationFormat); } + @Override + public boolean isEquivalentGraph(String graphURI, + Model graph) throws RDFServiceException { + return s.isEquivalentGraph(graphURI, graph); + } + @Override public void close() { s.close(); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceFactorySingle.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceFactorySingle.java index ca89979e0..ec159b0be 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceFactorySingle.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/RDFServiceFactorySingle.java @@ -145,7 +145,13 @@ public class RDFServiceFactorySingle implements RDFServiceFactory { return s.isEquivalentGraph(graphURI, serializedGraph, serializationFormat); } - @Override + @Override + public boolean isEquivalentGraph(String graphURI, + Model graph) throws RDFServiceException { + return s.isEquivalentGraph(graphURI, graph); + } + + @Override public void registerListener(ChangeListener changeListener) throws RDFServiceException { s.registerListener(changeListener); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java index 51b52a19f..8e07752fa 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java @@ -607,7 +607,22 @@ public abstract class RDFServiceJena extends RDFServiceImpl implements RDFServic return fileModel.isIsomorphicWith(fromTripleStoreModel); } - @Override + /** + * The basic version. Parse the model from the file, read the model from the + * tripleStore, and ask whether they are isomorphic. + */ + @Override + public boolean isEquivalentGraph(String graphURI, Model graph) throws RDFServiceException { + // Retrieve the graph to compare + Model tripleStoreModel = new RDFServiceDataset(this).getNamedModel(graphURI); + + // Load the entire graph into memory (faster comparison) + Model fromTripleStoreModel = ModelFactory.createDefaultModel().add(tripleStoreModel); + + return graph.isIsomorphicWith(fromTripleStoreModel); + } + + @Override public void close() { // nothing } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/tdb/RDFServiceTDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/tdb/RDFServiceTDB.java index ed4a0f33f..1df088264 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/tdb/RDFServiceTDB.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/tdb/RDFServiceTDB.java @@ -3,6 +3,7 @@ package edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.tdb; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -211,6 +212,24 @@ public class RDFServiceTDB extends RDFServiceJena { serializationFormat); } + /** + * TDB has a bug: if given a literal of type xsd:nonNegativeInteger, it + * stores a literal of type xsd:integer. + * + * To determine whether this serialized graph is equivalent to what's in + * TDB, we need to do the same. + */ + @Override + public boolean isEquivalentGraph(String graphURI, + Model graph) + throws RDFServiceException { + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + graph.write(buffer, "N-TRIPLE"); + InputStream inStream = new ByteArrayInputStream(buffer.toByteArray()); + return isEquivalentGraph(graphURI, inStream, ModelSerializationFormat.NTRIPLE); + } + /** * Convert all of the references to "nonNegativeInteger" to "integer" in * this serialized graph. diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java index 6d0d46f98..2005b90f3 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java @@ -111,6 +111,15 @@ public class LoggingRDFService implements RDFService { } } + @Override + public boolean isEquivalentGraph(String graphURI, + Model graph) + throws RDFServiceException { + try (RDFServiceLogger l = new RDFServiceLogger(graphURI)) { + return innerService.isEquivalentGraph(graphURI, graph); + } + } + // ---------------------------------------------------------------------- // Untimed methods // ---------------------------------------------------------------------- diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java index a4edc0995..262c5b611 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java @@ -929,6 +929,17 @@ public class RDFServiceSparql extends RDFServiceImpl implements RDFService { return fileModel.isIsomorphicWith(fromTripleStoreModel); } + /** + * The basic version. Parse the model from the file, read the model from the + * tripleStore, and ask whether they are isomorphic. + */ + @Override + public boolean isEquivalentGraph(String graphURI, Model graph) throws RDFServiceException { + Model tripleStoreModel = new RDFServiceDataset(this).getNamedModel(graphURI); + Model fromTripleStoreModel = ModelFactory.createDefaultModel().add(tripleStoreModel); + return graph.isIsomorphicWith(fromTripleStoreModel); + } + protected HttpContext getContext(HttpRequestBase request) { UsernamePasswordCredentials credentials = getCredentials(); if (credentials != null) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/virtuoso/RDFServiceVirtuoso.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/virtuoso/RDFServiceVirtuoso.java index e7117f045..e7b19f325 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/virtuoso/RDFServiceVirtuoso.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/virtuoso/RDFServiceVirtuoso.java @@ -3,6 +3,7 @@ package edu.cornell.mannlib.vitro.webapp.rdfservice.impl.virtuoso; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -247,6 +248,24 @@ public class RDFServiceVirtuoso extends RDFServiceSparql { return true; } + /** + * TDB has a bug: if given a literal of type xsd:nonNegativeInteger, it + * stores a literal of type xsd:integer. + * + * To determine whether this serialized graph is equivalent to what's in + * TDB, we need to do the same. + */ + @Override + public boolean isEquivalentGraph(String graphURI, + Model graph) + throws RDFServiceException { + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + graph.write(buffer, "N-TRIPLE"); + InputStream inStream = new ByteArrayInputStream(buffer.toByteArray()); + return isEquivalentGraph(graphURI, inStream, ModelSerializationFormat.NTRIPLE); + } + /** * Convert all of the references to "nonNegativeInteger" to "integer" in * this serialized graph. diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/FileGraphSetup.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/FileGraphSetup.java index 840abeae0..0a42817f2 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/FileGraphSetup.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/FileGraphSetup.java @@ -214,13 +214,10 @@ public class FileGraphSetup implements ServletContextListener { public boolean updateGraphInDB(RDFService rdfService, Model fileModel, String type, Path path) throws RDFServiceException { String graphURI = pathToURI(path,type); - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - fileModel.write(buffer, "N-TRIPLE"); - InputStream inStream = new ByteArrayInputStream(buffer.toByteArray()); - if (rdfService.isEquivalentGraph(graphURI, inStream, ModelSerializationFormat.NTRIPLE)) { - return false; - } - + if (rdfService.isEquivalentGraph(graphURI, fileModel)) { + return false; + } + Model dbModel = new RDFServiceDataset(rdfService).getNamedModel(graphURI); if (log.isDebugEnabled()) { log.debug(String.format(