package org.aksw.jena_sparql_api.pagination.core;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.aksw.commons.collections.PrefetchIterator;
import org.aksw.jena_sparql_api.core.QueryExecutionFactory;
import org.aksw.jena_sparql_api.core.ResultSetCloseable;
import org.aksw.jena_sparql_api.utils.CloseableQueryExecution;
import org.apache.jena.atlas.lib.Closeable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.engine.iterator.QueryIteratorResultSet;
/*
class ConstructPaginated
extends PrefetchIterator<Statement>
{
private Sparqler sparqler;
private PaginationQueryIterator state;
public ConstructPaginated(Sparqler sparqler, String queryString, long pageSize) {
this(sparqler, QueryFactory.create(queryString), pageSize);
}
public ConstructPaginated(Sparqler sparqler, Query query, long pageSize) {
this.sparqler = sparqler;
this.state = new PaginationQueryIterator(query, pageSize);
}
@Override
protected Iterator<Statement> prefetch() throws Exception {
Query query = state.next();
if(query == null) {
return null;
}
Model model = ModelFactory.createDefaultModel();
return sparqler.executeConstruct(model, query).listStatements();
}
}
*/
public class ResultSetPaginated
extends PrefetchIterator<Binding>
implements Closeable
{
private static Logger logger = LoggerFactory.getLogger(ResultSetPaginated.class);
private QueryExecutionFactory serviceFactory;
//private QueryExecutionIterated execution;
private Iterator<Query> queryIterator;
private boolean stopOnEmptyResult = true;
private ResultSet currentResultSet = null;
private QueryExecution currentExecution = null;
// A cache of the resultVars of the current resultSet
// This is needed, because we might empty result sets might close immediately before we
// have a change to access their metadata (i.e. the result vars)
// Jene even raises an exception when calling getResultVars() on a closed result set.
private List<String> currentResultVars = null;
/*
public ResultSetPaginated(QueryExecutionIterated execution,QueryExecutionFactory service, Iterator<Query> queryIterator) {
this(execution, service, QueryFactory.create(queryString),);
}
*/
public ResultSetPaginated(QueryExecutionFactory service, Iterator<Query> queryIterator, boolean stopOnEmptyResult) {
//this.execution = execution;
this.serviceFactory = service;
//this.state = new PaginationQueryIterator(query, pageSize);
this.queryIterator = queryIterator;
}
public ResultSet getCurrentResultSet() {
return currentResultSet;
}
public List<String> getCurrentResultVars() {
return currentResultVars;
}
@Override
protected QueryIteratorResultSet prefetch() throws Exception {
while(queryIterator.hasNext()) {
Query query = queryIterator.next();
if(query == null) {
throw new RuntimeException("Null query encountered in iterator");
}
final QueryExecution qe = serviceFactory.createQueryExecution(query);
logger.trace("Executing: " + query);
// TODO Virtuoso sometimes yields invalid XML (probably due to encoding issues) and thus execSelect fails
// Should this happen, we could try to recover by
// doing a binary partitioning of the current query range, and try to locate the bindings causing the error
currentResultSet = qe.execSelect();
//currentResultVars = new ArrayList<String>(currentResultSet.getResultVars());
currentResultVars = currentResultSet.getResultVars();
currentResultSet = new ResultSetCloseable(currentResultSet, new CloseableQueryExecution(qe));
if(!currentResultSet.hasNext()) {
if(stopOnEmptyResult) {
break;
}
continue;
}
return new QueryIteratorResultSet(currentResultSet);
}
return null;
}
@Override
public void close() {
if(currentExecution != null) {
currentExecution.close();
}
/*
if(execution != null) {
execution.close();
}
*/
}
}