// Path: src/main/java/shopJava/util/Constants.java
// public interface Constants {
// 
//     int MAX_ORDERS_PER_USER = 10;
// 
//     String MONGODB_URI = "mongodb://localhost:27017";
//     String SHOP_DB_NAME = "shop";
//     String USERS_COLLECTION_NAME = "users";
//     String ORDERS_COLLECTION_NAME = "orders";
// 
//     String HOMER = "homer";
//     String MARGE = "marge";
//     String BART = "bart";
//     String LISA = "lisa";
//     String MAGGIE = "maggie";
// 
//     String[] SIMPSONS = {HOMER, MARGE, BART, LISA, MAGGIE};
// }
// 
// Path: src/main/java/shopJava/util/Util.java
// public static int average(final int totalAmount, final int orderCount) {
//     return orderCount == 0 ? 0 : Math.round((100.0f * totalAmount / orderCount) / 100);
// }
// 
// Path: src/main/java/shopJava/util/Util.java
// public static User checkUserLoggedIn(final Optional<User> optUser, final Credentials credentials) {
// 
//     if (!optUser.isPresent()) {     // replaces if (user != null)
//         throw new RuntimeException(new IllegalAccessException("User unknown: " + credentials.username));
//     }
//     final User user = optUser.get();
//     return checkUserLoggedIn(user, credentials);
// }


import com.mongodb.async.SingleResultCallback;
import com.mongodb.async.client.MongoClient;
import com.mongodb.async.client.MongoClients;
import com.mongodb.async.client.MongoCollection;
import com.mongodb.async.client.MongoDatabase;
import org.bson.Document;
import shopJava.model.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.*;
import static com.mongodb.client.model.Filters.eq;
import static java.lang.Thread.sleep;
import static shopJava.util.Constants.*;
import static shopJava.util.Util.average;
import static shopJava.util.Util.checkUserLoggedIn;
            final CompletableFuture<Optional<User>> future = new CompletableFuture<>();

            _findUserByName(name, callbackToCompleteFuture(future));

            return future;
        }

        CompletionStage<List<Order>> findOrdersByUsername(final String username) {

            final CompletableFuture<List<Order>> future = new CompletableFuture<>();

            _findOrdersByUsername(username, callbackToCompleteFuture(future));

            return future;
        }

        private <T> SingleResultCallback<T> callbackToCompleteFuture(final CompletableFuture<T> future) {
            return (result, t) -> {
                if (t == null) {
                    future.complete(result);
                } else {
                    future.completeExceptionally(t);
                }
            };
        }
    }   // end DAO


    private CompletionStage<String> logIn(final Credentials credentials) {
        return dao.findUserByName(credentials.username)
// Path: src/main/java/shopJava/util/Constants.java
// public interface Constants {
// 
//     int MAX_ORDERS_PER_USER = 10;
// 
//     String MONGODB_URI = "mongodb://localhost:27017";
//     String SHOP_DB_NAME = "shop";
//     String USERS_COLLECTION_NAME = "users";
//     String ORDERS_COLLECTION_NAME = "orders";
// 
//     String HOMER = "homer";
//     String MARGE = "marge";
//     String BART = "bart";
//     String LISA = "lisa";
//     String MAGGIE = "maggie";
// 
//     String[] SIMPSONS = {HOMER, MARGE, BART, LISA, MAGGIE};
// }
// 
// Path: src/main/java/shopJava/util/Util.java
// public static int average(final int totalAmount, final int orderCount) {
//     return orderCount == 0 ? 0 : Math.round((100.0f * totalAmount / orderCount) / 100);
// }
// 
// Path: src/main/java/shopJava/util/Util.java
// public static User checkUserLoggedIn(final Optional<User> optUser, final Credentials credentials) {
// 
//     if (!optUser.isPresent()) {     // replaces if (user != null)
//         throw new RuntimeException(new IllegalAccessException("User unknown: " + credentials.username));
//     }
//     final User user = optUser.get();
//     return checkUserLoggedIn(user, credentials);
// }


// Path: src/main/java/shopJava/queries/QueryJ06bCompletionStageCompleteCallbackRefactored.java
import com.mongodb.async.SingleResultCallback;
import com.mongodb.async.client.MongoClient;
import com.mongodb.async.client.MongoClients;
import com.mongodb.async.client.MongoCollection;
import com.mongodb.async.client.MongoDatabase;
import org.bson.Document;
import shopJava.model.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.*;
import static com.mongodb.client.model.Filters.eq;
import static java.lang.Thread.sleep;
import static shopJava.util.Constants.*;
import static shopJava.util.Util.average;
import static shopJava.util.Util.checkUserLoggedIn;

            final CompletableFuture<Optional<User>> future = new CompletableFuture<>();

            _findUserByName(name, callbackToCompleteFuture(future));

            return future;
        }

        CompletionStage<List<Order>> findOrdersByUsername(final String username) {

            final CompletableFuture<List<Order>> future = new CompletableFuture<>();

            _findOrdersByUsername(username, callbackToCompleteFuture(future));

            return future;
        }

        private <T> SingleResultCallback<T> callbackToCompleteFuture(final CompletableFuture<T> future) {
            return (result, t) -> {
                if (t == null) {
                    future.complete(result);
                } else {
                    future.completeExceptionally(t);
                }
            };
        }
    }   // end DAO


    private CompletionStage<String> logIn(final Credentials credentials) {
        return dao.findUserByName(credentials.username)
                .thenApply(optUser -> checkUserLoggedIn(optUser, credentials))