package org.aksw.jena_sparql_api.concept_cache.dirty;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.aksw.jena_sparql_api.concept_cache.core.SparqlCacheUtils;
import org.aksw.jena_sparql_api.concept_cache.domain.QuadFilterPattern;
import org.aksw.jena_sparql_api.core.FluentQueryExecutionFactory;
import org.aksw.jena_sparql_api.core.QueryExecutionFactory;
import org.aksw.jena_sparql_api.core.utils.QueryExecutionUtils;
import org.aksw.jena_sparql_api.lookup.CountInfo;
import org.aksw.jena_sparql_api.utils.CnfUtils;
import org.apache.jena.graph.Node;
import org.apache.jena.query.Query;
import org.apache.jena.sparql.algebra.Op;
import org.apache.jena.sparql.algebra.OpAsQuery;
import org.apache.jena.sparql.algebra.op.OpFilter;
import org.apache.jena.sparql.algebra.op.OpQuadPattern;
import org.apache.jena.sparql.core.BasicPattern;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.core.Var;
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.expr.aggregate.AggCount;
import org.apache.jena.sparql.lang.ParserSPARQL11;
import org.apache.jena.sparql.syntax.Element;
import org.apache.jena.sparql.syntax.ElementGroup;
import org.apache.jena.sparql.syntax.ElementSubQuery;
/*
class QuadFilter {
private Quad quad;
private QuadFilterPatternCanonical qfp;
}
*/
class CountInfoComparator
implements Comparator<CountInfo>
{
@Override
public int compare(CountInfo a, CountInfo b) {
int result = doCompare(a, b);
return result;
}
// Sort known item counts first
public static int doCompare(CountInfo a, CountInfo b) {
int ah = a.isHasMoreItems() ? 1 : -1;
int bh = b.isHasMoreItems() ? 1 : -1;
int x = bh - ah;
long y = b.getCount() - a.getCount();
int r = x == 0 ? (int)y : x;
return r;
}
}
public class JoinSizeChecker {
public static CountInfo fetchCount(QueryExecutionFactory qef, Element e, Long limit) {
Var vc = Var.alloc("_c_");
Long l = limit != null ? limit + 1 : null;
Query query = createQueryCount(vc, e, l);
Node node = QueryExecutionUtils.executeSingle(qef, query, vc);
Number value = (Number)node.getLiteralValue();
long c = value.longValue();
boolean hasMoreItems = limit != null ? c >= l : false;
long v = hasMoreItems ? c - 1 : c;
CountInfo result = new CountInfo(v, hasMoreItems, limit);
return result;
}
public static Element limitElement(Element e, long limit) {
Query subQuery = new Query();
subQuery.setQuerySelectType();
subQuery.setQueryResultStar(true);
subQuery.setQueryPattern(e);
subQuery.setLimit(limit);
Element result = new ElementSubQuery(subQuery);
return result;
}
public static Query createQueryCount(Var countVar, Element e, Long limit) {
if(limit != null) {
e = limitElement(e, limit);
}
Var tmpVar = Var.alloc(countVar.getName() + "_tmp_");
Query result = new Query();
result.setQuerySelectType();
result.getProject().add(countVar, new ExprAggregator(tmpVar, new AggCount()));
result.setQueryPattern(e);
return result;
}
public static Element toElement(Quad quad, Set<Set<Expr>> cnf) {
ExprList exprs = CnfUtils.toExprList(cnf);
BasicPattern bp = new BasicPattern();
bp.add(quad.asTriple());
OpQuadPattern opA = new OpQuadPattern(quad.getGraph(), bp);
Op opB = OpFilter.filter(exprs, opA);
Query query = OpAsQuery.asQuery(opB);
Element result = query.getQueryPattern();
return result;
}
/**
*
* @param qef
* @param qfp
*/
public static Map<Quad, CountInfo> analyze(QueryExecutionFactory qef, QuadFilterPattern qfp, Long limit) {
Map<Quad, Set<Set<Expr>>> quadToCnf = SparqlCacheUtils.quadToCnf(qfp);
Map<Quad, CountInfo> result = analyze(qef, quadToCnf, limit);
return result;
}
public static List<Quad> orderBySelectivity(Map<Quad, CountInfo> quadToCountInfo) {
return null;
}
public static Map<Quad, CountInfo> analyze(QueryExecutionFactory qef, Map<Quad, Set<Set<Expr>>> quadToCnf, Long limit) {
Map<Quad, CountInfo> result = new HashMap<Quad, CountInfo>();
for(Entry<Quad, Set<Set<Expr>>> entry : quadToCnf.entrySet()) {
Quad quad = entry.getKey();
Element e = toElement(quad, entry.getValue());
System.out.println(e);
CountInfo countInfo = fetchCount(qef, e, limit);
result.put(quad, countInfo);
}
return result;
}
/*
* Given a quad filter pattern (i.e. a set of quads and corresponding filters in CNF),
* create a QuadFilter for each quad.
*/
public static void partition(QuadFilterPattern qfp) {
}
// public static void analyze(QueryExecutionFactory qef, Element a, Element b, Long memberLimit, Long joinLimit) {
// long ca = fetchCount(qef, a, memberLimit);
// long cb = fetchCount(qef, b, memberLimit);
//
// ElementGroup group = new ElementGroup();
// group.addElement(a);
// group.addElement(b);
//
// long cc = fetchCount(qef, group, joinLimit);
//
//
// // Both sides of the join must be large in size
// // and the result of the join must be small
//
// }
public static void main(String[] args) {
QueryExecutionFactory qef =
FluentQueryExecutionFactory
.http("http://dbpedia.org/sparql", "http://dbpedia.org")
.create();
Element a = ParserSPARQL11.parseElement("{ ?s a <http://dbpedia.org/ontology/Museum> }");
Element b = ParserSPARQL11.parseElement("{ ?s <http://dbpedia.org/ontology/location> <http://dbpedia.org/resource/Leipzig> }");
ElementGroup c = new ElementGroup();
c.addElement(a);
c.addElement(b);
// QuadFilterPattern qfp = SparqlCacheUtils.transform(c);
// Map<Quad, CountInfo> map = analyze(qef, qfp, 1000l);
// System.out.println(map);
/*
CountInfo cia = fetchCount(qef, a, null);
System.out.println(cia);
CountInfo cib = fetchCount(qef, b, null);
System.out.println(cib);
CountInfo cic = fetchCount(qef, c, null);
System.out.println(cic);
*/
}
}