You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@clerezza.apache.org by en...@apache.org on 2013/09/10 12:38:53 UTC

svn commit: r1521431 [1/2] - in /clerezza/trunk/clerezza-virtuoso: ./ ext.virtuoso.jdbc/ ext.virtuoso.jdbc/src/ ext.virtuoso.jdbc/src/main/ ext.virtuoso.jdbc/src/main/resources/ ext.virtuoso.jdbc/src/main/resources/maven/ ext.virtuoso.jdbc/src/main/res...

Author: enridaga
Date: Tue Sep 10 10:38:51 2013
New Revision: 1521431

URL: http://svn.apache.org/r1521431
Log:
CLEREZZA-811 Initial commit

Added:
    clerezza/trunk/clerezza-virtuoso/README.md
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/pom.xml   (with props)
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.jar   (with props)
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.pom   (with props)
    clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/maven-metadata-local.xml   (with props)
    clerezza/trunk/clerezza-virtuoso/pom.xml   (with props)
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/pom.xml   (with props)
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/access/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/access/VirtuosoWeightedProviderTest.java
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/resources/
    clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/resources/log4j.properties
Modified:
    clerezza/trunk/clerezza-virtuoso/   (props changed)

Propchange: clerezza/trunk/clerezza-virtuoso/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Tue Sep 10 10:38:51 2013
@@ -0,0 +1 @@
+target

Added: clerezza/trunk/clerezza-virtuoso/README.md
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/README.md?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/README.md (added)
+++ clerezza/trunk/clerezza-virtuoso/README.md Tue Sep 10 10:38:51 2013
@@ -0,0 +1,54 @@
+# Virtuoso/Clerezza storage adapter
+
+This is an implementation of the storage API of Clerezza[1] to use Virtuoso as storage.
+ 
+
+## Build and Install
+To build this project you need Maven. 
+
+### Simple build
+From the main folder:
+
+ $ mvn clean install
+
+Results will be 2 bundles:
+
+* ext.virtuoso.jdbc : contains JDBC drivers form Virtuoso
+* rdf.virtuoso.storage : contains the implementation of the clerezza storage API for Virtuoso
+
+Bundles are in the /target folders:
+
+* ext.virtuoso.jdbc/target/ext.virtuoso.jdbc-<version>.jar
+* rdf.virtuoso.storage/target/rdf.virtuoso.storage-<version>.jar
+
+### Build forcing tests
+You must have a Virtuoso running server to do tests.
+To activate tests, you must execute maven with the virtuoso-do-tests profile, for example:
+
+ $ mvn test -Pvirtuoso-do-tests
+ 
+By default, the tests will use the parameters configured in the pom.xml. Change the parameters' values to the ones that fit your installation of Virtuoso.
+
+You can configure the following parameters:
+
+* virtuoso.test (default is null, sets to true if you activate the 'virtuoso-do-tests' profile)
+* virtuoso.driver (default is 'virtuoso.jdbc4.Driver')
+* virtuoso.host (default is 'localhost')
+* virtuoso.port (default is '1111')
+* virtuoso.user (default is 'dba')
+* virtuoso.password (default is 'dba')
+
+To override them from cli, you can also do the following:
+
+ $ mvn test -Pvirtuoso-do-tests -DargLine="-Dvirtuoso.password=mypassword -Dvirtuoso.port=1234"
+ 
+
+### Hot deploy on a Clerezza or Stanbol[2] running servers
+
+To deploy the bundles in a running Sling instance you can do:
+
+ $ mvn install -PinstallBundle -Dsling.url=http://localhost:8080/system/console (change this to be the actual server admin interface)
+
+
+* [1] http://incubator.apache.org/clerezza/
+* [2] http://incubator.apache.org/stanbol/
\ No newline at end of file

Added: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/pom.xml
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/pom.xml?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.

Propchange: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.jar
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.jar?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.

Propchange: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.jar
------------------------------------------------------------------------------
    svn:mime-type = application/jar

Added: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.pom
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.pom?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.

Propchange: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/4.0/virtjdbc-4.0.pom
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/maven-metadata-local.xml
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/maven-metadata-local.xml?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.

Propchange: clerezza/trunk/clerezza-virtuoso/ext.virtuoso.jdbc/src/main/resources/maven/repo/virtuoso/virtjdbc/maven-metadata-local.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: clerezza/trunk/clerezza-virtuoso/pom.xml
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/pom.xml?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.

Propchange: clerezza/trunk/clerezza-virtuoso/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/README.md Tue Sep 10 10:38:51 2013
@@ -0,0 +1,3 @@
+# Virtuoso Storage bindings for Clerezza
+
+See the README.md in ../

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/pom.xml
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/pom.xml?rev=1521431&view=auto
==============================================================================
Binary file - no diff available.

Propchange: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoGraph.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,75 @@
+package rdf.virtuoso.storage;
+
+import java.util.Collection;
+
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.Triple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import virtuoso.jdbc4.VirtuosoConnection;
+/**
+ * This is a read-only version of {@link VirtuosoMGraph}
+ * @author enridaga
+ *
+ */
+public class VirtuosoGraph extends VirtuosoMGraph implements Graph{
+
+	/**
+	 * Logger
+	 */
+	protected Logger logger = LoggerFactory
+			.getLogger(VirtuosoGraph.class);
+	
+	public VirtuosoGraph(String name, VirtuosoConnection connection) {
+		super(name, connection);
+	}
+
+	@Override
+	public synchronized boolean add(Triple e) {
+		logger.warn("Attempting modifying an immutable graph");
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public synchronized boolean addAll(Collection<? extends Triple> c) {
+		logger.warn("Attempting modifying an immutable graph");
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public synchronized void clear() {
+		logger.warn("Attempting modifying an immutable graph");
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public synchronized boolean remove(Object o) {
+		logger.warn("Attempting modifying an immutable graph");
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public synchronized boolean removeAll(Collection<?> col) {
+		logger.warn("Attempting modifying an immutable graph");
+		throw new UnsupportedOperationException();
+	}
+	
+	/**
+	 * Must be a VirtuosoGraph with the same name.
+	 */
+	@Override
+	public boolean equals(Object o) {
+		logger.debug("equals({})",o.getClass());
+		if (o instanceof VirtuosoGraph) {
+			logger.debug("{} is a VirtuosoGraph)",o);
+			if (((VirtuosoGraph) o).getName().equals(this.getName())) {
+				logger.debug("Names are equal! They are equal!");
+				return true;
+			}
+		}else{
+			logger.debug("Not a VirtuosoGraph instance: {}",o.getClass());
+		}
+		return false;
+	}
+}

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/VirtuosoMGraph.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,646 @@
+package rdf.virtuoso.storage;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.clerezza.rdf.core.BNode;
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.Language;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.NonLiteral;
+import org.apache.clerezza.rdf.core.PlainLiteral;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.TypedLiteral;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.LockableMGraph;
+import org.apache.clerezza.rdf.core.impl.AbstractMGraph;
+import org.apache.clerezza.rdf.core.impl.PlainLiteralImpl;
+import org.apache.clerezza.rdf.core.impl.TypedLiteralImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.wymiwyg.commons.util.collections.BidiMap;
+import org.wymiwyg.commons.util.collections.BidiMapImpl;
+
+import virtuoso.jdbc4.VirtuosoConnection;
+import virtuoso.jdbc4.VirtuosoException;
+import virtuoso.jdbc4.VirtuosoExtendedString;
+import virtuoso.jdbc4.VirtuosoRdfBox;
+import virtuoso.jdbc4.VirtuosoResultSet;
+
+/**
+ * Implementation of MGraph for the Virtuoso quad store.
+ * 
+ * @author enridaga
+ * 
+ */
+public class VirtuosoMGraph extends AbstractMGraph implements MGraph,
+		LockableMGraph {
+	private final ReadWriteLock lock = new ReentrantReadWriteLock();
+	private final Lock readLock = lock.readLock();
+	private final Lock writeLock = lock.writeLock();
+
+	/**
+	 * Bidirectional map for managing the conversion from virtuoso blank nodes
+	 * (strings) to clerezza blank nodes and vice versa.
+	 */
+	private final BidiMap<String, BNode> bnodesMap;
+	private int maxVirtBnodeIndex = 0;
+
+	/**
+	 * Logger
+	 */
+	protected Logger logger = LoggerFactory.getLogger(VirtuosoMGraph.class);
+
+	/**
+	 * Connection
+	 */
+	private VirtuosoConnection connection = null;
+	/**
+	 * The name of the graph
+	 */
+	private String name = null;
+	private int size = 0;
+
+	private VirtuosoGraph readOnly = null;
+
+	/**
+	 * Creates a {@link VirtuosoMGraph} Virtuoso MGraph binds directly to the
+	 * store.
+	 * 
+	 * @param connection
+	 */
+	public VirtuosoMGraph(String name, VirtuosoConnection connection) {
+		logger.debug("VirtuosoMGraph(String {}, VirtuosoConnection {})", name,
+				connection);
+		this.name = name;
+		this.connection = connection;
+		this.bnodesMap = new BidiMapImpl<String, BNode>();
+	}
+
+	/**
+	 * Gets the connection
+	 * 
+	 * @return
+	 */
+	protected VirtuosoConnection getConnection() {
+		logger.debug("getConnection()");
+		return this.connection;
+	}
+
+	@Override
+	public ReadWriteLock getLock() {
+		logger.debug("getLock()");
+		return lock;
+	}
+
+	@Override
+	public Graph getGraph() {
+		logger.debug("getGraph()");
+		return asVirtuosoGraph();
+	}
+
+	public VirtuosoGraph asVirtuosoGraph() {
+		logger.debug("asVirtuosoGraph()");
+		if (this.readOnly == null) {
+			logger.debug("create embedded singleton read-only instance");
+			this.readOnly = new VirtuosoGraph(name, connection);
+		}
+		return readOnly;
+	}
+
+	@Override
+	protected Iterator<Triple> performFilter(NonLiteral subject,
+			UriRef predicate, Resource object) {
+		if (logger.isDebugEnabled()) {
+			logger.debug("performFilter(NonLiteral s, UriRef p, Resource o)");
+			logger.debug(" > s: {}", subject);
+			logger.debug(" > p: {}", predicate);
+			logger.debug(" > o: {}", object);
+		}
+		StringBuilder sb = new StringBuilder();
+		String virtSubject = toVirtSubject(subject);
+		String virtPredicate = toVirtPredicate(predicate);
+		String virtObject = toVirtObject(object);
+		sb.append("SPARQL SELECT ?SUBJECT ?PREDICATE ?OBJECT WHERE { GRAPH <")
+				.append(this.getName()).append("> { ")
+				.append(" ?SUBJECT ?PREDICATE ?OBJECT ");
+		if (virtSubject != null) {
+			sb.append(". FILTER( ").append("?SUBJECT = ").append(virtSubject)
+					.append(") ");
+		}
+		if (virtPredicate != null) {
+			sb.append(". FILTER( ").append("?PREDICATE = ")
+					.append(virtPredicate).append(") ");
+		}
+		if (virtObject != null) {
+			sb.append(". FILTER( ").append("?OBJECT = ").append(virtObject)
+					.append(") ");
+		}
+		sb.append(" } } ");
+
+		String sql = sb.toString();
+		logger.debug("Executing SQL: {}", sql);
+		Statement st;
+		try {
+			readLock.lock();
+			st = connection.createStatement();
+			boolean has = st.execute(sql);
+			final VirtuosoResultSet rs = (VirtuosoResultSet) st.getResultSet();
+			readLock.unlock();
+			return new Iterator<Triple>() {
+				Triple current = null;
+				private boolean didNext = false;
+				private boolean hasNext = false;
+
+				@Override
+				public boolean hasNext() {
+					readLock.lock();
+					try {
+						if (!didNext) {
+							hasNext = rs.next();
+							didNext = true;
+						}
+						return hasNext;
+					} catch (SQLException e) {
+						logger.error("Error while iterating results", e);
+						return false;
+					} finally {
+						readLock.unlock();
+					}
+				}
+
+				@Override
+				public Triple next() {
+					try {
+						readLock.lock();
+						if (!didNext) {
+							rs.next();
+						}
+						didNext = false;
+						current = new TripleBuilder(rs.getObject(1),
+								rs.getObject(2), rs.getObject(3)).build();
+					} catch (VirtuosoException e) {
+						logger.error("Error while iterating results", e);
+					} finally {
+						readLock.unlock();
+					}
+					return current;
+				}
+
+				@Override
+				public void remove() {
+					writeLock.lock();
+					try {
+						if (current == null) {
+							throw new IllegalStateException();
+						}
+						VirtuosoMGraph.this.performRemove(current);
+						current = null;
+					} finally {
+						writeLock.unlock();
+					}
+				}
+
+			};
+		} catch (VirtuosoException e) {
+			logger.error("ERROR while executing statement", e);
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			logger.error("ERROR while executing statement", e);
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * We load the size every time it is requested.
+	 */
+	@Override
+	public int size() {
+		logger.debug("size()");
+		loadSize();
+		return this.size;
+	}
+
+	@Override
+	public void clear() {
+		logger.debug("clear()");
+		String SQL = "SPARQL CLEAR GRAPH <" + this.getName() + ">";
+		this.writeLock.lock();
+		try {
+			logger.debug("Executing SQL: {}", SQL);
+			Statement st = getConnection().createStatement();
+			boolean success = st.execute(SQL);
+			if (success) {
+				this.size = 0;
+			} else {
+				throw new RuntimeException(
+						"Problems on clear() method. Cannot clear the graph!");
+			}
+		} catch (VirtuosoException e) {
+			logger.error("ERROR while executing statement", e);
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			logger.error("ERROR while executing statement", e);
+			throw new RuntimeException(e);
+		} finally {
+			this.writeLock.unlock();
+		}
+	}
+
+	private void loadSize() {
+		logger.debug("loadSize()");
+		String SQL = "SPARQL SELECT COUNT(*) FROM <" + this.getName()
+				+ "> WHERE { ?s ?p ?o } ";
+		int size = 0;
+		this.readLock.lock();
+		try {
+			logger.debug("Executing SQL: {}", SQL);
+			Statement st = getConnection().createStatement();
+			VirtuosoResultSet rs = (VirtuosoResultSet) st.executeQuery(SQL);
+			rs.next();
+			size = rs.getInt(1);
+		} catch (VirtuosoException e) {
+			logger.error("ERROR while executing statement", e);
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			logger.error("ERROR while executing statement", e);
+			throw new RuntimeException(e);
+		} finally {
+			this.readLock.unlock();
+		}
+		this.size = size;
+	}
+
+	protected boolean performAdd(Triple triple) {
+		return add(triple, connection);
+	}
+
+	protected boolean performRemove(Triple triple) {
+		return remove(triple, connection);
+	}
+
+	/**
+	 * Adds a triple in the store
+	 * 
+	 * @param triple
+	 * @param connection
+	 * @return
+	 */
+	private boolean add(Triple triple, VirtuosoConnection connection) {
+		logger.debug("add(Triple {}, VirtuosoConnection {})", triple,
+				connection);
+		String sql = getAddSQLStatement(triple);
+		logger.debug("Executing SQL: {}", sql);
+		writeLock.lock();
+		try {
+			Statement st = connection.createStatement();
+			st.execute(sql);
+		} catch (VirtuosoException e) {
+			logger.error("ERROR while executing statement", e);
+			return false;
+		} catch (SQLException e) {
+			logger.error("ERROR while executing statement", e);
+			return false;
+		} finally {
+			writeLock.unlock();
+		}
+		return true;
+	}
+
+	/**
+	 * Removes a triple from the store.
+	 * 
+	 * @param triple
+	 * @param connection
+	 * @return
+	 */
+	private boolean remove(Triple triple, VirtuosoConnection connection) {
+		logger.debug("remove(Triple triple, VirtuosoConnection connection)",
+				triple, connection);
+		String sql = getRemoveSQLStatement(triple);
+		logger.debug("Executing SQL: {}", sql);
+		writeLock.lock();
+		try {
+			Statement st = connection.createStatement();
+			st.execute(sql);
+		} catch (SQLException e) {
+			logger.error("ERROR while executing statement", e);
+			return false;
+		} finally {
+			writeLock.unlock();
+		}
+		return true;
+	}
+
+	/**
+	 * Returns the graph name
+	 * 
+	 * @return
+	 */
+	public String getName() {
+		logger.debug("getName()");
+		return name;
+	}
+
+	/**
+	 * Get the clerezza BNode corresponding to the given String from a Virtuoso
+	 * resultset.
+	 * 
+	 * @param virtbnode
+	 * @return
+	 */
+	private BNode toBNode(String virtbnode) {
+		logger.debug("toBNode(String {})", virtbnode);
+		BNode bnode = bnodesMap.get(virtbnode);
+		if (bnode == null) {
+			bnode = new BNode();
+			bnodesMap.put(virtbnode, bnode);
+		}
+		// Subject is BNode
+		return bnode;
+	}
+
+	/**
+	 * Generate a new local bnode to be used in virtuoso queries
+	 * 
+	 * @return
+	 */
+	private String nextVirtBnode() {
+		logger.debug("nextVirtBnode()");
+		maxVirtBnodeIndex++;
+		return new StringBuilder().append("_:b").append(maxVirtBnodeIndex)
+				.toString();
+	}
+
+	/**
+	 * 
+	 * @param bnode
+	 * @return
+	 */
+	private String toVirtBnode(BNode bnode) {
+		logger.debug("toVirtBnode(BNode {})", bnode);
+		String virtBnode = bnodesMap.getKey(bnode);
+		if (virtBnode == null) {
+			// We create a local bnode mapped to the BNode given
+			virtBnode = nextVirtBnode();
+			bnodesMap.put(virtBnode, bnode);
+		}
+		return virtBnode;
+	}
+
+	private String getAddSQLStatement(Triple triple) {
+		logger.debug("getAddSQLStatement(Triple {})", triple);
+		StringBuilder sb = new StringBuilder();
+		String subject = toVirtSubject(triple.getSubject());
+		String predicate = toVirtPredicate(triple.getPredicate());
+		String object = toVirtObject(triple.getObject());
+		String sql = sb.append("SPARQL INSERT INTO <").append(this.getName())
+				.append("> { ").append(subject).append(" ").append(predicate)
+				.append(" ").append(object).append(" }").toString();
+		return sql;
+	}
+
+	private String getRemoveSQLStatement(Triple triple) {
+		logger.debug("getRemoveSQLStatement(Triple {})", triple);
+		StringBuilder sb = new StringBuilder();
+		String subject = toVirtSubject(triple.getSubject());
+		String predicate = toVirtPredicate(triple.getPredicate());
+		String object = toVirtObject(triple.getObject());
+		String sql = sb.append("SPARQL DELETE FROM <").append(this.getName())
+				.append("> { ").append(subject).append(" ").append(predicate)
+				.append(" ").append(object).append(" } FROM <")
+				.append(this.getName()).append("> ").append(" WHERE { ")
+				.append(subject).append(" ").append(predicate).append(" ")
+				.append(object).append(" }").toString();
+		return sql;
+	}
+
+	/**
+	 * Returns a string to be used in SQL statements as Object of a triple.
+	 * 
+	 * @param object
+	 * @return
+	 */
+	private String toVirtObject(Resource object) {
+		logger.debug("toVirtObject(Resource {})", object);
+		if (object == null)
+			return null;
+		if (object instanceof UriRef) {
+			return toVirtIri((UriRef) object);
+		} else if (object instanceof BNode) {
+			return toVirtBnode((BNode) object);
+		} else if (object instanceof PlainLiteral) {
+			return toVirtPlainLiteral((PlainLiteral) object);
+		} else if (object instanceof TypedLiteral) {
+			return toVirtTypedLiteral((TypedLiteral) object);
+		}
+		return null;
+	}
+
+	/**
+	 * Returns a string to be used in SQL statements.
+	 * 
+	 * @param object
+	 * @return
+	 */
+	private String toVirtTypedLiteral(TypedLiteral object) {
+		logger.debug("toVirtTypedLiteral(TypedLiteral {})", object);
+		UriRef dt = object.getDataType();
+		String literal = object.getLexicalForm();
+		return new StringBuilder().append('"').append(literal).append('"')
+				.append("^^").append(toVirtIri(dt)).toString();
+	}
+
+	/**
+	 * Returns a string to be used in SQL statements.
+	 * 
+	 * @param object
+	 * @return
+	 */
+	private String toVirtPlainLiteral(PlainLiteral object) {
+		logger.debug("toVirtPlainLiteral(PlainLiteral {})", object);
+		Language lang = object.getLanguage();
+		String literal = object.getLexicalForm();
+		StringBuilder sb = new StringBuilder().append('"').append(literal)
+				.append('"');
+		if (lang == null) {
+			return sb.toString();
+		} else {
+			return sb.append("@").append(lang).toString();
+		}
+	}
+
+	/**
+	 * Returns a string to be used in SQL statements as Predicate of a triple.
+	 * 
+	 * @param predicate
+	 * @return
+	 */
+	private String toVirtPredicate(UriRef predicate) {
+		logger.debug("toVirtPredicate(UriRef {}) ", predicate);
+		if (predicate == null)
+			return null;
+		return toVirtIri(predicate);
+	}
+
+	private String toVirtIri(UriRef ur) {
+		logger.debug("toVirtIri(UriRef {})", ur);
+		return "<" + ur.getUnicodeString() + ">";
+	}
+
+	/**
+	 * Returns a string to be used in SQL statements as Subject of a triple.
+	 * 
+	 * @param subject
+	 * @return
+	 */
+	private String toVirtSubject(NonLiteral subject) {
+		logger.debug("toVirtSubject(NonLiteral {})", subject);
+		if (subject == null) {
+			return null;
+		}
+		if (subject instanceof UriRef) {
+			return toVirtIri((UriRef) subject);
+		} else if (subject instanceof BNode) {
+			return toVirtBnode((BNode) subject);
+		} else {
+			// These should be the only 2 implementations
+			throw new IllegalArgumentException(
+					"subject must be BNode or UriRef");
+		}
+	}
+
+	/**
+	 * Builds a clerezza Triple from Virtuoso result types
+	 * 
+	 */
+	private class TripleBuilder {
+
+		Object s = null;
+		Object p = null;
+		Object o = null;
+
+		public TripleBuilder(Object s, Object p, Object o) {
+			if (logger.isDebugEnabled()) {
+				logger.debug("TripleBuilder(Object s, Object p, Object o)");
+				logger.debug("> s: {}", s);
+				logger.debug("> p: {}", p);
+				logger.debug("> o: {}", o);
+			}
+			this.s = s;
+			this.p = p;
+			this.o = o;
+		}
+
+		public Triple build() {
+			logger.debug("TripleBuilder.build()");
+			return new Triple() {
+				@Override
+				public NonLiteral getSubject() {
+					logger.debug("TripleBuilder.getSubject() : {}", s);
+					if (s instanceof VirtuosoExtendedString) {
+						VirtuosoExtendedString vs = (VirtuosoExtendedString) s;
+						if (vs.iriType == VirtuosoExtendedString.IRI
+								&& (vs.strType & 0x01) == 0x01) {
+							// Subject is IRI
+							return new UriRef(vs.str);
+						} else if (vs.iriType == VirtuosoExtendedString.BNODE) {
+							return VirtuosoMGraph.this.toBNode(vs.str);
+						} else {
+							// !Cannot happen
+							throw new IllegalStateException(
+									"Subject must be an IRI or a BNODE");
+						}
+					} else {
+						throw new IllegalStateException(
+								"Subject must be an instance of VirtuosoExtendedString");
+					}
+				}
+
+				@Override
+				public UriRef getPredicate() {
+					logger.debug("TripleBuilder.getPredicate() : {}", p);
+					if (p instanceof VirtuosoExtendedString) {
+						VirtuosoExtendedString vs = (VirtuosoExtendedString) p;
+						if (vs.iriType == VirtuosoExtendedString.IRI
+								&& (vs.strType & 0x01) == 0x01) {
+							// Subject is IRI
+							return new UriRef(vs.str);
+						} else {
+							// !Cannot happen
+							throw new IllegalStateException(
+									"Predicate must be an IRI ");
+						}
+					} else {
+						throw new IllegalStateException(
+								"Predicate must be an IRI");
+					}
+				}
+
+				@Override
+				public Resource getObject() {
+					logger.debug("TripleBuilder.getObject() : {}", o);
+					if (o instanceof VirtuosoExtendedString) {
+						// In case is IRI
+						VirtuosoExtendedString vs = (VirtuosoExtendedString) o;
+						if (vs.iriType == VirtuosoExtendedString.IRI
+								&& (vs.strType & 0x01) == 0x01) {
+							// Is IRI
+							return new UriRef(vs.str);
+						} else if (vs.iriType == VirtuosoExtendedString.BNODE) {
+							//
+							return VirtuosoMGraph.this.toBNode(vs.str);
+						} else {
+							// Is a plain literal
+							return new PlainLiteralImpl(vs.str);
+						}
+					} else if (o instanceof VirtuosoRdfBox) {
+						// In case is typed literal
+						VirtuosoRdfBox rb = (VirtuosoRdfBox) o;
+						String value = (String) rb.rb_box;
+						String lang = rb.getLang();
+						String type = rb.getType();
+						if (type == null) {
+							Language language = lang == null ? null
+									: new Language(lang);
+							return new PlainLiteralImpl(value, language);
+						} else {
+							return new TypedLiteralImpl(value, new UriRef(type));
+						}
+					} else if (o == null) {
+						// Raise an exception
+						throw new IllegalStateException(
+								"Object cannot be NULL!");
+					} else {
+						// FIXME (not clear this...)
+						return new PlainLiteralImpl(o.toString());
+					}
+				}
+			};
+		}
+	}
+
+	/**
+	 * Must be a VirtuosoMGraph with the same name. Subclasses are not assumed
+	 * to be equals (VirtuosoGraph is not the same as VirtuosoMGraph)
+	 */
+	public boolean equals(Object o) {
+		logger.debug("equals({})", o.getClass());
+		// It must be an instance of VirtuosoMGraph
+		if (o.getClass().equals(VirtuosoMGraph.class)) {
+			logger.debug("{} is a VirtuosoMGraph)", o);
+			if (((VirtuosoMGraph) o).getName().equals(this.getName())) {
+				logger.debug("Names are equal! They are equal!");
+				return true;
+			}
+		} else {
+			logger.debug("Not a VirtuosoMGraph instance: {}", o.getClass());
+		}
+		return false;
+	}
+}

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/java/rdf/virtuoso/storage/access/VirtuosoWeightedProvider.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,629 @@
+package rdf.virtuoso.storage.access;
+
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+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.EntityAlreadyExistsException;
+import org.apache.clerezza.rdf.core.access.EntityUndeletableException;
+import org.apache.clerezza.rdf.core.access.NoSuchEntityException;
+import org.apache.clerezza.rdf.core.access.WeightedTcProvider;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.ComponentException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import rdf.virtuoso.storage.VirtuosoMGraph;
+import virtuoso.jdbc4.VirtuosoConnection;
+import virtuoso.jdbc4.VirtuosoException;
+import virtuoso.jdbc4.VirtuosoResultSet;
+import virtuoso.jdbc4.VirtuosoStatement;
+
+/**
+ * A {@link org.apache.clerezza.rdf.core.access.WeightedTcProvider} for Virtuoso.
+ * 
+ * @scr.component metatype="true" immediate="true"
+ * @scr.services interface="org.apache.clerezza.rdf.core.access.WeightedTcProvider"
+ * @scr.property name="weight" type="Integer" value="110"
+ * @scr.property name="host" type="String" value="localhost"
+ * @scr.property name="port" type="Integer" value="1111"
+ * @scr.property name="user" type="String" value="dba"
+ * @scr.property name="password" type="String" value="dba"
+ * 
+ * @author enridaga
+ * 
+ */
+@Component(metatype=true, immediate=true)
+@Service(WeightedTcProvider.class)
+public class VirtuosoWeightedProvider implements WeightedTcProvider {
+	@Property(value="localhost", description="The host running the Virtuoso server")
+	public static final String HOST = "host";
+	@Property(intValue=1111, description="The port number")
+	public static final String PORT= "port";
+	@Property(value="dba", description="User name")
+	public static final String USER = "user";
+	@Property(value="dba", description="User password")
+	public static final String PASSWORD = "password";
+	
+	/**
+	 * Virtuoso JDBC Driver class
+	 */
+	public static final String DRIVER = "virtuoso.jdbc4.Driver";
+	
+	public static final int DEFAULT_WEIGHT = 110;
+	
+	@Property(intValue=DEFAULT_WEIGHT, description="Weight assigned to this provider")
+	public static final String WEIGHT = "weight";
+	
+	/**
+	 * MAP OF LOADED GRAPHS
+	 */
+	private Map<UriRef, VirtuosoMGraph> graphs = null;
+
+	/**
+	 * JDBC Connection to Virtuoso DBMS
+	 */
+	private VirtuosoConnection connection = null;
+
+	/**
+	 * Weight
+	 */
+	private int weight = DEFAULT_WEIGHT;
+
+	/**
+	 * Logger
+	 */
+	private Logger logger = LoggerFactory
+			.getLogger(VirtuosoWeightedProvider.class);
+
+	/**
+	 * Creates a new {@link VirtuosoWeightedProvider}.
+	 * 
+	 * Before the weighted provider can be used, the method
+	 * <code>activate</code> has to be called.
+	 */
+	public VirtuosoWeightedProvider() {
+		logger.debug("Created VirtuosoWeightedProvider.");
+	}
+
+	/**
+	 * Creates a new {@link VirtuosoWeightedProvider}
+	 * 
+	 * @param connection
+	 */
+	public VirtuosoWeightedProvider(VirtuosoConnection connection) {
+		logger.debug("Created VirtuosoWeightedProvider with connection: {}",
+				connection);
+		this.connection = connection;
+	}
+
+	/**
+	 * Creates a new {@link VirtuosoWeightedProvider}
+	 * 
+	 * @param connection
+	 * @param weight
+	 */
+	public VirtuosoWeightedProvider(VirtuosoConnection connection, int weight) {
+		logger.debug(
+				"Created VirtuosoWeightedProvider with connection = {} and weight = {}.",
+				connection, weight);
+		this.weight = weight;
+		this.connection = connection;
+	}
+
+	/**
+	 * Activates this component.<br />
+	 * 
+	 * @param cCtx
+	 *            Execution context of this component. A value of null is
+	 *            acceptable when you set the property connection
+	 * @throws ConfigurationException
+	 * @throws IllegalArgumentException
+	 *             No component context given and connection was not set.
+	 */
+	@Activate
+	public void activate(ComponentContext cCtx) {
+		logger.info("activate(ComponentContext {})", cCtx);
+		logger.info("Activating VirtuosoWeightedProvider...");
+		if (cCtx == null && connection == null) {
+			logger.error("No component context given and connection was not set");
+			throw new IllegalArgumentException(
+					"No component context given and connection was not set");
+		} else if (cCtx != null) {
+			logger.debug("Context is given: {}", cCtx);
+			String pid = (String) cCtx.getProperties().get(
+					Constants.SERVICE_PID);
+			try { 
+				// FIXME The following should not be needed...
+				try {
+					this.weight = (Integer) cCtx.getProperties().get(WEIGHT);
+				} catch (NumberFormatException nfe) {
+					logger.warn(nfe.toString());
+					logger.warn("Setting weight to defaults");
+					this.weight = DEFAULT_WEIGHT;
+				}
+
+				/**
+				 * Retrieve connection properties
+				 */
+				String host = (String) cCtx.getProperties().get(HOST);
+				int port = (Integer) cCtx.getProperties().get(PORT);
+				String user = (String) cCtx.getProperties().get(USER);
+				String pwd = (String) cCtx.getProperties().get(PASSWORD);
+
+				// Build connection string
+				String connStr = new StringBuilder().append("jdbc:virtuoso://")
+						.append(host).append(":").append(port).toString();
+				// Init connection
+				this.initConnection(connStr, user, pwd);
+
+				// Debug activation
+				if (logger.isDebugEnabled()) {
+					logger.debug("Component context properties: ");
+					logger.debug("> host: {}", host);
+					logger.debug("> port: {}", port);
+					logger.debug("> user: {}", user);
+					// We hide the password in log files:
+					MessageDigest algorithm;
+					try {
+						algorithm = MessageDigest.getInstance("MD5");
+					} catch (NoSuchAlgorithmException e) {
+						throw new RuntimeException(e);
+					}
+					algorithm.reset();
+					algorithm.update(pwd.getBytes());
+					byte messageDigest[] = algorithm.digest();
+
+					StringBuffer hexString = new StringBuffer();
+					for (int i = 0; i < messageDigest.length; i++) {
+						hexString.append(Integer
+								.toHexString(0xFF & messageDigest[i]));
+					}
+					String foo = messageDigest.toString();
+					logger.debug("> password: {}", foo);
+				}
+				logger.info("Connection to {} initialized. User is {}",
+						connStr, user);
+			} catch (VirtuosoException e) {
+				logger.error(
+						"A problem occurred while intializing connection to Virtuoso",
+						e);
+				logger.error("Be sure you have configured the connection parameters correctly in the OSGi/SCR configuration");
+				cCtx.disableComponent(pid);
+				throw new ComponentException(e.getLocalizedMessage());
+			} catch (SQLException e) {
+				logger.error(
+						"A problem occurred while intializing connection to Virtuoso",
+						e);
+				logger.error("Be sure you have configured the connection parameters correctly in the OSGi/SCR configuration");
+				cCtx.disableComponent(pid);
+				throw new ComponentException(e.getLocalizedMessage());
+			} catch (ClassNotFoundException e) {
+				logger.error(
+						"A problem occurred while intializing connection to Virtuoso",
+						e);
+				logger.error("Be sure you have configured the connection parameters correctly in the OSGi/SCR configuration");
+				cCtx.disableComponent(pid);
+				throw new ComponentException(e.getLocalizedMessage());
+			}
+		}
+		logger.info("Activated VirtuosoWeightedProvider.");
+	}
+
+	/**
+	 * Deactivates this component.
+	 * 
+	 * @param cCtx
+	 *            component context provided by OSGi
+	 */
+	@Deactivate
+	public void deactivate(ComponentContext cCtx) {
+		logger.debug("deactivate(ComponentContext {})", cCtx);
+		try {
+			if (this.connection != null) {
+				if (this.connection.isClosed()) {
+					logger.debug("Connection is already closed");
+				} else {
+					logger.debug("Closing connection");
+					// We close the connection
+					this.connection.close();
+				}
+			}
+		} catch (Exception re) {
+			logger.warn(re.toString(), re);
+			throw new RuntimeException(re);
+		}
+		logger.info("Shutdown complete.");
+	}
+
+	/**
+	 * Initialize the JDBC connection
+	 * 
+	 * @param connStr
+	 * @param user
+	 * @param pwd
+	 * @throws SQLException
+	 * @throws ClassNotFoundException
+	 */
+	private void initConnection(String connStr, String user, String pwd)
+			throws SQLException, ClassNotFoundException {
+		logger.debug("initConnection(String {}, String {}, String *******)",
+				connStr, user);
+		if (this.connection != null) {
+			logger.debug("Connection already instantiated: {}", this.connection);
+			logger.debug("Closing connection");
+			this.connection.close();
+		}
+		/**
+		 * FIXME For some reasons, it looks the DriverManager is instantiating a
+		 * new virtuoso.jdbc4.Driver instance upon any activation. (Enable debug
+		 * to see this in the stderr stream)
+		 */
+		logger.debug("Loading JDBC Driver");
+		Class.forName(VirtuosoWeightedProvider.DRIVER, true, this.getClass()
+				.getClassLoader());
+		if (logger.isDebugEnabled()) {
+			logger.debug("Activating logging for DriverManager in stderr");
+			// FIXME! How to redirect logging to our logger???
+			DriverManager.setLogWriter(new PrintWriter(System.err));
+		}
+		connection = (VirtuosoConnection) DriverManager.getConnection(connStr,
+				user, pwd);
+		logger.debug("Connection initialized: {}", connection);
+	}
+
+	/**
+	 * Whether the connection is active or not
+	 * 
+	 * @return
+	 */
+	public boolean isConnectionAlive() {
+		logger.debug("isConnectionAlive() : {}", connection);
+		if (this.connection == null) {
+			logger.warn("Connection is null");
+			return false;
+		}
+		if (this.connection.isClosed()) {
+			logger.warn("Connection is closed");
+			return false;
+		}
+		if (this.connection.isConnectionLost()) {
+			logger.warn("Connection is lost");
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Retrieves the Graph (unmodifiable) with the given UriRef If no graph
+	 * exists with such name, throws a NoSuchEntityException
+	 */
+	@Override
+	public Graph getGraph(UriRef name) throws NoSuchEntityException {
+		logger.debug("getGraph(UriRef {}) ", name);
+		// If it is read-only, returns the Graph
+		// If it is not read-only, returns the getGraph() version of the MGraph
+		VirtuosoMGraph g = loadGraphOnce(name);
+		if (g instanceof Graph) {
+			return (Graph) g;
+		} else {
+			return g.getGraph();
+		}
+	}
+
+	/**
+	 * Retrieves the MGraph (modifiable) with the given UriRef. If no graph
+	 * exists with such name, throws a NoSuchEntityException.
+	 * 
+	 * @return mgraph
+	 */
+	@Override
+	public MGraph getMGraph(UriRef name) throws NoSuchEntityException {
+		logger.debug("getMGraph(UriRef {}) ", name);
+		VirtuosoMGraph g = loadGraphOnce(name);
+		if (g instanceof Graph) {
+			// We have this graph but only in read-only mode!
+			throw new NoSuchEntityException(name);
+		}
+		return g;
+	}
+
+	/**
+	 * Load the graph once. It check whether a graph object have been alrady
+	 * created for that UriRef, if yes returns it.
+	 * 
+	 * If not check if at least 1 triple is present in the quad for such graph
+	 * identifier. If yes, creates a new graph object and loads it in the map,
+	 * referring to it on next calls.
+	 * 
+	 * If no triples exists, the graph does not exists or it is not readable.
+	 * 
+	 * WARNING! THIS SHOULD BE THE ONLY METHOD TO ACCESS THE MAP graphs
+	 * 
+	 * @param name
+	 * @return
+	 */
+	private VirtuosoMGraph loadGraphOnce(UriRef name) {
+		logger.debug("loadGraphOnce({})", name);
+		// Is it the first itme we invoke a graph here?
+		if (graphs == null) {
+			graphs = new HashMap<UriRef, VirtuosoMGraph>();
+		}
+		// Check whether the graph have been already loaded once
+		if (graphs.containsKey(name)) {
+			logger.debug("{} is already loaded", name);
+			return graphs.get(name);
+		}
+
+		logger.debug("Attempt to load {}", name);
+		// Let's create the graph object
+		String SQL = "SPARQL SELECT ?G WHERE { GRAPH ?G {?A ?B ?C} . FILTER(?G = "
+				+ name + ")} LIMIT 1";
+
+		Statement st;
+		try {
+			st = connection.createStatement();
+			logger.debug("Executing SQL: {}", SQL);
+			st.execute(SQL);
+			VirtuosoResultSet rs = (VirtuosoResultSet) st.getResultSet();
+			if (rs.next() == false) {
+				// The graph is empty, it is not readable or does not exists
+				logger.warn("Graph does not exists: {}", name);
+				throw new NoSuchEntityException(name);
+			} else {
+				// The graph exists and it is readable ...
+				logger.debug("Graph {} is readable", name);
+				// is it writable?
+				logger.debug("Is {} writable?", name);
+				if (canModify(name)) {
+					logger.debug("Creating writable MGraph for graph {}", name);
+					graphs.put(name, new VirtuosoMGraph(
+							name.getUnicodeString(), connection));
+				} else {
+					logger.debug("Creating read-only Graph for graph {}", name);
+					graphs.put(name, new VirtuosoMGraph(
+							name.getUnicodeString(), connection)
+							.asVirtuosoGraph());
+				}
+				return graphs.get(name);
+			}
+		} catch (VirtuosoException e) {
+			logger.error("Error while executing query/connection.", e);
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			logger.error("Error while executing query/connection.", e);
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * Generic implementation of the get(M)Graph method. If the named graph is
+	 * modifiable, behaves the same as getMGraph(UriRef name), elsewhere,
+	 * behaves as getGraph(UriRef name)
+	 */
+	@Override
+	public TripleCollection getTriples(UriRef name)
+			throws NoSuchEntityException {
+		logger.debug("getTriples(UriRef {}) ", name);
+		return loadGraphOnce(name);
+	}
+
+	/**
+	 * Returns the list of graphs in the virtuoso quad store. The returned set
+	 * is unmodifiable.
+	 * 
+	 * @return graphs
+	 */
+	@Override
+	public Set<UriRef> listGraphs() {
+		logger.debug("listGraphs()");
+		Set<UriRef> graphs = new HashSet<UriRef>();
+		// Returns the list of graphs in the virtuoso quad store
+		String SQL = "SPARQL SELECT DISTINCT ?G WHERE {GRAPH ?G {?S ?P ?O} }";
+		try {
+			VirtuosoStatement st = (VirtuosoStatement) this.connection
+					.createStatement();
+			logger.debug("Executing SQL: {}", SQL);
+			VirtuosoResultSet rs = (VirtuosoResultSet) st.executeQuery(SQL);
+			while (rs.next()) {
+				UriRef graph = new UriRef(rs.getString(1));
+				logger.debug(" > Graph {}", graph);
+				graphs.add(graph);
+			}
+		} catch (VirtuosoException e) {
+			logger.error("Error while executing query/connection.", e);
+			throw new RuntimeException(e);
+		}
+		return Collections.unmodifiableSet(graphs);
+	}
+
+	@Override
+	public Set<UriRef> listMGraphs() {
+		logger.debug("listMGraphs()");
+		Set<UriRef> graphs = listGraphs();
+		Set<UriRef> mgraphs = new HashSet<UriRef>();
+		logger.debug("Modifiable graphs:");
+		for (UriRef u : graphs) {
+			if (canModify(u)) {
+				logger.debug(" > {}", u);
+				mgraphs.add(u);
+			}
+		}
+		return Collections.unmodifiableSet(mgraphs);
+	}
+
+	private long getPermissions(String graph) {
+		try {
+			logger.debug("getPermissions(String {})", graph);
+			ResultSet rs;
+			String sql = "SELECT DB.DBA.RDF_GRAPH_USER_PERMS_GET ('" + graph
+					+ "','" + connection.getMetaData().getUserName() + "') ";
+			logger.debug("Executing SQL: {}", sql);
+			Statement st = connection.createStatement();
+			st.execute(sql);
+			rs = st.getResultSet();
+			rs.next();
+			long result = rs.getLong(1);
+			logger.debug("Permission: {}", result);
+			return result;
+		} catch (VirtuosoException e) {
+			logger.error("A virtuoso SQL exception occurred.");
+			throw new RuntimeException(e);
+		} catch (SQLException e) {
+			logger.error("An SQL exception occurred.");
+			throw new RuntimeException(e);
+		}
+	}
+
+	public boolean canRead(UriRef graph) {
+		logger.debug("canRead(UriRef {})", graph);
+		return (isRead(getPermissions(graph.getUnicodeString())));
+	}
+
+	public boolean canModify(UriRef graph) {
+		logger.debug("canModify(UriRef {})", graph);
+		return (isWrite(getPermissions(graph.getUnicodeString())));
+	}
+
+	private boolean testPermission(long value, int bit) {
+		logger.debug("testPermission(long {},int {})", value, bit);
+		return BigInteger.valueOf(value).testBit(bit);
+	}
+
+	private boolean isRead(long permission) {
+		logger.debug("isRead(long {})", permission);
+		return testPermission(permission, 1);
+	}
+
+	private boolean isWrite(long permission) {
+		logger.debug("isWrite(long {})", permission);
+		return testPermission(permission, 2);
+	}
+
+	@Override
+	public Set<UriRef> listTripleCollections() {
+		logger.debug("listTripleCollections()");
+		// I think this should behave the same as listGraphs() in our case.
+		return listGraphs();
+	}
+
+	private VirtuosoMGraph createVirtuosoMGraph(UriRef name)
+			throws UnsupportedOperationException, EntityAlreadyExistsException {
+		logger.debug("createVirtuosoMGraph(UriRef {})", name);
+		// If the graph already exists, we throw an exception
+		try {
+			loadGraphOnce(name);
+			throw new EntityAlreadyExistsException(name);
+		} catch (NoSuchEntityException nsee) {
+			if (canModify(name)) {
+				graphs.put(name, new VirtuosoMGraph(name.getUnicodeString(),
+						connection));
+				return graphs.get(name);
+			} else {
+				logger.error("Cannot create MGraph {}", name);
+				throw new UnsupportedOperationException();
+			}
+		}
+	}
+
+	/**
+	 * Creates an initially empty MGraph. If the name already exists in the
+	 * store, throws an {@see EntityAlreadyExistsException}
+	 */
+	@Override
+	public MGraph createMGraph(UriRef name)
+			throws UnsupportedOperationException, EntityAlreadyExistsException {
+		logger.debug("createMGraph(UriRef {})", name);
+		return createVirtuosoMGraph(name);
+	}
+
+	/**
+	 * Creates a new graph with the given triples, then returns the readable
+	 * (not modifiable) version of the graph
+	 * 
+	 */
+	@Override
+	public Graph createGraph(UriRef name, TripleCollection triples)
+			throws UnsupportedOperationException, EntityAlreadyExistsException {
+		logger.debug("createGraph(UriRef {}, TripleCollection {})", name,
+				triples);
+		VirtuosoMGraph mgraph = createVirtuosoMGraph(name);
+		mgraph.addAll(triples);
+		return mgraph.getGraph();
+	}
+
+	/**
+	 * Clears the given graph and removes it from the loaded graphs.
+	 * 
+	 */
+	@Override
+	public void deleteTripleCollection(UriRef name)
+			throws UnsupportedOperationException, NoSuchEntityException,
+			EntityUndeletableException {
+		logger.debug("deleteTripleCollection(UriRef {})", name);
+		TripleCollection g = (VirtuosoMGraph) getTriples(name);
+		if (g instanceof Graph) {
+			throw new EntityUndeletableException(name);
+		} else {
+			((MGraph) g).clear();
+			graphs.remove(name);
+		}
+	}
+
+	/**
+	 * Returns the names of a graph. Personally don't know why a graph should
+	 * have more then 1 identifier. Anyway, this does not happen with Virtuoso
+	 * 
+	 * @return names
+	 */
+	@Override
+	public Set<UriRef> getNames(Graph graph) {
+		logger.debug("getNames(Graph {})", graph);
+		return Collections.singleton(new UriRef(((VirtuosoMGraph) graph)
+				.getName()));
+	}
+
+	/**
+	 * Returns the weight of this provider.
+	 * 
+	 */
+	@Override
+	public int getWeight() {
+		logger.debug("getWeight()");
+		/**
+		 * The weight
+		 */
+		return this.weight;
+	}
+
+	/**
+	 * Sets the weight
+	 * 
+	 * @param weight
+	 */
+	public void setWeight(int weight) {
+		logger.debug("setWeight(int {})",weight);
+		this.weight = weight;
+	}
+}

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider Tue Sep 10 10:38:51 2013
@@ -0,0 +1 @@
+rdf.virtuoso.storage.access.VirtuosoWeightedProvider
\ No newline at end of file

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/main/resources/log4j.properties Tue Sep 10 10:38:51 2013
@@ -0,0 +1,5 @@
+#log4j.rootLogger=DEBUG, S
+#log4j.appender.S = org.apache.log4j.ConsoleAppender
+#log4j.appender.S.layout = org.apache.log4j.PatternLayout
+#log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n
+

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ConnectionTest.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,139 @@
+package rdf.virtuoso.storage;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import virtuoso.jdbc4.VirtuosoConnection;
+import virtuoso.jdbc4.VirtuosoException;
+
+/**
+ * Tests the connection to the Virtuoso DBMS
+ * 
+ * @author enridaga
+ */
+public class ConnectionTest {
+
+	static final Logger log = LoggerFactory.getLogger(ConnectionTest.class);
+
+	private static VirtuosoConnection connection = null;
+
+	@BeforeClass
+	public static void before() throws ClassNotFoundException, SQLException {
+		connection = TestUtils.getConnection();
+	}
+
+	@Test
+	public void testIsClosed() {
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		assertFalse(connection.isClosed());
+	}
+
+	@Test
+	public void testIsConnectionLost() {
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		assertFalse(connection.isConnectionLost());
+	}
+
+	@Test
+	public void testIsReadOnly() throws VirtuosoException {
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		assertFalse(connection.isReadOnly());
+	}
+
+	@Test
+	public void testConnection() {
+		log.info("testConnection()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		try {
+
+			Statement st = connection.createStatement();
+			log.debug("Populate graph <mytest>");
+			String[] queries = {
+					"sparql clear graph <mytest>",
+					"sparql insert into graph <mytest> { <xxx> <P01> \"test1\"@en }",
+					"sparql insert into graph <mytest> { <xxx> <P01> \"test2\"@it }",
+					"sparql PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> insert into graph <mytest> { <xxx> <P01> \"test3\"^^xsd:string }",
+					"sparql insert into graph <mytest> { <xxx> <P01> \"test4\" }",
+					"sparql insert into graph <mytest> { <xxx> <P01> \"test5\" . <xxx> <P02> _:b1"
+							+ " . _:b1 <P03> <yyy> " + " . _:b3 <P05> <zzz> "
+							+ " . _:b3 <P05> <ppp> " +
+							// This is to consider that we can force it
+							" .  <nodeID://b10005> <P05> <ooo> " + " }",
+					"sparql insert into graph <mytest> { <nodeID://b10005> <property> <nodeID://b10007>}",
+					"sparql insert into graph <mytest> { <enridaga> <property> \"Literal value\"^^<http://datatype#type>}",
+					"sparql insert into graph <mytest> { <nodeID://b10005> <property> <nodeID://b10007>}" };
+			for (String q : queries) {
+				log.debug("Querying: {}", q);
+				st.execute(q);
+			}
+
+			String query = "sparql SELECT * from <mytest> WHERE {?s ?p ?o}";
+			log.debug("Querying: {}", query);
+			ResultSet rs = st.executeQuery(query);
+			TestUtils.stamp(rs);
+		} catch (SQLException e) {
+			log.error("SQL ERROR: ", e);
+			assertTrue(false);
+		} catch (Exception e) {
+			log.error("SQL ERROR: ", e);
+			assertTrue(false);
+		}
+	}
+
+	@Test
+	public void test() throws ClassNotFoundException, SQLException {
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		DatabaseMetaData dm = connection.getMetaData();
+		log.debug("Username is {}", dm.getUserName());
+		Properties p = connection.getClientInfo();
+		if (p == null) {
+			log.warn("Client info is null...");
+		} else
+			for (Entry<Object, Object> e : p.entrySet()) {
+				log.info("Client info property: {} => {}", e.getKey(),
+						e.getValue());
+			}
+		String SQL = "SELECT DISTINCT id_to_iri(G) FROM DB.DBA.RDF_QUAD quad ";
+		VirtuosoConnection cn = TestUtils.getConnection();
+		long startAt = System.currentTimeMillis();
+		// get the list of quad using SQL
+		log.debug("Executing SQL: {}", SQL);
+		cn.createStatement().executeQuery(SQL);
+		long endAt = System.currentTimeMillis();
+		log.debug("Using SQL: {}ms", endAt - startAt);
+		SQL = "SPARQL SELECT DISTINCT ?G WHERE {GRAPH ?G {?S ?P ?O} }";
+		startAt = System.currentTimeMillis();
+		// get the list of quad using SQL+SPARQL
+		log.debug("Executing SQL: {}", SQL);
+		cn.createStatement().executeQuery(SQL);
+		endAt = System.currentTimeMillis();
+		log.debug("Using SQL+SPARQL: {}ms", endAt - startAt);
+	}
+}

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/TestUtils.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,165 @@
+package rdf.virtuoso.storage;
+
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+import org.apache.clerezza.rdf.core.Triple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import rdf.virtuoso.storage.access.VirtuosoWeightedProvider;
+import virtuoso.jdbc4.VirtuosoConnection;
+import virtuoso.jdbc4.VirtuosoExtendedString;
+import virtuoso.jdbc4.VirtuosoRdfBox;
+import virtuoso.jdbc4.VirtuosoResultSet;
+
+/**
+ * Utilities for tests
+ * 
+ * @author enridaga
+ * 
+ */
+public class TestUtils {
+
+	public static final String FOAF_NS = "http://xmlns.com/foaf/0.1/";
+
+	private static VirtuosoConnection connection = null;
+	private static String jdbcConnectionString = null;
+	private static String jdbcUser = null;
+	private static String jdbcPassword = null;
+	private static String jdbcDriver = null;
+
+	static Logger log = LoggerFactory.getLogger(TestUtils.class);
+	public static boolean SKIP = false;
+	static {
+		String skipProperty = System.getProperty("virtuoso.test");
+		if (skipProperty == null) {
+			log.warn("virtuoso.skip property is not set. We skip tests by default.");
+			SKIP = true;
+		} else
+			SKIP = !skipProperty.equals("true");
+	}
+
+	public static VirtuosoConnection getConnection()
+			throws ClassNotFoundException, SQLException {
+		if (connection == null) {
+			initConnection();
+		}
+		return connection;
+	}
+
+	private static void initConnection() throws ClassNotFoundException,
+			SQLException {
+		if (SKIP) {
+			log.warn("SKIPPING ALL TESTS!");
+			return;
+		}
+		String host = System.getProperty("virtuoso.host");
+		String port = System.getProperty("virtuoso.port");
+		jdbcUser = System.getProperty("virtuoso.user");
+		jdbcPassword = System.getProperty("virtuoso.password");
+		jdbcDriver = System.getProperty("virtuoso.driver");
+		if (host == null) {
+			host = "localhost";
+			log.info("Missing param 'host', setting to default: {}", host);
+		}
+		if (port == null) {
+			port = "1111";
+			log.info("Missing param 'port', setting to default: {}", port);
+		}
+		if (jdbcUser == null) {
+			jdbcUser = "dba";
+			log.info("Missing param 'user', setting to default: {}", jdbcUser);
+		}
+		if (jdbcPassword == null) {
+			jdbcPassword = "dba";
+			log.info("Missing param 'password', setting to default: {}",
+					jdbcPassword);
+		}
+		if (jdbcDriver == null) {
+			jdbcDriver = "virtuoso.jdbc4.Driver";
+			log.info("Missing param 'password', setting to default: {}",
+					jdbcDriver);
+		}
+
+		StringBuilder cb = new StringBuilder();
+		cb.append("jdbc:virtuoso://");
+		cb.append(host);
+		cb.append(":");
+		cb.append(port);
+		jdbcConnectionString = cb.toString();
+		Class.forName(VirtuosoWeightedProvider.DRIVER);
+		log.info("Create connection");
+		connection = (VirtuosoConnection) DriverManager.getConnection(
+				jdbcConnectionString, jdbcUser, jdbcPassword);
+
+		log.debug("Connection URL: {}", jdbcConnectionString);
+		log.debug("Connection user: {}", jdbcUser);
+	}
+
+	public static void stamp(ResultSet rs) {
+		try {
+			ResultSetMetaData rsmd;
+
+			StringBuilder output = new StringBuilder();
+			output.append(System.getProperty("line.separator"));
+			output.append("------------------------------");
+			output.append(System.getProperty("line.separator"));
+			rsmd = rs.getMetaData();
+
+			while (rs.next()) {
+				for (int i = 1; i <= rsmd.getColumnCount(); i++) {
+					String s = rs.getString(i);
+					Object o = ((VirtuosoResultSet) rs).getObject(i);
+					if (o instanceof VirtuosoExtendedString) {
+						// In case is IRI
+						VirtuosoExtendedString vs = (VirtuosoExtendedString) o;
+						if (vs.iriType == VirtuosoExtendedString.IRI
+								&& (vs.strType & 0x01) == 0x01) {
+							output.append(" <" + vs.str + "> ");
+							log.debug(" {} is IRI", vs.str);
+						} else if (vs.iriType == VirtuosoExtendedString.BNODE) {
+							log.debug(" {} is BNODE", vs.str);
+							output.append(" <" + vs.str + "> ");
+						} else {
+							// In case is untyped literal
+							log.debug(" {} is an untyped literal", vs.str);
+							output.append(vs.str);
+						}
+					} else if (o instanceof VirtuosoRdfBox) {
+						// In case is typed literal
+						VirtuosoRdfBox rb = (VirtuosoRdfBox) o;
+						output.append(rb.rb_box + " lang=" + rb.getLang()
+								+ " type=" + rb.getType());
+						log.debug(" {} is an typed literal", rb.rb_box);
+
+					} else if (rs.wasNull()) {
+						log.debug(" NULL ");
+						output.append("NULL");
+					} else {
+						// Is simple untyped string
+						output.append(s);
+					}
+
+				}
+				output.append("\n");
+			}
+
+			output.append(System.getProperty("line.separator"));
+			output.append("------------------------------");
+			output.append(System.getProperty("line.separator"));
+			log.info(output.toString());
+		} catch (Exception e) {
+			log.error("ERROR", e);
+		}
+	}
+
+	public static void stamp(Triple next) {
+		log.info("> TRIPLE : "+next.getSubject().toString() + " "
+				+ next.getPredicate().toString() + " "
+				+ next.getObject().toString());
+	}
+
+}

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/ThreadSafetyTest.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,332 @@
+package rdf.virtuoso.storage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.impl.TripleImpl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 
+ * Credit: This code is largely cloned by the thread safe test in
+ * {@see org.apache.clerezza.rdf.sesame.storage.ThreadSafetyTest}
+ * 
+ * @author enridaga
+ * 
+ */
+public class ThreadSafetyTest {
+
+	private ExecutorService executor;
+	private VirtuosoMGraph mgraph;
+
+	static Logger log = LoggerFactory.getLogger(ThreadSafetyTest.class);
+
+	@Before
+	public void setUp() throws Exception {
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		mgraph = new VirtuosoMGraph("ThreadSafetyTest",
+				TestUtils.getConnection());
+		executor = Executors.newCachedThreadPool();
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		try {
+			executor.shutdown();
+			if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
+				fail("Timeout while waiting for termination");
+			}
+		} finally {
+			mgraph.clear();
+			mgraph = null;
+		}
+	}
+
+	@Test
+	public void testProduceFirstAndThenConsume() throws Exception {
+		log.info("testProduceFirstAndThenConsume()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		// Produce first...
+		Future<Result> fp = executor.submit(new Producer("A", 100));
+		fp.get().assertResult();
+
+		// ...and then consume
+		Future<Result> fc = executor.submit(new Consumer("A", 100));
+		fc.get().assertResult();
+		Iterator<Triple> it = mgraph.iterator();
+		while (it.hasNext()) {
+			TestUtils.stamp(it.next());
+		}
+		// test graph size
+		assertEquals(0, mgraph.size());
+	}
+
+	@Test
+	public void testProduceAndConsumeSingle() throws Exception {
+		log.info("testProduceAndConsumeSingle()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		List<Task> tasks = Arrays.asList(
+				new Consumer("A", 100), new Producer("A", 100));
+		List<Future<Result>> futures = executor.invokeAll(tasks);
+		for (Future<Result> future : futures) {
+			future.get().assertResult();
+		}
+		assertEquals(0, mgraph.size());
+	}
+
+	@Test
+	public void testProduceAndConsumeMultiple() throws Exception {
+		log.info("testProduceAndConsumeMultiple()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		List<Task> tasks = Arrays.asList(
+				new Consumer("A", 100), new Producer("A", 100),
+				new Consumer("B", 100), new Producer("B", 100),
+				new Consumer("C", 100), new Producer("C", 100),
+				new Consumer("D", 100), new Producer("D", 100));
+		List<Future<Result>> futures = executor.invokeAll(tasks);
+		for (Future<Result> future : futures) {
+			future.get().assertResult();
+		}
+		assertEquals(0, mgraph.size());
+	}
+
+	@Test
+	public void testProduceAndConsumeMixed() throws Exception {
+		log.info("testProduceAndConsumeMixed()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		List<? extends Task> tasks = Arrays.asList(
+				new Consumer("A", 110), new Consumer("A", 170),
+				new Consumer("B", 100), new Consumer("B", 500),
+				new Consumer("C", 230), new Consumer("C", 230),
+				new Consumer("D", 540), new Consumer("D", 10),
+				new Producer("D", 50), new Producer("D", 500),
+				new Producer("C", 400), new Producer("C", 60),
+				new Producer("B", 300), new Producer("B", 300),
+				new Producer("A", 200), new Producer("A", 80));
+		List<Future<Result>> futures = executor.invokeAll(tasks);
+		for (Future<Result> future : futures) {
+			future.get().assertResult();
+		}
+		assertEquals(0, mgraph.size());
+	}
+	/**
+	 * The <code>Task</code> specifies a <code>Callable</code> whoes execution
+	 * results in an <code>Integer</code>.
+	 */
+	private abstract class Task implements Callable<Result> {
+
+		protected final String collectionName;
+		protected final UriRef subject;
+		protected final UriRef predicate;
+		protected final int numElements;
+
+		/**
+		 * Creates a new <code>Task</code>.
+		 * 
+		 * @param collectionName
+		 *            Name of the task's collection.
+		 * @param numElements
+		 *            The number of elements to process.
+		 */
+		protected Task(String collectionName, int numElements) {
+			if (collectionName == null) {
+				throw new IllegalArgumentException("Invalid name: null");
+			} else if (collectionName.length() <= 0) {
+				throw new IllegalArgumentException("Invalid name: '"
+						+ collectionName + "'");
+			} else if (numElements < 0) {
+				throw new IllegalArgumentException("Invalid numElements: "
+						+ numElements);
+			}
+			this.numElements = numElements;
+			this.collectionName = collectionName;
+			subject = new UriRef("http://example.org/" + "collection/"
+					+ collectionName);
+			predicate = new UriRef("http://example.org/ontology/contains");
+		}
+
+		/**
+		 * Causes the currently executing thread object to temporarily pause and
+		 * allow other threads to execute.
+		 */
+		protected void yield() {
+			try {
+				Thread.sleep(5);
+			} catch (InterruptedException e) {
+				Thread.currentThread().interrupt();
+			}
+		}
+	}
+
+	/**
+	 * This class represents a task that produces triples that are stored in the
+	 * graph.
+	 */
+	private class Producer extends Task {
+
+		/**
+		 * Creates a new <code>Producer</code> task.
+		 * 
+		 * @param collectionName
+		 *            Name of the task's collection.
+		 * @param numElements
+		 *            The number of elements to produce.
+		 */
+		public Producer(String collectionName, int numElements) {
+			super(collectionName, numElements);
+		}
+
+		@Override
+		public Result call() throws InterruptedException {
+			int counter = 0;
+			for (int elementName = 1; counter < numElements; elementName++) {
+				yield();
+				final Triple t = createTriple(elementName);
+				if (mgraph.add(t)) {
+					counter++;
+					yield();
+				} else {
+					System.out.println("WARNING: element " + t + "NOT created");
+				}
+			}
+			return new Result(collectionName, "Produced elements", numElements,
+					counter);
+		}
+
+		/**
+		 * Creates a new collection element triple.
+		 * 
+		 * @param value
+		 *            Value of the collection element.
+		 * @return A new triple representing the collection element.
+		 */
+		protected Triple createTriple(int value) {
+			final UriRef object = new UriRef("http://example.org/"
+					+ collectionName + "/" + Integer.valueOf(value)
+					+ Math.random());
+			return new TripleImpl(subject, predicate, object);
+		}
+	}
+
+	/**
+	 * This class represents a task that produces triples that are stored in the
+	 * graph.
+	 */
+	private class Consumer extends Task {
+
+		/**
+		 * Creates a new <code>Consumer</code> task.
+		 * 
+		 * @param collectionName
+		 *            Name of the task's collection.
+		 * @param numElements
+		 *            The number of elements to consume.
+		 */
+		public Consumer(String collectionName, int numElements) {
+			super(collectionName, numElements);
+		}
+
+		/**
+		 * Performs this task.
+		 * 
+		 * @return the number of elements successfully added to the graph.
+		 */
+		@Override
+		public Result call() throws InterruptedException {
+			int counter = 0;
+			while (counter < numElements) {
+				yield();
+
+				Triple triple = null;
+				mgraph.getLock().writeLock().lock();
+				try {
+					// System.out.println("synchonized");
+					Iterator<Triple> i = mgraph
+							.filter(subject, predicate, null);
+					if (i.hasNext()) {
+						triple = i.next();
+					}
+
+					if (triple != null && mgraph.remove(triple)) {
+						counter++;
+					}
+				} finally {
+					mgraph.getLock().writeLock().unlock();
+				}
+			}
+			return new Result(collectionName, "Consumed elements", numElements,
+					counter);
+		}
+	}
+
+	/**
+	 * Task result that asserts the number of processed elements.
+	 */
+	private class Result {
+
+		private final int expected;
+		private final int actual;
+		private final String msg;
+		private final String cn;
+
+		/**
+		 * Creates a new task result that asserts the element count.
+		 * 
+		 * @param cn
+		 *            Name of the affected collection.
+		 * @param msg
+		 *            Assertion message to print.
+		 * @param expected
+		 *            Expected number of processed elements.
+		 * @param actual
+		 *            Actual number of processed elements.
+		 */
+		public Result(String cn, String msg, int expected, int actual) {
+			this.expected = expected;
+			this.actual = actual;
+			this.msg = msg;
+			this.cn = cn;
+		}
+
+		/**
+		 * Asserts this result.
+		 */
+		public void assertResult() {
+			assertEquals("[" + cn + "] " + msg, expected, actual);
+		}
+	}
+}

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoGraphTest.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,13 @@
+package rdf.virtuoso.storage;
+
+import org.apache.clerezza.rdf.core.Graph;
+
+/**
+ * Tests the {@link VirtuosoGraph} implementation of {@link Graph}
+ * 
+ * @author enridaga
+ *
+ */
+public class VirtuosoGraphTest {
+
+}

Added: clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java
URL: http://svn.apache.org/viewvc/clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java?rev=1521431&view=auto
==============================================================================
--- clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java (added)
+++ clerezza/trunk/clerezza-virtuoso/rdf.virtuoso.storage/src/test/java/rdf/virtuoso/storage/VirtuosoMGraphTest.java Tue Sep 10 10:38:51 2013
@@ -0,0 +1,361 @@
+package rdf.virtuoso.storage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.NonLiteral;
+import org.apache.clerezza.rdf.core.PlainLiteral;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.impl.PlainLiteralImpl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import virtuoso.jdbc4.VirtuosoException;
+
+public class VirtuosoMGraphTest {
+	static VirtuosoMGraph mgraph = null;
+	static final String TEST_GRAPH_NAME = "VirtuosoMGraphTest";
+
+	static Logger log = LoggerFactory.getLogger(VirtuosoMGraphTest.class);
+	
+	/**
+	 * Clean before any test
+	 * 
+	 * @throws ClassNotFoundException
+	 * @throws SQLException
+	 */
+	@Before
+	public void before() throws ClassNotFoundException, SQLException {
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		mgraph = new VirtuosoMGraph(TEST_GRAPH_NAME, TestUtils.getConnection());
+		mgraph.clear();
+		log.debug("Clearing graph <{}>", TEST_GRAPH_NAME);
+	}
+
+	final UriRef enridaga = new UriRef("enridaga");
+	final UriRef alexdma = new UriRef("alexdma");
+	final UriRef anuzzolese = new UriRef("anuzzolese");
+	final UriRef predicate = new UriRef("http://property/name");
+	final PlainLiteral object = new PlainLiteralImpl("Enrico Daga");
+	final UriRef knows = new UriRef(TestUtils.FOAF_NS + "knows");
+
+	@Test
+	public void testAddSingle() {
+		log.info("testAddSingle()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		Triple triple = new Triple() {
+
+			@Override
+			public NonLiteral getSubject() {
+				return enridaga;
+			}
+
+			@Override
+			public UriRef getPredicate() {
+				return predicate;
+			}
+
+			@Override
+			public Resource getObject() {
+				return object;
+			}
+		};
+
+		boolean success = mgraph.add(triple);
+		assertTrue(success);
+		assertTrue(mgraph.size() == 1);
+	}
+
+	@Test
+	public void testFilter() {
+		log.info("testFilter(); Test filter(s,p,o)");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		// We use testAdd to prepare this
+		testAddSingle();
+		Iterator<Triple> it = mgraph.filter(enridaga, predicate, object);
+		boolean found = false;
+		while (it.hasNext()) {
+			found = true;
+			Triple t = it.next();
+			log.debug("Found matching triple: {}", t);
+			assertEquals(t.getSubject(), enridaga);
+			assertEquals(t.getPredicate(), predicate);
+			assertEquals(t.getObject(), object);
+		}
+		assertTrue(found);
+	}
+
+	@Test
+	public void testFilterSubject() {
+		log.info("testFilterSubject(); Test filter(s,null,null)");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		// We use testAdd to prepare this
+		testAddSingle();
+		Iterator<Triple> it = mgraph.filter(enridaga, null, null);
+		boolean found = false;
+		while (it.hasNext()) {
+			found = true;
+			Triple t = it.next();
+			if (log.isDebugEnabled()) {
+				log.debug("Found matching triple: {}", t);
+				TestUtils.stamp(t);
+			}
+			assertEquals(t.getSubject(), enridaga);
+		}
+		assertTrue(found);
+	}
+
+	@Test
+	public void testFilterPredicate() {
+		log.info("testFilterPredicate(); Test filter(null,p,null)");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		// We use testAdd to prepare this
+		testAddSingle();
+		Iterator<Triple> it = mgraph.filter(null, predicate, null);
+		boolean found = false;
+		while (it.hasNext()) {
+			found = true;
+			Triple t = it.next();
+			if (log.isDebugEnabled()) {
+				log.debug("Found matching triple: {}", t);
+				TestUtils.stamp(t);
+			}
+			assertEquals(t.getPredicate(), predicate);
+		}
+		assertTrue(found);
+	}
+
+	@Test
+	public void testFilterObject() {
+		log.info("testFilterObject(); Test filter(null,null,o)");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		// We use testAdd to prepare this
+		testAddSingle();
+		Iterator<Triple> it = mgraph.filter(null, null, object);
+		boolean found = false;
+		while (it.hasNext()) {
+			found = true;
+			Triple t = it.next();
+			if (log.isDebugEnabled()) {
+				log.debug("Found matching triple: {}", t);
+				TestUtils.stamp(t);
+			}
+			assertEquals(t.getObject(), object);
+		}
+		assertTrue(found);
+	}
+
+	@Test
+	public void testSize() {
+		log.info("testSize()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		// We use testAdd to prepare this
+		testAddSingle();
+		// Should be 1 at this time
+		log.debug("How many triples are in graph <{}>? {}", TEST_GRAPH_NAME,
+				mgraph.size());
+		assertTrue(mgraph.size() > 0);
+	}
+
+	@Test
+	public void testIncreaseSize() {
+		log.info("testIncreaseSize()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		int beforeSize = mgraph.size();
+		Triple t = new Triple() {
+
+			@Override
+			public NonLiteral getSubject() {
+				return enridaga;
+			}
+
+			@Override
+			public UriRef getPredicate() {
+				return knows;
+			}
+
+			@Override
+			public Resource getObject() {
+				return alexdma;
+			}
+		};
+		assertTrue(mgraph.add(t));
+		int afterSize = mgraph.size();
+		assertEquals(beforeSize + 1, afterSize);
+	}
+
+	@Test
+	public void testAddRemoveSize() {
+		log.info("testAddRemoveSize()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		int beforeSize = mgraph.size();
+		Triple t = new Triple() {
+
+			@Override
+			public NonLiteral getSubject() {
+				return enridaga;
+			}
+
+			@Override
+			public UriRef getPredicate() {
+				return knows;
+			}
+
+			@Override
+			public Resource getObject() {
+				return alexdma;
+			}
+		};
+		assertTrue(mgraph.add(t));
+		assertTrue(mgraph.remove(t));
+		int afterSize = mgraph.size();
+		assertEquals(beforeSize, afterSize);
+	}
+
+	@Test
+	public void testGetGraphReadOnly() {
+		log.info("testGetGraphReadOnly()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		Graph g = mgraph.getGraph();
+		Triple t = new Triple() {
+
+			@Override
+			public NonLiteral getSubject() {
+				return enridaga;
+			}
+
+			@Override
+			public UriRef getPredicate() {
+				return knows;
+			}
+
+			@Override
+			public Resource getObject() {
+				return anuzzolese;
+			}
+		};
+		// This should not be allowed
+		boolean success;
+		try {
+			success = g.add(t);
+		} catch (UnsupportedOperationException e) {
+			success = false;
+		}
+		assertFalse(success);
+	}
+
+	@Test
+	public void testContains() {
+		log.info("testContains()");
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		Triple t = new Triple() {
+
+			@Override
+			public NonLiteral getSubject() {
+				return enridaga;
+			}
+
+			@Override
+			public UriRef getPredicate() {
+				return knows;
+			}
+
+			@Override
+			public Resource getObject() {
+				return anuzzolese;
+			}
+		};
+		boolean addWorks = mgraph.add(t);
+		assertTrue(addWorks);
+
+		// This second triple is equivalent
+		Triple t2 = new Triple() {
+
+			@Override
+			public NonLiteral getSubject() {
+				return enridaga;
+			}
+
+			@Override
+			public UriRef getPredicate() {
+				return knows;
+			}
+
+			@Override
+			public Resource getObject() {
+				return anuzzolese;
+			}
+		};
+		Iterator<Triple> it = mgraph.filter(t2.getSubject(), t2.getPredicate(),
+				t2.getObject());
+		while (it.hasNext()) {
+			if (log.isDebugEnabled()) {
+				log.debug("Found matching triple");
+				TestUtils.stamp(it.next());
+			}else{
+				it.next();
+			}
+		}
+		assertTrue(mgraph.contains(t2));
+		// Also the related read-only graph
+		assertTrue(mgraph.getGraph().contains(t2));
+	}
+
+	@After
+	public void clear() throws VirtuosoException, ClassNotFoundException,
+			SQLException {
+		if (TestUtils.SKIP) {
+			log.warn("SKIPPED");
+			return;
+		}
+		log.debug("Clearing graph <{}> of size {}", TEST_GRAPH_NAME,
+				mgraph.size());
+		log.debug("Removing graph <{}>", TEST_GRAPH_NAME);
+		Statement st = TestUtils.getConnection().createStatement();
+		st.execute("SPARQL CLEAR GRAPH <" + TEST_GRAPH_NAME + ">");
+	}
+}