package eu.play_project.dcep.distributedetalis;
import jpl.PrologException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.hp.hpl.jena.graph.Node;
import com.jtalis.core.JtalisContextImpl;
import eu.play_project.dcep.distributedetalis.api.DistributedEtalisException;
import eu.play_project.dcep.distributedetalis.api.UsePrologSemWebLib;
import fr.inria.eventcloud.api.CompoundEvent;
import fr.inria.eventcloud.api.Quadruple;
public class PrologSemWebLib implements UsePrologSemWebLib {
private static JtalisContextImpl ctx;
int oldValue = 0;
long internalEventId = 0; // Ordered event ids. id_0 < id_1 < id2 ...
private static Logger logger = LoggerFactory.getLogger(PrologSemWebLib.class);
@Override
public void init(JtalisContextImpl ctx) throws DistributedEtalisException {
logger.debug("Initializing " + PrologSemWebLib.class.getSimpleName());
PrologSemWebLib.ctx = ctx;
try {
// Load SWI-Prolog Semantic Web Library
logger.debug("Loading SWI-Prolog Semantic Web Library");
ctx.getEngineWrapper().executeGoal("[library(semweb/rdf_db)]");
ctx.getEngineWrapper().executeGoal("[library(xpath)]");
ctx.getEngineWrapper().executeGoal("use_module(library(xpath))");
ctx.getEngineWrapper().executeGoal("use_module(library(random))");
ctx.setEtalisFlags("garbage_clt", "on");
ctx.setEtalisFlags("garbage_control","general");
ctx.setEtalisFlags("save_ruleId", "on");
} catch (PrologException e) {
throw new DistributedEtalisException("Error loading SWI-Prolog libraries: " + e.getMessage());
}
}
@Override
public Boolean addEvent(CompoundEvent event)
throws DistributedEtalisException {
Boolean dataAddedToTriplestore = true;
Boolean gcDataAdded = true;
StringBuilder prologString = new StringBuilder();
int i = 0;
for (Quadruple quadruple : event) {
i++;
// TODO use prolog type system
Node o = quadruple.getObject();
String rdfObject;
if (o.isLiteral()) {
rdfObject = "'"
+ escapeForProlog(quadruple.getObject()
.getLiteralLexicalForm()) + "'";
} else {
// 5.) Resource URI
rdfObject = "'" + o.getURI() + "'";
}
if (i > 1) {
prologString.append(", ");
}
// Add data to triplestore
prologString.append("rdf_assert(" + "'" + quadruple.getSubject()
+ "', " + "'" + quadruple.getPredicate() + "', "
+ rdfObject + ", " + "'" + event.getGraph() + "')");
}
dataAddedToTriplestore = addPayloadToPlTriplestore(prologString.toString());
// Add GC counter.
gcDataAdded = ctx.getEngineWrapper().executeGoal(
"assert(referenceCounter('" + event.getGraph() + "', "
+ internalEventId + ", -1))");
internalEventId++;
if (!gcDataAdded) {
throw new DistributedEtalisException(
"Failed to insert garbage collection information in Prolog.");
}
return (dataAddedToTriplestore && gcDataAdded);
}
/**
* Execute given String in prolog. If it was not possible retry it after 1ms.
* @param prologString code to execute in prolog.
* @return true if code was executed.
*/
private boolean addPayloadToPlTriplestore(String prologString){
try{
boolean result = ctx.getEngineWrapper().executeGoal(prologString);
// ctx.getEngineWrapper().executeGoal("printRdfStat");
// ctx.getEngineWrapper().executeGoal("printNumberOfEvents");
// ctx.getEngineWrapper().executeGoal("printRefCountN");
// ctx.getEngineWrapper().executeGoal("printReferenceCounters");
return result;
} catch (PrologException e) {
if (e.getMessage().contains("error(permission_error(write, rdf_db, default)")) {
logger.warn("Error: db is locked. Try again.");
try {
Thread.sleep(1);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
return this.addPayloadToPlTriplestore(prologString);
} else {
logger.error("Error on new event.", e);
return false;
}
}
}
@Override
public CompoundEvent getRdfData(String complexEventID) {
throw new RuntimeException("Not implemented in this class.");
}
/**
* Escape all characters which are illegal in Prolog's quoted strings:
* {@code It's me, Mario.} becomes {@code It\'s me, Mario.}. The resulting
* strings are meanto to be used as <i>quoted atoms</i> in Prolog, between
* single quotes.
*
* @see <a
* href="http://www.swi-prolog.org/pldoc/doc_for?object=section%284,%272.15.1.2%27,swi%28%27/doc/Manual/syntax.html%27%29%29">SWI
* Prolog Character Escape Syntax</a>
*/
public static String escapeForProlog(String s) {
return s.replaceAll("'", "\'");
}
}