package org.aksw.jena_sparql_api.concept_cache.core;
import java.util.stream.Stream;
import org.aksw.jena_sparql_api.algebra.transform.TransformPushSlice;
import org.aksw.jena_sparql_api.util.RewriteUtils;
import org.aksw.jena_sparql_api.util.collection.RangedSupplier;
import org.aksw.jena_sparql_api.util.collection.StreamUtils;
import org.aksw.jena_sparql_api.utils.QueryUtils;
import org.apache.jena.sparql.algebra.Op;
import org.apache.jena.sparql.algebra.Transformer;
import org.apache.jena.sparql.algebra.op.OpSlice;
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.core.DatasetGraphFactory;
import org.apache.jena.sparql.engine.ExecutionContext;
import org.apache.jena.sparql.engine.QueryIterator;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.engine.iterator.QueryIter;
import org.apache.jena.sparql.engine.iterator.QueryIterRoot;
import org.apache.jena.sparql.engine.main.OpExecutor;
import org.apache.jena.sparql.engine.main.OpExecutorFactory;
import org.apache.jena.sparql.engine.main.QC;
import org.apache.jena.sparql.util.Context;
import com.google.common.collect.Range;
public class RangedSupplierOp
implements RangedSupplier<Long, Binding>, OpAttribute
{
protected Op op;
protected Context context;
public RangedSupplierOp(Op op, Context context) {
super();
this.op = op;
this.context = context;
}
@Override
public Stream<Binding> apply(Range<Long> range) {
long offset = QueryUtils.rangeToOffset(range);
long limit = QueryUtils.rangeToLimit(range);
Op effectiveOp = new OpSlice(op, offset, limit);
// The base op may be a service reference (or some other expression)
// Push down the newly added slice for best performance
//effectiveOp = Transformer.transform(TransformPushSlice.fn, effectiveOp);
// TODO Make this transformation configurable
effectiveOp = RewriteUtils.transformUntilNoChange(effectiveOp, op -> Transformer.transform(TransformPushSlice.fn, op));
QueryIterator it = execute(effectiveOp, context);
Stream<Binding> result = StreamUtils.stream(it);
//ClosableIterator<Binding> result = new IteratorClosable<>(it, () -> it.close());
return result;
}
// @Override
// public <X> X unwrap(Class<X> clazz, boolean reflexive) {
// @SuppressWarnings("unchecked")
// X result = reflexive && this.getClass().isAssignableFrom(clazz)
// ? (X)this
// : null;
//
// return result;
// }
/**
* This is partly a repetition of private functions in QC
* @param op
* @param context
* @return
*/
public static QueryIterator execute(Op op, Context context) {
DatasetGraph dg = DatasetGraphFactory.create();
OpExecutorFactory opExecutorFactory = QC.getFactory(context);
ExecutionContext execCxt = new ExecutionContext(context, dg.getDefaultGraph(), dg, opExecutorFactory);
QueryIter qIter = QueryIterRoot.create(execCxt);
OpExecutor opExecutor = opExecutorFactory.create(execCxt);
QueryIterator result = opExecutor.executeOp(op, qIter);
return result;
}
@Override
public Op getOp() {
return op;
}
}