/* * Copyright James Leigh (c) 2007. * * Licensed under the Aduna BSD-style license. */ package org.openrdf.repository.event.base; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import org.openrdf.model.Namespace; import org.openrdf.model.Resource; import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; import org.openrdf.repository.Repository; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryException; import org.openrdf.repository.RepositoryResult; import org.openrdf.repository.base.RepositoryConnectionWrapper; import org.openrdf.repository.event.NotifyingRepositoryConnection; import org.openrdf.repository.event.RepositoryConnectionListener; /** * This broadcaster is used by the RepositoryBroadcaster to wrap the delegate * repository connection. There are two types of listeners for the repository * connection, {@link RepositoryConnectionStateListener} and * {@link RepositoryConnectionListener}. Listeners are notified of changes * after they have occurred. * * @author James Leigh * @author Herko ter Horst */ public class NotifyingRepositoryConnectionWrapper extends RepositoryConnectionWrapper implements NotifyingRepositoryConnection { /*-----------* * Variables * *-----------*/ private boolean activated = false; private boolean reportDeltas = false; private Set<RepositoryConnectionListener> listeners = new CopyOnWriteArraySet<RepositoryConnectionListener>(); /*--------------* * Constructors * *--------------*/ public NotifyingRepositoryConnectionWrapper(Repository repository, RepositoryConnection connection) { super(repository, connection); } public NotifyingRepositoryConnectionWrapper(Repository repository, RepositoryConnection connection, boolean reportDeltas) { this(repository, connection); setReportDeltas(reportDeltas); } /*---------* * Methods * *---------*/ public boolean reportDeltas() { return reportDeltas; } public void setReportDeltas(boolean reportDeltas) { this.reportDeltas = reportDeltas; } /** * Registers a <tt>RepositoryConnectionListener</tt> that will receive * notifications of operations that are performed on this connection. */ public void addRepositoryConnectionListener(RepositoryConnectionListener listener) { listeners.add(listener); activated = true; } /** * Removes a registered <tt>RepositoryConnectionListener</tt> from this * connection. */ public void removeRepositoryConnectionListener(RepositoryConnectionListener listener) { listeners.remove(listener); activated = !listeners.isEmpty(); } @Override protected boolean isDelegatingAdd() { return !activated; } @Override protected boolean isDelegatingRemove() { return !activated; } @Override public void addWithoutCommit(Resource subject, URI predicate, Value object, Resource... contexts) throws RepositoryException { boolean reportEvent = activated; if (reportEvent && reportDeltas()) { // Only report if the stament is not present yet reportEvent = !getDelegate().hasStatement(subject, predicate, object, false, contexts); } getDelegate().add(subject, predicate, object, contexts); if (reportEvent) { for (RepositoryConnectionListener listener : listeners) { listener.add(this, subject, predicate, object, contexts); } } } @Override public void clear(Resource... contexts) throws RepositoryException { if (activated && reportDeltas()) { removeWithoutCommit(null, null, null, contexts); } else if (activated) { getDelegate().clear(contexts); for (RepositoryConnectionListener listener : listeners) { listener.clear(this, contexts); } } else { getDelegate().clear(contexts); } } @Override public void close() throws RepositoryException { super.close(); if (activated) { for (RepositoryConnectionListener listener : listeners) { listener.close(this); } } } @Override public void commit() throws RepositoryException { getDelegate().commit(); if (activated) { for (RepositoryConnectionListener listener : listeners) { listener.commit(this); } } } @Override public void removeWithoutCommit(Resource subj, URI pred, Value obj, Resource... ctx) throws RepositoryException { if (activated && reportDeltas()) { RepositoryResult<Statement> stmts; stmts = getDelegate().getStatements(subj, pred, obj, false, ctx); List<Statement> list = new ArrayList<Statement>(); try { while (stmts.hasNext()) { list.add(stmts.next()); } } finally { stmts.close(); } getDelegate().remove(subj, pred, obj, ctx); for (RepositoryConnectionListener listener : listeners) { for (Statement stmt : list) { Resource s = stmt.getSubject(); URI p = stmt.getPredicate(); Value o = stmt.getObject(); Resource c = stmt.getContext(); listener.remove(this, s, p, o, c); } } } else if (activated) { getDelegate().remove(subj, pred, obj, ctx); for (RepositoryConnectionListener listener : listeners) { listener.remove(this, subj, pred, obj, ctx); } } else { getDelegate().remove(subj, pred, obj, ctx); } } @Override public void removeNamespace(String prefix) throws RepositoryException { getDelegate().removeNamespace(prefix); if (activated) { for (RepositoryConnectionListener listener : listeners) { listener.removeNamespace(this, prefix); } } } @Override public void clearNamespaces() throws RepositoryException { if (activated && reportDeltas()) { RepositoryResult<Namespace> namespaces; namespaces = getDelegate().getNamespaces(); List<String> prefix = new ArrayList<String>(); try { while (namespaces.hasNext()) { Namespace ns = namespaces.next(); prefix.add(ns.getPrefix()); } } finally { namespaces.close(); } getDelegate().clearNamespaces(); for (String p : prefix) { removeNamespace(p); } } else if (activated) { getDelegate().clearNamespaces(); for (RepositoryConnectionListener listener : listeners) { listener.clearNamespaces(this); } } else { getDelegate().clearNamespaces(); } } @Override public void rollback() throws RepositoryException { getDelegate().rollback(); if (activated) { for (RepositoryConnectionListener listener : listeners) { listener.rollback(this); } } } @Override public void setAutoCommit(boolean autoCommit) throws RepositoryException { boolean wasAutoCommit = isAutoCommit(); getDelegate().setAutoCommit(autoCommit); if (activated && wasAutoCommit != autoCommit) { for (RepositoryConnectionListener listener : listeners) { listener.setAutoCommit(this, autoCommit); } if (autoCommit) { for (RepositoryConnectionListener listener : listeners) { listener.commit(this); } } } } @Override public void setNamespace(String prefix, String name) throws RepositoryException { getDelegate().setNamespace(prefix, name); if (activated) { for (RepositoryConnectionListener listener : listeners) { listener.setNamespace(this, prefix, name); } } } }