Line data Source code
1 : // Copyright (C) 2015 The Android Open Source Project
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : package com.google.gerrit.index;
16 :
17 : import static com.google.common.base.Preconditions.checkArgument;
18 :
19 : import com.google.auto.value.AutoValue;
20 : import com.google.common.collect.ImmutableSet;
21 : import com.google.common.primitives.Ints;
22 : import com.google.gerrit.common.Nullable;
23 : import java.util.Set;
24 : import java.util.function.Function;
25 :
26 : @AutoValue
27 151 : public abstract class QueryOptions {
28 : public static QueryOptions create(IndexConfig config, int start, int limit, Set<String> fields) {
29 8 : return create(config, start, null, limit, config.pageSizeMultiplier(), limit, fields);
30 : }
31 :
32 : public static QueryOptions create(
33 : IndexConfig config, int start, int pageSize, int limit, Set<String> fields) {
34 4 : return create(config, start, null, pageSize, config.pageSizeMultiplier(), limit, fields);
35 : }
36 :
37 : public static QueryOptions create(
38 : IndexConfig config,
39 : int start,
40 : int pageSize,
41 : int pageSizeMultiplier,
42 : int limit,
43 : Set<String> fields) {
44 151 : return create(config, start, null, pageSize, pageSizeMultiplier, limit, fields);
45 : }
46 :
47 : public static QueryOptions create(
48 : IndexConfig config,
49 : int start,
50 : Object searchAfter,
51 : int pageSize,
52 : int pageSizeMultiplier,
53 : int limit,
54 : Set<String> fields) {
55 151 : checkArgument(start >= 0, "start must be nonnegative: %s", start);
56 151 : checkArgument(limit > 0, "limit must be positive: %s", limit);
57 151 : if (searchAfter != null) {
58 4 : checkArgument(start == 0, "start must be 0 when searchAfter is specified: %s", start);
59 : }
60 151 : return new AutoValue_QueryOptions(
61 : config,
62 : start,
63 : searchAfter,
64 : pageSize,
65 : pageSizeMultiplier,
66 : limit,
67 151 : ImmutableSet.copyOf(fields));
68 : }
69 :
70 : public QueryOptions convertForBackend() {
71 : // Increase the limit rather than skipping, since we don't know how many
72 : // skipped results would have been filtered out by the enclosing AndSource.
73 151 : int backendLimit = config().maxLimit();
74 151 : int limit = Ints.saturatedCast((long) limit() + start());
75 151 : limit = Math.min(limit, backendLimit);
76 151 : int pageSize = Math.min(Ints.saturatedCast((long) pageSize() + start()), backendLimit);
77 151 : return create(config(), 0, null, pageSize, pageSizeMultiplier(), limit, fields());
78 : }
79 :
80 : public abstract IndexConfig config();
81 :
82 : public abstract int start();
83 :
84 : @Nullable
85 : public abstract Object searchAfter();
86 :
87 : public abstract int pageSize();
88 :
89 : public abstract int pageSizeMultiplier();
90 :
91 : public abstract int limit();
92 :
93 : public abstract ImmutableSet<String> fields();
94 :
95 : public QueryOptions withPageSize(int pageSize) {
96 6 : return create(
97 6 : config(), start(), searchAfter(), pageSize, pageSizeMultiplier(), limit(), fields());
98 : }
99 :
100 : public QueryOptions withLimit(int newLimit) {
101 16 : return create(
102 16 : config(), start(), searchAfter(), pageSize(), pageSizeMultiplier(), newLimit, fields());
103 : }
104 :
105 : public QueryOptions withStart(int newStart) {
106 17 : return create(
107 17 : config(), newStart, searchAfter(), pageSize(), pageSizeMultiplier(), limit(), fields());
108 : }
109 :
110 : public QueryOptions withSearchAfter(Object newSearchAfter) {
111 : // Index search-after APIs don't use 'start', so set it to 0 to be safe. ElasticSearch for
112 : // example, expects it to be 0 when using search-after APIs.
113 4 : return create(
114 4 : config(), start(), newSearchAfter, pageSize(), pageSizeMultiplier(), limit(), fields())
115 4 : .withStart(0);
116 : }
117 :
118 : public QueryOptions filterFields(Function<QueryOptions, Set<String>> filter) {
119 7 : return create(
120 7 : config(),
121 7 : start(),
122 7 : searchAfter(),
123 7 : pageSize(),
124 7 : pageSizeMultiplier(),
125 7 : limit(),
126 7 : filter.apply(this));
127 : }
128 : }
|