private <T> SienaFuture<Iterable<T>> doFetchIterable(QueryAsync<T> query, int limit, int offset)
{
QueryOptionGaeContext gaeCtx = (QueryOptionGaeContext)query.option(QueryOptionGaeContext.ID);
QueryOptionState state = (QueryOptionState)query.option(QueryOptionState.ID);
QueryOptionFetchType fetchType = (QueryOptionFetchType)query.option(QueryOptionFetchType.ID);
if(gaeCtx==null){
gaeCtx = new QueryOptionGaeContext();
query.customize(gaeCtx);
}
FetchOptions fetchOptions = FetchOptions.Builder.withDefaults();
QueryOptionPage pag = (QueryOptionPage)query.option(QueryOptionPage.ID);
if(!pag.isPaginating()){
// no pagination but pageOption active
if(pag.isActive()){
// if local limit is set, it overrides the pageOption.pageSize
if(limit!=Integer.MAX_VALUE){
gaeCtx.realPageSize = limit;
fetchOptions.limit(gaeCtx.realPageSize);
// pageOption is passivated to be sure it is not reused
pag.passivate();
}
// using pageOption.pageSize
else {
gaeCtx.realPageSize = pag.pageSize;
fetchOptions.limit(gaeCtx.realPageSize);
// passivates the pageOption in stateless mode not to keep anything between 2 requests
if(state.isStateless()){
pag.passivate();
}
}
}
else {
if(limit != Integer.MAX_VALUE){
gaeCtx.realPageSize = limit;
fetchOptions.limit(gaeCtx.realPageSize);
}
}
}else {
// paginating so use the pagesize and don't passivate pageOption
// local limit is not taken into account
gaeCtx.realPageSize = pag.pageSize;
fetchOptions.limit(gaeCtx.realPageSize);
}
QueryOptionOffset off = (QueryOptionOffset)query.option(QueryOptionOffset.ID);
// if local offset has been set, uses it
if(offset!=0){
off.activate();
off.offset = offset;
}
// if previousPage has detected there is no more data, simply returns an empty list
if(gaeCtx.noMoreDataBefore){
return new SienaFutureMock<Iterable<T>>(new ArrayList<T>());
}
if(state.isStateless()) {
if(pag.isPaginating()){
if(off.isActive()){
gaeCtx.realOffset+=off.offset;
fetchOptions.offset(gaeCtx.realOffset);
off.passivate();