View Javadoc
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 &lt;major&gt;.&lt;minor&gt;.&lt;bugfix&gt;) 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 &lt;major&gt;.&lt;minor&gt;.&lt;bugfix&gt;)
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 }