/*******************************************************************************
* 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
*
* Contributors:
* Cambridge Semantics Incorporated
*******************************************************************************/
package org.openanzo.client;
import java.util.Collection;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.ontologies.openanzo.AnzoFactory;
import org.openanzo.ontologies.openanzo.NamedGraph;
import org.openanzo.rdf.INamedGraph;
import org.openanzo.rdf.IQuadStore;
import org.openanzo.rdf.Statement;
import org.openanzo.rdf.URI;
import org.openanzo.services.INamedGraphUpdate;
import org.openanzo.services.serialization.INamedGraphUpdateHandler;
/**
*
* @author Ben Szekely ( <a href="mailto:ben@cambridgesemantics.com">ben@cambridgesemantics.com </a>)
*
*/
public class ReplicaUpdater implements INamedGraphUpdateHandler {
enum Type {
REPLICATION, NAMED_GRAPH_UPDATE
}
private final AnzoClient client;
private final IQuadStore replicaQuadStore;
private final Type type;
ReplicaUpdater(IQuadStore replicaQuadStore, AnzoClient client, Type type) {
this.replicaQuadStore = replicaQuadStore;
this.client = client;
this.type = type;
}
public void start() throws AnzoException {
}
public void end() throws AnzoException {
}
/**
* revision is defined only if this is called from the Named graph update mechanism
*/
public boolean handleNamedGraphUpdate(INamedGraphUpdate update) throws AnzoException {
ClientGraph replicaGraph = null;
ClientGraph serverGraph = null;
boolean replicaInSync = true;
URI namedGraphUri = update.getNamedGraphURI();
try {
client.clientLock.lockInterruptibly();
try {
replicaGraph = client.replicaGraphTable.get(namedGraphUri);
if (replicaGraph != null) {
long currentRevision = replicaGraph.getRevision();
if (currentRevision != -1) {
if (currentRevision >= update.getRevision()) {
client.replicaGraphTable.release(namedGraphUri);
replicaGraph = null; // signal that everything is ok, but no need for us to update
replicaInSync = true;
} else if (type == Type.NAMED_GRAPH_UPDATE && currentRevision < update.getRevision() - 1) {
client.replicaGraphTable.release(namedGraphUri);
replicaGraph = null; // signal that our replica is too out of date to process this update
replicaInSync = false;
}
}
}
serverGraph = client.serverGraphTable.get(namedGraphUri);
if (serverGraph != null) {
long currentRevision = serverGraph.getRevision();
if (currentRevision >= update.getRevision()) {
client.serverGraphTable.release(namedGraphUri);
serverGraph = null; // signal that everything is ok, but no need for us to update
}
}
INamedGraph replicaMeta = (replicaGraph != null) ? replicaGraph.getMetadataGraph() : null;
INamedGraph serverMeta = (serverGraph != null) ? serverGraph.getMetadataGraph() : null;
if (replicaMeta != null) {
NamedGraph namedGraph = AnzoFactory.getNamedGraph(namedGraphUri, replicaMeta);
Boolean revisioned = namedGraph.getRevisioned();
if (type == Type.NAMED_GRAPH_UPDATE || (revisioned != null && revisioned == true)) {
this.removeStatements(update.getMetaRemovals(), replicaMeta);
this.removeStatements(update.getRemovals(), replicaGraph);
} else {
this.replicaQuadStore.remove(null, null, null, namedGraphUri);
this.replicaQuadStore.remove(null, null, null, replicaMeta.getNamedGraphUri());
}
this.addStatements(update.getMetaAdditions(), replicaMeta);
this.addStatements(update.getAdditions(), replicaGraph);
}
this.notifyRemoveStatements(update.getMetaRemovals(), replicaMeta, serverMeta);
this.notifyRemoveStatements(update.getRemovals(), replicaGraph, serverGraph);
this.notifyAddStatements(update.getMetaAdditions(), replicaMeta, serverMeta);
this.notifyAddStatements(update.getAdditions(), replicaGraph, serverGraph);
if (replicaGraph != null) {
replicaGraph.setRevision(update.getRevision());
}
if (serverGraph != null) {
serverGraph.setRevision(update.getRevision());
}
return replicaInSync;
} finally {
if (replicaGraph != null) {
client.replicaGraphTable.release(namedGraphUri);
}
if (serverGraph != null) {
client.serverGraphTable.release(namedGraphUri);
}
client.clientLock.unlock();
}
} catch (InterruptedException ie) {
return false;
}
}
private void addStatements(Collection<Statement> stmts, INamedGraph replicaGraph) {
if (stmts.size() == 0) {
return;
}
replicaQuadStore.add(stmts);
}
private void removeStatements(Collection<Statement> stmts, INamedGraph replicaGraph) {
if (stmts.size() == 0) {
return;
}
replicaQuadStore.remove(stmts);
}
private void notifyAddStatements(Collection<Statement> stmts, INamedGraph replicaGraph, INamedGraph serverGraph) {
if (stmts.size() == 0) {
return;
}
if (replicaGraph != null) {
replicaGraph.notifyAddStatements(stmts.toArray(new Statement[0]));
}
if (serverGraph != null) {
serverGraph.notifyAddStatements(stmts.toArray(new Statement[0]));
}
}
private void notifyRemoveStatements(Collection<Statement> stmts, INamedGraph replicaGraph, INamedGraph serverGraph) {
if (stmts.size() == 0) {
return;
}
if (replicaGraph != null) {
replicaGraph.notifyRemoveStatements(stmts.toArray(new Statement[0]));
}
if (serverGraph != null) {
serverGraph.notifyRemoveStatements(stmts.toArray(new Statement[0]));
}
}
}