/*
 * Copyright 2014 Red Hat, Inc.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Apache License v2.0 which accompanies this distribution.
 *
 *  The Eclipse Public License is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  The Apache License v2.0 is available at
 *  http://www.opensource.org/licenses/apache2.0.php
 *
 *  You may elect to redistribute this code under either of these licenses.
 */

/**
 * = Vert.x MongoDB Client
 *
 * A Vert.x client allowing applications to interact with a MongoDB instance, whether that's
 * saving, retrieving, searching, or deleting documents. Mongo is a great match for persisting data in a Vert.x application
 * as it natively handles JSON (BSON) documents.
 *
 * *Features*
 *
 * * Completely non-blocking
 * * Custom codec to support fast serialization to/from Vert.x JSON
 * * Supports a majority of the configuration options from the MongoDB Java Driver
 *
 * This client is based on the
 * http://mongodb.github.io/mongo-java-driver/3.2/driver-async/getting-started[MongoDB Async Driver].
 *
 * == Using Vert.x MongoDB Client
 *
 * To use this project, add the following dependency to the _dependencies_ section of your build descriptor:
 *
 * * Maven (in your `pom.xml`):
 *
 * [source,xml,subs="+attributes"]
 * ----
 * <dependency>
 *   <groupId>${maven.groupId}</groupId>
 *   <artifactId>${maven.artifactId}</artifactId>
 *   <version>${maven.version}</version>
 * </dependency>
 * ----
 *
 * * Gradle (in your `build.gradle` file):
 *
 * [source,groovy,subs="+attributes"]
 * ----
 * compile '${maven.groupId}:${maven.artifactId}:${maven.version}'
 * ----
 *
 *
 * == Creating a client
 *
 * You can create a client in several ways:
 *
 * === Using the default shared pool
 *
 * In most cases you will want to share a pool between different client instances.
 *
 * E.g. you scale your application by deploying multiple instances of your verticle and you want each verticle instance
 * to share the same pool so you don't end up with multiple pools
 *
 * The simplest way to do this is as follows:
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#exampleCreateDefault}
 * ----
 *
 * The first call to {@link io.vertx.ext.mongo.MongoClient#createShared(io.vertx.core.Vertx, io.vertx.core.json.JsonObject)}
 * will actually create the pool, and the specified config will be used.
 *
 * Subsequent calls will return a new client instance that uses the same pool, so the configuration won't be used.
 *
 * === Specifying a pool source name
 *
 * You can create a client specifying a pool source name as follows
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#exampleCreatePoolName}
 * ----
 *
 * If different clients are created using the same Vert.x instance and specifying the same pool name, they will
 * share the same pool.
 *
 * The first call to {@link io.vertx.ext.mongo.MongoClient#createShared(io.vertx.core.Vertx, io.vertx.core.json.JsonObject)}
 * will actually create the pool, and the specified config will be used.
 *
 * Subsequent calls will return a new client instance that uses the same pool, so the configuration won't be used.
 *
 * Use this way of creating if you wish different groups of clients to have different pools, e.g. they're
 * interacting with different databases.
 *
 * === Creating a client with a non shared data pool
 *
 * In most cases you will want to share a pool between different client instances.
 * However, it's possible you want to create a client instance that doesn't share its pool with any other client.
 *
 * In that case you can use {@link io.vertx.ext.mongo.MongoClient#createNonShared(io.vertx.core.Vertx, io.vertx.core.json.JsonObject)}.
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#exampleCreateNonShared}
 * ----
 *
 * This is equivalent to calling {@link io.vertx.ext.mongo.MongoClient#createShared(io.vertx.core.Vertx, io.vertx.core.json.JsonObject, String)}
 * with a unique pool name each time.
 *
 *
 * == Using the API
 *
 * The client API is represented by {@link io.vertx.ext.mongo.MongoClient}.
 *
 * === Saving documents
 *
 * To save a document you use {@link io.vertx.ext.mongo.MongoClient#save}.
 *
 * If the document has no `\_id` field, it is inserted, otherwise, it is __upserted__.
 * Upserted means it is inserted if it doesn't already exist, otherwise it is updated.
 *
 * If the document is inserted and has no id, then the id field generated will be returned to the result handler.
 *
 * Here's an example of saving a document and getting the id back
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example1}
 * ----
 *
 * And here's an example of saving a document which already has an id.
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example2}
 * ----
 *
 * === Inserting documents
 *
 * To insert a document you use {@link io.vertx.ext.mongo.MongoClient#insert}.
 *
 * If the document is inserted and has no id, then the id field generated will be returned to the result handler.
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example3}
 * ----
 *
 * If a document is inserted with an id, and a document with that id already exists, the insert will fail:
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example4}
 * ----
 *
 * === Updating documents
 *
 * To update a documents you use {@link io.vertx.ext.mongo.MongoClient#updateCollection}.
 *
 * This updates one or multiple documents in a collection.
 * The json object that is passed in the `updateCollection` parameter must contain
 * http://docs.mongodb.org/manual/reference/operator/update-field/[Update Operators]
 * and determines how the object is updated.
 *
 * The json object specified in the query parameter determines which documents in the collection will be updated.
 *
 * Here's an example of updating a document in the books collection:
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example5}
 * ----
 *
 * To specify if the update should upsert or update multiple documents, use
 * {@link io.vertx.ext.mongo.MongoClient#updateCollectionWithOptions}
 * and pass in an instance of {@link io.vertx.ext.mongo.UpdateOptions}.
 *
 * This has the following fields:
 *
 * `multi`:: set to true to update multiple documents
 * `upsert`:: set to true to insert the document if the query doesn't match
 * `writeConcern`:: the write concern for this operation
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example6}
 * ----
 *
 * === Replacing documents
 *
 * To replace documents you use {@link io.vertx.ext.mongo.MongoClient#replaceDocuments}.
 *
 * This is similar to the update operation, however it does not take any operator.
 * Instead it replaces the entire document with the one provided.
 *
 * Here's an example of replacing a document in the books collection
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example7}
 * ----
 *
 * === Bulk operations
 *
 * To execute multiple insert, update, replace, or delete operations at once, use {@link io.vertx.ext.mongo.MongoClient#bulkWrite}.
 *
 * You can pass a list of {@link io.vertx.ext.mongo.BulkOperation BulkOperations}, with each working similar to the matching single operation.
 * You can pass as many operations, even of the same type, as you wish.
 *
 * To specify if the bulk operation should be executed in order, and with what write option, use {@link io.vertx.ext.mongo.MongoClient#bulkWriteWithOptions}
 * and pass an instance of {@link io.vertx.ext.mongo.BulkWriteOptions}.
 * For more explanation what ordered means, see
 * https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#execution-of-operations[Execution of Operations].
 *
 * === Finding documents
 *
 * To find documents you use {@link io.vertx.ext.mongo.MongoClient#find}.
 *
 * The `query` parameter is used to match the documents in the collection.
 *
 * Here's a simple example with an empty query that will match all books:
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example8}
 * ----
 *
 * Here's another example that will match all books by Tolkien:
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example9}
 * ----
 *
 * The matching documents are returned as a list of json objects in the result handler.
 *
 * To specify things like what fields to return, how many results to return, etc use {@link io.vertx.ext.mongo.MongoClient#findWithOptions}
 * and pass in the an instance of {@link io.vertx.ext.mongo.FindOptions}.
 *
 * This has the following fields:
 *
 * `fields`:: The fields to return in the results. Defaults to `null`, meaning all fields will be returned
 * `sort`:: The fields to sort by. Defaults to `null`.
 * `limit`:: The limit of the number of results to return. Default to `-1`, meaning all results will be returned.
 * `skip`:: The number of documents to skip before returning the results. Defaults to `0`.
 *
 * === Finding documents in batches
 *
 * When dealing with large data sets, it is not advised to use the
 * {@link io.vertx.ext.mongo.MongoClient#find} and
 * {@link io.vertx.ext.mongo.MongoClient#findWithOptions} methods.
 * In order to avoid inflating the whole response into memory, use {@link io.vertx.ext.mongo.MongoClient#findBatch}:
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#findBatch}
 * ----
 *
 * The matching documents are emitted one by one by the {@link io.vertx.core.streams.ReadStream} handler.
 *
 * {@link io.vertx.ext.mongo.FindOptions} has an extra parameter `batchSize` which you can use to set the number of documents to load at once:
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#findBatchWithOptions}
 * ----
 *
 * By default, `batchSize` is set to 20.
 *
 * === Finding a single document
 *
 * To find a single document you use {@link io.vertx.ext.mongo.MongoClient#findOne}.
 *
 * This works just like {@link io.vertx.ext.mongo.MongoClient#find} but it returns just the first matching document.
 *
 * === Removing documents
 *
 * To remove documents use {@link io.vertx.ext.mongo.MongoClient#removeDocuments}.
 *
 * The `query` parameter is used to match the documents in the collection to determine which ones to remove.
 *
 * Here's an example of removing all Tolkien books:
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example10}
 * ----
 *
 * === Removing a single document
 *
 * To remove a single document you use {@link io.vertx.ext.mongo.MongoClient#removeDocument}.
 *
 * This works just like {@link io.vertx.ext.mongo.MongoClient#removeDocuments} but it removes just the first matching document.
 *
 * === Counting documents
 *
 * To count documents use {@link io.vertx.ext.mongo.MongoClient#count}.
 *
 * Here's an example that counts the number of Tolkien books. The number is passed to the result handler.
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example11}
 * ----
 *
 * === Managing MongoDB collections
 *
 * All MongoDB documents are stored in collections.
 *
 * To get a list of all collections you can use {@link io.vertx.ext.mongo.MongoClient#getCollections}
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example11_1}
 * ----
 *
 * To create a new collection you can use {@link io.vertx.ext.mongo.MongoClient#createCollection}
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example11_2}
 * ----
 *
 * To drop a collection you can use {@link io.vertx.ext.mongo.MongoClient#dropCollection}
 *
 * NOTE: Dropping a collection will delete all documents within it!
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example11_3}
 * ----
 *
 *
 * === Running other MongoDB commands
 *
 * You can run arbitrary MongoDB commands with {@link io.vertx.ext.mongo.MongoClient#runCommand}.
 *
 * Commands can be used to run more advanced MongoDB features, such as using MapReduce.
 * For more information see the mongo docs for supported http://docs.mongodb.org/manual/reference/command[Commands].
 *
 * Here's an example of running an aggregate command. Note that the command name must be specified as a parameter
 * and also be contained in the JSON that represents the command. This is because JSON is not ordered but BSON is
 * ordered and MongoDB expects the first BSON entry to be the name of the command. In order for us to know which
 * of the entries in the JSON is the command name it must be specified as a parameter.
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example12}
 * ----
 *
 * === MongoDB Extended JSON support
 *
 * For now, only `date`, `oid` and `binary` types are supported
 * (see http://docs.mongodb.org/manual/reference/mongodb-extended-json[MongoDB Extended JSON]).
 *
 * Here's an example of inserting a document with a `date` field:
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example13_0}
 * ----
 *
 * Here's an example (in Java) of inserting a document with a binary field and reading it back
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example14_01_dl}
 * ----
 *
 * Here's an example of inserting a base 64 encoded string, typing it as binary a binary field, and reading it back
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example14_02_dl}
 * ----
 * Here's an example of inserting an object ID and reading it back
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example15_dl}
 * ----
 *
 * === Getting distinct values
 *
 * Here's an example of getting distinct value
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example16}
 * ----
 * Here's an example of getting distinct value in batch mode
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example16_d1}
 * ----
 * * Here's an example of getting distinct value with query
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example17}
 * ----
 * Here's an example of getting distinct value in batch mode with query
 *
 * [source,$lang]
 * ----
 * {@link examples.Examples#example17_d1}
 * ----
 *
 * == Configuring the client
 *
 * The client is configured with a json object.
 *
 * The following configuration is supported by the mongo client:
 *
 *
 * `db_name`:: Name of the database in the MongoDB instance to use. Defaults to `default_db`
 * `useObjectId`:: Toggle this option to support persisting and retrieving ObjectId's as strings. If `true`, hex-strings will
 * be saved as native Mongodb ObjectId types in the document collection. This will allow the sorting of documents based on creation
 * time. You can also derive the creation time from the hex-string using ObjectId::getDate(). Set to `false` for other types of your choosing.
 * If set to false, or left to default, hex strings will be generated as the document _id if the _id is omitted from the document.
 * Defaults to `false`.
 *
 * The mongo client tries to support most options that are allowed by the driver. There are two ways to configure mongo
 * for use by the driver, either by a connection string or by separate configuration options.
 *
 * NOTE: If the connection string is used the mongo client will ignore any driver configuration options.
 *
 * `connection_string`:: The connection string the driver uses to create the client. E.g. `mongodb://localhost:27017`.
 * For more information on the format of the connection string please consult the driver documentation.
 *
 * *Specific driver configuration options*
 *
 * [source,js]
 * ----
 * {
 *   // Single Cluster Settings
 *   "host" : "127.0.0.1", // string
 *   "port" : 27017,      // int
 *
 *   // Multiple Cluster Settings
 *   "hosts" : [
 *     {
 *       "host" : "cluster1", // string
 *       "port" : 27000       // int
 *     },
 *     {
 *       "host" : "cluster2", // string
 *       "port" : 28000       // int
 *     },
 *     ...
 *   ],
 *   "replicaSet" :  "foo",    // string
 *   "serverSelectionTimeoutMS" : 30000, // long
 *
 *   // Connection Pool Settings
 *   "maxPoolSize" : 50,                // int
 *   "minPoolSize" : 25,                // int
 *   "maxIdleTimeMS" : 300000,          // long
 *   "maxLifeTimeMS" : 3600000,         // long
 *   "waitQueueMultiple"  : 10,         // int
 *   "waitQueueTimeoutMS" : 10000,      // long
 *   "maintenanceFrequencyMS" : 2000,   // long
 *   "maintenanceInitialDelayMS" : 500, // long
 *
 *   // Credentials / Auth
 *   "username"   : "john",     // string
 *   "password"   : "passw0rd", // string
 *   "authSource" : "some.db"   // string
 *   // Auth mechanism
 *   "authMechanism"     : "GSSAPI",        // string
 *   "gssapiServiceName" : "myservicename", // string
 *
 *   // Socket Settings
 *   "connectTimeoutMS" : 300000, // int
 *   "socketTimeoutMS"  : 100000, // int
 *   "sendBufferSize"    : 8192,  // int
 *   "receiveBufferSize" : 8192,  // int
 *   "keepAlive" : true           // boolean
 *
 *   // Heartbeat socket settings
 *   "heartbeat.socket" : {
 *   "connectTimeoutMS" : 300000, // int
 *   "socketTimeoutMS"  : 100000, // int
 *   "sendBufferSize"    : 8192,  // int
 *   "receiveBufferSize" : 8192,  // int
 *   "keepAlive" : true           // boolean
 *   }
 *
 *   // Server Settings
 *   "heartbeatFrequencyMS" :    1000 // long
 *   "minHeartbeatFrequencyMS" : 500 // long
 * }
 * ----
 *
 * *Driver option descriptions*
 *
 * `host`:: The host the MongoDB instance is running. Defaults to `127.0.0.1`. This is ignored if `hosts` is specified
 * `port`:: The port the MongoDB instance is listening on. Defaults to `27017`. This is ignored if `hosts` is specified
 * `hosts`:: An array representing the hosts and ports to support a MongoDB cluster (sharding / replication)
 * `host`:: A host in the cluster
 * `port`:: The port a host in the cluster is listening on
 * `replicaSet`:: The name of the replica set, if the MongoDB instance is a member of a replica set
 * `serverSelectionTimeoutMS`:: The time in milliseconds that the mongo driver will wait to select a server for an operation before raising an error.
 * `maxPoolSize`:: The maximum number of connections in the connection pool. The default value is `100`
 * `minPoolSize`:: The minimum number of connections in the connection pool. The default value is `0`
 * `maxIdleTimeMS`:: The maximum idle time of a pooled connection. The default value is `0` which means there is no limit
 * `maxLifeTimeMS`:: The maximum time a pooled connection can live for. The default value is `0` which means there is no limit
 * `waitQueueMultiple`:: The maximum number of waiters for a connection to become available from the pool. Default value is `500`
 * `waitQueueTimeoutMS`:: The maximum time that a thread may wait for a connection to become available. Default value is `120000` (2 minutes)
 * `maintenanceFrequencyMS`:: The time period between runs of the maintenance job. Default is `0`.
 * `maintenanceInitialDelayMS`:: The period of time to wait before running the first maintenance job on the connection pool. Default is `0`.
 * `username`:: The username to authenticate. Default is `null` (meaning no authentication required)
 * `password`:: The password to use to authenticate.
 * `authSource`:: The database name associated with the user's credentials. Default value is the `db_name` value.
 * `authMechanism`:: The authentication mechanism to use. See [Authentication](http://docs.mongodb.org/manual/core/authentication/) for more details.
 * `gssapiServiceName`:: The Kerberos service name if `GSSAPI` is specified as the `authMechanism`.
 * `connectTimeoutMS`:: The time in milliseconds to attempt a connection before timing out. Default is `10000` (10 seconds)
 * `socketTimeoutMS`:: The time in milliseconds to attempt a send or receive on a socket before the attempt times out. Default is `0` meaning there is no timeout
 * `sendBufferSize`:: Sets the send buffer size (SO_SNDBUF) for the socket. Default is `0`, meaning it will use the OS default for this option.
 * `receiveBufferSize`:: Sets the receive buffer size (SO_RCVBUF) for the socket. Default is `0`, meaning it will use the OS default for this option.
 * `keepAlive`:: Sets the keep alive (SO_KEEPALIVE) for the socket. Default is `false`
 * `heartbeat.socket`:: Configures the socket settings for the cluster monitor of the MongoDB java driver.
 * `heartbeatFrequencyMS`:: The frequency that the cluster monitor attempts to reach each server. Default is `5000` (5 seconds)
 * `minHeartbeatFrequencyMS`:: The minimum heartbeat frequency. The default value is `1000` (1 second)
 *
 * NOTE: Most of the default values listed above use the default values of the MongoDB Java Driver.
 * Please consult the driver documentation for up to date information.
 */
@Document(fileName = "index.adoc")
@ModuleGen(name = "vertx-mongo", groupPackage = "io.vertx")
package io.vertx.ext.mongo;

import io.vertx.codegen.annotations.ModuleGen;
import io.vertx.docgen.Document;
