package org.aksw.sparqlify.core.algorithms; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import org.aksw.jena_sparql_api.restriction.RestrictionManagerImpl; import org.aksw.jena_sparql_api.restriction.UnsatisfiabilityException; import org.aksw.jena_sparql_api.views.CandidateViewSelectorBase; import org.aksw.jena_sparql_api.views.E_RdfTerm; import org.aksw.jena_sparql_api.views.OpViewInstanceJoin; import org.aksw.jena_sparql_api.views.RecursionResult; import org.aksw.jena_sparql_api.views.RestrictedExpr; import org.aksw.jena_sparql_api.views.VarBinding; import org.aksw.jena_sparql_api.views.VarDefinition; import org.aksw.jena_sparql_api.views.ViewInstance; import org.aksw.sparqlify.algebra.sql.nodes.SqlOpEmpty; import org.aksw.sparqlify.core.domain.input.Mapping; import org.aksw.sparqlify.core.domain.input.ViewDefinition; import org.aksw.sparqlify.core.interfaces.MappingOps; import org.aksw.sparqlify.core.sparql.algebra.transform.FilterPlacementOptimizer2Sparqlify; import org.aksw.sparqlify.database.GetVarsMentioned; import org.aksw.sparqlify.sparqlview.ViewInstanceJoin; import org.apache.jena.sdb.core.Generator; import org.apache.jena.sdb.core.Gensym; import org.apache.jena.sparql.algebra.Op; import org.apache.jena.sparql.algebra.op.OpDisjunction; import org.apache.jena.sparql.algebra.op.OpQuadBlock; import org.apache.jena.sparql.core.QuadPattern; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.expr.Expr; import org.apache.jena.sparql.expr.ExprVar; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; /** * The candidate selector for RDB-RDF * @author raven * * @param <T> */ public class CandidateViewSelectorSparqlify extends CandidateViewSelectorBase<ViewDefinition, Mapping> { private static final Logger logger = LoggerFactory.getLogger(CandidateViewSelectorSparqlify.class); //private OpMappingRewriter opMappingRewriter;// = new OpMappingRewriterImpl(new MappingOps) private MappingOps mappingOps; private ViewDefinitionNormalizer<ViewDefinition> viewDefinitionNormalizer; public CandidateViewSelectorSparqlify() { this(null); logger.warn("No mappingOps provided. This means that view candidates cannot be pruned efficently which is most likely not what you want!!!"); } public CandidateViewSelectorSparqlify(MappingOps mappingOps) { this(mappingOps, new ViewDefinitionNormalizerImpl()); } public CandidateViewSelectorSparqlify(MappingOps mappingOps, ViewDefinitionNormalizer<ViewDefinition> viewDefinitionNormalizer) { super((op, rm) -> FilterPlacementOptimizer2Sparqlify.optimizeStatic(op, rm)); //super(viewDefinitionNormalizer); this.viewDefinitionNormalizer = viewDefinitionNormalizer; this.mappingOps = mappingOps; } @Override public ViewDefinition normalizeView(ViewDefinition view) { ViewDefinition normalized = viewDefinitionNormalizer.normalize(view); logger.trace("Normalized view:\n" + normalized); return normalized; } /** * Create a new context based on the baseContext and the current candidate viewInstance * * if null is returned, the candidateViewInstance becomes rejected, otherwise, the new context * will be passed to this function together with all sub candidate viewInstances. * * @return */ @Override public Mapping createContext(Mapping baseMapping, ViewInstance<ViewDefinition> viewInstance) throws UnsatisfiabilityException { Mapping nextMapping = null; boolean enablePruningMappingRewrite = true; if(enablePruningMappingRewrite && mappingOps != null) { Mapping mapping = mappingOps.createMapping(viewInstance); if(baseMapping == null) { nextMapping = mapping; } else { nextMapping = mappingOps.join(baseMapping, mapping); } if(nextMapping.isEmpty()) { throw new UnsatisfiabilityException(); } } return nextMapping; } /* @Override public ViewInstanceJoin createUnionItem(List<ViewInstance<ViewDefinition>> viewInstances, RestrictionManagerImpl subRestrictions) { ViewInstanceJoin viewConjunction = new ViewInstanceJoin(viewInstances, subRestrictions); // remove self joins SelfJoinEliminator.merge(viewConjunction); //result.add(viewConjunction); return viewConjunction; } */ @Override public Op createOp(OpQuadBlock opQuadPattern, List<RecursionResult<ViewDefinition, Mapping>> conjunctions) { OpDisjunction result = OpDisjunction.create(); for(RecursionResult<ViewDefinition, Mapping> entry : conjunctions) { Mapping mapping = entry.getFinalContext(); RestrictionManagerImpl restrictions = entry.getViewInstances().getRestrictions(); Op tmp = new OpMapping(mapping, restrictions); result.add(tmp); } // If there were no candidates, we fake a view definition where all variables of // the quad pattern (of the query) are bound to Node.nvNothing if(result.size() == 0) { Op tmp = createEmptyViewInstance(opQuadPattern); result.add(tmp); } return result; } //@Override public Op createOpOldButWorking(OpQuadBlock opQuadPattern, List<RecursionResult<ViewDefinition, Mapping>> conjunctions) { for(RecursionResult<ViewDefinition, Mapping> tmp : conjunctions) { ViewInstanceJoin<ViewDefinition> conjunction = tmp.getViewInstances(); SelfJoinEliminator.merge(conjunction); } OpDisjunction result = OpDisjunction.create(); for(RecursionResult<ViewDefinition, Mapping> entry : conjunctions) { ViewInstanceJoin<ViewDefinition> item = entry.getViewInstances(); Op tmp = new OpViewInstanceJoin(item); result.add(tmp); } // If there were no candidates, we fake a view definition where all variables of // the quad pattern (of the query) are bound to Node.nvNothing if(result.size() == 0) { Op tmp = createEmptyViewInstance(opQuadPattern); result.add(tmp); } return result; } public static Generator emptyViewNameGenerator = Gensym.create("emptyView"); public static Op createEmptyViewInstance(OpQuadBlock opQuadBlock) { Set<Var> vars = GetVarsMentioned.getVarsMentioned(opQuadBlock); VarBinding binding = new VarBinding(); Multimap<Var, RestrictedExpr> varDefMap = HashMultimap.create(); String colName = "nll"; SqlOpEmpty sqlOpEmpty = SqlOpEmpty.create(colName); //MappingOpsImpl.createEmptyMapping() for(Var queryVar : vars) { // Bind the query var to a view var with the same name Var viewVar = queryVar; binding.put(queryVar, viewVar);//NodeValue.TRUE.asNode());//NodeValue.nvNothing.asNode());; ExprVar colVar = new ExprVar(colName); Expr termCtor = E_RdfTerm.createPlainLiteral(colVar); // Bind the view var to a column in the table varDefMap.put(viewVar, new RestrictedExpr(termCtor)); //binding.put(var, null); //map.put(var, new RestrictedExpr(NodeValue.nvNothing)); } VarDefinition varDef = new VarDefinition(varDefMap); Mapping mapping = new Mapping(varDef, sqlOpEmpty); String viewName = emptyViewNameGenerator.next(); ViewDefinition viewDef = new ViewDefinition(viewName, new QuadPattern(), null, mapping, null); ViewInstance<ViewDefinition> viewInstance = new ViewInstance<ViewDefinition>(viewDef, binding); List<ViewInstance<ViewDefinition>> tmp = new ArrayList<ViewInstance<ViewDefinition>>(); tmp.add(viewInstance); ViewInstanceJoin<ViewDefinition> join = new ViewInstanceJoin<ViewDefinition>(tmp, new RestrictionManagerImpl()); Op result = new OpViewInstanceJoin<ViewDefinition>(join); return result; } @Override public RestrictionManagerImpl getRestrictions2(Op op) { if(op instanceof OpMapping) { OpMapping opMapping = (OpMapping)op; return opMapping.getRestrictions(); } else { // TODO Auto-generated method stub return super.getRestrictions2(op); } } @Override public void getRestrictions(Op op, Collection<RestrictionManagerImpl> result) { // if(op instanceof OpRdfViewPattern) { // OpRdfViewPattern o = (OpRdfViewPattern)op; // result.add(o.getConjunction().getRestrictions()); // } else { super.getRestrictions(op, result); // } } }