// Path: domain-model/src/main/java/net/safedata/java8/training/bootstrap/StoreSetup.java
// public final class StoreSetup {
// 
//     private static Store defaultStore;
// 
//     static {
//         final Section tabletsSection = new Section(1, StoreSection.Tablets, buildDefaultTablets());
//         final Section monitorsSection = new Section(2, StoreSection.Monitors, buildDefaultMonitors());
//         final Section laptopsSection = new Section(3, StoreSection.Laptops, buildDefaultLaptops());
// 
//         final Manager john = new Manager(1, "John Doe");
//         final Manager jane = new Manager(2, "Jane Charming");
// 
//         defaultStore = new Store(1, "Goodies", "Over there",
//                                  new HashSet<>(Arrays.asList(tabletsSection, monitorsSection, laptopsSection)),
//                                  new HashSet<>(Arrays.asList(john, jane)));
//     }
// 
//     public static Store getDefaultStore() {
//         return defaultStore;
//     }
// 
//     private StoreSetup() {}
// 
//     private static List<Product> buildDefaultTablets() {
//         return Arrays.asList(
//                 new Product(1, "Google Nexus 7 2013", 200, new Discount(50, Discount.Type.Value)),
//                 new Product(2, "Apple iPad Pro 9.7", 300, new Discount(10, Discount.Type.Percent)),
//                 new Product(3, "Samsung Galaxy Tab S2", 350),
//                 new Product(4, "Microsoft Surface Pro 4", 400)
//         );
//     }
// 
//     private static List<Product> buildDefaultMonitors() {
//         return Arrays.asList(
//                 new Product(5, "Samsung CF791", 500),
//                 new Product(6, "LG 32UD99", 550),
//                 new Product(7, "Samsung CH711", 600)
//         );
//     }
// 
//     private static List<Product> buildDefaultLaptops() {
//         return Arrays.asList(
//                 new Product(10, "Lenovo X11", 1500),
//                 new Product(11, "Apple MacBook Pro", 2000)
//         );
//     }
// }
// 
// Path: domain-model/src/main/java/net/safedata/java8/training/model/Section.java
// public class Section extends AbstractEntity {
// 
//     private final int id;
//     private final StoreSection name;
//     private final List<Product> products;
// 
//     public Section(final int id, final StoreSection name, final List<Product> products) {
//         this.id = id;
//         this.name = name;
//         this.products = products;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public StoreSection getName() {
//         return name;
//     }
// 
//     public Optional<List<Product>> getProducts() {
//         return Optional.ofNullable(products);
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (!(o instanceof Section)) return false;
//         Section that = (Section) o;
//         return id == that.id &&
//                 Objects.equals(name, that.name);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(id, name);
//     }
// }
// 
// Path: domain-model/src/main/java/net/safedata/java8/training/model/Store.java
// public class Store extends AbstractEntity {
// 
//     private final int id;
//     private final String name;
//     private final String location;
//     private final Set<Section> storeSections;
//     private final Set<Manager> storeManagers;
// 
//     public Store(final int id, final String name, final String location,
//                  final Set<Section> storeSections, final Set<Manager> storeManagers) {
//         this.id = id;
//         this.name = name;
//         this.location = location;
//         this.storeSections = storeSections;
//         this.storeManagers = storeManagers;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public String getLocation() {
//         return location;
//     }
// 
//     public Set<Manager> getStoreManagers() {
//         return storeManagers;
//     }
// 
//     public Set<Section> getStoreSections() {
//         return storeSections;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (!(o instanceof Store)) return false;
//         Store store = (Store) o;
//         return id == store.id &&
//                 Objects.equals(name, store.name);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(id, name);
//     }
// }


import net.safedata.java8.training.bootstrap.StoreSetup;
import net.safedata.java8.training.model.Section;
import net.safedata.java8.training.model.Store;
import org.jooq.lambda.Unchecked;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.IntStream;
package net.safedata.java8.training.completable.future;



class ProductProcessor {

    private static final Random RANDOM = new Random();

    private static final int MAX_SLEEP_TIME = 2000;

    CompletableFuture<Long> getProductsStock(final String productName) {
        return CompletableFuture.supplyAsync(() -> {
            displayStageAndThreadName("Getting the product stock for '" + productName + "'");
            sleepALittle();

            final Store store = StoreSetup.getDefaultStore();
            return store.getStoreSections()
                        .stream()
// Path: domain-model/src/main/java/net/safedata/java8/training/bootstrap/StoreSetup.java
// public final class StoreSetup {
// 
//     private static Store defaultStore;
// 
//     static {
//         final Section tabletsSection = new Section(1, StoreSection.Tablets, buildDefaultTablets());
//         final Section monitorsSection = new Section(2, StoreSection.Monitors, buildDefaultMonitors());
//         final Section laptopsSection = new Section(3, StoreSection.Laptops, buildDefaultLaptops());
// 
//         final Manager john = new Manager(1, "John Doe");
//         final Manager jane = new Manager(2, "Jane Charming");
// 
//         defaultStore = new Store(1, "Goodies", "Over there",
//                                  new HashSet<>(Arrays.asList(tabletsSection, monitorsSection, laptopsSection)),
//                                  new HashSet<>(Arrays.asList(john, jane)));
//     }
// 
//     public static Store getDefaultStore() {
//         return defaultStore;
//     }
// 
//     private StoreSetup() {}
// 
//     private static List<Product> buildDefaultTablets() {
//         return Arrays.asList(
//                 new Product(1, "Google Nexus 7 2013", 200, new Discount(50, Discount.Type.Value)),
//                 new Product(2, "Apple iPad Pro 9.7", 300, new Discount(10, Discount.Type.Percent)),
//                 new Product(3, "Samsung Galaxy Tab S2", 350),
//                 new Product(4, "Microsoft Surface Pro 4", 400)
//         );
//     }
// 
//     private static List<Product> buildDefaultMonitors() {
//         return Arrays.asList(
//                 new Product(5, "Samsung CF791", 500),
//                 new Product(6, "LG 32UD99", 550),
//                 new Product(7, "Samsung CH711", 600)
//         );
//     }
// 
//     private static List<Product> buildDefaultLaptops() {
//         return Arrays.asList(
//                 new Product(10, "Lenovo X11", 1500),
//                 new Product(11, "Apple MacBook Pro", 2000)
//         );
//     }
// }
// 
// Path: domain-model/src/main/java/net/safedata/java8/training/model/Section.java
// public class Section extends AbstractEntity {
// 
//     private final int id;
//     private final StoreSection name;
//     private final List<Product> products;
// 
//     public Section(final int id, final StoreSection name, final List<Product> products) {
//         this.id = id;
//         this.name = name;
//         this.products = products;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public StoreSection getName() {
//         return name;
//     }
// 
//     public Optional<List<Product>> getProducts() {
//         return Optional.ofNullable(products);
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (!(o instanceof Section)) return false;
//         Section that = (Section) o;
//         return id == that.id &&
//                 Objects.equals(name, that.name);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(id, name);
//     }
// }
// 
// Path: domain-model/src/main/java/net/safedata/java8/training/model/Store.java
// public class Store extends AbstractEntity {
// 
//     private final int id;
//     private final String name;
//     private final String location;
//     private final Set<Section> storeSections;
//     private final Set<Manager> storeManagers;
// 
//     public Store(final int id, final String name, final String location,
//                  final Set<Section> storeSections, final Set<Manager> storeManagers) {
//         this.id = id;
//         this.name = name;
//         this.location = location;
//         this.storeSections = storeSections;
//         this.storeManagers = storeManagers;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public String getLocation() {
//         return location;
//     }
// 
//     public Set<Manager> getStoreManagers() {
//         return storeManagers;
//     }
// 
//     public Set<Section> getStoreSections() {
//         return storeSections;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (!(o instanceof Store)) return false;
//         Store store = (Store) o;
//         return id == store.id &&
//                 Objects.equals(name, store.name);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(id, name);
//     }
// }


// Path: s03/s03e03-completable-future/src/main/java/net/safedata/java8/training/completable/future/ProductProcessor.java
import net.safedata.java8.training.bootstrap.StoreSetup;
import net.safedata.java8.training.model.Section;
import net.safedata.java8.training.model.Store;
import org.jooq.lambda.Unchecked;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.IntStream;

package net.safedata.java8.training.completable.future;



class ProductProcessor {

    private static final Random RANDOM = new Random();

    private static final int MAX_SLEEP_TIME = 2000;

    CompletableFuture<Long> getProductsStock(final String productName) {
        return CompletableFuture.supplyAsync(() -> {
            displayStageAndThreadName("Getting the product stock for '" + productName + "'");
            sleepALittle();

            final Store store = StoreSetup.getDefaultStore();
            return store.getStoreSections()
                        .stream()
                        .map(Section::getProducts)