/*******************************************************************************
* Copyright (c) 2007 Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* File: $Source$
* Created by: Ben Szekely ( <a href="mailto:ben@cambridgesemantics.com">ben@cambridgesemantics.com </a>)
* Created on: Dec 12, 2007
* Revision: $Id$
*
* Contributors:
* Cambridge Semantics Incorporated - initial API and implementation
*******************************************************************************/
package org.openanzo.rdf.jastor;
import java.lang.ref.SoftReference;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.LogUtils;
import org.openanzo.glitter.query.QueryResults;
import org.openanzo.rdf.IDataset;
import org.openanzo.rdf.INamedGraph;
import org.openanzo.rdf.IStatementListener;
import org.openanzo.rdf.Resource;
import org.openanzo.rdf.Statement;
import org.openanzo.rdf.URI;
import org.openanzo.rdf.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Ben Szekely (<a href="mailto:ben@cambridgesemantics.com">ben@cambridgesemantics.com</a>)
*
*/
public class SingletonDataset implements IDataset {
private static final Logger log = LoggerFactory.getLogger(SingletonDataset.class);
private final INamedGraph graph;
private IStatementListener<INamedGraph> graphListener;
private final CopyOnWriteArraySet<IStatementListener<IDataset>> listeners = new CopyOnWriteArraySet<IStatementListener<IDataset>>();
/** WeakHashMap cache of uris */
static private final Map<INamedGraph, SoftReference<SingletonDataset>> cache = new WeakHashMap<INamedGraph, SoftReference<SingletonDataset>>();
/**
* Get an instance of a singleton dataset for the graph provided, resuing one from cache if possible
*
* @param graph
* graph for which to wrap with a dataset
* @return dataset encapsulating a single graph
*/
public static final SingletonDataset getInstance(INamedGraph graph) {
synchronized (cache) {
SingletonDataset result = null;
SoftReference<SingletonDataset> ref = cache.get(graph);
if (ref != null) {
result = ref.get();
}
if (result == null) {
result = new SingletonDataset(graph);
cache.put(graph, new SoftReference<SingletonDataset>(result));
}
return result;
}
}
private SingletonDataset(INamedGraph graph) {
this.graph = graph;
}
public INamedGraph addDefaultGraph(URI uri) {
throw new UnsupportedOperationException();
}
public INamedGraph addNamedGraph(URI uri) {
throw new UnsupportedOperationException();
}
public void clear() {
graph.clear();
}
public INamedGraph getDatasetGraph() {
throw new UnsupportedOperationException();
}
public INamedGraph getDefaultGraph(URI uri) {
if (uri.equals(graph.getNamedGraphUri())) {
return graph;
} else {
return null;
}
}
public void removeDefaultGraph(URI uri) {
throw new UnsupportedOperationException();
}
public void removeNamedGraph(URI uri) {
throw new UnsupportedOperationException();
}
public void setDefaultGraphs(Set<URI> defaultGraphUris) {
throw new UnsupportedOperationException();
}
public void setNamedGraphs(Set<URI> namedGraphUris) {
throw new UnsupportedOperationException();
}
public void close() {
if (graphListener != null)
graph.unregisterListener(graphListener);
}
public boolean containsDefaultGraph(URI uri) {
return uri.equals(graph.getNamedGraphUri());
}
public boolean containsNamedGraph(URI uri) {
return uri.equals(graph.getNamedGraphUri());
}
public QueryResults executeQuery(String query) throws AnzoException {
throw new UnsupportedOperationException();
}
public Collection<Statement> find(boolean includeEntireDataset, Resource subj, URI prop, Value obj, URI... namedGraphUris) {
boolean found = false;
for (int i = 0; i < namedGraphUris.length; i++) {
if (namedGraphUris[i].equals(graph.getNamedGraphUri())) {
found = true;
break;
}
}
if (found) {
return graph.find(subj, prop, obj);
} else {
return Collections.<Statement> emptySet();
}
}
public Set<URI> getDefaultGraphUris() {
return Collections.singleton(graph.getNamedGraphUri());
}
public Set<URI> getNamedGraphUris() {
return Collections.singleton(graph.getNamedGraphUri());
}
public INamedGraph getNamedGraph(URI uri) {
if (uri.equals(graph.getNamedGraphUri())) {
return graph;
} else {
return null;
}
}
public int size() {
return graph.size();
}
public void registerListener(IStatementListener<IDataset> listener) {
listeners.add(listener);
if (graphListener == null) {
graphListener = new IStatementListener<INamedGraph>() {
public void statementsAdded(INamedGraph source, Statement... statements) {
notifyAddStatements(statements);
}
public void statementsRemoved(INamedGraph source, Statement... statements) {
notifyRemoveStatements(statements);
}
};
graph.registerListener(graphListener);
}
}
public void unregisterListener(IStatementListener<IDataset> listener) {
listeners.remove(listener);
if (listeners.size() == 0 && graphListener != null) {
graph.unregisterListener(graphListener);
graphListener = null;
}
}
public void notifyAddStatements(Statement... statements) {
if (getURI().toString().equals("http://openanzo.org/registries/Datasources")) {
log.debug(LogUtils.GLITTER_MARKER, "Notifying singleton dataset..." + listeners);
}
for (IStatementListener<IDataset> listener : listeners) {
listener.statementsAdded(this, statements);
}
}
public void notifyRemoveStatements(Statement... statements) {
for (IStatementListener<IDataset> listener : listeners) {
listener.statementsRemoved(this, statements);
}
}
public void add(Collection<Statement> statements) {
for (Statement stmt : statements) {
add(stmt);
}
}
public void add(Resource subj, URI pred, Value obj, URI namedGraphUri) {
if (namedGraphUri.equals(graph.getNamedGraphUri())) {
graph.add(subj, pred, obj);
}
}
public void add(Statement... statements) {
for (Statement statement : statements) {
add(statement.getSubject(), statement.getPredicate(), statement.getObject(), statement.getNamedGraphUri());
}
}
public boolean contains(Resource subj, URI prop, Value obj, URI... namedGraphUris) {
for (URI nguri : namedGraphUris) {
if (nguri.equals(graph.getNamedGraphUri())) {
return graph.contains(subj, prop, obj);
}
}
return false;
}
public boolean contains(Statement statement) {
if (statement.getNamedGraphUri().equals(graph.getNamedGraphUri())) {
return graph.contains(statement);
} else {
return false;
}
}
public QueryResults executeQuery(Set<URI> defaultGraph, Set<URI> namedGraphs, Set<URI> namedDatasets, String query, URI baseUri) throws AnzoException {
throw new UnsupportedOperationException();
}
public Collection<Statement> find(Resource subj, URI prop, Value obj, URI... namedGraphUri) {
return find(false, subj, prop, obj, namedGraphUri);
}
public Collection<Statement> getStatements() {
return graph.getStatements();
}
public boolean isEmpty() {
return graph.isEmpty();
}
public void remove(Collection<Statement> statements) {
for (Statement stmt : statements) {
remove(stmt);
}
}
public void remove(Resource subj, URI pred, Value obj, URI... namedGraphUri) {
if (namedGraphUri == null || namedGraphUri[0].equals(graph.getNamedGraphUri())) {
graph.remove(subj, pred, obj);
}
}
public void remove(Statement... statements) {
for (Statement statement : statements) {
remove(statement.getSubject(), statement.getPredicate(), statement.getObject(), statement.getNamedGraphUri());
}
}
public int size(URI... namedGraphUris) {
for (URI nguri : namedGraphUris) {
if (nguri.equals(graph.getNamedGraphUri())) {
return graph.size();
}
}
return 0;
}
public URI getURI() {
return graph.getNamedGraphUri();
}
}