package org.aksw.sparqlify.core.algorithms; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.aksw.jena_sparql_api.views.OpViewInstanceJoin; import org.aksw.jena_sparql_api.views.Ops; import org.aksw.jena_sparql_api.views.VarDefinition; import org.aksw.jena_sparql_api.views.ViewInstance; import org.aksw.sparqlify.core.domain.input.Mapping; import org.aksw.sparqlify.core.interfaces.MappingOps; import org.aksw.sparqlify.core.interfaces.OpMappingRewriter; import org.aksw.sparqlify.database.OpFilterIndexed; import org.apache.jena.query.Query; import org.apache.jena.query.SortCondition; import org.apache.jena.sparql.algebra.Op; import org.apache.jena.sparql.algebra.op.OpAssign; import org.apache.jena.sparql.algebra.op.OpConditional; import org.apache.jena.sparql.algebra.op.OpDisjunction; 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.OpGroup; import org.apache.jena.sparql.algebra.op.OpJoin; import org.apache.jena.sparql.algebra.op.OpLeftJoin; import org.apache.jena.sparql.algebra.op.OpOrder; import org.apache.jena.sparql.algebra.op.OpProject; import org.apache.jena.sparql.algebra.op.OpQuadPattern; import org.apache.jena.sparql.algebra.op.OpSequence; import org.apache.jena.sparql.algebra.op.OpSlice; import org.apache.jena.sparql.algebra.op.OpTopN; import org.apache.jena.sparql.algebra.op.OpUnion; import org.apache.jena.sparql.expr.ExprList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class OpMappingRewriterImpl implements OpMappingRewriter { private static final Logger logger = LoggerFactory.getLogger(OpMappingRewriterImpl.class); private MappingOps ops; //private Map<Class<?>, OpMappingRewriter> map; /* public OpMappingRewriterImpl(DatatypeAssigner datatypeAssigner) { this.ops = new MappingOpsImpl(); } */ /* public OpMappingRewriterMap(Map<Class<?>, OpMappingRewriter> map) { this.map = map; } */ public OpMappingRewriterImpl(MappingOps ops) { this.ops = ops; } public MappingOps getMappingOps() { return this.ops; } public Mapping rewrite(OpViewInstanceJoin op) { Collection<ViewInstance> vis = op.getJoin().getViewInstances(); Mapping result = null; for(ViewInstance vi : vis) { Mapping tmp = ops.createMapping(vi); //System.out.println(vi + "\n --> " + tmp); if(result == null) { result = tmp; } else { result = ops.join(result, tmp); } } return result; } public List<Mapping> rewriteList(List<Op> ops) { List<Mapping> mappings = new ArrayList<Mapping>(ops.size()); for(Op op : ops) { Mapping tmp = rewrite(op); mappings.add(tmp); } return mappings; } public Mapping rewrite(OpDisjunction op) { List<Op> elements = op.getElements(); List<Mapping> mappings = rewriteList(elements); Mapping result = ops.union(mappings); return result; } public Mapping rewrite(OpSequence op) { List<Op> members = op.getElements(); if(members.isEmpty()) { MappingOpsImpl.createEmptyMapping(); } Mapping a = null; for(Op member : members) { Mapping b = rewrite(member); if(a == null) { a = b; } else { a = ops.join(a, b); } } return a; } public Mapping join(Op a, Op b) { Mapping ma = rewrite(a); Mapping mb = rewrite(b); Mapping result = ops.join(ma, mb); return result; } public Mapping rewrite(OpJoin op) { Mapping result = join(op.getLeft(), op.getRight()); return result; } public Mapping rewrite(OpLeftJoin op) { Mapping a = rewrite(op.getLeft()); Mapping b = rewrite(op.getRight()); ExprList exprs = op.getExprs(); Mapping result = ops.leftJoin(a, b, exprs); return result; } public Mapping rewrite(OpConditional op) { OpLeftJoin tmp = (OpLeftJoin)OpLeftJoin.create(op.getLeft(), op.getRight(), new ExprList()); Mapping result = rewrite(tmp); return result; } public Mapping rewrite(OpFilterIndexed op) { Mapping a = rewrite(op.getSubOp()); Mapping result = ops.filter(a, op.getRestrictions().getExprs()); return result; } public Mapping rewrite(OpSlice op) { Mapping a = rewrite(op.getSubOp()); Long limit = (op.getLength() == Query.NOLIMIT) ? null : op.getLength(); Long offset = (op.getStart() == Query.NOLIMIT) ? null : op.getStart(); Mapping result = ops.slice(a, limit, offset); return result; } public Mapping rewrite(OpAssign op) { OpExtend tmp = (OpExtend)OpExtend.extend(op.getSubOp(), op.getVarExprList()); Mapping result = rewrite(tmp); return result; } public Mapping rewrite(OpExtend op) { Mapping a = rewrite(op.getSubOp()); logger.warn("OpExtend: We need to check whether term constructors must be injected"); /* * A thought on injecting term constructors: * Can we just rewrite the expression to SQL, and then make it a typed literal? * No, because the expression might actually compute a URI, so we can't just guess the type. * * Maybe for now we could assume, that the expressions that go here are all sane (i.e. have the appropriate term ctors) * */ //Multimap<Var, RestrictedExpr> map = HashMultimap.create(a.getVarDefinition().getMap()); VarDefinition varDef = VarDefinition.create(op.getVarExprList()); Mapping result = ops.extend(a, varDef); return result; } public Mapping rewrite(OpProject op) { Mapping a = rewrite(op.getSubOp()); Mapping result = ops.project(a, op.getVars()); return result; } public Mapping rewrite(OpDistinct op) { Mapping a = rewrite(op.getSubOp()); Mapping result = ops.distinct(a); return result; } public Mapping rewrite(OpOrder op) { // If the op is a union, we try to sort the members based on their prefix // constraints Mapping a = rewrite(op.getSubOp()); List<SortCondition> sortConditions = op.getConditions(); Mapping result = ops.order(a, sortConditions); return result; } /** * The aggregators need to be wrapped with an appropriate term ctor. * E.g. count(*) -> typedLiteral(count(*), xsd:long) * * @param op * @return */ public Mapping rewrite(OpGroup op) { Mapping a = rewrite(op.getSubOp()); Mapping result = ops.groupBy(a, op.getGroupVars(), op.getAggregators()); return result; } /* public Mapping rewrite(OpNull op) { Mapping a = new Mapping(SqlOpEmpty.create(schema)); } */ public Mapping rewrite(OpTopN op) { // We convert this 'back' into an order by followed by limit Op sub = op.getSubOp(); OpOrder inner = new OpOrder(sub, op.getConditions()); OpSlice outer = new OpSlice(inner, 0, op.getLimit()); Mapping result = rewrite(outer); return result; } public Mapping rewrite(OpMapping op) { Mapping result = op.getMapping(); return result; } @Override public Mapping rewrite(Op op) { Mapping result; Ops type = Ops.valueOf(op.getClass().getSimpleName()); switch(type) { case OpOrder: result = rewrite((OpOrder)op); break; case OpDistinct: result = rewrite((OpDistinct)op); break; case OpFilter: result = rewrite((OpFilter)op); break; case OpGroup: result = rewrite((OpGroup)op); break; case OpJoin: result = rewrite((OpJoin)op); break; case OpLeftJoin: result = rewrite((OpLeftJoin)op); break; case OpExtend: result = rewrite((OpExtend)op); break; case OpQuadPattern: result = rewrite((OpQuadPattern)op); break; case OpSlice: result = rewrite((OpSlice)op); break; case OpProject: result = rewrite((OpProject)op); break; case OpFilterIndexed: result = rewrite((OpFilterIndexed)op); break; case OpMapping: result = rewrite((OpMapping)op); break; case OpUnion: result = rewrite((OpUnion)op); break; case OpDisjunction: result = rewrite((OpDisjunction)op); break; case OpViewInstanceJoin: result = rewrite((OpViewInstanceJoin)op); break; default: throw new RuntimeException("Unknown op type: " + op.getClass()); } return result; // if(op instanceof OpViewInstanceJoin) { // result = rewrite((OpViewInstanceJoin)op); // } // else if (op instanceof OpMapping) { // result = ((OpMapping)op).getMapping(); // } // else if (op instanceof OpDisjunction) { // result = rewrite((OpDisjunction)op); // } // else if (op instanceof OpFilterIndexed) { // result = rewrite((OpFilterIndexed)op); // } // else if (op instanceof OpProject) { // result = rewrite((OpProject)op); // } // else if (op instanceof OpJoin) { // result = rewrite((OpJoin)op); // } // else if (op instanceof OpLeftJoin) { // result = rewrite((OpLeftJoin)op); // } // else if (op instanceof OpSequence) { // result = rewrite((OpSequence)op); // } // else if (op instanceof OpConditional) { // result = rewrite((OpConditional)op); // } // else if (op instanceof OpSlice) { // result = rewrite((OpSlice)op); // } // else if (op instanceof OpDistinct) { // result = rewrite((OpDistinct)op); // } // else if (op instanceof OpGroup) { // result = rewrite((OpGroup)op); // } // else if (op instanceof OpExtend) { // result = rewrite((OpExtend)op); // } // else if (op instanceof OpAssign) { // result = rewrite((OpAssign)op); // } // else if (op instanceof OpOrder) { // result = rewrite((OpOrder)op); // } // else if(op instanceof OpTopN) { // OpTopN o = (OpTopN)op; // // // We convert this 'back' into an order by followed by limit // Op sub = o.getSubOp(); // OpOrder inner = new OpOrder(sub, o.getConditions()); // OpSlice outer = new OpSlice(inner, 0, o.getLimit()); // // result = rewrite(outer); // //// return result; // // } // /* // else if(op instanceof OpNull) { // result = rewrite((OpNull) op); // }*/ // else { // throw new RuntimeException("Unhandled op type: " + op.getClass() + "; " + op); // } // // return result; } /* public Map<Class<?>, OpMappingRewriter> createDefaultMap() { Map<Class<?>, OpMappingRewriter> map = new HashMap<Class<?>, OpMappingRewriter>(); }*/ }