// 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: s01/s01e02-predicates/src/main/java/net/safedata/java8/training/predicate/service/ProductService.java
// 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()
//                          .filter(tabletsSection())
//                          .findFirst()
//                          .orElseThrow(() -> new IllegalArgumentException("There's no section named 'Tablets'"));
//     }
// 
//     private List<Product> getProductsOrThrow(final Section tablets) {
//         return tablets.getProducts()
//                       .orElseThrow(() -> new IllegalArgumentException("There are no available tablets"));
//     }
// 
//     private List<Product> getNexusTablets(final List<Product> products) {
//         return products.stream()
//                        .filter(product -> product.getName().toLowerCase().contains("nexus"))
//                        .collect(Collectors.toList());
//     }
// 
//     private Predicate<Section> tabletsSection() {
//         return section -> section.getName().equals(StoreSection.Tablets);
//     }
// }


import net.safedata.java8.training.model.Product;
import net.safedata.java8.training.predicate.service.ProductService;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
        multipleStatementsMethodPredicate.test(441d);

        // TODO try other simple predicates - Integer, String, ...
    }

    private static void removeCollectionItems() {
        // removing the elements of a collection - imperative and functional

        // imperative way
        final List<String> strings = Arrays.asList("I want a holiday".split(" "));
        final Iterator<String> iterator = strings.iterator();
        while (iterator.hasNext()) {
            String value = iterator.next();
            if (value.length() < 2) {
                iterator.remove();
            }
        }

        // functional way
        strings.removeIf(value -> value.length() < 2);
    }

    private static void productPredicates() {
        final Product product = new Product(10, "iSomething", 500);
        final Predicate<Product> hasAppleBranding = it -> it.getName().startsWith("i");
        System.out.println(hasAppleBranding.test(product));

        Predicate<Product> isCheap = it -> it.getPrice() < 100;
        System.out.println(isCheap.test(product));

// 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: s01/s01e02-predicates/src/main/java/net/safedata/java8/training/predicate/service/ProductService.java
// 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()
//                          .filter(tabletsSection())
//                          .findFirst()
//                          .orElseThrow(() -> new IllegalArgumentException("There's no section named 'Tablets'"));
//     }
// 
//     private List<Product> getProductsOrThrow(final Section tablets) {
//         return tablets.getProducts()
//                       .orElseThrow(() -> new IllegalArgumentException("There are no available tablets"));
//     }
// 
//     private List<Product> getNexusTablets(final List<Product> products) {
//         return products.stream()
//                        .filter(product -> product.getName().toLowerCase().contains("nexus"))
//                        .collect(Collectors.toList());
//     }
// 
//     private Predicate<Section> tabletsSection() {
//         return section -> section.getName().equals(StoreSection.Tablets);
//     }
// }


// Path: s01/s01e02-predicates/src/main/java/net/safedata/java8/training/predicate/PredicatesMain.java
import net.safedata.java8.training.model.Product;
import net.safedata.java8.training.predicate.service.ProductService;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

        multipleStatementsMethodPredicate.test(441d);

        // TODO try other simple predicates - Integer, String, ...
    }

    private static void removeCollectionItems() {
        // removing the elements of a collection - imperative and functional

        // imperative way
        final List<String> strings = Arrays.asList("I want a holiday".split(" "));
        final Iterator<String> iterator = strings.iterator();
        while (iterator.hasNext()) {
            String value = iterator.next();
            if (value.length() < 2) {
                iterator.remove();
            }
        }

        // functional way
        strings.removeIf(value -> value.length() < 2);
    }

    private static void productPredicates() {
        final Product product = new Product(10, "iSomething", 500);
        final Predicate<Product> hasAppleBranding = it -> it.getName().startsWith("i");
        System.out.println(hasAppleBranding.test(product));

        Predicate<Product> isCheap = it -> it.getPrice() < 100;
        System.out.println(isCheap.test(product));

        final ProductService productService = new ProductService();