package org.apache.clerezza.rdf.jena.tdb.internals;
import java.util.concurrent.locks.ReadWriteLock;
import org.apache.clerezza.rdf.core.Graph;
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.TripleCollection;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.access.LockableMGraphWrapper;
import org.apache.clerezza.rdf.core.impl.SimpleGraph;
import org.apache.clerezza.rdf.core.impl.util.PrivilegedGraphWrapper;
import org.apache.clerezza.rdf.core.impl.util.PrivilegedMGraphWrapper;
import org.apache.clerezza.rdf.jena.storage.JenaGraphAdaptor;
import org.apache.clerezza.rdf.jena.tdb.storage.SingleTdbDatasetTcProvider;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.sparql.core.DatasetGraph;
import com.hp.hpl.jena.sparql.core.Quad;
import com.hp.hpl.jena.tdb.TDB;
/**
* Represents the Jena {@link Model} and the Clerezza {@link Graph} or
* {@link MGraph}. It also provide access to the {@link JenaGraphAdaptor}
* so that this component can add parsed data to {@link Graph}s created
* by calls to {@link SingleTdbDatasetTcProvider#createGraph(UriRef, TripleCollection)}.
* @author Rupert Westenthaler
*
*/
public class ModelGraph {
/**
* The Jena Model
*/
private final Model model;
/**
* The JenaGraphAdapter. Note that in case of read-only in anonymous
* subclass is used that prevents the creation of an in-memory copy
* of the data when calling {@link JenaGraphAdaptor#getGraph()}.
*/
private JenaGraphAdaptor jenaAdapter;
/**
* The {@link Graph}(in case of read-only) or {@link MGraph} (if read/write)
* that can be shared with other components. The instance stored by this
* variable will use all the required Wrappers such as such as
* {@link LockableMGraphWrapper lockable} and {@link PrivilegedMGraphWrapper
* privileged}.
*/
private TripleCollection graph;
/**
* keeps the state if this represents an {@link Graph} (read-only) or
* {@link MGraph}(read/write) ModelGraph.
*/
private final boolean readWrite;
/**
* Constructs and initializes the ModelGraph
* @param model the Jena Model
* @param readWrite if the Clerezza counterpart should be read- and
* write-able or read-only.
*/
public ModelGraph(final ReadWriteLock lock, Model model, boolean readWrite){
if(model == null){
throw new IllegalArgumentException("The parsed Model MUST NOT be NULL");
}
this.model = model;
this.readWrite = readWrite;
if(!readWrite){ //construct an graph
jenaAdapter = new JenaGraphAdaptor(model.getGraph()){
/**
* Ensure that no in-memory copies are created for read only
* Jena Graphs
* @return
*/
@Override
public Graph getGraph() {
return new SimpleGraph(this,true);
}
};
graph = new PrivilegedGraphWrapper(jenaAdapter.getGraph());
} else { //construct an MGraph
jenaAdapter = new JenaGraphAdaptor(model.getGraph());
this.graph = new DatasetLockedMGraph(lock,
new PrivilegedMGraphWrapper(jenaAdapter));
}
}
/**
* The {@link JenaGraphAdaptor}. For internal use only! Do not pass
* this instance to other components. Use {@link #getGraph()} and
* {@link #getMGraph()} instead!
* @return the plain {@link JenaGraphAdaptor}
*/
public JenaGraphAdaptor getJenaAdapter(){
return jenaAdapter;
}
public boolean isReadWrite(){
return readWrite;
}
/**
* Getter for the {@link MGraph}
* @return the {@link MGraph}
* @throws IllegalStateException if this {@link ModelGraph} is NOT
* {@link #readWrite}
*/
public MGraph getMGraph(){
if(!readWrite){
throw new IllegalStateException("Unable to return MGraph for read-only models");
}
return (MGraph)graph;
}
/**
* Getter for the {@link Graph}
* @return the {@link Graph}
* @throws IllegalStateException if this {@link ModelGraph} is
* {@link #readWrite}
*/
public Graph getGraph() {
if(readWrite){
throw new IllegalStateException("Unable to return Graph for read/write models.");
}
return (Graph)graph;
}
/**
* closes this ModelGraph and frees up all Jena TDB related resources.
*/
public void close(){
this.graph = null;
this.jenaAdapter = null;
sync();
this.model.close();
}
/**
* Synchronize the Jena Model with the field system by calling
* {@link TDB#sync(Model)}
*/
public void sync(){
TDB.sync(model);
}
/**
* Removes all triples from the Jena Model and than calls {@link #close()}
* to free remaining resources. Note that in Jena TDB a named model is
* deleted if no more triples with the given context are present within
* the {@link Quad} store of the Jena TDB {@link DatasetGraph}.
*/
public void delete(){
this.model.removeAll();
close();
}
}