blob: ada0717c5700e39905c2be2832d4cf2e0c8c0ff3 [file] [log] [blame]
/*
* Licensed 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.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*/
package org.apache.jena.dboe.storage.system;
import java.util.Iterator;
import org.apache.jena.atlas.iterator.Iter;
import org.apache.jena.dboe.storage.DatabaseRDF;
import org.apache.jena.dboe.storage.StoragePrefixes;
import org.apache.jena.dboe.storage.StorageRDF;
import org.apache.jena.dboe.transaction.txn.IteratorTxnTracker;
import org.apache.jena.dboe.transaction.txn.TransactionalSystem;
import org.apache.jena.dboe.transaction.txn.TxnId;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.query.ReadWrite;
import org.apache.jena.query.TxnType;
import org.apache.jena.sparql.core.*;
/** Alternative: DatasetGraph over RDFStorage, using DatasetGraphBaseFind
* Collapses DatasetGraphTriplesQuads into this adapter class.
<pre>
DatasetGraph
DatasetGraphBase
DatasetGraphBaseFind
DatasetGraphStorageDirect
</pre>
/**
* A DatasetGraph base class for triples+quads storage. The machinery is really
* the splitting between default and named graphs. This happens in two classes,
* {@link DatasetGraphBaseFind} (for find splitting) and
* {@link DatasetGraphTriplesQuads} add/delete splitting (it inherits
* {@link DatasetGraphBaseFind}).
* <p>
* Because storage is usually decomposing quads and triples, the default
* behaviour is to work in s/p/o and g/s/p/o.
*/
public class DatasetGraphStorage extends DatasetGraphBaseFind implements DatabaseRDF
{
private final Transactional txn;
@Override public void begin() { txn.begin(); }
@Override public void begin(TxnType txnType) { txn.begin(txnType); }
@Override public void begin(ReadWrite mode) { txn.begin(mode); }
@Override public boolean promote(Promote mode) { return txn.promote(mode); }
@Override public void commit() { txn.commit(); }
@Override public void abort() { txn.abort(); }
@Override public boolean isInTransaction() { return txn.isInTransaction(); }
@Override public void end() { txn.end(); }
@Override public ReadWrite transactionMode() { return txn.transactionMode(); }
@Override public TxnType transactionType() { return txn.transactionType(); }
@Override public boolean supportsTransactions() { return true; }
@Override public boolean supportsTransactionAbort() { return false; }
private final StorageRDF storage;
private final StoragePrefixes prefixes;
public DatasetGraphStorage(StorageRDF storage, StoragePrefixes prefixes, Transactional transactional) {
this.storage = storage;
this.prefixes = prefixes;
this.txn = transactional;
}
@Override public StorageRDF getData() { return storage; }
@Override public StoragePrefixes getPrefixes() { return prefixes; }
@Override public Transactional getTransactional() { return txn; }
/**
* Provide a general implementation of "listGraphNodes". Implementations may wish
* to override and do this operation in a more efficient manner.
*/
@Override
public Iterator<Node> listGraphNodes() {
Iterator<Quad> iter = findNG(null, null, null, null);
return Iter.iter(iter).map(Quad::getGraph).distinct();
}
private <T> Iterator<T> isolate(Iterator<T> iterator) {
if ( txn.isInTransaction() && txn instanceof TransactionalSystem) {
// Needs TxnId to track.
TransactionalSystem txnSystem = (TransactionalSystem)txn;
TxnId txnId = txnSystem.getThreadTransaction().getTxnId();
// Add transaction protection.
return new IteratorTxnTracker<>(iterator, txnSystem, txnId);
}
return Iter.iterator(iterator);
}
private Iterator<Triple> findStorage(Node s, Node p, Node o) {
return isolate(storage.find(s, p, o));
}
private Iterator<Quad> findStorage(Node g, Node s, Node p, Node o) {
return isolate(storage.find(g, s, p, o));
}
@Override
protected Iterator<Quad> findInDftGraph(Node s, Node p, Node o) {
return Iter.map(findStorage(s, p, o), t -> Quad.create(Quad.defaultGraphIRI, t));
}
@Override
protected Iterator<Quad> findInSpecificNamedGraph(Node g, Node s, Node p, Node o) {
return findStorage(g, s, p, o);
}
@Override
protected Iterator<Quad> findInAnyNamedGraphs(Node s, Node p, Node o) {
// Implementations may wish to do better.
return findStorage(Node.ANY, s, p, o);
}
@Override
public Graph getDefaultGraph() {
return GraphViewStorage.createDefaultGraphStorage(this, prefixes);
}
@Override
public Graph getUnionGraph() {
return GraphViewStorage.createUnionGraphStorage(this, prefixes);
}
@Override
public Graph getGraph(Node graphNode) {
return GraphViewStorage.createNamedGraphStorage(this, graphNode, prefixes);
}
@Override
public void add(Quad quad) {
if ( Quad.isDefaultGraph(quad.getGraph()) )
storage.add(quad.getSubject(), quad.getPredicate(), quad.getObject());
else
storage.add(quad);
}
@Override
public void delete(Quad quad) {
if ( Quad.isDefaultGraph(quad.getGraph()) )
storage.delete(quad.getSubject(), quad.getPredicate(), quad.getObject());
else
storage.delete(quad);
}
@Override
public void add(Node g, Node s, Node p, Node o) {
if ( g == null || Quad.isDefaultGraph(g) )
storage.add(s,p,o);
else
storage.add(g,s,p,o);
}
@Override
public void delete(Node g, Node s, Node p, Node o) {
if ( g == null || Quad.isDefaultGraph(g) )
storage.delete(s,p,o);
else
storage.delete(g,s,p,o);
}
@Override
public void addGraph(Node graphName, Graph graph) {
graph.find(null,null,null).forEachRemaining(t->add(graphName, t.getSubject(), t.getPredicate(), t.getObject()));
}
@Override
public void removeGraph(Node graphName) {
storage.removeAll(graphName, null, null, null);
prefixes.deleteAll(graphName);
}
}