/******************************************************************************* * 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: Jan 4, 2008 * Revision: $Id$ * * Contributors: * Cambridge Semantics Incorporated - initial API and implementation *******************************************************************************/ package org.openanzo.client; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.ReentrantLock; import org.openanzo.exceptions.AnzoException; import org.openanzo.exceptions.AnzoRuntimeException; import org.openanzo.exceptions.ExceptionConstants; import org.openanzo.rdf.DatasetBase; import org.openanzo.rdf.INamedGraph; import org.openanzo.rdf.NamedGraph; import org.openanzo.rdf.URI; import org.openanzo.rdf.vocabulary.Anzo; import org.openanzo.rdf.vocabulary.RDF; /** * * @author Ben Szekely (<a href="mailto:ben@cambridgesemantics.com">ben@cambridgesemantics.com</a>) * */ class AnzoClientDataset extends DatasetBase { //private static final Logger log = LoggerFactory.getLogger(AnzoClientDataset.class); enum DatasetType { SERVER, REPLICA, MEMORY_ONLY } private ThreadLocal<HashSet<URI>> isolatedDefaultGraphs = new ThreadLocal<HashSet<URI>>(); private ThreadLocal<HashSet<URI>> isolatedNamedGraphs = new ThreadLocal<HashSet<URI>>(); private ThreadLocal<HashMap<URI, INamedGraph>> isolatedGraphs = new ThreadLocal<HashMap<URI, INamedGraph>>(); private boolean persisted = false; private final DatasetType type; private final AnzoClient client; private final INamedGraphInitializer[] initializers; AnzoClientDataset(AnzoClient client, URI datasetUri, DatasetType type, boolean persisted, Set<URI> defaultGraphUris, Set<URI> namedGraphUris, INamedGraphInitializer... namedGraphInitializers) { this.datasetUri = datasetUri; this.type = type; this.persisted = persisted; this.client = client; this.initializers = namedGraphInitializers; super.initialize(); if (namedGraphUris != null) { for (URI uri : namedGraphUris) { addNamedGraph(uri); } } if (defaultGraphUris != null) { for (URI uri : defaultGraphUris) { addDefaultGraph(uri); } } client.datasets.add(this); } @Override public void close() { super.close(); client.datasets.remove(this); } protected void commit() { if (isolatedDefaultGraphs.get() != null) { if (getLock() != null) { getLock().lock(); } try { for (URI uri : isolatedDefaultGraphs.get()) { defaultGraphUris.add(uri); } isolatedDefaultGraphs.get().clear(); } finally { if (getLock() != null) { getLock().unlock(); } } } if (isolatedNamedGraphs.get() != null) { if (getLock() != null) { getLock().lock(); } try { for (URI uri : isolatedNamedGraphs.get()) { namedGraphUris.add(uri); } isolatedNamedGraphs.get().clear(); } finally { if (getLock() != null) { getLock().unlock(); } } } if (isolatedGraphs.get() != null) { if (getLock() != null) { getLock().lock(); } try { synchronized (graphs) { for (Map.Entry<URI, INamedGraph> entry : isolatedGraphs.get().entrySet()) { graphs.put(entry.getKey(), entry.getValue()); } } isolatedGraphs.get().clear(); } finally { if (getLock() != null) { getLock().unlock(); } } } } @Override public void clear() { super.clear(); abort(); } protected void abort() { if (isolatedDefaultGraphs.get() != null) { isolatedDefaultGraphs.get().clear(); } if (isolatedNamedGraphs.get() != null) { isolatedNamedGraphs.get().clear(); } if (isolatedGraphs.get() != null) { isolatedGraphs.get().clear(); } } @Override protected ReentrantLock getLock() { return client.clientLock; } @Override protected boolean addType() { if (datasetUri == null) { return false; } if (type != DatasetType.SERVER) { return !datasetGraph.contains(datasetUri, RDF.TYPE, Anzo.DATASET_TYPE); } else { return true; } } @Override protected NamedGraph createNamedGraph(URI namedGraphUri) { try { switch (type) { case MEMORY_ONLY: return new NamedGraph(namedGraphUri); case REPLICA: boolean exists = client.namedGraphExists(namedGraphUri); if (!exists) { client.begin(); } ClientGraph graph = client.getReplicaGraph(namedGraphUri, initializers); if (!exists) { client.commit(); if (!client.inTransaction()) { client.updateRepository(); } } return graph; default: return client.getServerGraph(namedGraphUri, initializers); } } catch (AnzoException e) { throw new AnzoRuntimeException(e); } } @Override protected INamedGraph createDatasetGraph() { try { if (type == DatasetType.MEMORY_ONLY || type == DatasetType.REPLICA) { if (persisted) { return client.getReplicaGraph(this.datasetUri, initializers); } else { return new NamedGraph(this.datasetUri); } } else { // server if (persisted) { return client.getServerGraph(this.datasetUri, initializers); } else { return new NamedGraph(this.datasetUri); } } } catch (AnzoException e) { throw new AnzoRuntimeException(e); } } @Override public INamedGraph addDefaultGraphInternal(URI namedGraphUri) { if (namedGraphUri == null) { throw new AnzoRuntimeException(ExceptionConstants.CORE.NULL_PARAMETER); } if (defaultGraphUris.contains(namedGraphUri)) { return graphs.get(namedGraphUri); } INamedGraph graph = null; if (client.inTransaction()) { graph = graphs.get(namedGraphUri); if (isolatedDefaultGraphs.get() == null) { isolatedDefaultGraphs.set(new HashSet<URI>()); } if (isolatedGraphs.get() != null && isolatedGraphs.get().containsKey(namedGraphUri) && graph == null) { graph = isolatedGraphs.get().get(namedGraphUri); } if (graph == null) { graph = createNamedGraph(namedGraphUri); if (graphListener != null) { graph.registerListener(graphListener); } if (isolatedGraphs.get() == null) { isolatedGraphs.set(new HashMap<URI, INamedGraph>()); } isolatedGraphs.get().put(namedGraphUri, graph); } if (!isolatedDefaultGraphs.get().contains(namedGraphUri)) { isolatedDefaultGraphs.get().add(namedGraphUri); } } else { graph = super.addDefaultGraphInternal(namedGraphUri); } return graph; } @Override public INamedGraph addNamedGraphInternal(URI namedGraphUri) { if (namedGraphUri == null) { throw new AnzoRuntimeException(ExceptionConstants.CORE.NULL_PARAMETER); } if (namedGraphUris.contains(namedGraphUri)) { return graphs.get(namedGraphUri); } INamedGraph graph = null; if (client.inTransaction()) { graph = graphs.get(namedGraphUri); if (isolatedNamedGraphs.get() == null) { isolatedNamedGraphs.set(new HashSet<URI>()); } if (isolatedGraphs.get() != null && isolatedGraphs.get().containsKey(namedGraphUri) && graph == null) { graph = isolatedGraphs.get().get(namedGraphUri); } if (graph == null) { graph = createNamedGraph(namedGraphUri); if (graphListener != null) { graph.registerListener(graphListener); } if (isolatedGraphs.get() == null) { isolatedGraphs.set(new HashMap<URI, INamedGraph>()); } isolatedGraphs.get().put(namedGraphUri, graph); } if (!isolatedNamedGraphs.get().contains(namedGraphUri)) { isolatedNamedGraphs.get().add(namedGraphUri); } } else { graph = super.addNamedGraphInternal(namedGraphUri); } return graph; } @Override public INamedGraph getDefaultGraph(URI namedGraphUri) { if (!defaultGraphUris.contains(namedGraphUri)) { if (client.inTransaction()) { if (isolatedDefaultGraphs.get() != null) { if (isolatedDefaultGraphs.get().contains(namedGraphUri)) { if (graphs.containsKey(namedGraphUri)) { return graphs.get(namedGraphUri); } else if (isolatedGraphs.get() != null) { return isolatedGraphs.get().get(namedGraphUri); } } } return null; } else { return null; } } return graphs.get(namedGraphUri); } @Override public INamedGraph getNamedGraph(URI namedGraphUri) { if (!namedGraphUris.contains(namedGraphUri)) { if (client.inTransaction()) { if (isolatedNamedGraphs.get() != null) { if (isolatedNamedGraphs.get().contains(namedGraphUri)) { if (graphs.containsKey(namedGraphUri)) { return graphs.get(namedGraphUri); } else if (isolatedGraphs.get() != null) { return isolatedGraphs.get().get(namedGraphUri); } } } return null; } else { return null; } } return graphs.get(namedGraphUri); } @Override public boolean containsNamedGraph(URI uri) { boolean result = namedGraphUris.contains(uri); if (result) { return result; } else { if (client.inTransaction()) { return (isolatedNamedGraphs.get() != null) ? isolatedNamedGraphs.get().contains(uri) : false; } } return false; } @Override public boolean containsDefaultGraph(URI uri) { boolean result = defaultGraphUris.contains(uri); if (result) { return result; } else { if (client.inTransaction()) { return (isolatedDefaultGraphs.get() != null) ? isolatedDefaultGraphs.get().contains(uri) : false; } } return false; } @Override public Set<URI> getDefaultGraphUris() { Set<URI> results = super.getDefaultGraphUris(); if (client.inTransaction() && isolatedDefaultGraphs.get() != null) { HashSet<URI> newResults = new HashSet<URI>(); newResults.addAll(results); newResults.addAll(isolatedDefaultGraphs.get()); return newResults; } return results; } @Override public Set<URI> getNamedGraphUris() { Set<URI> results = super.getNamedGraphUris(); if (client.inTransaction() && isolatedNamedGraphs.get() != null) { HashSet<URI> newResults = new HashSet<URI>(); newResults.addAll(results); newResults.addAll(isolatedNamedGraphs.get()); return newResults; } return results; } @Override protected INamedGraph getGraph(URI namedGraphUri) { INamedGraph graph = super.getGraph(namedGraphUri); if (graph == null && client.inTransaction() && isolatedGraphs.get() != null) { return isolatedGraphs.get().get(namedGraphUri); } return graph; } @Override protected Map<URI, INamedGraph> getGraphs() { Map<URI, INamedGraph> results = super.getGraphs(); if (client.inTransaction() && isolatedGraphs.get() != null) { HashMap<URI, INamedGraph> newResults = new HashMap<URI, INamedGraph>(results); newResults.putAll(isolatedGraphs.get()); return newResults; } return results; } }