package ru.semiot.services.analyzing.cep;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.sparql.core.Var;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Alternative;
import javax.inject.Inject;
import javax.inject.Named;
import org.deri.cqels.data.Mapping;
import org.deri.cqels.engine.ConstructListener;
import org.deri.cqels.engine.ContinuousConstruct;
import org.deri.cqels.engine.ContinuousListener;
import org.deri.cqels.engine.ContinuousSelect;
import org.deri.cqels.engine.ExecContext;
import org.deri.cqels.engine.OpRouter1;
import org.deri.cqels.engine.RDFStream;
import org.slf4j.LoggerFactory;
import ru.semiot.services.analyzing.ServiceConfig;
import ru.semiot.services.analyzing.database.QueryDataBase;
import ru.semiot.services.analyzing.wamp.WAMPClient;
@Named
@Alternative
@ApplicationScoped
public class CQELS implements Engine {
private final org.slf4j.Logger logger = LoggerFactory
.getLogger(CQELS.class);
private final String CQELS_HOME = "cqels_home";
private static CQELS engine = null;
private ExecContext context = null;
private final String STREAM_ID = "http://example.org/simpletest/test";
private DefaultRDFStream stream = null;
private Map<Integer, OpRouter1> queries = null;
//private Map<String, DefaultRDFStream> streams = null;
@Inject
QueryDataBase db;
public CQELS() {
logger.info("Initialize home directory for cqels");
File home = new File(CQELS_HOME);
if (!home.exists()) {
home.mkdir();
}
context = new ExecContext(home.getAbsolutePath(), true);
stream = new DefaultRDFStream(context, STREAM_ID);
//streams = new HashMap<>();
queries = new HashMap<>();
}
@Override
public boolean registerQuery(int query_id) {
String query = db.getQuery(query_id).getString("text");
try {
if (query.toLowerCase().contains("select") || query.toLowerCase().contains("construct")) {
if (query.toLowerCase().contains("construct")) {
ContinuousConstruct cc = context.registerConstruct(query);
cc.register(new ConstructListener(context) {
@Override
public void update(List<Triple> graph) {
String message = getString(graph);
sendToWAMP(message);
//appendData(message);
}
});
queries.put(query_id, cc);
} else {
ContinuousSelect cs = context.registerSelect(query);
cs.register(new ContinuousListener() {
@Override
public void update(Mapping m) {
sendToWAMP(getString(m));
}
});
queries.put(query_id, cs);
}
}
} catch (com.hp.hpl.jena.query.QueryException e) {
logger.debug("Query \n" + query + "\n has ERROR!\n + " + e.getMessage());
return false;
}
return true;
}
public void removeAllQueries() {
for (Integer s : queries.keySet()) {
removeQuery(s);
}
queries.clear();
}
@Override
public void removeQuery(int query_id) {
if (queries.containsKey(query_id)) {
logger.debug("Removing query");
OpRouter1 op = queries.get(query_id);
if (op instanceof ContinuousConstruct) {
context.unregisterConstruct((ContinuousConstruct) op);
} else {
context.unregisterSelect((ContinuousSelect) op);
}
queries.remove(query_id, op);
} else {
logger.error("Select not found!");
logger.debug(queries.keySet().toString());
}
}
@Override
public void appendData(Model description) {
stream.stream(description);
/*
String streamName = description.getNsPrefixURI("");
if(!streams.containsKey(streamName))
streams.put(streamName, new DefaultRDFStream(context, streamName));
streams.get(streamName).stream(description);
*/
}
public void sendToWAMP(String message) {
logger.info("Get alert! " + message);
WAMPClient.getInstance().publish(ServiceConfig.config.topicsAlert(), message);
}
private String getString(Mapping m) {
List<Node> list = toNodeList(m);
String message = "";
for (Node n : list) {
if (n != null) {
message += n.toString() + "\n";
}
}
return message;
}
private String getString(List<Triple> list) {
String message = "";
String object;
for (Triple t : list) {
if (t != null) {
if (t.getObject().isURI()) {
object = "<" + t.getObject().getURI() + ">";
} else {
object = t.getObject().toString();
object = object.replace("^^", "^^<").concat(">");
}
message += "<" + t.getSubject().getURI() + "> <"
+ t.getPredicate().getURI() + "> "
+ object + " .\n";
//message += t.toString() + "\n";
}
}
return message;
}
private List<Node> toNodeList(Mapping mapping) {
List<Node> nodes = new ArrayList<Node>();
for (Iterator<Var> vars = mapping.vars(); vars.hasNext();) {
final long id = mapping.get(vars.next());
if (id > 0) {
nodes.add(context.engine().decode(id));
} else {
nodes.add(null);
}
}
return nodes;
}
private static class DefaultRDFStream extends RDFStream {
public DefaultRDFStream(ExecContext context, String uri) {
super(context, uri);
}
public void stream(Model t) {
StmtIterator iter = t.listStatements();
Triple trip;
Node sub, obj, pred;
while (iter.hasNext()) {
trip = iter.next().asTriple();
pred = trip.getPredicate();
obj = trip.getObject();
sub = trip.getSubject();
super.stream(sub, pred, obj);
}
}
@Override
public void stop() {
}
}
}