package org.aksw.sparqlify.inverse; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.aksw.jena_sparql_api.normal_form.Clause; import org.aksw.jena_sparql_api.normal_form.NestedNormalForm; import org.aksw.jena_sparql_api.restriction.RestrictionManagerImpl; import org.aksw.jena_sparql_api.utils.ExprUtils; import org.aksw.jena_sparql_api.utils.QuadUtils; import org.aksw.jena_sparql_api.views.VarDefinition; import org.aksw.jena_sparql_api.views.ViewQuad; import org.aksw.sparqlify.algebra.sql.exprs2.S_ColumnRef; import org.aksw.sparqlify.algebra.sql.exprs2.SqlExpr; import org.aksw.sparqlify.algebra.sql.exprs2.SqlExprFunction; import org.aksw.sparqlify.algebra.sql.nodes.SqlOp; import org.aksw.sparqlify.algebra.sql.nodes.SqlOpTable; import org.aksw.sparqlify.core.TypeToken; import org.aksw.sparqlify.core.algorithms.CandidateViewSelectorSparqlify; import org.aksw.sparqlify.core.algorithms.MappingOpsImpl; import org.aksw.sparqlify.core.cast.SqlValue; import org.aksw.sparqlify.core.domain.input.ViewDefinition; import org.aksw.sparqlify.core.interfaces.SqlTranslator; import org.apache.jena.graph.Node; import org.apache.jena.sparql.core.Quad; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.expr.E_Equals; import org.apache.jena.sparql.expr.Expr; import org.apache.jena.sparql.expr.ExprList; import org.apache.jena.sparql.expr.ExprVar; import org.apache.jena.sparql.expr.NodeValue; public class SparqlSqlInverseMapperImpl implements SparqlSqlInverseMapper { private CandidateViewSelectorSparqlify candidateViewSelector; private SqlTranslator sqlTranslator; public SparqlSqlInverseMapperImpl(CandidateViewSelectorSparqlify candidateViewSelector, SqlTranslator sqlTranslator) { this.candidateViewSelector = candidateViewSelector; this.sqlTranslator = sqlTranslator; } // public static List<Sq$lExpr> swapVarFirst(List<SqlExpr> sqlExpr) { // // } @Override public List<SparqlSqlInverseMap> map(Quad quad) { Set<ViewQuad<ViewDefinition>> viewQuads = getCandidateViews(candidateViewSelector, quad); List<SparqlSqlInverseMap> result = new ArrayList<SparqlSqlInverseMap>(); /* * For each view-quad: Try to figure out, what values the * underlying table needs no have in order to yield the quad. */ for(ViewQuad<ViewDefinition> viewQuad : viewQuads) { ViewDefinition viewDef = viewQuad.getView(); VarDefinition varDef = viewDef.getMapping().getVarDefinition(); Map<String, TypeToken> typeMap = viewDef.getMapping().getSqlOp().getSchema().getTypeMap(); //ViewDefinitionNormalizer viewDefNormalizer = new ViewDefinitionNormalizer(); //ViewDefinition viewDef = viewDefNormalizer.normalize(tmpViewDef); // Retrieve the view's table SqlOp tmpTable = viewDef.getMapping().getSqlOp(); if(!(tmpTable instanceof SqlOpTable)) { throw new RuntimeException("Not supported: " + tmpTable); } //SqlOpTable table = (SqlOpTable)tmpTable; //table.g Quad q = viewQuad.getQuad(); ExprList exprs = new ExprList(); for(int i = 0; i < 4; ++i) { Node n = QuadUtils.getNode(q, i); if(!n.isVariable()) { continue; } Var v = (Var)n; Node insertNode = QuadUtils.getNode(quad, i); if(insertNode.isVariable() || insertNode.isBlank()) { continue; } //exprs.add(new E_Equals(NodeValue.makeNode(quad.getSubject()), NodeValue.makeNode(insertQuad.getSubject()))); exprs.add(new E_Equals(new ExprVar(v), NodeValue.makeNode(insertNode))); } Expr condition = ExprUtils.andifyBalanced(exprs); // System.out.println("Condition: " + condition); // System.out.println("VarDef : " + varDef); /* * */ List<SqlExpr> sqlExprs = MappingOpsImpl.createSqlConditionItems(condition, varDef, typeMap, sqlTranslator); Map<S_ColumnRef, SqlValue> columnToValue = new HashMap<S_ColumnRef, SqlValue>(); for(SqlExpr sqlExpr : sqlExprs) { List<SqlExpr> args = sqlExpr.getArgs(); SqlExpr left = args.get(0); SqlExpr right = args.get(1); // Get rid of redundant expression items (such as conversion from string to string) // TODO Move this to a generic optimization function if(left.isFunction()) { SqlExprFunction fn = left.asFunction(); if(fn.getName().equals("str@str")) { left = fn.getArgs().get(0); } } if(left.isConstant()) { SqlExpr tmp = right; right = left; left = tmp; } if(!left.isVariable()) { throw new RuntimeException("Variable expected, instead got: " + left); } if(!right.isConstant()) { throw new RuntimeException("Variable expected, instead got: " + right); } S_ColumnRef columnRef = (S_ColumnRef)left.asVariable(); SqlValue sqlValue = right.asConstant().getValue(); //System.out.println(" " + left.getClass() + ", " + right.getClass()); columnToValue.put(columnRef, sqlValue); } SparqlSqlInverseMap inverseMap = new SparqlSqlInverseMap(quad, viewDef, viewQuad.getQuad(), columnToValue); result.add(inverseMap); } return result; } /** * Utility function that returns the set of candidate views for * a variable-free quad. * * @param candidateSelector * @param quad * @return */ public static Set<ViewQuad<ViewDefinition>> getCandidateViews(CandidateViewSelectorSparqlify candidateSelector, Quad quad) { Var g = Var.alloc("g"); Var s = Var.alloc("s"); Var p = Var.alloc("p"); Var o = Var.alloc("o"); Node gv = quad.getGraph(); Node sv = quad.getSubject(); Node pv = quad.getPredicate(); Node ov = quad.getObject(); Quad tmpQuad = new Quad(g, s, p, o); RestrictionManagerImpl r = new RestrictionManagerImpl(); /* ExprList exprs = new ExprList(); exprs.add(new E_Equals(new ExprVar(g), NodeValue.makeNode(gv))); exprs.add(new E_Equals(new ExprVar(s), NodeValue.makeNode(sv))); exprs.add(new E_Equals(new ExprVar(p), NodeValue.makeNode(pv))); exprs.add(new E_Equals(new ExprVar(o), NodeValue.makeNode(ov))); Clause clause = new Clause(new HashSet<Expr>(exprs.getList())); */ /* * Create a conjunctive normal form (literals ORed, clauses ANDed), * with one clause for constraint of {g, s, p, o} */ Set<Clause> clauses = new HashSet<Clause>(); Var[] vars = new Var[]{g, s, p, o}; Node[] nodes = new Node[]{gv, sv, pv, ov}; for(int i = 0; i < 4; ++i) { Var v = vars[i]; Node n = nodes[i]; if(!n.isVariable() && !n.isBlank()) { clauses.add(new Clause(new E_Equals(new ExprVar(v), NodeValue.makeNode(n)))); } } /* clauses.add(new Clause(new E_Equals(new ExprVar(g), NodeValue.makeNode(gv)))); clauses.add(new Clause(new E_Equals(new ExprVar(s), NodeValue.makeNode(sv)))); clauses.add(new Clause(new E_Equals(new ExprVar(p), NodeValue.makeNode(pv)))); clauses.add(new Clause(new E_Equals(new ExprVar(o), NodeValue.makeNode(ov)))); */ NestedNormalForm nnf = new NestedNormalForm(clauses); r.stateCnf(nnf); /* * BUG: stating a Node does not change the CNF (should it do that?) r.stateNode(g, gv); r.stateNode(s, sv); r.stateNode(p, pv); r.stateNode(o, ov); */ // TODO The quad may only consist of variables.... Set<ViewQuad<ViewDefinition>> result = candidateSelector.findCandidates(tmpQuad, r); return result; } }