// Path: domain-model/src/main/java/net/safedata/java8/training/model/Product.java
// public class Product extends AbstractEntity {
// 
//     private final int id;
//     private final String name;
//     private final double price;
//     private final Discount discount;
//     private final List<String> tags;
// 
//     public Product(final int id, final String name, final double price, final Discount discount,
//                    final List<String> tags) {
//         this.id = id;
//         this.name = name;
//         this.price = price;
//         this.discount = discount;
//         this.tags = tags;
//     }
// 
//     public Product(final int id, final String name, final double price, final Discount discount) {
//         this.id = id;
//         this.name = name;
//         this.price = price;
//         this.discount = discount;
//         this.tags = null;
//     }
// 
//     public Product(final int id, final String name, final double price) {
//         this.id = id;
//         this.name = name;
//         this.price = price;
//         this.discount = null;
//         this.tags = null;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public double getPrice() {
//         return price;
//     }
// 
//     public Optional<Discount> getDiscount() {
//         return Optional.ofNullable(discount);
//     }
// 
//     public Optional<List<String>> getTags() {
//         return Optional.ofNullable(tags);
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (!(o instanceof Product)) return false;
//         Product product = (Product) o;
//         return id == product.id &&
//                 Objects.equals(name, product.name) &&
//                 Objects.equals(price, product.price);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(id, name, price);
//     }
// 
//     @Override
//     public String toString() {
//         return id + ", " + name + ": " + price;
//     }
// }
// 
// 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/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/StoreSection.java
// public enum StoreSection {
//     Tablets,
//     Monitors,
//     Laptops
// }


import net.safedata.java8.training.model.Product;
import net.safedata.java8.training.model.Section;
import net.safedata.java8.training.bootstrap.StoreSetup;
import net.safedata.java8.training.model.StoreSection;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
package net.safedata.java8.training.predicate.service;



/**
 * A simple service for managing {@link Product} entities
 *
 * @author bogdan.solga
 */
public class ProductService {

    public List<Product> getNexusTablets() {
        final Section tablets = getTablets();

        final List<Product> products = getProductsOrThrow(tablets);

        return getNexusTablets(products);
    }

    private Section getTablets() {
        return StoreSetup.getDefaultStore()
                         .getStoreSections()
// Path: domain-model/src/main/java/net/safedata/java8/training/model/Product.java
// public class Product extends AbstractEntity {
// 
//     private final int id;
//     private final String name;
//     private final double price;
//     private final Discount discount;
//     private final List<String> tags;
// 
//     public Product(final int id, final String name, final double price, final Discount discount,
//                    final List<String> tags) {
//         this.id = id;
//         this.name = name;
//         this.price = price;
//         this.discount = discount;
//         this.tags = tags;
//     }
// 
//     public Product(final int id, final String name, final double price, final Discount discount) {
//         this.id = id;
//         this.name = name;
//         this.price = price;
//         this.discount = discount;
//         this.tags = null;
//     }
// 
//     public Product(final int id, final String name, final double price) {
//         this.id = id;
//         this.name = name;
//         this.price = price;
//         this.discount = null;
//         this.tags = null;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public double getPrice() {
//         return price;
//     }
// 
//     public Optional<Discount> getDiscount() {
//         return Optional.ofNullable(discount);
//     }
// 
//     public Optional<List<String>> getTags() {
//         return Optional.ofNullable(tags);
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (!(o instanceof Product)) return false;
//         Product product = (Product) o;
//         return id == product.id &&
//                 Objects.equals(name, product.name) &&
//                 Objects.equals(price, product.price);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(id, name, price);
//     }
// 
//     @Override
//     public String toString() {
//         return id + ", " + name + ": " + price;
//     }
// }
// 
// 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/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/StoreSection.java
// public enum StoreSection {
//     Tablets,
//     Monitors,
//     Laptops
// }


// Path: s01/s01e02-predicates/src/main/java/net/safedata/java8/training/predicate/service/ProductService.java
import net.safedata.java8.training.model.Product;
import net.safedata.java8.training.model.Section;
import net.safedata.java8.training.bootstrap.StoreSetup;
import net.safedata.java8.training.model.StoreSection;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

package net.safedata.java8.training.predicate.service;



/**
 * A simple service for managing {@link Product} entities
 *
 * @author bogdan.solga
 */
public class ProductService {

    public List<Product> getNexusTablets() {
        final Section tablets = getTablets();

        final List<Product> products = getProductsOrThrow(tablets);

        return getNexusTablets(products);
    }

    private Section getTablets() {
        return StoreSetup.getDefaultStore()
                         .getStoreSections()
                         .stream()