package eu.play_project.play_platformservices;
import static eu.play_project.play_commons.constants.Event.EVENT_ID_PLACEHOLDER;
import java.io.Serializable;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import com.hp.hpl.jena.graph.Node;
import eu.play_project.play_commons.eventtypes.EventHelpers;
import eu.play_project.play_platformservices.api.HistoricalData;
import eu.play_project.play_platformservices.api.QueryTemplate;
import fr.inria.eventcloud.api.Quadruple;
public class QueryTemplateImpl implements QueryTemplate, Serializable {
private static final long serialVersionUID = 100L;
List<Quadruple> templateQuads = new LinkedList<Quadruple>();
@Override
public void appendLine(Node graph, Node subject, Node predicate, Node object) {
appendLine(new Quadruple(graph, subject, predicate, object));
}
@Override
public void appendLine(Quadruple line) {
templateQuads.add(line);
}
@Override
public List<Quadruple> fillTemplate(HistoricalData historicalData, Node graph, Node eventId) {
List<Quadruple> result = new LinkedList<Quadruple>();
for (Quadruple templ : templateQuads) {
Set<Node[]> t = new HashSet<Node[]>();
// PLAY requires the graph name of each event to be unique, i.e. it cannot be taken from the template:
Node [] templArray = templ.toArray();
templArray[0] = graph;
// The subsject will also be replaced if it contains the placeholder ":e"
if (templArray[1].toString().equals(EVENT_ID_PLACEHOLDER)) {
templArray[1] = eventId;
}
t.add(templArray);
result.addAll(fillTemplateHelper(t, historicalData, 0));
}
return result;
}
/**
* Recursive method to go through each step (graph, subject, predicate,
* object) of the template quadruples and multiply each step (cross product)
* if there are more than one variable values.
*
* @param t
* Set of (partially filled template lines from the previous
* step.
* @param historicalData
* Variable names and their (multiple) values to be replaced in
* the template.
* @param step
* The recursion step... the method starts at step {@code 0} to
* fill the RDF graph names moving on until step {@code 3}
* filling the RDF objects.
* @return Returns a collection of quadruples fulfilling the variable
* values.
*/
private List<Quadruple> fillTemplateHelper(Set<Node[]> t, HistoricalData historicalData, int step) {
Set<Node[]> tNext = new HashSet<Node[]>();
for (Node[] tempLine : t) {
if (tempLine[step].isVariable()) {
for (String value : historicalData.get(tempLine[step].getName())) {
Node[] qNext = tempLine.clone();
qNext[step] = EventHelpers.toJenaNode(value);
tNext.add(qNext);
}
}
else {
tNext.add(tempLine);
}
}
/*
* Go into recursion...
*/
if (step < 3) {
// Recursion to next step (e.g. moving on to filling triple subjects)
return fillTemplateHelper(tNext, historicalData, step + 1);
}
/*
* ...or return results.
*/
else {
List<Quadruple> result = new LinkedList<Quadruple>();
for (Node[] quad : tNext) {
result.add(new Quadruple(quad[0], quad[1], quad[2], quad[3]));
}
return result;
}
}
}