1 // Copyright 2008 Google Inc. All Rights Reserved.
2 package com
.google
.appengine
.api
.datastore
;
4 import java
.util
.ArrayList
;
5 import java
.util
.Iterator
;
9 * Describes the limit, offset, and chunk size to be applied when
10 * executing a {@link PreparedQuery}.
12 * {@code limit} is the maximum number of results the query will return.
14 * {@code offset} is the number of results to skip before returning any
15 * results. Results that are skipped due to offset do not count against
17 * <b>Note:</b> Using {@code offset} still retrieves skipped entities internally.
18 * This affects the latency of the query, and <b>your application is billed for the
19 * operations</b> required to retrieve them. Using cursors lets you avoid these costs.
21 * {@code startCursor} and {@code endCursor} are previously generated cursors
22 * that point to locations in a result set. If specified queries will start
23 * and end at these locations.
25 * {@code prefetchSize} is the number of results retrieved on the first call
28 * {@code chunkSize} determines the internal chunking strategy of the
29 * {@link Iterator} returned by {@link PreparedQuery#asIterator(FetchOptions)}
30 * and the {@link Iterable} returned by
31 * {@link PreparedQuery#asIterable(FetchOptions)}.
33 * Note that unlike {@code limit}, {@code offset} and {@code cursor},
34 * {@code prefetchSize} and {@code chunkSize} have no impact on the result of
35 * the {@link PreparedQuery}, but rather only the performance of the
36 * {@link PreparedQuery}.
39 * The recommended way to instantiate a {@code FetchOptions} object is to
40 * statically import {@link Builder}.* and invoke a static
41 * creation method followed by an instance mutator (if needed):
44 * import static com.google.appengine.api.datastore.FetchOptions.Builder.*;
51 * datastoreService.prepare(query).asList(withLimit(10));
53 * // limit 10, start cursor
54 * datastoreService.prepare(query).asList(withLimit(10).startCursor(cursor);
58 public final class FetchOptions
{
60 /** @deprecated Instead of using DEFAULT_CHUNK_SIZE, do not specify a chunk size. */
62 public static final int DEFAULT_CHUNK_SIZE
= 20;
64 private Integer limit
;
65 private Integer offset
;
66 private Integer prefetchSize
;
67 private Integer chunkSize
;
68 private Cursor startCursor
;
69 private Cursor endCursor
;
70 private Boolean compile
;
72 private FetchOptions() {
75 FetchOptions(FetchOptions original
) {
76 this.limit
= original
.limit
;
77 this.offset
= original
.offset
;
78 this.prefetchSize
= original
.prefetchSize
;
79 this.chunkSize
= original
.chunkSize
;
80 this.startCursor
= original
.startCursor
;
81 this.endCursor
= original
.endCursor
;
82 this.compile
= original
.compile
;
86 * Sets the limit. Please read the class javadoc for an explanation of how
88 * @param limit The limit to set. Must be non-negative.
89 * @return {@code this} (for chaining)
91 public FetchOptions
limit(int limit
) {
93 throw new IllegalArgumentException("Limit must be non-negative.");
99 FetchOptions
clearLimit() {
105 * Sets the offset. Please read the class javadoc for an explanation of how
107 * @param offset The offset to set. Must be 0 or greater.
108 * @return {@code this} (for chaining)
110 public FetchOptions
offset(int offset
) {
112 throw new IllegalArgumentException("Offset must be 0 or greater.");
114 this.offset
= offset
;
118 FetchOptions
clearOffset() {
124 * Sets the chunk size. Please read the class javadoc for an explanation of
125 * how chunk size is used.
126 * @param chunkSize The chunk size to set. Must be greater than 0.
127 * @return {@code this} (for chaining)
129 public FetchOptions
chunkSize(int chunkSize
) {
131 throw new IllegalArgumentException("Chunk size must be greater than 0.");
133 this.chunkSize
= chunkSize
;
137 FetchOptions
clearChunkSize() {
143 * Sets the number of entities to prefetch.
144 * @param prefetchSize The prefetch size to set. Must be {@literal >= 0}.
145 * @return {@code this} (for chaining)
147 public FetchOptions
prefetchSize(int prefetchSize
) {
148 if (prefetchSize
< 0) {
149 throw new IllegalArgumentException("Prefetch size must be 0 or greater.");
151 this.prefetchSize
= prefetchSize
;
155 FetchOptions
clearPrefetchSize() {
161 * Sets the cursor to start the query from.
162 * @param cursor the cursor to set
163 * @return {@code this} (for chaining)
164 * @deprecated use {@link #startCursor} instead.
167 public FetchOptions
cursor(Cursor cursor
) {
168 return startCursor(cursor
);
172 * Sets the cursor at which to start the query.
174 * @param startCursor the cursor to set
175 * @return {@code this} (for chaining)
177 public FetchOptions
startCursor(Cursor startCursor
) {
178 if (startCursor
== null) {
179 throw new NullPointerException("start cursor cannot be null.");
181 this.startCursor
= startCursor
;
186 * Sets the cursor at which to end the query.
188 * @param endCursor the cursor to set
189 * @return {@code this} (for chaining)
191 public FetchOptions
endCursor(Cursor endCursor
) {
192 if (endCursor
== null) {
193 throw new NullPointerException("end cursor cannot be null.");
195 this.endCursor
= endCursor
;
199 FetchOptions
clearStartCursor() {
204 FetchOptions
clearEndCursor() {
209 FetchOptions
compile(boolean compile
) {
210 this.compile
= compile
;
214 FetchOptions
clearCompile() {
220 * @return The limit, or {@code null} if no limit was provided.
222 public Integer
getLimit() {
227 * @return The offset, or {@code null} if no offset was provided.
229 public Integer
getOffset() {
234 * @return The chunk size, or {@code null} if no chunk size was provided.
236 public Integer
getChunkSize() {
241 * @return The prefetch size, or {@code null} if no prefetch size was
244 public Integer
getPrefetchSize() {
249 * @return The start cursor, or {@code null} if no cursor was provided.
250 * @deprecated use {@link #getStartCursor()} instead
253 public Cursor
getCursor() {
254 return getStartCursor();
258 * @return The start cursor, or {@code null} if no start cursor was provided.
260 public Cursor
getStartCursor() {
265 * @return The end cursor, or {@code null} if no end cursor was provided.
267 public Cursor
getEndCursor() {
271 Boolean
getCompile() {
276 public int hashCode() {
279 if (prefetchSize
!= null) {
280 result
= result
* 31 + prefetchSize
.hashCode();
283 if (chunkSize
!= null) {
284 result
= result
* 31 + chunkSize
.hashCode();
288 result
= result
* 31 + limit
.hashCode();
291 if (offset
!= null) {
292 result
= result
* 31 + offset
.hashCode();
295 if (startCursor
!= null) {
296 result
= result
* 31 + startCursor
.hashCode();
299 if (endCursor
!= null) {
300 result
= result
* 31 + endCursor
.hashCode();
303 if (compile
!= null) {
304 result
= result
* 31 + compile
.hashCode();
311 public boolean equals(Object obj
) {
316 if (obj
.getClass() != this.getClass()) {
320 FetchOptions that
= (FetchOptions
) obj
;
322 if (prefetchSize
!= null) {
323 if (!prefetchSize
.equals(that
.prefetchSize
)) {
326 } else if (that
.prefetchSize
!= null) {
330 if (chunkSize
!= null) {
331 if (!chunkSize
.equals(that
.chunkSize
)) {
334 } else if (that
.chunkSize
!= null) {
339 if (!limit
.equals(that
.limit
)) {
342 } else if (that
.limit
!= null) {
346 if (offset
!= null) {
347 if (!offset
.equals(that
.offset
)) {
350 } else if (that
.offset
!= null) {
354 if (startCursor
!= null) {
355 if (!startCursor
.equals(that
.startCursor
)) {
358 } else if (that
.startCursor
!= null) {
362 if (endCursor
!= null) {
363 if (!endCursor
.equals(that
.endCursor
)) {
366 } else if (that
.endCursor
!= null) {
370 if (compile
!= null) {
371 if (!compile
.equals(that
.compile
)) {
374 } else if (that
.compile
!= null) {
382 public String
toString() {
383 List
<String
> result
= new ArrayList
<String
>();
385 if (prefetchSize
!= null) {
386 result
.add("prefetchSize=" + prefetchSize
);
389 if (chunkSize
!= null) {
390 result
.add("chunkSize=" + chunkSize
);
394 result
.add("limit=" + limit
);
397 if (offset
!= null) {
398 result
.add("offset=" + offset
);
401 if (startCursor
!= null) {
402 result
.add("startCursor=" + startCursor
);
405 if (endCursor
!= null) {
406 result
.add("endCursor=" + endCursor
);
409 if (compile
!= null) {
410 result
.add("compile=" + compile
);
412 return "FetchOptions" + result
;
416 * Contains static creation methods for {@link FetchOptions}.
418 public static final class Builder
{
421 * Create a {@link FetchOptions} with the given limit. Shorthand for
422 * <code>FetchOptions.withDefaults().limit(...);</code> Please read the
423 * {@link FetchOptions} class javadoc for an explanation of how limit
425 * @param limit the limit to set.
426 * @return The newly created FetchOptions instance.
428 public static FetchOptions
withLimit(int limit
) {
429 return withDefaults().limit(limit
);
433 * Create a {@link FetchOptions} with the given offset. Shorthand for
434 * <code>FetchOptions.withDefaults().offset(...);</code> Please read the
435 * {@link FetchOptions} class javadoc for an explanation of how offset
437 * @param offset the offset to set.
438 * @return The newly created FetchOptions instance.
440 public static FetchOptions
withOffset(int offset
) {
441 return withDefaults().offset(offset
);
445 * Create a {@link FetchOptions} with the given chunk size. Shorthand for
446 * <code>FetchOptions.withDefaults().chunkSize(...);</code> Please read the
447 * {@link FetchOptions} class javadoc for an explanation of how chunk size
449 * @param chunkSize the chunkSize to set.
450 * @return The newly created FetchOptions instance.
452 public static FetchOptions
withChunkSize(int chunkSize
) {
453 return withDefaults().chunkSize(chunkSize
);
457 * Create a {@link FetchOptions} with the given prefetch size.
458 * Shorthand for <code>FetchOptions.withDefaults().prefetchSize(...);</code>.
459 * Please read the {@link FetchOptions} class javadoc for an explanation of
460 * how prefetch size is used.
461 * @param prefetchSize the prefetchSize to set.
462 * @return The newly created FetchOptions instance.
464 public static FetchOptions
withPrefetchSize(int prefetchSize
) {
465 return withDefaults().prefetchSize(prefetchSize
);
469 * Create a {@link FetchOptions} with the given cursor.
470 * Shorthand for <code>FetchOptions.withDefaults().cursor(cursor);</code>.
471 * Please read the {@link FetchOptions} class javadoc for an explanation of
472 * how cursors are used.
473 * @param cursor the cursor to set.
474 * @return The newly created FetchOptions instance.
475 * @deprecated use {@link #withStartCursor} instead.
478 public static FetchOptions
withCursor(Cursor cursor
) {
479 return withStartCursor(cursor
);
483 * Create a {@link FetchOptions} with the given start cursor.
484 * Shorthand for <code>FetchOptions.withDefaults().startCursor(cursor);</code>.
485 * Please read the {@link FetchOptions} class javadoc for an explanation of
486 * how cursors are used.
487 * @param startCursor the cursor to set.
488 * @return The newly created FetchOptions instance.
490 public static FetchOptions
withStartCursor(Cursor startCursor
) {
491 return withDefaults().startCursor(startCursor
);
495 * Create a {@link FetchOptions} with the given end cursor.
496 * Shorthand for <code>FetchOptions.withDefaults().endCursor(cursor);</code>.
497 * Please read the {@link FetchOptions} class javadoc for an explanation of
498 * how cursors are used.
499 * @param endCursor the cursor to set.
500 * @return The newly created FetchOptions instance.
502 public static FetchOptions
withEndCursor(Cursor endCursor
) {
503 return withDefaults().endCursor(endCursor
);
507 * Helper method for creating a {@link FetchOptions} instance with
508 * default values. The defaults are {@code null} for all values.
510 public static FetchOptions
withDefaults() {
511 return new FetchOptions();