package org.aksw.jena_sparql_api.cache.tests;
import java.util.List;
import org.apache.jena.atlas.io.IndentedWriter;
import org.apache.jena.sparql.algebra.Op;
import org.apache.jena.sparql.algebra.OpVisitor;
import org.apache.jena.sparql.algebra.Table;
import org.apache.jena.sparql.algebra.Transform;
import org.apache.jena.sparql.algebra.op.Op1;
import org.apache.jena.sparql.algebra.op.OpDistinct;
import org.apache.jena.sparql.algebra.op.OpExtend;
import org.apache.jena.sparql.algebra.op.OpFilter;
import org.apache.jena.sparql.algebra.op.OpJoin;
import org.apache.jena.sparql.algebra.op.OpOrder;
import org.apache.jena.sparql.algebra.op.OpProject;
import org.apache.jena.sparql.algebra.op.OpQuadBlock;
import org.apache.jena.sparql.algebra.op.OpReduced;
import org.apache.jena.sparql.algebra.op.OpSlice;
import org.apache.jena.sparql.algebra.op.OpTable;
import org.apache.jena.sparql.core.QuadPattern;
import org.apache.jena.sparql.core.VarExprList;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprAggregator;
import org.apache.jena.sparql.expr.ExprList;
import org.apache.jena.sparql.serializer.SerializationContext;
import org.apache.jena.sparql.util.NodeIsomorphismMap;
import com.google.common.collect.Range;
/**
* The main question is still how to represent children of thi tree structure.
* Options:
* (a) Every tree level node has a list of children and a field for the operator (union, join. etc)
* (b) We create an OpQueryLevel node - hence, union, join and left join nodes remain as usual
* (c) We create a custom class for sub-ops which depending on the operator type holds different attributes
*
* i suppose option (b) is the most advantageous one
*
*
*
*
* @author raven
*
*/
/**
* Make a bottom op traversal and generate the algebra
* @author raven
*
*/
class QueryLevelToOp {
public Op process(QueryLevel ql) {
//Op = process(ql.getSubgetSubLevel());
//Op
Op result = null;
for(Table table : ql.getTables()) {
OpTable op = OpTable.create(table);
result = OpJoin.create(result, op);
}
for(Expr expr : ql.getFilters()) {
result = OpFilter.filter(expr, result);
}
if(ql.getQuadPattern() != null) {
result = new OpQuadBlock(ql.getQuadPattern());
}
return result;
}
public static void applySolutionModifiers(SolutionModifiers sm, Op op) {
// https://www.w3.org/TR/sparql11-query/#convertGroupAggSelectExpressions
// Grouping
// Aggregates
// HAVING
// VALUES
// Select expressions
Op result = op;
if(sm.getProjection() != null) {
result = new OpProject(result, sm.getProjection());
}
if(sm.getExtend() != null) {
result = OpExtend.create(op, sm.getExtend());
}
if(sm.getSlice() != null) {
Range<Long> range = sm.getSlice();
long lower = range.lowerEndpoint();
long upper = range.upperEndpoint();
long length = upper - lower;
result = new OpSlice(result, lower, length);
}
if(sm.getSortConditions() != null) {
result = new OpOrder(result, sm.getSortConditions());
}
int dedupLevel = sm.getDeduplicationLevel();
switch(dedupLevel) {
case 0: /* nothing todo */
case 1: result = OpReduced.create(result); break;
case 2: result = OpDistinct.create(result); break;
default: throw new RuntimeException("Invalid deduplication level");
}
}
//public QueryLevel
}
class QueryLevel {
protected SolutionModifiers solutionModifiers;
protected VarExprList groupExprs;
protected List<ExprAggregator> aggregators;
// TODO how to get the canonical quad filter pattern here?
// Probably it would be best to have a map which maps the query level to the
// canonical quad filter pattern
protected ExprList filters;
protected QuadPattern quadPattern;
protected List<Table> tables;
public SolutionModifiers getSolutionModifiers() {
return solutionModifiers;
}
public void setSolutionModifiers(SolutionModifiers solutionModifiers) {
this.solutionModifiers = solutionModifiers;
}
public VarExprList getGroupExprs() {
return groupExprs;
}
public void setGroupVars(VarExprList groupExprs) {
this.groupExprs = groupExprs;
}
public List<ExprAggregator> getAggregators() {
return aggregators;
}
public void setAggregators(List<ExprAggregator> aggregators) {
this.aggregators = aggregators;
}
public ExprList getFilters() {
return filters;
}
public void setFilters(ExprList filters) {
this.filters = filters;
}
public QuadPattern getQuadPattern() {
return quadPattern;
}
public void setQuadPattern(QuadPattern quadPattern) {
this.quadPattern = quadPattern;
}
public List<Table> getTables() {
return tables;
}
public void setTables(List<Table> tables) {
this.tables = tables;
}
@Override
public String toString() {
return "QueryLevel [solutionModifiers=" + solutionModifiers + ", groupExprs=" + groupExprs + ", aggregators="
+ aggregators + ", filters=" + filters + ", quadPattern=" + quadPattern + ", tables=" + tables + "]";
}
}
//class OpQueryLevel {
// protected QueryLevel queryLevel;
// protected Op subOp; // may be null
//}
public class OpQueryLevel
extends Op1
{
protected QueryLevel data;
// Probably we should remove the implied data attribute, and use a map
// to associate a query level which the additional information
protected QueryLevel impliedData;
public OpQueryLevel(Op subOp) {
super(subOp);
}
// public Op getSubLevel() {
// return subOp;
// }
public QueryLevel getData() {
return data;
}
public void setData(QueryLevel data) {
this.data = data;
}
public QueryLevel getImpliedData() {
return impliedData;
}
public void setImpliedData(QueryLevel impliedData) {
this.impliedData = impliedData;
}
@Override
public void visit(OpVisitor opVisitor) {
// TODO Auto-generated method stub
}
@Override
public String getName() {
// TODO Auto-generated method stub
return null;
}
@Override
public Op apply(Transform transform, Op subOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public Op1 copy(Op subOp) {
// TODO Auto-generated method stub
return null;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return 0;
}
@Override
public boolean equalTo(Op other, NodeIsomorphismMap labelMap) {
// TODO Auto-generated method stub
return false;
}
@Override
public void output(IndentedWriter out, SerializationContext sCxt) {
out.println("( QueryLevel:");
out.incIndent();
SolutionModifiers sm = data.getSolutionModifiers();
out.println("DeduplicationLevel: " + sm.getDeduplicationLevel());
out.println("Projection: " + sm.getProjection());
out.println("Extend: " + sm.getExtend());
out.println("Slice: " + sm.getSlice());
out.println("Sort Conditions: " + sm.getSortConditions());
out.println("Aggregators: " + data.getAggregators());
out.println("Group Exprs: " + data.getGroupExprs());
out.println("Filters: " + data.getFilters());
out.println("QuadPattern: " + data.getQuadPattern());
out.println("SubOp:");
// data.get
out.decIndent();
out.println(")");
// TODO Auto-generated method stub
super.output(out, sCxt);
}
// return "QueryLevel [" + "impliedSolutionModifiers=" + impliedSolutionModifiers
// + ", solutionModifiers=" + solutionModifiers + ", filters=" + filters + ", quadPattern=" + quadPattern
// + ", subOp=" + this.getSubOp() + "]";
}