package eu.play_project.play_platformservices_querydispatcher.bdpl.visitor.realtime;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import com.hp.hpl.jena.graph.Node_URI;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.sparql.core.TriplePath;
import com.hp.hpl.jena.sparql.pfunction.library.str;
import com.hp.hpl.jena.sparql.syntax.Element;
import com.hp.hpl.jena.sparql.syntax.ElementEventGraph;
import com.hp.hpl.jena.sparql.syntax.ElementGroup;
import com.hp.hpl.jena.sparql.syntax.ElementNamedGraph;
import com.hp.hpl.jena.sparql.syntax.ElementPathBlock;
import eu.play_project.play_commons.constants.Stream;
import eu.play_project.play_platformservices.api.QueryDetails;
/**
* Enriches a {@linkplain QueryDetails} object with information about the streams in a query.
*
* @author sobermeier
* @author stuehmer
*/
public class StreamIdCollector {
public void getStreamIds(Query query, QueryDetails qd) {
if (qd == null) {
throw new RuntimeException("Parameter QueryDetails is null");
} else {
qd.setOutputStream(getOutputStream(query));
qd.setInputStreams(getInputStreams(query));
qd.setHistoricStreams(getHistoricStreams(query));
}
}
/**
* Returns the stream ID without {@code #stream} suffix to be used with EC and DSB.
*
* @param query
* @return
*/
private String getOutputStream(Query query) {
TypeCheckVisitor v = new TypeCheckVisitor();
UriValueVisitor valueVisitor = new UriValueVisitor();
boolean streamIdFound = false;
Iterator<Triple> iter = query.getConstructTemplate().getTriples().iterator();
Triple triple;
while (iter.hasNext() && !streamIdFound) {
triple = iter.next();
if (triple.getPredicate().visitWith(v) != null) {
if (triple.getObject().visitWith(valueVisitor) == null) {
throw new RuntimeException("Output stream Id is not a URI or Literal");
} else {
String streamId = (String) triple.getObject().visitWith(valueVisitor);
return Stream.toTopicUri(streamId);
}
}
}
return null;
}
/**
* Returns the input stream IDs without the {@code #stream} suffix to be used with EC and DSB.
*
* @param query
* @return
*/
private Set<String> getInputStreams(Query query) {
Set<String> streams = new HashSet<String>();
ValueOrganizerVisitor valueOrganizerVisitor = new ValueOrganizerVisitor();
for (Element element : query.getEventQuery()) {
element.visit(valueOrganizerVisitor);
if (valueOrganizerVisitor.getStreamURIs() != null) {
Set<String> streamIds = valueOrganizerVisitor.getStreamURIs();
for (String id : streamIds) {
streams.add(Stream.toTopicUri(id));
}
}
}
return streams;
}
/**
* Returns the historic stream IDs without the {@code #stream} suffix to be used with EC and DSB.
*
* @param query
* @return
*/
private Set<String> getHistoricStreams(Query query) {
Set<String> streams = null;
ValueOrganizerVisitor valueOrganizerVisitor = new ValueOrganizerVisitor();
Element element = query.getQueryPattern(); //Historic query.
element.visit(valueOrganizerVisitor);
if (valueOrganizerVisitor.getStreamURIs().size() > 0) {
streams = new HashSet<String>();
for (String stream : valueOrganizerVisitor.getStreamURIs()) {
streams.add(Stream.toTopicUri(stream));
}
}
return streams;
}
// Return value of URI elment and travers form ElementPathBlock to URI
// elment.
private class ValueOrganizerVisitor extends GenericVisitor {
Set<String> streamURIs;
public ValueOrganizerVisitor(){
streamURIs = new HashSet<String>();
}
@Override
public void visit(ElementPathBlock el) {
TypeCheckVisitor v = new TypeCheckVisitor();
UriValueVisitor valueVisotor = new UriValueVisitor();
for (TriplePath tmpTriplePath : el.getPattern().getList()) {
// Check if type is ok
if (tmpTriplePath.getPredicate().visitWith(v) != null) {
if (tmpTriplePath.getObject().visitWith(valueVisotor) == null) {
throw new RuntimeException("Input stream Id is not a URI or Literal");
} else {
streamURIs.add((String) tmpTriplePath.getObject().visitWith(valueVisotor));
break;
}
}
}
}
@Override
public void visit(ElementNamedGraph el){
el.getElement().visit(this);
}
public Set<String> getStreamURIs() {
return streamURIs;
}
@Override
public void visit(ElementEventGraph el) {
el.getElement().visit(this);
}
@Override
public void visit(ElementGroup el) {
// Visit all group elements
for (Element element : el.getElements()) {
element.visit(this);
}
}
}
// Test if the type is http://events.event-processing.org/types/stream
private class TypeCheckVisitor extends GenericVisitor {
private final String ok = "OK";
@Override
public Object visitURI(Node_URI it, String uri) {
if (uri.equals(org.event_processing.events.types.Event.STREAM.toString()) || uri.equals((org.event_processing.events.types.Event.STREAM + "/"))) {
return ok;
}
return null;
}
}
// Test if the type is http://events.event-processing.org/types/stream
private class UriValueVisitor extends GenericVisitor {
@Override
public Object visitURI(Node_URI it, String uri) {
return uri;
}
}
}