the type of credentials this database uses
+ * @param the type of pipeline for this database
+ * @param the type of async pipeline for this database
+ */
+public interface IDatabase extends Closeable {
+ /**
+ * Get the name of this database.
+ *
+ * @return the database name
+ */
+ @NonNull String getName();
+
+ /**
+ * Initialize a connection to this database.
+ *
+ * @param credentials the optional credentials to use
+ */
+ void connect(A credentials);
+
+ /**
+ * Check if this database is connected.
+ *
+ * @return the database connection state
+ */
+ boolean isConnected();
+
+ /**
+ * Get the bootstrap class
+ * instance for this database.
+ *
+ * @return the bootstrap class instance, null if none
+ * @see B for bootstrap class
+ */
+ B getBootstrap();
+
+ /**
+ * Get the synchronized
+ * pipeline for this database.
+ *
+ * @return the synchronized pipeline
+ * @see P for synchronized pipeline
+ */
+ @NonNull P sync();
+
+ /**
+ * Get the asynchronous
+ * pipeline for this database.
+ *
+ * @return the asynchronous pipeline
+ * @see AP for asynchronous pipeline
+ */
+ @NonNull AP async();
+}
\ No newline at end of file
diff --git a/src/main/java/me/braydon/feather/Playground.java b/src/main/java/me/braydon/feather/Playground.java
new file mode 100644
index 0000000..d0c443c
--- /dev/null
+++ b/src/main/java/me/braydon/feather/Playground.java
@@ -0,0 +1,26 @@
+package me.braydon.feather;
+
+import com.mongodb.ConnectionString;
+import me.braydon.feather.databases.mongodb.MongoDB;
+
+/**
+ * @author Braydon
+ */
+public final class Playground {
+ public static void main(String[] args) {
+ MongoDB mongoDB = new MongoDB(); // Create the database instance
+ mongoDB.connect(new ConnectionString("mongodb://root:p4$$w0rd@localhost:27017/database")); // Connect to the MongoDB server
+
+ // Get the ping to the database synchronously (blocking)
+ long ping = mongoDB.sync().getPing();
+ System.out.println("ping = " + ping);
+
+ // ...or get the ping to the database asynchronously (another thread)
+ mongoDB.async().getPing().thenAccept(asyncPing -> {
+ System.out.println("asyncPing = " + asyncPing);
+ });
+
+ // Close the connection after our app is done
+ mongoDB.close();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/me/braydon/feather/databases/mongodb/MongoAsyncPipeline.java b/src/main/java/me/braydon/feather/databases/mongodb/MongoAsyncPipeline.java
new file mode 100644
index 0000000..f88995d
--- /dev/null
+++ b/src/main/java/me/braydon/feather/databases/mongodb/MongoAsyncPipeline.java
@@ -0,0 +1,51 @@
+package me.braydon.feather.databases.mongodb;
+
+import com.mongodb.BasicDBObject;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.NonNull;
+import me.braydon.feather.FeatherThreads;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+
+/**
+ * The pipeline for handling asynchronous {@link MongoDB} operations.
+ *
+ * @author Braydon
+ */
+@AllArgsConstructor(access = AccessLevel.PROTECTED)
+public final class MongoAsyncPipeline {
+ /**
+ * The database to handle operations for.
+ */
+ @NonNull private final MongoDB database;
+
+ /**
+ * Get the latency to the database.
+ *
+ * @return the latency
+ */
+ public CompletableFuture getPing() {
+ return getPing(FeatherThreads.THREAD_POOL);
+ }
+
+ /**
+ * Get the latency to the database.
+ *
+ * @param executor the thread executor to use
+ * @return the latency
+ * @see Executor for executor
+ */
+ public CompletableFuture getPing(@NonNull Executor executor) {
+ return CompletableFuture.supplyAsync(() -> {
+ if (!database.isConnected()) { // Not connected
+ return -1L;
+ }
+ // Return ping
+ long before = System.currentTimeMillis();
+ database.getDatabase().runCommand(new BasicDBObject("ping", "1"));
+ return System.currentTimeMillis() - before;
+ }, executor);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/me/braydon/feather/databases/mongodb/MongoDB.java b/src/main/java/me/braydon/feather/databases/mongodb/MongoDB.java
new file mode 100644
index 0000000..53cd4b8
--- /dev/null
+++ b/src/main/java/me/braydon/feather/databases/mongodb/MongoDB.java
@@ -0,0 +1,125 @@
+package me.braydon.feather.databases.mongodb;
+
+import com.mongodb.ConnectionString;
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+import com.mongodb.client.MongoDatabase;
+import lombok.Getter;
+import lombok.NonNull;
+import me.braydon.feather.IDatabase;
+
+/**
+ * The {@link IDatabase} implementation for MongoDB.
+ *
+ * @author Braydon
+ * @see MongoClient for the bootstrap class
+ * @see ConnectionString for the credentials class
+ * @see MongoSyncPipeline for the sync pipeline class
+ * @see MongoAsyncPipeline for the async pipeline class
+ * @see MongoDB Official Site
+ */
+public class MongoDB implements IDatabase {
+ /**
+ * The current {@link MongoClient} instance.
+ */
+ private MongoClient client;
+
+ /**
+ * The {@link MongoDatabase} instance.
+ */
+ @Getter private MongoDatabase database;
+
+ /**
+ * Get the name of this database.
+ *
+ * @return the database name
+ */
+ @Override @NonNull
+ public String getName() {
+ return "MongoDB";
+ }
+
+ /**
+ * Initialize a connection to this database.
+ *
+ * @param credentials the optional credentials to use
+ */
+ @Override
+ public void connect(ConnectionString credentials) {
+ if (credentials == null) { // We need valid credentials
+ throw new IllegalArgumentException("No credentials defined");
+ }
+ if (isConnected()) { // Already connected
+ throw new IllegalStateException("Already connected");
+ }
+ String databaseName = credentials.getDatabase(); // Get the database name
+ if (databaseName == null) {
+ throw new IllegalArgumentException("A database name is required");
+ }
+ if (client != null) { // We have a client, close it first
+ client.close();
+ }
+ client = MongoClients.create(credentials); // Create a new client
+ database = client.getDatabase(databaseName); // Get the database
+ }
+
+ /**
+ * Check if this database is connected.
+ *
+ * @return the database connection state
+ */
+ @Override
+ public boolean isConnected() {
+ return client != null;
+ }
+
+ /**
+ * Get the bootstrap class
+ * instance for this database.
+ *
+ * @return the bootstrap class instance, null if none
+ * @see MongoClients for bootstrap class
+ */
+ @Override
+ public MongoClient getBootstrap() {
+ return client;
+ }
+
+ /**
+ * Get the synchronized
+ * pipeline for this database.
+ *
+ * @return the synchronized pipeline
+ * @see MongoSyncPipeline for synchronized pipeline
+ */
+ @Override @NonNull
+ public MongoSyncPipeline sync() {
+ return new MongoSyncPipeline(this);
+ }
+
+ /**
+ * Get the asynchronous
+ * pipeline for this database.
+ *
+ * @return the asynchronous pipeline
+ * @see MongoAsyncPipeline for asynchronous pipeline
+ */
+ @Override @NonNull
+ public MongoAsyncPipeline async() {
+ return new MongoAsyncPipeline(this);
+ }
+
+ /**
+ * Closes this stream and releases any system resources associated
+ * with it. If the stream is already closed then invoking this
+ * method has no effect.
+ */
+ @Override
+ public void close() {
+ if (client != null) {
+ client.close();
+ }
+ client = null;
+ database = null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/me/braydon/feather/databases/mongodb/MongoSyncPipeline.java b/src/main/java/me/braydon/feather/databases/mongodb/MongoSyncPipeline.java
new file mode 100644
index 0000000..89bbb4f
--- /dev/null
+++ b/src/main/java/me/braydon/feather/databases/mongodb/MongoSyncPipeline.java
@@ -0,0 +1,34 @@
+package me.braydon.feather.databases.mongodb;
+
+import com.mongodb.BasicDBObject;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.NonNull;
+
+/**
+ * The pipeline for handling {@link MongoDB} operations.
+ *
+ * @author Braydon
+ */
+@AllArgsConstructor(access = AccessLevel.PROTECTED)
+public final class MongoSyncPipeline {
+ /**
+ * The database to handle operations for.
+ */
+ @NonNull private final MongoDB database;
+
+ /**
+ * Get the latency to the database.
+ *
+ * @return the latency
+ */
+ public long getPing() {
+ if (!database.isConnected()) { // Not connected
+ return -1L;
+ }
+ // Return ping
+ long before = System.currentTimeMillis();
+ database.getDatabase().runCommand(new BasicDBObject("ping", "1"));
+ return System.currentTimeMillis() - before;
+ }
+}
\ No newline at end of file