View Javadoc
1   /*
2   Copyright (c) 2013 James Ahlborn
3   
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7   
8       http://www.apache.org/licenses/LICENSE-2.0
9   
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15  */
16  
17  package com.healthmarketscience.jackcess;
18  
19  import java.io.IOException;
20  import java.util.Collection;
21  import java.util.Iterator;
22  import java.util.Map;
23  
24  import com.healthmarketscience.jackcess.util.ColumnMatcher;
25  import com.healthmarketscience.jackcess.util.ErrorHandler;
26  import com.healthmarketscience.jackcess.util.IterableBuilder;
27  
28  /**
29   * Manages iteration for a {@link Table}.  Different cursors provide different
30   * methods of traversing a table.  Cursors should be fairly robust in the face
31   * of table modification during traversal (although depending on how the table
32   * is traversed, row updates may or may not be seen).  Multiple cursors may
33   * traverse the same table simultaneously.
34   * <p/>
35   * Basic cursors will generally iterate table data in the order it appears in
36   * the database and searches will require scanning the entire table.
37   * Additional features are available when utilizing an {@link Index} backed
38   * {@link IndexCursor}.
39   * <p>
40   * The {@link CursorBuilder} provides a variety of static utility methods to
41   * construct cursors with given characteristics or easily search for specific
42   * values as well as friendly and flexible construction options.
43   * <p>
44   * A Cursor instance is not thread-safe (see {@link Database} for more
45   * thread-safety details).
46   *
47   * @author James Ahlborn
48   * @usage _general_class_
49   */
50  public interface Cursor extends Iterable<Row>
51  {
52  
53    public Id getId();
54  
55    public Table getTable();
56  
57    /**
58     * Gets the currently configured ErrorHandler (always non-{@code null}).
59     * This will be used to handle all errors.
60     */
61    public ErrorHandler getErrorHandler();
62  
63    /**
64     * Sets a new ErrorHandler.  If {@code null}, resets to using the
65     * ErrorHandler configured at the Table level.
66     */
67    public void setErrorHandler(ErrorHandler newErrorHandler);
68  
69    /**
70     * Returns the currently configured ColumnMatcher, always non-{@code null}.
71     */
72    public ColumnMatcher getColumnMatcher();
73  
74    /**
75     * Sets a new ColumnMatcher.  If {@code null}, resets to using the default
76     * matcher (default depends on Cursor type).
77     */
78    public void setColumnMatcher(ColumnMatcher columnMatcher);
79  
80    /**
81     * Returns the current state of the cursor which can be restored at a future
82     * point in time by a call to {@link #restoreSavepoint}.
83     * <p>
84     * Savepoints may be used across different cursor instances for the same
85     * table, but they must have the same {@link Id}.
86     */
87    public Savepoint getSavepoint();
88  
89    /**
90     * Moves the cursor to a savepoint previously returned from
91     * {@link #getSavepoint}.
92     * @throws IllegalArgumentException if the given savepoint does not have a
93     *         cursorId equal to this cursor's id
94     */
95    public void restoreSavepoint(Savepoint savepoint)
96      throws IOException;
97  
98    /**
99     * Resets this cursor for forward traversal.  Calls {@link #beforeFirst}.
100    */
101   public void reset();
102 
103   /**
104    * Resets this cursor for forward traversal (sets cursor to before the first
105    * row).
106    */
107   public void beforeFirst();
108 
109   /**
110    * Resets this cursor for reverse traversal (sets cursor to after the last
111    * row).
112    */
113   public void afterLast();
114 
115   /**
116    * Returns {@code true} if the cursor is currently positioned before the
117    * first row, {@code false} otherwise.
118    */
119   public boolean isBeforeFirst() throws IOException;
120 
121   /**
122    * Returns {@code true} if the cursor is currently positioned after the
123    * last row, {@code false} otherwise.
124    */
125   public boolean isAfterLast() throws IOException;
126 
127   /**
128    * Returns {@code true} if the row at which the cursor is currently
129    * positioned is deleted, {@code false} otherwise (including invalid rows).
130    */
131   public boolean isCurrentRowDeleted() throws IOException;
132 
133   /**
134    * Calls {@link #beforeFirst} on this cursor and returns a modifiable
135    * Iterator which will iterate through all the rows of this table.  Use of
136    * the Iterator follows the same restrictions as a call to
137    * {@link #getNextRow}.
138    * <p/>
139    * For more flexible iteration see {@link #newIterable}.
140    * @throws RuntimeIOException if an IOException is thrown by one of the
141    *         operations, the actual exception will be contained within
142    */
143   public Iterator<Row> iterator();
144 
145   /**
146    * Convenience method for constructing a new IterableBuilder for this
147    * cursor.  An IterableBuilder provides a variety of options for more
148    * flexible iteration.
149    */
150   public IterableBuilder newIterable();
151 
152   /**
153    * Delete the current row.
154    * <p/>
155    * Note, re-deleting an already deleted row is allowed (it does nothing).
156    * @throws IllegalStateException if the current row is not valid (at
157    *         beginning or end of table)
158    */
159   public void deleteCurrentRow() throws IOException;
160 
161   /**
162    * Update the current row.
163    * @return the given row values if long enough, otherwise a new array,
164    *         updated with the current row values
165    * @throws IllegalStateException if the current row is not valid (at
166    *         beginning or end of table), or deleted.
167    */
168   public Object[] updateCurrentRow(Object... row) throws IOException;
169 
170   /**
171    * Update the current row.
172    * @return the given row, updated with the current row values
173    * @throws IllegalStateException if the current row is not valid (at
174    *         beginning or end of table), or deleted.
175    */
176   public <M extends Map<String,Object>> M updateCurrentRowFromMap(M row) 
177     throws IOException;
178 
179   /**
180    * Moves to the next row in the table and returns it.
181    * @return The next row in this table (Column name -> Column value), or
182    *         {@code null} if no next row is found
183    */
184   public Row getNextRow() throws IOException;
185 
186   /**
187    * Moves to the next row in the table and returns it.
188    * @param columnNames Only column names in this collection will be returned
189    * @return The next row in this table (Column name -> Column value), or
190    *         {@code null} if no next row is found
191    */
192   public Row getNextRow(Collection<String> columnNames) 
193     throws IOException;
194 
195   /**
196    * Moves to the previous row in the table and returns it.
197    * @return The previous row in this table (Column name -> Column value), or
198    *         {@code null} if no previous row is found
199    */
200   public Row getPreviousRow() throws IOException;
201 
202   /**
203    * Moves to the previous row in the table and returns it.
204    * @param columnNames Only column names in this collection will be returned
205    * @return The previous row in this table (Column name -> Column value), or
206    *         {@code null} if no previous row is found
207    */
208   public Row getPreviousRow(Collection<String> columnNames) 
209     throws IOException;
210 
211   /**
212    * Moves to the next row as defined by this cursor.
213    * @return {@code true} if a valid next row was found, {@code false}
214    *         otherwise
215    */
216   public boolean moveToNextRow() throws IOException;
217 
218   /**
219    * Moves to the previous row as defined by this cursor.
220    * @return {@code true} if a valid previous row was found, {@code false}
221    *         otherwise
222    */
223   public boolean moveToPreviousRow() throws IOException;
224   
225   /**
226    * Moves to the row with the given rowId.  If the row is not found (or an
227    * exception is thrown), the cursor is restored to its previous state.
228    * 
229    * @return {@code true} if a valid row was found with the given id,
230    *         {@code false} if no row was found
231    */
232   public boolean findRow(RowId rowId) throws IOException;
233 
234   /**
235    * Moves to the first row (as defined by the cursor) where the given column
236    * has the given value.  This may be more efficient on some cursors than
237    * others.  If a match is not found (or an exception is thrown), the cursor
238    * is restored to its previous state.
239    * <p>
240    * Warning, this method <i>always</i> starts searching from the beginning of
241    * the Table (you cannot use it to find successive matches).
242    *
243    * @param columnPattern column from the table for this cursor which is being
244    *                      matched by the valuePattern
245    * @param valuePattern value which is equal to the corresponding value in
246    *                     the matched row
247    * @return {@code true} if a valid row was found with the given value,
248    *         {@code false} if no row was found
249    */
250   public boolean findFirstRow(Column columnPattern, Object valuePattern)
251     throws IOException;
252 
253   /**
254    * Moves to the next row (as defined by the cursor) where the given column
255    * has the given value.  This may be more efficient on some cursors than
256    * others.  If a match is not found (or an exception is thrown), the cursor
257    * is restored to its previous state.
258    *
259    * @param columnPattern column from the table for this cursor which is being
260    *                      matched by the valuePattern
261    * @param valuePattern value which is equal to the corresponding value in
262    *                     the matched row
263    * @return {@code true} if a valid row was found with the given value,
264    *         {@code false} if no row was found
265    */
266   public boolean findNextRow(Column columnPattern, Object valuePattern)
267     throws IOException;
268 
269   /**
270    * Moves to the first row (as defined by the cursor) where the given columns
271    * have the given values.  This may be more efficient on some cursors than
272    * others.  If a match is not found (or an exception is thrown), the cursor
273    * is restored to its previous state.
274    * <p>
275    * Warning, this method <i>always</i> starts searching from the beginning of
276    * the Table (you cannot use it to find successive matches).
277    *
278    * @param rowPattern column names and values which must be equal to the
279    *                   corresponding values in the matched row
280    * @return {@code true} if a valid row was found with the given values,
281    *         {@code false} if no row was found
282    */
283   public boolean findFirstRow(Map<String,?> rowPattern) throws IOException;
284 
285   /**
286    * Moves to the next row (as defined by the cursor) where the given columns
287    * have the given values.  This may be more efficient on some cursors than
288    * others.  If a match is not found (or an exception is thrown), the cursor
289    * is restored to its previous state.
290    *
291    * @param rowPattern column names and values which must be equal to the
292    *                   corresponding values in the matched row
293    * @return {@code true} if a valid row was found with the given values,
294    *         {@code false} if no row was found
295    */
296   public boolean findNextRow(Map<String,?> rowPattern) throws IOException;
297 
298   /**
299    * Returns {@code true} if the current row matches the given pattern.
300    * @param columnPattern column from the table for this cursor which is being
301    *                      matched by the valuePattern
302    * @param valuePattern value which is tested for equality with the
303    *                     corresponding value in the current row
304    */
305   public boolean currentRowMatches(Column columnPattern, Object valuePattern)
306     throws IOException;
307 
308   /**
309    * Returns {@code true} if the current row matches the given pattern.
310    * @param rowPattern column names and values which must be equal to the
311    *                   corresponding values in the current row
312    */
313   public boolean currentRowMatches(Map<String,?> rowPattern) throws IOException;
314 
315   /**
316    * Moves forward as many rows as possible up to the given number of rows.
317    * @return the number of rows moved.
318    */
319   public int moveNextRows(int numRows) throws IOException;
320 
321   /**
322    * Moves backward as many rows as possible up to the given number of rows.
323    * @return the number of rows moved.
324    */
325   public int movePreviousRows(int numRows) throws IOException;
326 
327   /**
328    * Returns the current row in this cursor (Column name -> Column value).
329    */
330   public Row getCurrentRow() throws IOException;
331 
332   /**
333    * Returns the current row in this cursor (Column name -> Column value).
334    * @param columnNames Only column names in this collection will be returned
335    */
336   public Row getCurrentRow(Collection<String> columnNames)
337     throws IOException;
338 
339   /**
340    * Returns the given column from the current row.
341    */
342   public Object getCurrentRowValue(Column column) throws IOException;
343 
344   /**
345    * Updates a single value in the current row.
346    * @throws IllegalStateException if the current row is not valid (at
347    *         beginning or end of table), or deleted.
348    */
349   public void setCurrentRowValue(Column column, Object value)
350     throws IOException;
351 
352   /**
353    * Identifier for a cursor.  Will be equal to any other cursor of the same
354    * type for the same table.  Primarily used to check the validity of a
355    * Savepoint.
356    */
357   public interface Id
358   {    
359   }
360 
361   /**
362    * Value object which maintains the current position of the cursor.
363    */
364   public interface Position
365   {    
366     /**
367      * Returns the unique RowId of the position of the cursor.
368      */
369     public RowId getRowId();
370   }
371 
372   /**
373    * Value object which represents a complete save state of the cursor.
374    * Savepoints are created by calling {@link Cursor#getSavepoint} and used by
375    * calling {@link Cursor#restoreSavepoint} to return the the cursor state at
376    * the time the Savepoint was created.
377    */
378   public interface Savepoint
379   {
380     public Id getCursorId();
381 
382     public Position getCurrentPosition();
383   }
384 
385 }