Search code examples
javaspring-data-jpaspring-restcontroller

How to avoid if statements in method which gets Optional arguments


How to avoid if statements when we have service method with Optional arguments? Below is example. At this moment only 3 arguments are Optional and I must have many if statements. Does exists any design pattern which solve this problem?

public List<Order> getForHotelOrders(Long hotelId, Optional<LocalDate> fromDate, Optional<LocalDate> toDate, Optional<List<String>> paymentTypes) {
    List<Order> orders;
    if (fromDate.isPresent() && toDate.isPresent()) {
        if (paymentTypes.isPresent()) {
            orders = orderRepository.getForHotel(hotelId, fromDate.get(), toDate.get(), paymentTypes.get());
        } else {
            orders = orderRepository.getForHotel(hotelId, fromDate.get(), toDate.get(), Arrays.asList("CASH", "CARD"));
        }
    } else {
        if (paymentTypes.isPresent()) {
            orders = orderRepository.getForHotel(hotelId, paymentTypes.get());
        } else {
            orders = orderRepository.getForHotel(hotelId, Arrays.asList("CASH", "CARD"));
        }

    }
    return orders;
}

Solution

  • I would use orElse

    static final List<String> CASH_CARD = Arrays.asList("CASH", "CARD");
    
    public List<Order> getForHotelOrders(Long hotelId, 
                                         Optional<LocalDate> fromDate, 
                                         Optional<LocalDate> toDate, 
                                         Optional<List<String>> paymentTypes) {
        List<String> paymentTypes2 = paymentTypes.orElse(CASH_CARD);
        return fromDate.isPresent() && toDate.isPresent() 
           ? orderRepository.getForHotel(hotelId, fromDate.get(), toDate.get(), paymentTypes2)
           : orderRepository.getForHotel(hotelId, paymentTypes);
    }
    

    or

    public List<Order> getForHotelOrders(long hotelId, 
                                         Optional<LocalDate> fromDate, 
                                         Optional<LocalDate> toDate, 
                                         Optional<List<String>> paymentTypes) {
        return orderRepository.getForHotel(hotelId, 
                                           fromDate.orElse(LocalDate.MIN),
                                           toDate.orElse(LocalDate.MAX),
                                           paymentTypes.orElse(CASH_CARD));
    }
    

    BTW: If you are avoiding null values I would make hotelId either a long or a OptionalLong. Having a nullable Long seems inconsistent.