Coverage Report - com.allanbank.mongodb.builder.GroupBy
 
Classes in this File Line Coverage Branch Coverage Complexity
GroupBy
100%
21/21
100%
4/4
1.069
GroupBy$Builder
100%
40/40
100%
2/2
1.069
 
 1  
 /*
 2  
  * #%L
 3  
  * GroupBy.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.assertThat;
 24  
 
 25  
 import java.util.Collections;
 26  
 import java.util.HashSet;
 27  
 import java.util.Set;
 28  
 import java.util.concurrent.TimeUnit;
 29  
 
 30  
 import com.allanbank.mongodb.MongoCollection;
 31  
 import com.allanbank.mongodb.ReadPreference;
 32  
 import com.allanbank.mongodb.Version;
 33  
 import com.allanbank.mongodb.bson.Document;
 34  
 import com.allanbank.mongodb.bson.DocumentAssignable;
 35  
 
 36  
 /**
 37  
  * Group provides a container for all of the options to a <tt>group</tt>
 38  
  * command. A {@link Builder} is provided to assist in creating a
 39  
  * {@link GroupBy}.
 40  
  * 
 41  
  * @api.yes This class is part of the driver's API. Public and protected members
 42  
  *          will be deprecated for at least 1 non-bugfix release (version
 43  
  *          numbers are &lt;major&gt;.&lt;minor&gt;.&lt;bugfix&gt;) before being
 44  
  *          removed or modified.
 45  
  * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved
 46  
  */
 47  
 public class GroupBy {
 48  
     /**
 49  
      * The first version of MongoDB to support the {@code group} command with
 50  
      * the ability to limit the execution time on the server.
 51  
      */
 52  1
     public static final Version MAX_TIMEOUT_VERSION = Find.MAX_TIMEOUT_VERSION;
 53  
 
 54  
     /**
 55  
      * Creates a new builder for a {@link GroupBy}.
 56  
      * 
 57  
      * @return The builder to construct a {@link GroupBy}.
 58  
      */
 59  
     public static Builder builder() {
 60  4
         return new Builder();
 61  
     }
 62  
 
 63  
     /** The finalizer function to run for each group. */
 64  
     private final String myFinalizeFunction;
 65  
 
 66  
     /** The initial value for each group. */
 67  
     private final Document myInitialValue;
 68  
 
 69  
     /**
 70  
      * Function to return the key for a document. Used instead of the
 71  
      * {@link #getKeys} to dynamically determine the group for each document.
 72  
      */
 73  
     private final String myKeyFunction;
 74  
 
 75  
     /** The fields to group by. */
 76  
     private final Set<String> myKeys;
 77  
 
 78  
     /** The maximum amount of time to allow the command to run. */
 79  
     private final long myMaximumTimeMilliseconds;
 80  
 
 81  
     /** The query to select the documents to run the group against. */
 82  
     private final Document myQuery;
 83  
 
 84  
     /** The read preference to use. */
 85  
     private final ReadPreference myReadPreference;
 86  
 
 87  
     /**
 88  
      * The reduce function taking the previous value and the current value and
 89  
      * returning the new reduced value.
 90  
      */
 91  
     private final String myReduceFunction;
 92  
 
 93  
     /**
 94  
      * Creates a new GroupBy.
 95  
      * 
 96  
      * @param builder
 97  
      *            The builder to copy the state from.
 98  
      * @throws IllegalArgumentException
 99  
      *             If neither the {@link #getKeys() keys} nor
 100  
      *             {@link #getKeyFunction() key function} have been set.
 101  
      */
 102  19
     protected GroupBy(final Builder builder) throws IllegalArgumentException {
 103  19
         assertThat(
 104  
                 !builder.myKeys.isEmpty() || (builder.myKeyFunction != null),
 105  
                 "Must specify either a set of keys for the groupBy or a key function.");
 106  
 
 107  17
         myKeys = Collections
 108  
                 .unmodifiableSet(new HashSet<String>(builder.myKeys));
 109  17
         myReduceFunction = builder.myReduceFunction;
 110  17
         myInitialValue = builder.myInitialValue;
 111  17
         myKeyFunction = builder.myKeyFunction;
 112  17
         myQuery = builder.myQuery;
 113  17
         myFinalizeFunction = builder.myFinalizeFunction;
 114  17
         myReadPreference = builder.myReadPreference;
 115  17
         myMaximumTimeMilliseconds = builder.myMaximumTimeMilliseconds;
 116  17
     }
 117  
 
 118  
     /**
 119  
      * Returns the finalizer function to run for each group.
 120  
      * 
 121  
      * @return The finalizer function to run for each group.
 122  
      */
 123  
     public String getFinalizeFunction() {
 124  16
         return myFinalizeFunction;
 125  
     }
 126  
 
 127  
     /**
 128  
      * Returns the initial value for each group.
 129  
      * 
 130  
      * @return The initial value for each group.
 131  
      */
 132  
     public Document getInitialValue() {
 133  16
         return myInitialValue;
 134  
     }
 135  
 
 136  
     /**
 137  
      * Returns the function to return the key for a document. Used instead of
 138  
      * the {@link #getKeys} to dynamically determine the group for each
 139  
      * document.
 140  
      * 
 141  
      * @return The function to return the key for a document. Used instead of
 142  
      *         the {@link #getKeys} to dynamically determine the group for each
 143  
      *         document.
 144  
      */
 145  
     public String getKeyFunction() {
 146  16
         return myKeyFunction;
 147  
     }
 148  
 
 149  
     /**
 150  
      * Returns the fields to group by.
 151  
      * 
 152  
      * @return The fields to group by.
 153  
      */
 154  
     public Set<String> getKeys() {
 155  21
         return myKeys;
 156  
     }
 157  
 
 158  
     /**
 159  
      * Returns the maximum amount of time to allow the command to run on the
 160  
      * Server before it is aborted.
 161  
      * 
 162  
      * @return The maximum amount of time to allow the command to run on the
 163  
      *         Server before it is aborted.
 164  
      * 
 165  
      * @since MongoDB 2.6
 166  
      */
 167  
     public long getMaximumTimeMilliseconds() {
 168  12
         return myMaximumTimeMilliseconds;
 169  
     }
 170  
 
 171  
     /**
 172  
      * Returns the query to select the documents to run the group against.
 173  
      * 
 174  
      * @return The query to select the documents to run the group against.
 175  
      */
 176  
     public Document getQuery() {
 177  16
         return myQuery;
 178  
     }
 179  
 
 180  
     /**
 181  
      * Returns the {@link ReadPreference} specifying which servers may be used
 182  
      * to execute the {@link GroupBy} command.
 183  
      * <p>
 184  
      * If <code>null</code> then the {@link MongoCollection} instance's
 185  
      * {@link ReadPreference} will be used.
 186  
      * </p>
 187  
      * 
 188  
      * @return The read preference to use.
 189  
      * 
 190  
      * @see MongoCollection#getReadPreference()
 191  
      */
 192  
     public ReadPreference getReadPreference() {
 193  9
         return myReadPreference;
 194  
     }
 195  
 
 196  
     /**
 197  
      * Returns the reduce function taking the previous value and the current
 198  
      * value and returning the new reduced value.
 199  
      * 
 200  
      * @return The reduce function taking the previous value and the current
 201  
      *         value and returning the new reduced value.
 202  
      */
 203  
     public String getReduceFunction() {
 204  16
         return myReduceFunction;
 205  
     }
 206  
 
 207  
     /**
 208  
      * Builder provides a builder for Group commands.
 209  
      * 
 210  
      * @api.yes This class is part of the driver's API. Public and protected
 211  
      *          members will be deprecated for at least 1 non-bugfix release
 212  
      *          (version numbers are &lt;major&gt;.&lt;minor&gt;.&lt;bugfix&gt;)
 213  
      *          before being removed or modified.
 214  
      * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved
 215  
      */
 216  
     public static class Builder {
 217  
 
 218  
         /** The finalizer function to run for each group. */
 219  
         protected String myFinalizeFunction;
 220  
 
 221  
         /** The initial value for the group. */
 222  
         protected Document myInitialValue;
 223  
 
 224  
         /**
 225  
          * Function to return the key for a document. Used instead of the
 226  
          * {@link #setKeys} to dynamically determine the group for each
 227  
          * document.
 228  
          */
 229  
         protected String myKeyFunction;
 230  
 
 231  
         /** The fields to group by. */
 232  
         protected final Set<String> myKeys;
 233  
 
 234  
         /** The maximum amount of time to allow the command to run. */
 235  
         protected long myMaximumTimeMilliseconds;
 236  
 
 237  
         /** The query to select the documents to run the group against. */
 238  
         protected Document myQuery;
 239  
 
 240  
         /** The read preference to use. */
 241  
         protected ReadPreference myReadPreference;
 242  
 
 243  
         /**
 244  
          * The reduce function taking the previous value and the current value
 245  
          * and returning the new reduced value.
 246  
          */
 247  
         protected String myReduceFunction;
 248  
 
 249  
         /**
 250  
          * Creates a new Builder.
 251  
          */
 252  16
         public Builder() {
 253  16
             myKeys = new HashSet<String>();
 254  
 
 255  16
             reset();
 256  16
         }
 257  
 
 258  
         /**
 259  
          * Creates a new {@link GroupBy} based on the current state of the
 260  
          * builder.
 261  
          * 
 262  
          * @return A new {@link GroupBy} based on the current state of the
 263  
          *         builder.
 264  
          * @throws IllegalArgumentException
 265  
          *             If neither the {@link #getKeys() keys} nor
 266  
          *             {@link #getKeyFunction() key function} have been set.
 267  
          */
 268  
         public GroupBy build() throws IllegalArgumentException {
 269  19
             return new GroupBy(this);
 270  
         }
 271  
 
 272  
         /**
 273  
          * Sets the value of the finalizer function to run for each group.
 274  
          * <p>
 275  
          * This method delegates to {@link #setFinalizeFunction(String)}.
 276  
          * </p>
 277  
          * 
 278  
          * @param finalizeFunction
 279  
          *            The new value for the finalizer function to run for each
 280  
          *            group.
 281  
          * @return This {@link Builder} for method call chaining.
 282  
          */
 283  
         public Builder finalize(final String finalizeFunction) {
 284  1
             return setFinalizeFunction(finalizeFunction);
 285  
         }
 286  
 
 287  
         /**
 288  
          * Sets the value of the initial value for the group.
 289  
          * <p>
 290  
          * This method delegates to {@link #setInitialValue(DocumentAssignable)}
 291  
          * .
 292  
          * </p>
 293  
          * 
 294  
          * @param initialValue
 295  
          *            The new value for the initial value for the group.
 296  
          * @return This {@link Builder} for method call chaining.
 297  
          */
 298  
         public Builder initialValue(final DocumentAssignable initialValue) {
 299  1
             return setInitialValue(initialValue);
 300  
         }
 301  
 
 302  
         /**
 303  
          * Sets the value of the function to return the key for a document. Used
 304  
          * instead of the {@link #setKeys} to dynamically determine the group
 305  
          * for each document.
 306  
          * <p>
 307  
          * This method delegates to {@link #setKeyFunction(String)}.
 308  
          * </p>
 309  
          * 
 310  
          * @param keyFunction
 311  
          *            The new value for the function to return the key for a
 312  
          *            document. Used instead of the {@link #setKeys} to
 313  
          *            dynamically determine the group for each document.
 314  
          * @return This {@link Builder} for method call chaining.
 315  
          */
 316  
         public Builder key(final String keyFunction) {
 317  1
             return setKeyFunction(keyFunction);
 318  
         }
 319  
 
 320  
         /**
 321  
          * Sets the fields to group by
 322  
          * <p>
 323  
          * This method delegates to {@link #setKeys(Set)}.
 324  
          * </p>
 325  
          * 
 326  
          * @param keys
 327  
          *            The new fields to group by
 328  
          * @return This {@link Builder} for method call chaining.
 329  
          */
 330  
         public Builder keys(final Set<String> keys) {
 331  7
             return setKeys(keys);
 332  
         }
 333  
 
 334  
         /**
 335  
          * Sets the maximum number of milliseconds to allow the command to run
 336  
          * before aborting the request on the server.
 337  
          * <p>
 338  
          * This method equivalent to {@link #setMaximumTimeMilliseconds(long)
 339  
          * setMaximumTimeMilliseconds(timeLimitUnits.toMillis(timeLimit)}.
 340  
          * </p>
 341  
          * 
 342  
          * @param timeLimit
 343  
          *            The new maximum amount of time to allow the command to
 344  
          *            run.
 345  
          * @param timeLimitUnits
 346  
          *            The units for the maximum amount of time to allow the
 347  
          *            command to run.
 348  
          * 
 349  
          * @return This {@link Builder} for method call chaining.
 350  
          * 
 351  
          * @since MongoDB 2.6
 352  
          */
 353  
         public Builder maximumTime(final long timeLimit,
 354  
                 final TimeUnit timeLimitUnits) {
 355  1
             return setMaximumTimeMilliseconds(timeLimitUnits
 356  
                     .toMillis(timeLimit));
 357  
         }
 358  
 
 359  
         /**
 360  
          * Sets the value of the query to select the documents to run the group
 361  
          * against.
 362  
          * <p>
 363  
          * This method delegates to {@link #setQuery(DocumentAssignable)}.
 364  
          * </p>
 365  
          * 
 366  
          * @param query
 367  
          *            The new value for the query to select the documents to run
 368  
          *            the group against.
 369  
          * @return This {@link Builder} for method call chaining.
 370  
          */
 371  
         public Builder query(final DocumentAssignable query) {
 372  1
             return setQuery(query);
 373  
         }
 374  
 
 375  
         /**
 376  
          * Sets the {@link ReadPreference} specifying which servers may be used
 377  
          * to execute the {@link GroupBy} command.
 378  
          * <p>
 379  
          * If not set or set to <code>null</code> then the
 380  
          * {@link MongoCollection} instance's {@link ReadPreference} will be
 381  
          * used.
 382  
          * </p>
 383  
          * <p>
 384  
          * This method delegates to {@link #setReadPreference(ReadPreference)}.
 385  
          * </p>
 386  
          * 
 387  
          * @param readPreference
 388  
          *            The read preferences specifying which servers may be used.
 389  
          * @return This builder for chaining method calls.
 390  
          * 
 391  
          * @see MongoCollection#getReadPreference()
 392  
          */
 393  
         public Builder readPreference(final ReadPreference readPreference) {
 394  1
             return setReadPreference(readPreference);
 395  
         }
 396  
 
 397  
         /**
 398  
          * Sets the value of the reduce function taking the previous value and
 399  
          * the current value and returning the new reduced value.
 400  
          * <p>
 401  
          * This method delegates to {@link #setReduceFunction(String)}.
 402  
          * </p>
 403  
          * 
 404  
          * @param reduceFunction
 405  
          *            The new value for the reduce function taking the previous
 406  
          *            value and the current value and returning the new reduced
 407  
          *            value.
 408  
          * @return This {@link Builder} for method call chaining.
 409  
          */
 410  
         public Builder reduce(final String reduceFunction) {
 411  1
             return setReduceFunction(reduceFunction);
 412  
         }
 413  
 
 414  
         /**
 415  
          * Resets the builder back to its initial state.
 416  
          * 
 417  
          * @return This {@link Builder} for method call chaining.
 418  
          */
 419  
         public Builder reset() {
 420  17
             myFinalizeFunction = null;
 421  17
             myInitialValue = null;
 422  17
             myKeyFunction = null;
 423  17
             myKeys.clear();
 424  17
             myQuery = null;
 425  17
             myReadPreference = null;
 426  17
             myReduceFunction = null;
 427  17
             myMaximumTimeMilliseconds = 0;
 428  
 
 429  17
             return this;
 430  
         }
 431  
 
 432  
         /**
 433  
          * Sets the value of the finalizer function to run for each group.
 434  
          * 
 435  
          * @param finalizeFunction
 436  
          *            The new value for the finalizer function to run for each
 437  
          *            group.
 438  
          * @return This {@link Builder} for method call chaining.
 439  
          */
 440  
         public Builder setFinalizeFunction(final String finalizeFunction) {
 441  3
             myFinalizeFunction = finalizeFunction;
 442  3
             return this;
 443  
         }
 444  
 
 445  
         /**
 446  
          * Sets the value of the initial value for the group.
 447  
          * 
 448  
          * @param initialValue
 449  
          *            The new value for the initial value for the group.
 450  
          * @return This {@link Builder} for method call chaining.
 451  
          */
 452  
         public Builder setInitialValue(final DocumentAssignable initialValue) {
 453  3
             myInitialValue = initialValue.asDocument();
 454  3
             return this;
 455  
         }
 456  
 
 457  
         /**
 458  
          * Sets the value of the function to return the key for a document. Used
 459  
          * instead of the {@link #setKeys} to dynamically determine the group
 460  
          * for each document.
 461  
          * 
 462  
          * @param keyFunction
 463  
          *            The new value for the function to return the key for a
 464  
          *            document. Used instead of the {@link #setKeys} to
 465  
          *            dynamically determine the group for each document.
 466  
          * @return This {@link Builder} for method call chaining.
 467  
          */
 468  
         public Builder setKeyFunction(final String keyFunction) {
 469  3
             myKeyFunction = keyFunction;
 470  3
             return this;
 471  
         }
 472  
 
 473  
         /**
 474  
          * Sets the fields to group by
 475  
          * 
 476  
          * @param keys
 477  
          *            The new fields to group by
 478  
          * @return This {@link Builder} for method call chaining.
 479  
          */
 480  
         public Builder setKeys(final Set<String> keys) {
 481  15
             myKeys.clear();
 482  15
             if (keys != null) {
 483  14
                 myKeys.addAll(keys);
 484  
             }
 485  15
             return this;
 486  
         }
 487  
 
 488  
         /**
 489  
          * Sets the maximum number of milliseconds to allow the command to run
 490  
          * before aborting the request on the server.
 491  
          * 
 492  
          * @param maximumTimeMilliseconds
 493  
          *            The new maximum number of milliseconds to allow the
 494  
          *            command to run.
 495  
          * @return This {@link Builder} for method call chaining.
 496  
          * 
 497  
          * @since MongoDB 2.6
 498  
          */
 499  
         public Builder setMaximumTimeMilliseconds(
 500  
                 final long maximumTimeMilliseconds) {
 501  3
             myMaximumTimeMilliseconds = maximumTimeMilliseconds;
 502  3
             return this;
 503  
         }
 504  
 
 505  
         /**
 506  
          * Sets the value of the query to select the documents to run the group
 507  
          * against.
 508  
          * 
 509  
          * @param query
 510  
          *            The new value for the query to select the documents to run
 511  
          *            the group against.
 512  
          * @return This {@link Builder} for method call chaining.
 513  
          */
 514  
         public Builder setQuery(final DocumentAssignable query) {
 515  3
             myQuery = query.asDocument();
 516  3
             return this;
 517  
         }
 518  
 
 519  
         /**
 520  
          * Sets the {@link ReadPreference} specifying which servers may be used
 521  
          * to execute the {@link GroupBy} command.
 522  
          * <p>
 523  
          * If not set or set to <code>null</code> then the
 524  
          * {@link MongoCollection} instance's {@link ReadPreference} will be
 525  
          * used.
 526  
          * </p>
 527  
          * 
 528  
          * @param readPreference
 529  
          *            The read preferences specifying which servers may be used.
 530  
          * @return This builder for chaining method calls.
 531  
          * 
 532  
          * @see MongoCollection#getReadPreference()
 533  
          */
 534  
         public Builder setReadPreference(final ReadPreference readPreference) {
 535  3
             myReadPreference = readPreference;
 536  3
             return this;
 537  
         }
 538  
 
 539  
         /**
 540  
          * Sets the value of the reduce function taking the previous value and
 541  
          * the current value and returning the new reduced value.
 542  
          * 
 543  
          * @param reduceFunction
 544  
          *            The new value for the reduce function taking the previous
 545  
          *            value and the current value and returning the new reduced
 546  
          *            value.
 547  
          * @return This {@link Builder} for method call chaining.
 548  
          */
 549  
         public Builder setReduceFunction(final String reduceFunction) {
 550  3
             myReduceFunction = reduceFunction;
 551  3
             return this;
 552  
         }
 553  
     }
 554  
 }