001/* 002 * (C) Copyright 2017 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Kevin Leturc 018 */ 019package org.nuxeo.ecm.core.api; 020 021import java.io.Closeable; 022import java.io.IOException; 023import java.util.Iterator; 024 025/** 026 * A cursor result which holds a DB cursor and additional information to scroll this DB cursor. 027 * 028 * @param <C> The cursor type. 029 * @param <O> The cursor item type. 030 * @since 9.1 031 */ 032public class CursorResult<C, O> implements Iterator<O>, Closeable { 033 034 protected C cursor; 035 036 protected final int batchSize; 037 038 protected final int keepAliveSeconds; 039 040 protected long lastCallTimestamp; 041 042 public CursorResult(C cursor, int batchSize, int keepAliveSeconds) { 043 this.cursor = cursor; 044 this.batchSize = batchSize; 045 this.keepAliveSeconds = keepAliveSeconds; 046 this.lastCallTimestamp = System.currentTimeMillis(); 047 } 048 049 public C getCursor() { 050 return cursor; 051 } 052 053 public int getBatchSize() { 054 return batchSize; 055 } 056 057 public void touch() { 058 lastCallTimestamp = System.currentTimeMillis(); 059 } 060 061 public boolean timedOut() { 062 long now = System.currentTimeMillis(); 063 return now - lastCallTimestamp > keepAliveSeconds * 1000; 064 } 065 066 @Override 067 public boolean hasNext() { 068 if (cursor == null) { 069 return false; 070 } else if (cursor instanceof Iterator) { 071 return ((Iterator) cursor).hasNext(); 072 } 073 throw new IllegalStateException( 074 "Cursor doesn't implement Iterator interface, you must provide an implementation of #hasNext and #next method"); 075 } 076 077 @Override 078 @SuppressWarnings("unchecked") 079 public O next() { 080 if (cursor instanceof Iterator) { 081 return ((Iterator<O>) cursor).next(); 082 } 083 throw new IllegalStateException( 084 "Cursor doesn't implement Iterator interface, you must provide an implementation of #hasNext and #next method"); 085 } 086 087 /** 088 * CAUTION: if your cursor doesn't implement {@link Closeable}, we just set the field to null 089 */ 090 @Override 091 public void close() { 092 if (cursor instanceof Closeable) { 093 try { 094 ((Closeable) cursor).close(); 095 } catch (IOException e) { 096 throw new NuxeoException("Unable to close cursor", e); 097 } 098 } 099 cursor = null; 100 } 101 102}