You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2016/12/22 17:55:07 UTC
[07/11] jena git commit: Isolation modes, inc documentation and tests.
Isolation modes, inc documentation and tests.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/cdc9f143
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/cdc9f143
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/cdc9f143
Branch: refs/heads/master
Commit: cdc9f143c599da4924f4052f9fbbd4cfcc29504d
Parents: 53758b5
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Dec 18 19:55:09 2016 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Dec 18 20:04:22 2016 +0000
----------------------------------------------------------------------
jena-rdfconnection/Documentation.md | 23 ++++-
.../apache/jena/rdfconnection/Isolation.java | 5 ++
.../jena/rdfconnection/RDFConnection.java | 92 ++++++++++----------
.../rdfconnection/RDFConnectionFactory.java | 27 +++++-
.../jena/rdfconnection/RDFConnectionLocal.java | 77 ++++++++++------
.../jena/rdfconnection/TS_RDFConnection.java | 1 +
.../jena/rdfconnection/TestLocalIsolation.java | 84 ++++++++++++++++++
7 files changed, 234 insertions(+), 75 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/cdc9f143/jena-rdfconnection/Documentation.md
----------------------------------------------------------------------
diff --git a/jena-rdfconnection/Documentation.md b/jena-rdfconnection/Documentation.md
index d12bf34..e64eb67 100644
--- a/jena-rdfconnection/Documentation.md
+++ b/jena-rdfconnection/Documentation.md
@@ -18,8 +18,8 @@ Protocol</a>).
data in Java. It provides support for try-resource and functional code
passing styles, as well the more basic sequence of methods calls.
-`try-resources` to manage the connection, and two operations, one to load
-some data, and one to make a query:
+For example: using `try-resources` to manage the connection, and perform two operations, one to load
+some data, and one to make a query can be written as:
```
try ( RDFConnection conn = RDFConnectionFactory.connect(...) ) {
@@ -113,7 +113,7 @@ handled by the transaction pattern within a single JVM.
## Graph Store Protocol
The <a href="http://www.w3.org/TR/sparql11-http-rdf-update/">SPARQL Graph
-Store Protocol</a> is a set of operations to work on whole graphs in a
+Store Protocol</a> (GSP) is a set of operations to work on whole graphs in a
dataset. It provides a standardised way to manage the data in a dataset.
The operations are to fetch a graph, set the RDF data in a graph,
@@ -141,6 +141,23 @@ provided).
conn.loadDataset("data-complete.trig") ;
```
+### Local vs Remote
+
+GSP operations work on while models and datasets. When used on a remote connection,
+the result of a GSP operation is a separate copy of the remote RDF data. When working
+with local connections, 3 isolations modes are available:
+
+* Copy – the models and datasets returned are independent copies.
+Updates are made to the return copy only. This is most like
+a remote connectionand is useful for testing.
+* Read-only – the models and datasets are made read-only but any changes
+to the underlying RDF data by changes by another route will be visible.
+This provides a form of checking for large datasets when "copy" is impractical.
+* None – the models and datasets are passed back with no additional wrappers
+and they can be updated with the changes being made the underlying dataset.
+
+The default for a local `RDFConnection` is "none".
+
## Query Usage
`RDFConnection` provides methods for each of the SPARQL query forms (`SELECT`,
http://git-wip-us.apache.org/repos/asf/jena/blob/cdc9f143/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/Isolation.java
----------------------------------------------------------------------
diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/Isolation.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/Isolation.java
new file mode 100644
index 0000000..79c496f
--- /dev/null
+++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/Isolation.java
@@ -0,0 +1,5 @@
+package org.apache.jena.rdfconnection;
+public enum Isolation { COPY, READONLY, NONE }
+
+// XXX Expose copy-mode?
+
http://git-wip-us.apache.org/repos/asf/jena/blob/cdc9f143/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnection.java
----------------------------------------------------------------------
diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnection.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnection.java
index c1b95ea..3adae39 100644
--- a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnection.java
+++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnection.java
@@ -18,15 +18,15 @@
package org.apache.jena.rdfconnection;
-import java.util.function.Consumer ;
+import java.util.function.Consumer;
-import org.apache.jena.query.* ;
-import org.apache.jena.rdf.model.Model ;
-import org.apache.jena.sparql.core.Transactional ;
-import org.apache.jena.system.Txn ;
-import org.apache.jena.update.Update ;
-import org.apache.jena.update.UpdateFactory ;
-import org.apache.jena.update.UpdateRequest ;
+import org.apache.jena.query.*;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.sparql.core.Transactional;
+import org.apache.jena.system.Txn;
+import org.apache.jena.update.Update;
+import org.apache.jena.update.UpdateFactory;
+import org.apache.jena.update.UpdateRequest;
/**
* Interface for SPARQL operations on a datasets, whether local or remote.
@@ -82,7 +82,7 @@ public interface RDFConnection extends
*/
@Override
public default void queryResultSet(String query, Consumer<ResultSet> resultSetAction) {
- queryResultSet(QueryFactory.create(query), resultSetAction) ;
+ queryResultSet(QueryFactory.create(query), resultSetAction);
}
/**
@@ -93,14 +93,14 @@ public interface RDFConnection extends
@Override
public default void queryResultSet(Query query, Consumer<ResultSet> resultSetAction) {
if ( ! query.isSelectType() )
- throw new JenaConnectionException("Query is not a SELECT query") ;
+ throw new JenaConnectionException("Query is not a SELECT query");
Txn.executeRead(this, ()->{
try ( QueryExecution qExec = query(query) ) {
- ResultSet rs = qExec.execSelect() ;
+ ResultSet rs = qExec.execSelect();
resultSetAction.accept(rs);
}
- } ) ;
+ } );
}
/**
@@ -110,7 +110,7 @@ public interface RDFConnection extends
*/
@Override
public default void querySelect(String query, Consumer<QuerySolution> rowAction) {
- querySelect(QueryFactory.create(query), rowAction) ;
+ querySelect(QueryFactory.create(query), rowAction);
}
/**
@@ -121,18 +121,18 @@ public interface RDFConnection extends
@Override
public default void querySelect(Query query, Consumer<QuerySolution> rowAction) {
if ( ! query.isSelectType() )
- throw new JenaConnectionException("Query is not a SELECT query") ;
+ throw new JenaConnectionException("Query is not a SELECT query");
Txn.executeRead(this, ()->{
try ( QueryExecution qExec = query(query) ) {
qExec.execSelect().forEachRemaining(rowAction);
}
- } ) ;
+ } );
}
/** Execute a CONSTRUCT query and return as a Model */
@Override
public default Model queryConstruct(String query) {
- return queryConstruct(QueryFactory.create(query)) ;
+ return queryConstruct(QueryFactory.create(query));
}
/** Execute a CONSTRUCT query and return as a Model */
@@ -141,15 +141,15 @@ public interface RDFConnection extends
return
Txn.calculateRead(this, ()->{
try ( QueryExecution qExec = query(query) ) {
- return qExec.execConstruct() ;
+ return qExec.execConstruct();
}
- } ) ;
+ } );
}
/** Execute a DESCRIBE query and return as a Model */
@Override
public default Model queryDescribe(String query) {
- return queryDescribe(QueryFactory.create(query)) ;
+ return queryDescribe(QueryFactory.create(query));
}
/** Execute a DESCRIBE query and return as a Model */
@@ -158,15 +158,15 @@ public interface RDFConnection extends
return
Txn.calculateRead(this, ()->{
try ( QueryExecution qExec = query(query) ) {
- return qExec.execDescribe() ;
+ return qExec.execDescribe();
}
- } ) ;
+ } );
}
/** Execute a ASK query and return a boolean */
@Override
public default boolean queryAsk(String query) {
- return queryAsk(QueryFactory.create(query)) ;
+ return queryAsk(QueryFactory.create(query));
}
/** Execute a ASK query and return a boolean */
@@ -175,9 +175,9 @@ public interface RDFConnection extends
return
Txn.calculateRead(this, ()->{
try ( QueryExecution qExec = query(query) ) {
- return qExec.execAsk() ;
+ return qExec.execAsk();
}
- } ) ;
+ } );
}
/** Setup a SPARQL query execution.
@@ -190,7 +190,7 @@ public interface RDFConnection extends
* @return QueryExecution
*/
@Override
- public QueryExecution query(Query query) ;
+ public QueryExecution query(Query query);
/** Setup a SPARQL query execution.
*
@@ -203,7 +203,7 @@ public interface RDFConnection extends
*/
@Override
public default QueryExecution query(String queryString) {
- return query(QueryFactory.create(queryString)) ;
+ return query(QueryFactory.create(queryString));
}
// ---- SparqlUpdateConnection
@@ -214,7 +214,7 @@ public interface RDFConnection extends
*/
@Override
public default void update(Update update) {
- update(new UpdateRequest(update)) ;
+ update(new UpdateRequest(update));
}
/** Execute a SPARQL Update.
@@ -222,7 +222,7 @@ public interface RDFConnection extends
* @param update
*/
@Override
- public void update(UpdateRequest update) ;
+ public void update(UpdateRequest update);
/** Execute a SPARQL Update.
*
@@ -230,7 +230,7 @@ public interface RDFConnection extends
*/
@Override
public default void update(String updateString) {
- update(UpdateFactory.create(updateString)) ;
+ update(UpdateFactory.create(updateString));
}
// ---- RDFDatasetConnection
@@ -242,7 +242,7 @@ public interface RDFConnection extends
* @param file File of the data.
*/
@Override
- public void load(String graphName, String file) ;
+ public void load(String graphName, String file);
/** Load (add, append) RDF into the default graph of a dataset.
* This is SPARQL Graph Store Protocol HTTP POST or equivalent.
@@ -250,7 +250,7 @@ public interface RDFConnection extends
* @param file File of the data.
*/
@Override
- public void load(String file) ;
+ public void load(String file);
/** Load (add, append) RDF into a named graph in a dataset.
* This is SPARQL Graph Store Protocol HTTP POST or equivalent.
@@ -259,7 +259,7 @@ public interface RDFConnection extends
* @param model Data.
*/
@Override
- public void load(String graphName, Model model) ;
+ public void load(String graphName, Model model);
/** Load (add, append) RDF into the default graph of a dataset.
* This is SPARQL Graph Store Protocol HTTP POST or equivalent.
@@ -267,7 +267,7 @@ public interface RDFConnection extends
* @param model Data.
*/
@Override
- public void load(Model model) ;
+ public void load(Model model);
/** Set the contents of a named graph of a dataset.
* Any existing data is lost.
@@ -277,7 +277,7 @@ public interface RDFConnection extends
* @param file File of the data.
*/
@Override
- public void put(String graphName, String file) ;
+ public void put(String graphName, String file);
/** Set the contents of the default graph of a dataset.
* Any existing data is lost.
@@ -286,7 +286,7 @@ public interface RDFConnection extends
* @param file File of the data.
*/
@Override
- public void put(String file) ;
+ public void put(String file);
/** Set the contents of a named graph of a dataset.
* Any existing data is lost.
@@ -296,7 +296,7 @@ public interface RDFConnection extends
* @param model Data.
*/
@Override
- public void put(String graphName, Model model) ;
+ public void put(String graphName, Model model);
/** Set the contents of the default graph of a dataset.
* Any existing data is lost.
@@ -305,7 +305,7 @@ public interface RDFConnection extends
* @param model Data.
*/
@Override
- public void put( Model model) ;
+ public void put( Model model);
/**
* Delete a graph from the dataset.
@@ -314,27 +314,27 @@ public interface RDFConnection extends
* @param graphName
*/
@Override
- public void delete(String graphName) ;
+ public void delete(String graphName);
/**
* Remove all data from the default graph.
*/
@Override
- public void delete() ;
+ public void delete();
/* Load (add, append) RDF triple or quad data into a dataset. Triples wil go into the default graph.
* This is not a SPARQL Graph Store Protocol operation.
* It is an HTTP POST equivalent to the dataset.
*/
@Override
- public void loadDataset(String file) ;
+ public void loadDataset(String file);
/* Load (add, append) RDF triple or quad data into a dataset. Triples wil go into the default graph.
* This is not a SPARQL Graph Store Protocol operation.
* It is an HTTP POST equivalent to the dataset.
*/
@Override
- public void loadDataset(Dataset dataset) ;
+ public void loadDataset(Dataset dataset);
/* Set RDF triple or quad data as the dataset contents.
* Triples will go into the default graph, quads in named graphs.
@@ -342,7 +342,7 @@ public interface RDFConnection extends
* It is an HTTP PUT equivalent to the dataset.
*/
@Override
- public void putDataset(String file) ;
+ public void putDataset(String file);
/* Set RDF triple or quad data as the dataset contents.
* Triples will go into the default graph, quads in named graphs.
@@ -350,18 +350,18 @@ public interface RDFConnection extends
* It is an HTTP PUT equivalent to the dataset.
*/
@Override
- public void putDataset(Dataset dataset) ;
+ public void putDataset(Dataset dataset);
// /** Clear the dataset - remove all named graphs, clear the default graph. */
- // public void clearDataset() ;
+ // public void clearDataset();
/** Test whether this connection is closed or not */
@Override
- public boolean isClosed() ;
+ public boolean isClosed();
/** Close this connection. Use with try-resource. */
@Override
- public void close() ;
+ public void close();
}
http://git-wip-us.apache.org/repos/asf/jena/blob/cdc9f143/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java
----------------------------------------------------------------------
diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java
index e7cfb57..a8c0e45 100644
--- a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java
+++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionFactory.java
@@ -77,11 +77,36 @@ public class RDFConnectionFactory {
/**
* Connect to a local (same JVM) dataset.
+ * The default isolation is {@code NONE}.
+ * See {@link #connect(Dataset, Isolation)} to select an isolation mode.
+ *
* @param dataset
* @return RDFConnection
+ * @see RDFConnectionLocal
*/
public static RDFConnection connect(Dataset dataset) {
return new RDFConnectionLocal(dataset);
}
-
+
+ /**
+ * Connect to a local (same JVM) dataset.
+ * <p>
+ * Multiple levels of {@link Isolation} are provided, The default {@code COPY} level makes a local
+ * {@link RDFConnection} behave like a remote conenction.
+ * See <a href="https://jena.apache.org/documentation/rdfconnection/">the documentation for more details.</a>
+ * <ul>
+ * <li>{@code COPY} – {@code Model}s and {@code Dataset}s are copied.
+ * This is most like a remote connection.
+ * <li>{@code READONLY} – Read-only wrappers are added but changes to
+ * the underlying model or dataset will be seen.
+ * <li>{@code NONE} (default) – Changes to the returned {@code Model}s or {@code Dataset}s act on the original object.
+ * </ul>
+ *
+ * @param dataset
+ * @param isolation
+ * @return RDFConnection
+ */
+ public static RDFConnection connect(Dataset dataset, Isolation isolation) {
+ return new RDFConnectionLocal(dataset, isolation);
+ }
}
http://git-wip-us.apache.org/repos/asf/jena/blob/cdc9f143/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java
----------------------------------------------------------------------
diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java
index d2fb4df..8be2704 100644
--- a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java
+++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java
@@ -20,6 +20,7 @@ package org.apache.jena.rdfconnection;
import java.util.Objects;
+import org.apache.jena.atlas.lib.InternalErrorException;
import org.apache.jena.graph.Graph;
import org.apache.jena.query.*;
import org.apache.jena.rdf.model.Model;
@@ -36,21 +37,36 @@ import org.apache.jena.system.Txn;
import org.apache.jena.update.UpdateExecutionFactory;
import org.apache.jena.update.UpdateRequest;
-/**
+/**
* Implement of {@link RDFConnection} over a {@link Dataset} in the same JVM.
+ * <p>
+ * Multiple levels of {@link Isolation} are provided, The default {@code COPY} level makes a local
+ * {@link RDFConnection} behave like a remote conenction. This should be the normal use in
+ * testing.
+ * <ul>
+ * <li>{@code COPY} – {@code Model}s and {@code Dataset}s are copied.
+ * This is most like a remote connection.
+ * <li>{@code READONLY} – Read-only wrappers are added but changes to
+ * the underlying model or dataset will be seen.
+ * <li>{@code NONE} (default) – Changes to the returned {@code Model}s or {@code Dataset}s act on the original object.
+ * </ul>
*/
public class RDFConnectionLocal implements RDFConnection {
- // XXX Expose copy-mode?
-
private ThreadLocal<Boolean> transactionActive = ThreadLocal.withInitial(()->false);
- private static boolean isolateByCopy = true;
+
private Dataset dataset;
+ private final Isolation isolation;
public RDFConnectionLocal(Dataset dataset) {
- this.dataset = dataset;
+ this(dataset, Isolation.NONE);
}
+ public RDFConnectionLocal(Dataset dataset, Isolation isolation) {
+ this.dataset = dataset;
+ this.isolation = isolation;
+ }
+
@Override
public QueryExecution query(Query query) {
checkOpen();
@@ -176,35 +192,46 @@ public class RDFConnectionLocal implements RDFConnection {
}
/**
- * Called to isolate a model from it's storage. Must be inside a
- * transaction.
+ * Called to isolate a model from it's storage.
+ * Must be inside a transaction.
*/
private Model isolate(Model model) {
- if ( ! isolateByCopy ) {
- // Half-way - read-only but dataset changes can be seen.
- Graph g = new GraphReadOnly(model.getGraph());
- return ModelFactory.createModelForGraph(g);
+ switch(isolation) {
+ case COPY: {
+ // Copy - the model is completely isolated from the original.
+ Model m2 = ModelFactory.createDefaultModel();
+ m2.add(model);
+ return m2;
+ }
+ case READONLY : {
+ Graph g = new GraphReadOnly(model.getGraph());
+ return ModelFactory.createModelForGraph(g);
+ }
+ case NONE :
+ return model;
}
- // Copy.
- Model m2 = ModelFactory.createDefaultModel();
- m2.add(model);
- return m2;
+ throw new InternalErrorException();
}
/**
- * Called to isolate a dataset from it's storage. Must be inside a
- * transaction.
+ * Called to isolate a dataset from it's storage.
+ * Must be inside a transaction.
*/
private Dataset isolate(Dataset dataset) {
- if ( ! isolateByCopy ) {
- DatasetGraph dsg = new DatasetGraphReadOnly(dataset.asDatasetGraph());
- return DatasetFactory.wrap(dsg);
+ switch(isolation) {
+ case COPY: {
+ DatasetGraph dsg2 = DatasetGraphFactory.create();
+ dataset.asDatasetGraph().find().forEachRemaining(q -> dsg2.add(q) );
+ return DatasetFactory.wrap(dsg2);
+ }
+ case READONLY : {
+ DatasetGraph dsg = new DatasetGraphReadOnly(dataset.asDatasetGraph());
+ return DatasetFactory.wrap(dsg);
+ }
+ case NONE :
+ return dataset;
}
-
- // Copy.
- DatasetGraph dsg2 = DatasetGraphFactory.create();
- dataset.asDatasetGraph().find().forEachRemaining(q -> dsg2.add(q) );
- return DatasetFactory.wrap(dsg2);
+ throw new InternalErrorException();
}
private Model modelFor(String graph) {
http://git-wip-us.apache.org/repos/asf/jena/blob/cdc9f143/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TS_RDFConnection.java
----------------------------------------------------------------------
diff --git a/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TS_RDFConnection.java b/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TS_RDFConnection.java
index 3f8af53..373bd52 100644
--- a/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TS_RDFConnection.java
+++ b/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TS_RDFConnection.java
@@ -26,6 +26,7 @@ import org.junit.runners.Suite;
// Other tests are in jena-integration-tests
TestRDFConnectionLocalTxnMem.class
, TestRDFConnectionLocalMRSW.class
+ , TestLocalIsolation.class
})
public class TS_RDFConnection {}
http://git-wip-us.apache.org/repos/asf/jena/blob/cdc9f143/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestLocalIsolation.java
----------------------------------------------------------------------
diff --git a/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestLocalIsolation.java b/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestLocalIsolation.java
new file mode 100644
index 0000000..bc4fc20
--- /dev/null
+++ b/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestLocalIsolation.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.rdfconnection;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.rdf.model.*;
+import org.apache.jena.shared.JenaException;
+import org.apache.jena.sparql.core.Quad;
+import org.apache.jena.sparql.sse.SSE;
+import org.junit.Test;
+
+public class TestLocalIsolation {
+
+ private static Resource subject = ResourceFactory.createResource();
+ private static Property property = ResourceFactory.createProperty("http://example/p");
+ private static Resource object = ResourceFactory.createResource("http://example/o");
+
+ @Test public void localIsolation_model_1() {
+ isolationModel(Isolation.COPY,false);
+ }
+
+ @Test public void localIsolation_model_2() {
+ isolationModel(Isolation.NONE, true);
+ }
+
+ @Test(expected=JenaException.class)
+ public void localIsolation_model_3() {
+ isolationModel(Isolation.READONLY, true);
+ }
+
+ @Test public void localIsolation_dataset_1() {
+ isolationDataset(Isolation.COPY,false);
+ }
+
+ @Test public void localIsolation_dataset_2() {
+ isolationDataset(Isolation.NONE,true);
+ }
+
+ @Test(expected=UnsupportedOperationException.class)
+ public void localIsolation_dataset_3() {
+ isolationDataset(Isolation.READONLY, true);
+ }
+
+ private void isolationDataset(Isolation isolation, boolean expected) {
+ Dataset base = DatasetFactory.createTxnMem();
+ RDFConnection conn1 = RDFConnectionFactory.connect(base, isolation);
+ Quad quad = SSE.parseQuad("(:g :s :p :o)") ;
+ try (RDFConnection conn2 = conn1;) {
+ Dataset ds = conn2.fetchDataset();
+ ds.asDatasetGraph().add(quad);
+ }
+ assertEquals(expected, base.asDatasetGraph().contains(quad));
+ }
+
+ private void isolationModel(Isolation level, boolean expected) {
+ Dataset base = DatasetFactory.createTxnMem();
+ Statement stmt = base.getDefaultModel().createStatement(subject, property, object);
+ RDFConnection conn1 = RDFConnectionFactory.connect(base, level);
+ try (RDFConnection conn2 = conn1;) {
+ Model m = conn2.fetch();
+ m.add(stmt);
+ }
+ assertEquals(expected, base.getDefaultModel().contains(stmt));
+ }
+}