diff --git a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFStarUtil.java b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFStarUtil.java index d34d6e38ac5..283c88b7e7d 100644 --- a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFStarUtil.java +++ b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFStarUtil.java @@ -73,6 +73,30 @@ public static T fromRDFEncodedValue(T encodedValue) { } } + /** + * Converts the supplied value from an RDF-compatible representation to an RDF-star value. + *

+ * See {@link #toRDFEncodedValue(Value)}. + * + * @param encodedValue an RDF {@link Value} to convert to RDF-star. + * @param valueFactory the {@link ValueFactory} to use for parsing the triple. + * @param + * @return the decoded RDF-star triple, if a {@link Triple} encoded as {@link IRI} was supplied, or the supplied + * value otherwise. + * @throws IllegalArgumentException if the supplied value looked like an RDF-star triple encoded as an IRI but it + * could not be decoded successfully. + */ + public static T fromRDFEncodedValue(T encodedValue, ValueFactory valueFactory) { + try { + return isEncodedTriple(encodedValue) + ? (T) NTriplesUtil.parseTriple(decode( + encodedValue.stringValue().substring(TRIPLE_PREFIX.length())), valueFactory) + : encodedValue; + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Invalid RDF-star encoded triple: " + encodedValue); + } + } + /** * Checks if the supplied {@link Value} represents an RDF-star triple encoded as an IRI. * diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/FileIO.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/FileIO.java index 8bd76bdcb82..04d9639d4d8 100644 --- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/FileIO.java +++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/FileIO.java @@ -35,6 +35,7 @@ import org.eclipse.rdf4j.model.Namespace; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Triple; import org.eclipse.rdf4j.model.Value; import org.eclipse.rdf4j.model.ValueFactory; import org.eclipse.rdf4j.model.util.Literals; @@ -45,6 +46,7 @@ import org.eclipse.rdf4j.sail.memory.model.MemIRI; import org.eclipse.rdf4j.sail.memory.model.MemResource; import org.eclipse.rdf4j.sail.memory.model.MemValue; +import org.eclipse.rdf4j.sail.memory.model.MemValueFactory; /** * Functionality to read and write MemoryStore to/from a file. @@ -100,7 +102,7 @@ class FileIO { * Variables * *-----------*/ - private final ValueFactory vf; + private final MemValueFactory vf; private final CharsetEncoder charsetEncoder = StandardCharsets.UTF_8.newEncoder(); @@ -112,7 +114,7 @@ class FileIO { * Constructors * *--------------*/ - public FileIO(ValueFactory vf) { + public FileIO(MemValueFactory vf) { this.vf = vf; } @@ -320,7 +322,8 @@ private Value readValue(DataInputStream dataIn) throws IOException, ClassCastExc return vf.createLiteral(label, datatype); } else if (valueTypeMarker == RDFSTAR_TRIPLE_MARKER) { IRI rdfStarEncodedTriple = (IRI) readValue(dataIn); - return RDFStarUtil.fromRDFEncodedValue(rdfStarEncodedTriple); + Triple triple = (Triple) RDFStarUtil.fromRDFEncodedValue(rdfStarEncodedTriple, vf); + return vf.getOrCreateMemTriple(triple); } else { throw new IOException("Invalid value type marker: " + valueTypeMarker); } diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStore.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStore.java index 3d9cb45bc60..61670d6dfa3 100644 --- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStore.java +++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStore.java @@ -32,6 +32,7 @@ import org.eclipse.rdf4j.sail.base.SailStore; import org.eclipse.rdf4j.sail.helpers.AbstractNotifyingSail; import org.eclipse.rdf4j.sail.helpers.DirectoryLockManager; +import org.eclipse.rdf4j.sail.memory.model.MemValueFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -286,7 +287,7 @@ protected void initializeInternal() throws SailException { SailSink explicit = store.getExplicitSailSource().sink(IsolationLevels.NONE); SailSink inferred = store.getInferredSailSource().sink(IsolationLevels.NONE); try { - new FileIO(store.getValueFactory()).read(dataFile, explicit, inferred); + new FileIO((MemValueFactory) store.getValueFactory()).read(dataFile, explicit, inferred); logger.debug("Data file read successfully"); } catch (IOException e) { logger.error("Failed to read data file", e); @@ -317,7 +318,8 @@ protected void initializeInternal() throws SailException { logger.debug("Initializing data file..."); try (SailDataset explicit = store.getExplicitSailSource().dataset(IsolationLevels.SNAPSHOT); SailDataset inferred = store.getInferredSailSource().dataset(IsolationLevels.SNAPSHOT)) { - new FileIO(store.getValueFactory()).write(explicit, inferred, syncFile, dataFile); + new FileIO((MemValueFactory) store.getValueFactory()).write(explicit, inferred, syncFile, + dataFile); } logger.debug("Data file initialized"); } catch (IOException | SailException e) { @@ -452,7 +454,8 @@ public void sync() throws SailException { IsolationLevels level = IsolationLevels.SNAPSHOT; try (SailDataset explicit = store.getExplicitSailSource().dataset(level); SailDataset inferred = store.getInferredSailSource().dataset(level)) { - new FileIO(store.getValueFactory()).write(explicit, inferred, syncFile, dataFile); + new FileIO((MemValueFactory) store.getValueFactory()).write(explicit, inferred, syncFile, + dataFile); } contentsChanged = false; logger.debug("Data synced to file"); diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java index e2a12b6577a..4350840a250 100644 --- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java +++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java @@ -378,7 +378,7 @@ public MemLiteral getOrCreateMemLiteral(Literal literal) { /** * See {@link #getOrCreateMemValue(Value)} for description. */ - private MemTriple getOrCreateMemTriple(Triple triple) { + public MemTriple getOrCreateMemTriple(Triple triple) { MemTriple memTriple = getMemTriple(triple); if (memTriple == null) { @@ -474,4 +474,8 @@ private Literal getSharedLiteral(MemLiteral newLiteral) { return literalRegistry.getOrAdd(newLiteral, () -> newLiteral); } + @Override + public Triple createTriple(Resource subject, IRI predicate, Value object) { + return getOrCreateMemTriple(super.createTriple(subject, predicate, object)); + } } diff --git a/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/StoreSerializationTest.java b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/StoreSerializationTest.java index 713d5c0df9a..3b7db076c6d 100644 --- a/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/StoreSerializationTest.java +++ b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/StoreSerializationTest.java @@ -21,8 +21,10 @@ import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Literal; import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Triple; import org.eclipse.rdf4j.model.ValueFactory; import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; import org.eclipse.rdf4j.query.BindingSet; import org.eclipse.rdf4j.query.QueryEvaluationException; import org.eclipse.rdf4j.query.QueryLanguage; @@ -171,4 +173,35 @@ public void testLongLiterals() { con.close(); store.shutDown(); } + + @Test + public void testMemTriple() { + MemoryStore store = new MemoryStore(dataDir); + store.init(); + + ValueFactory factory = store.getValueFactory(); + Triple triple = factory.createTriple(RDF.TYPE, RDF.TYPE, RDF.TYPE); + Literal longLiteral = factory.createLiteral("a".repeat(4)); + + try (SailConnection con = store.getConnection()) { + con.begin(); + con.addStatement(triple, RDFS.LABEL, longLiteral); + con.commit(); + + } + store.shutDown(); + + store = new MemoryStore(dataDir); + store.init(); + + try (SailConnection con = store.getConnection()) { + try (CloseableIteration iter = con.getStatements(null, RDFS.LABEL, null, + false)) { + assertTrue(iter.hasNext()); + Statement next = iter.next(); + assertEquals(next.getSubject(), triple); + } + } + store.shutDown(); + } }