/*******************************************************************************
* Copyright (c) 2007-2008 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.execution.echo;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import org.openanzo.client.AnzoClient;
import org.openanzo.client.ClientGraph;
import org.openanzo.client.IStatementChannel;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.ExceptionConstants;
import org.openanzo.execution.IExecutionContext;
import org.openanzo.execution.java.ISemanticService;
import org.openanzo.ontologies.execution.JavaSemanticService;
import org.openanzo.rdf.Constants;
import org.openanzo.rdf.IDataset;
import org.openanzo.rdf.INamedGraph;
import org.openanzo.rdf.IStatementListener;
import org.openanzo.rdf.Literal;
import org.openanzo.rdf.Statement;
import org.openanzo.rdf.URI;
import org.openanzo.services.DynamicServiceStats;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* Simple service, deployed for testing.
*
* @author Ben Szekely ( <a href="mailto:ben@cambridgesemantics.com">ben@cambridgesemantics.com </a>)
*
*/
public class LongRunningService implements ISemanticService {
private static final Logger log = LoggerFactory.getLogger(LongRunningService.class);
private boolean activated = false;
HashMap<Long, UpdateData> updateData = new HashMap<Long, UpdateData>();
DynamicServiceStats stats = new DynamicServiceStats();
LongRunningService() {
}
public void initialize(JavaSemanticService serviceConfig, AnzoClient anzoClient) throws AnzoException {
}
public void stop(AnzoClient anzoClient) throws AnzoException {
for (Long l : updateData.keySet()) {
UpdateData data = updateData.get(l);
if (!data.graph.isClosed()) {
data.graph.close();
}
data.timer.cancel();
}
}
public String getDescription() {
return "Long running service";
}
public String getName() {
return "Service=LongRunningService";
}
public DynamicServiceStats getStatistics() {
return stats;
}
/**
* Activate the service
*
* @param context
* @param request
* @param response
* @throws AnzoException
*/
public void activate(IExecutionContext context, IDataset request, IDataset response) throws AnzoException {
if (activated) {
response.addNamedGraph(context.getOperationURI());
INamedGraph graph = response.getNamedGraph(context.getOperationURI());
URI predicate = Constants.valueFactory.createURI(context.getServiceURI().toString() + "#activationStatus");
Literal literal = Constants.valueFactory.createLiteral("alreadyActivated");
graph.add(context.getOperationURI(), predicate, literal);
return;
}
AnzoClient anzoClient = context.getAnzoClient();
anzoClient.begin();
ClientGraph graph = anzoClient.getReplicaGraph(context.getServiceURI());
anzoClient.commit();
URI channelUri = Constants.valueFactory.createURI(context.getServiceURI().toString() + "#channel");
final IStatementChannel channel = anzoClient.getStatementChannel(channelUri, AnzoClient.NON_REVISIONED_NAMED_GRAPH);
anzoClient.updateRepository();
graph.registerListener(new IStatementListener<INamedGraph>() {
public void statementsAdded(INamedGraph source, Statement... statements) {
try {
log.debug("Relaying statements: " + statements.length);
channel.sendMessage(null, Collections.singleton(statements[0]));
} catch (AnzoException e) {
log.error("Error forwarding event to channel.", e);
}
}
public void statementsRemoved(INamedGraph source, Statement... statements) {
System.err.println("Sending - statement on channel: " + statements[0]);
}
});
activated = true;
response.addNamedGraph(context.getOperationURI());
INamedGraph g = response.getNamedGraph(context.getOperationURI());
URI predicate = Constants.valueFactory.createURI(context.getServiceURI().toString() + "#activationStatus");
Literal literal = Constants.valueFactory.createLiteral("activationSuccessful");
g.add(context.getOperationURI(), predicate, literal);
return;
}
/**
*
* @param context
* @param request
* @param response
* @throws AnzoException
*/
public void count(IExecutionContext context, IDataset request, IDataset response) throws AnzoException {
ClientGraph graph = null;
try {
context.executeAsRequestUser();
AnzoClient anzoClient = context.getAnzoClient();
anzoClient.begin();
graph = anzoClient.getServerGraph(context.getServiceURI());
URI predicate = Constants.valueFactory.createURI(context.getServiceURI().toString() + "#hasCount");
Collection<Statement> stmts = graph.find(context.getServiceURI(), predicate, null);
if (stmts.isEmpty()) {
graph.add(context.getServiceURI(), predicate, Constants.valueFactory.createLiteral(1));
} else {
Literal literal = (Literal) stmts.iterator().next().getObject();
int count = Integer.parseInt(literal.getLabel());
graph.remove(stmts);
graph.add(context.getServiceURI(), predicate, Constants.valueFactory.createLiteral(count + 1));
}
response.addNamedGraph(graph.getNamedGraphUri());
response.add(graph.getStatements());
anzoClient.commit();
anzoClient.updateRepository();
} finally {
if (graph != null) {
graph.close();
}
}
}
/**
*
* @param context
* @param request
* @param response
* @throws AnzoException
*/
public void startUpdating(IExecutionContext context, IDataset request, IDataset response) throws AnzoException {
URI updateNamedGraphPredicate = Constants.valueFactory.createURI(context.getServiceURI() + "#updateNamedGraph");
URI updatePeriodPredicate = Constants.valueFactory.createURI(context.getServiceURI() + "#updatePeriod");
URI updatePredicatePredicate = Constants.valueFactory.createURI(context.getServiceURI() + "#updatePredicate");
URI updateResourcePredicate = Constants.valueFactory.createURI(context.getServiceURI() + "#updateResource");
URI updateRangePredicate = Constants.valueFactory.createURI(context.getServiceURI() + "#updateRange");
URI updateKeyPredicate = Constants.valueFactory.createURI(context.getServiceURI() + "#updateKey");
Collection<Statement> stmts = request.find(context.getOperationURI(), updateNamedGraphPredicate, null, context.getOperationURI());
if (stmts.isEmpty()) {
throw new AnzoException(ExceptionConstants.EXECUTION.EXECUTION_ERROR, "Missing predicate: " + updateNamedGraphPredicate);
}
final URI updateNamedGraph = (URI) stmts.iterator().next().getObject();
stmts = request.find(context.getOperationURI(), updatePeriodPredicate, null, context.getOperationURI());
if (stmts.isEmpty()) {
throw new AnzoException(ExceptionConstants.EXECUTION.EXECUTION_ERROR, "Missing predicate: " + updatePeriodPredicate);
}
final long updatePeriod = Long.parseLong(((Literal) stmts.iterator().next().getObject()).getLabel());
stmts = request.find(context.getOperationURI(), updatePredicatePredicate, null, context.getOperationURI());
if (stmts.isEmpty()) {
throw new AnzoException(ExceptionConstants.EXECUTION.EXECUTION_ERROR, "Missing predicate: " + updatePredicatePredicate);
}
final URI updatePredicate = (URI) stmts.iterator().next().getObject();
stmts = request.find(context.getOperationURI(), updateResourcePredicate, null, context.getOperationURI());
if (stmts.isEmpty()) {
throw new AnzoException(ExceptionConstants.EXECUTION.EXECUTION_ERROR, "Missing predicate: " + updateResourcePredicate);
}
final URI updateResource = (URI) stmts.iterator().next().getObject();
stmts = request.find(context.getOperationURI(), updateRangePredicate, null, context.getOperationURI());
if (stmts.isEmpty()) {
throw new AnzoException(ExceptionConstants.EXECUTION.EXECUTION_ERROR, "Missing predicate: " + updateRangePredicate);
}
final long updateRange = Long.parseLong(((Literal) stmts.iterator().next().getObject()).getLabel());
final long updateKey = Math.round(Math.random() * 100000);
final AnzoClient client = context.getAnzoClient();
client.begin();
final ClientGraph graph = context.getAnzoClient().getServerGraph(updateNamedGraph);
client.commit();
client.updateRepository();
TimerTask task = new TimerTask() {
@Override
public void run() {
client.begin();
graph.remove(updateResource, updatePredicate, null);
long rand = Math.round(Math.random() * updateRange);
graph.add(updateResource, updatePredicate, Constants.valueFactory.createLiteral(rand));
client.commit();
try {
client.updateRepository();
} catch (Exception e) {
log.error("Error updating repository in timer", e);
}
}
};
Timer timer = new Timer();
UpdateData data = new UpdateData();
data.timer = timer;
data.graph = graph;
updateData.put(updateKey, data);
timer.schedule(task, updatePeriod, updatePeriod);
response.addNamedGraph(context.getOperationURI());
response.add(context.getOperationURI(), updateKeyPredicate, Constants.valueFactory.createLiteral(updateKey), context.getOperationURI());
}
/**
*
* @param context
* @param request
* @param response
* @throws AnzoException
*/
public void stopUpdating(IExecutionContext context, IDataset request, IDataset response) throws AnzoException {
URI updateKeyPredicate = Constants.valueFactory.createURI(context.getServiceURI() + "#updateKey");
Collection<Statement> stmts = request.find(context.getOperationURI(), updateKeyPredicate, null, context.getOperationURI());
if (stmts.isEmpty()) {
throw new AnzoException(ExceptionConstants.EXECUTION.EXECUTION_ERROR, "Missing predicate: " + updateKeyPredicate);
}
long updateKey = Long.parseLong(((Literal) stmts.iterator().next().getObject()).getLabel());
UpdateData data = updateData.get(updateKey);
if (data == null) {
throw new AnzoException(ExceptionConstants.EXECUTION.EXECUTION_ERROR, "Unknown update key: " + updateKey);
}
data.timer.cancel();
data.graph.close();
}
static class UpdateData {
Timer timer = null;
ClientGraph graph = null;
}
}