1 /*
2 * #%L
3 * Distinct.java - mongodb-async-driver - Allanbank Consulting, Inc.
4 * %%
5 * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6 * %%
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * #L%
19 */
20
21 package com.allanbank.mongodb.builder;
22
23 import static com.allanbank.mongodb.util.Assertions.assertNotEmpty;
24
25 import java.util.concurrent.TimeUnit;
26
27 import com.allanbank.mongodb.MongoCollection;
28 import com.allanbank.mongodb.ReadPreference;
29 import com.allanbank.mongodb.Version;
30 import com.allanbank.mongodb.bson.Document;
31 import com.allanbank.mongodb.bson.DocumentAssignable;
32
33 /**
34 * Distinct provides container for all of the options to a <tt>distinct</tt>
35 * command. A {@link Builder} is provided to assist in creating a
36 * {@link Distinct}.
37 *
38 * @api.yes This class is part of the driver's API. Public and protected members
39 * will be deprecated for at least 1 non-bugfix release (version
40 * numbers are <major>.<minor>.<bugfix>) before being
41 * removed or modified.
42 * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved
43 */
44 public class Distinct {
45 /**
46 * The first version of MongoDB to support the {@code distinct} command with
47 * the ability to limit the execution time on the server.
48 */
49 public static final Version MAX_TIMEOUT_VERSION = Find.MAX_TIMEOUT_VERSION;
50
51 /**
52 * Creates a new builder for a {@link Distinct}.
53 *
54 * @return The builder to construct a {@link Distinct}.
55 */
56 public static Builder builder() {
57 return new Builder();
58 }
59
60 /** The name of the key to collect distinct values for. */
61 private final String myKey;
62
63 /** The maximum amount of time to allow the command to run. */
64 private final long myMaximumTimeMilliseconds;
65
66 /** The query to select document to perform a distinct query across. */
67 private final Document myQuery;
68
69 /** The read preference to use. */
70 private final ReadPreference myReadPreference;
71
72 /**
73 * Creates a new Distinct.
74 *
75 * @param builder
76 * The builder to copy the state from.
77 * @throws IllegalArgumentException
78 * If neither the {@link #getKey() key} is <code>null</code> or
79 * empty.
80 */
81 protected Distinct(final Builder builder) {
82 assertNotEmpty(builder.myKey,
83 "The distinct's command key cannot be null or empty.");
84
85 myKey = builder.myKey;
86 myQuery = builder.myQuery;
87 myReadPreference = builder.myReadPreference;
88 myMaximumTimeMilliseconds = builder.myMaximumTimeMilliseconds;
89 }
90
91 /**
92 * Returns the name of the key to collect distinct values for.
93 *
94 * @return The name of the key to collect distinct values for.
95 */
96 public String getKey() {
97 return myKey;
98 }
99
100 /**
101 * Returns the maximum amount of time to allow the command to run on the
102 * Server before it is aborted.
103 *
104 * @return The maximum amount of time to allow the command to run on the
105 * Server before it is aborted.
106 *
107 * @since MongoDB 2.6
108 */
109 public long getMaximumTimeMilliseconds() {
110 return myMaximumTimeMilliseconds;
111 }
112
113 /**
114 * Returns the query to select the documents to run the distinct against.
115 *
116 * @return The query to select the documents to run the distinct against.
117 */
118 public Document getQuery() {
119 return myQuery;
120 }
121
122 /**
123 * Returns the {@link ReadPreference} specifying which servers may be used
124 * to execute the {@link Distinct} command.
125 * <p>
126 * If <code>null</code> then the {@link MongoCollection} instance's
127 * {@link ReadPreference} will be used.
128 * </p>
129 *
130 * @return The read preference to use.
131 *
132 * @see MongoCollection#getReadPreference()
133 */
134 public ReadPreference getReadPreference() {
135 return myReadPreference;
136 }
137
138 /**
139 * Builder provides support for creating a {@link Distinct} object.
140 *
141 * @api.yes This class is part of the driver's API. Public and protected
142 * members will be deprecated for at least 1 non-bugfix release
143 * (version numbers are <major>.<minor>.<bugfix>)
144 * before being removed or modified.
145 * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved
146 */
147 public static class Builder {
148
149 /** The name of the key to collect distinct values for. */
150 protected String myKey;
151
152 /** The maximum amount of time to allow the command to run. */
153 protected long myMaximumTimeMilliseconds;
154
155 /** The query to select document to perform a distinct query across. */
156 protected Document myQuery;
157
158 /** The read preference to use. */
159 protected ReadPreference myReadPreference;
160
161 /**
162 * Creates a new Builder.
163 */
164 public Builder() {
165 reset();
166 }
167
168 /**
169 * Creates a new {@link GroupBy} based on the current state of the
170 * builder.
171 *
172 * @return A new {@link GroupBy} based on the current state of the
173 * builder.
174 * @throws IllegalArgumentException
175 * If neither the {@link #setKey key} is <code>null</code>
176 * or empty.
177 */
178 public Distinct build() throws IllegalArgumentException {
179 return new Distinct(this);
180 }
181
182 /**
183 * Sets the name of the key to collect distinct values for.
184 * <p>
185 * This method delegates to {@link #setKey(String)}.
186 * </p>
187 *
188 * @param key
189 * The new name of the key to collect distinct values for.
190 * @return This {@link Builder} for method call chaining.
191 */
192 public Builder key(final String key) {
193 return setKey(key);
194 }
195
196 /**
197 * Sets the maximum number of milliseconds to allow the command to run
198 * before aborting the request on the server.
199 * <p>
200 * This method equivalent to {@link #setMaximumTimeMilliseconds(long)
201 * setMaximumTimeMilliseconds(timeLimitUnits.toMillis(timeLimit)}.
202 * </p>
203 *
204 * @param timeLimit
205 * The new maximum amount of time to allow the command to
206 * run.
207 * @param timeLimitUnits
208 * The units for the maximum amount of time to allow the
209 * command to run.
210 *
211 * @return This {@link Builder} for method call chaining.
212 *
213 * @since MongoDB 2.6
214 */
215 public Builder maximumTime(final long timeLimit,
216 final TimeUnit timeLimitUnits) {
217 return setMaximumTimeMilliseconds(timeLimitUnits
218 .toMillis(timeLimit));
219 }
220
221 /**
222 * Sets the value of the query to select the documents to run the
223 * distinct against.
224 * <p>
225 * This method delegates to {@link #setQuery(DocumentAssignable)}.
226 * </p>
227 *
228 * @param query
229 * The new value for the query to select the documents to run
230 * the distinct against.
231 * @return This {@link Builder} for method call chaining.
232 */
233 public Builder query(final DocumentAssignable query) {
234 return setQuery(query);
235 }
236
237 /**
238 * Sets the {@link ReadPreference} specifying which servers may be used
239 * to execute the {@link Distinct} command.
240 * <p>
241 * If not set or set to <code>null</code> then the
242 * {@link MongoCollection} instance's {@link ReadPreference} will be
243 * used.
244 * </p>
245 * <p>
246 * This method delegates to {@link #setReadPreference(ReadPreference)}.
247 * </p>
248 *
249 * @param readPreference
250 * The read preferences specifying which servers may be used.
251 * @return This builder for chaining method calls.
252 *
253 * @see MongoCollection#getReadPreference()
254 */
255 public Builder readPreference(final ReadPreference readPreference) {
256 return setReadPreference(readPreference);
257 }
258
259 /**
260 * Resets the builder back to its initial state.
261 *
262 * @return This {@link Builder} for method call chaining.
263 */
264 public Builder reset() {
265 myKey = null;
266 myQuery = null;
267 myReadPreference = null;
268 myMaximumTimeMilliseconds = 0;
269
270 return this;
271 }
272
273 /**
274 * Sets the name of the key to collect distinct values for.
275 *
276 * @param key
277 * The new name of the key to collect distinct values for.
278 * @return This {@link Builder} for method call chaining.
279 */
280 public Builder setKey(final String key) {
281 myKey = key;
282 return this;
283 }
284
285 /**
286 * Sets the maximum number of milliseconds to allow the command to run
287 * before aborting the request on the server.
288 *
289 * @param maximumTimeMilliseconds
290 * The new maximum number of milliseconds to allow the
291 * command to run.
292 * @return This {@link Builder} for method call chaining.
293 *
294 * @since MongoDB 2.6
295 */
296 public Builder setMaximumTimeMilliseconds(
297 final long maximumTimeMilliseconds) {
298 myMaximumTimeMilliseconds = maximumTimeMilliseconds;
299 return this;
300 }
301
302 /**
303 * Sets the value of the query to select the documents to run the
304 * distinct against.
305 *
306 * @param query
307 * The new value for the query to select the documents to run
308 * the distinct against.
309 * @return This {@link Builder} for method call chaining.
310 */
311 public Builder setQuery(final DocumentAssignable query) {
312 myQuery = query.asDocument();
313 return this;
314 }
315
316 /**
317 * Sets the {@link ReadPreference} specifying which servers may be used
318 * to execute the {@link Distinct} command.
319 * <p>
320 * If not set or set to <code>null</code> then the
321 * {@link MongoCollection} instance's {@link ReadPreference} will be
322 * used.
323 * </p>
324 *
325 * @param readPreference
326 * The read preferences specifying which servers may be used.
327 * @return This builder for chaining method calls.
328 *
329 * @see MongoCollection#getReadPreference()
330 */
331 public Builder setReadPreference(final ReadPreference readPreference) {
332 myReadPreference = readPreference;
333 return this;
334 }
335 }
336 }