import java.util.*;
import java.util.stream.*;

 
public class Main
{
	public static void main (String[] args) throws java.lang.Exception
	{
		List<Order> orderList = new ArrayList<Order>();
	    List<Shipment> shipmentList = new ArrayList<Shipment>();
	    List<Item> itemList = new ArrayList<Item>();
 
	    Shipment shipment = new Shipment();
	    shipment.setItem(itemList);
	    shipmentList.add(shipment);
 
	    Order order = new Order();
	    order.setShipment(shipmentList);
	    orderList.add(order);
 
	    List<Shipment> shipmentList2 = new ArrayList<Shipment>();
	    List<Item> itemList2 = new ArrayList<Item>();
 
	    Shipment shipment2 = new Shipment();
	    shipment2.setItem(itemList2);
	    shipmentList2.add(shipment2);
 
	    Order order2 = new Order();
	    order2.setShipment(shipmentList2);
	    orderList.add(order2);
 
	    List<Shipment> shipmentList3 = new ArrayList<Shipment>();
	    List<Item> itemList3 = new ArrayList<Item>();
 
	    Shipment shipment3 = new Shipment();
	    shipment3.setItem(itemList3);
	    shipmentList3.add(shipment3);
 
	    Order order3 = new Order();
	    order3.setShipment(shipmentList3);
	    orderList.add(order3);
 
	    Item item = new Item();
	    Item item1 = new Item();
	    Item item2 = new Item();
	    Item item3 = new Item();
	    Item item4 = new Item();
	    Item item5 = new Item();
	    Item item6 = new Item();
	    Item item7 = new Item();
 
	    Product product = new Product();
	    product.setName("Mobile");
	    Product product1 = new Product();
	    product1.setName("Mobile");
	    Product product2 = new Product();
	    product2.setName("Tv");
	    Product product3 = new Product();
	    product3.setName("AC");
	    Product product4 = new Product();
	    product4.setName("Tab");
	    Product product5 = new Product();
	    product5.setName("Bike");
	    Product product6 = new Product();
	    product6.setName("Bike");
	    Product product7 = new Product();
	    product7.setName("Bike");
 
	    item.setProduct(product);
	    item1.setProduct(product1);
	    item2.setProduct(product2);
	    item3.setProduct(product3);
	    item4.setProduct(product4);
	    item5.setProduct(product5);
	    item6.setProduct(product7);
	    item7.setProduct(product7);
 
	    itemList.add(item);
	    itemList2.add(item1);
	    itemList2.add(item2);
	    itemList3.add(item3);
	    itemList3.add(item4);
	    itemList2.add(item5);
	    itemList3.add(item6);
	    itemList.add(item7);
 
	    orderList.forEach(System.out::println);
	    System.out.println("-----------");
 
	    List<Order> filteredOrders = orderList
	            .stream()
                .filter(o -> o.getShipment().stream()
                                            .flatMap(s -> s.getItem().stream()) // stream of Item
                                            .map(i -> i.getProduct().getName()) // stream of product
                                            //.map(Product::getName) // stream of product names
                                            .anyMatch("Mobile"::equals)
                )
                .collect(Collectors.toList()); 
 
        filteredOrders.forEach(System.out::println);
        
        List<Order> filteredOrderProducts = orderList
	            .stream()
                .filter(o -> 
                        o.getShipment().stream()
                                       .flatMap(s -> s.getItem().stream()) // stream of Item
                                       .anyMatch(i -> "Mobile".equals(i.getProduct().getName()))
                )
                .map(o -> new Order(
                    o.getShipment().stream()
                                   .map(s -> new Shipment(
                                       s.getItem().stream()
                                                  .filter(i -> "Mobile".equals(i.getProduct().getName()))
                                                  .map(i -> new Item(i))
                                                  .collect(Collectors.toList())
                                   ))
                                   .collect(Collectors.toList())
                ))
                .collect(Collectors.toList()); 
        System.out.println("----\norders with filtered products");
        filteredOrderProducts.forEach(System.out::println);
	}
}
 
class Order {
    public Order(List<Shipment> shipments) {
        this.shipment = shipments;
    }
    
    public Order() {
        this(new ArrayList<>());
    }
 
    private List<Shipment> shipment;
 
    public List<Shipment> getShipment() {
        return shipment;
    }
 
    public void setShipment(List<Shipment> shipment) {
        this.shipment = shipment;
    }
    @Override
    public String toString() {
    	return "order: shipments=" + shipment;
    }
}
 
class Shipment {
 
    private List<Item> item;
    
    public Shipment(List<Item> items) {
        this.item = items;
    }
    
    public Shipment() {
        this(new ArrayList<>());
    }
 
    public List<Item> getItem() {
        return item;
    }
 
    public void setItem(List<Item> item) {
        this.item = item;
    }
 
    @Override
    public String toString() {
    	return "items=" + item;
    }
}
 
class Item {
 
    private Product product;

    public Item(Item item) {
        this(new Product(item.getProduct()));
    }
    
    public Item(Product product) {
        this.product = product;
    }
    
    public Item() {
        this((Product)null);
    }
 
    public Product getProduct() {
        return product;
    }
 
    public void setProduct(Product product) {
        this.product = product;
    }
 
    @Override
    public String toString() {
    	return ":product=" + product;
    }
}
 
class Product {
 
    private String name;
    
    public Product(Product p) {
        this(p.getName());
    }
    
    public Product(String name) {
        this.name = name;
    }
    
    public Product() {
        this("Unknown");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
    	return "product.name=" + name;
    }    
}