summaryrefslogtreecommitdiff
path: root/src/main/java/com/amazon/carbonado/Cursor.java
blob: 00b2dbc138274e0d284b4207f48ef008444ebd2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
 * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
 * of Amazon Technologies, Inc. or its affiliates.  All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.amazon.carbonado;

import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * Represents the results of a {@link com.amazon.carbonado.Query}'s fetch
 * operation. Cursors must be closed promptly when no longer
 * needed. Failure to do so may result in excessive resource consumption or
 * deadlock. As a convenience, the close operation is automatically performed
 * when the end is reached or when an exception is thrown.
 *
 * <P>Note: because a Cursor manages resources, it is inapproprate to create a long-lived one and
 * pass it around in your code.  A cursor is expected to live close to the Query which vended
 * it.  To discourage inappropriate retention, the cursor does not implement methods (like
 * "getQuery" or "reset") which would make it more convenient to operate on in isolation.
 *
 * <P>Similarly, it is difficult to guarantee that the results of a cursor will
 * be the same in case of a "reset" or reverse iteration.  For this reason,
 * neither is supported; if you need to iterate the same set of objects twice,
 * simply retain the query object and reissue it. Be aware that the results may
 * not be identical, if any relevant objects are added to or removed the
 * repository in the interim. To guard against this, operate within a
 * serializable {@link IsolationLevel isolation level}.
 *
 * <p>Cursor instances are mutable, but they should be thread-safe. Still, only
 * one thread should ever operate on a cursor instance.
 *
 * @author Brian S O'Neill
 * @author Don Schneider
 */
public interface Cursor<S> {
    /**
     * Call close to release any resources being held by this cursor. Further
     * operations on this cursor will behave as if there are no results.
     */
    void close() throws FetchException;

    /**
     * Returns true if this cursor has more elements. In other words, returns
     * true if {@link #next next} would return an element rather than throwing
     * an exception.
     *
     * @throws FetchException if storage layer throws an exception
     */
    boolean hasNext() throws FetchException;

    /**
     * Returns the next element from this cursor. This method may be called
     * repeatedly to iterate through the results.
     *
     * @throws FetchException if storage layer throws an exception
     * @throws NoSuchElementException if the cursor has no next element.
     */
    S next() throws FetchException;

    /**
     * Skips forward by the specified amount of elements, returning the actual
     * amount skipped. The actual amount may be less than the requested amount
     * if the end of the results was reached.
     *
     * @param amount maximum amount of elements to skip
     * @return actual amount skipped
     * @throws FetchException if storage layer throws an exception
     * @throws IllegalArgumentException if amount is negative
     */
    int skipNext(int amount) throws FetchException;

    /**
     * Copies all remaining next elements into the given collection. This
     * method is roughly equivalent to the following:
     * <pre>
     * Cursor cursor;
     * ...
     * while (cursor.hasNext()) {
     *     c.add(cursor.next());
     * }
     * </pre>
     *
     * <p>As a side-effect of calling this method, the cursor is closed.
     *
     * @return actual amount of results added
     * @throws FetchException if storage layer throws an exception
     */
    int copyInto(Collection<? super S> c) throws FetchException;

    /**
     * Copies a limited amount of remaining next elements into the given
     * collection. This method is roughly equivalent to the following:
     * <pre>
     * Cursor cursor;
     * ...
     * while (--limit >= 0 && cursor.hasNext()) {
     *     c.add(cursor.next());
     * }
     * </pre>
     *
     * @param limit maximum amount of elements to copy
     * @return actual amount of results added
     * @throws FetchException if storage layer throws an exception
     * @throws IllegalArgumentException if limit is negative
     */
    int copyInto(Collection<? super S> c, int limit) throws FetchException;

    /**
     * Copies all remaining next elements into a new modifiable list. This
     * method is roughly equivalent to the following:
     * <pre>
     * Cursor&lt;S&gt; cursor;
     * ...
     * List&lt;S&gt; list = new ...
     * cursor.copyInto(list);
     * </pre>
     *
     * <p>As a side-effect of calling this method, the cursor is closed.
     *
     * @return a new modifiable list
     * @throws FetchException if storage layer throws an exception
     */
    List<S> toList() throws FetchException;

    /**
     * Copies a limited amount of remaining next elements into a new modifiable
     * list. This method is roughly equivalent to the following:
     * <pre>
     * Cursor&lt;S&gt; cursor;
     * ...
     * List&lt;S&gt; list = new ...
     * cursor.copyInto(list, limit);
     * </pre>
     *
     * @param limit maximum amount of elements to copy
     * @return a new modifiable list
     * @throws FetchException if storage layer throws an exception
     * @throws IllegalArgumentException if limit is negative
     */
    List<S> toList(int limit) throws FetchException;
}