Weeedooo
Weeedooo

Reputation: 557

Predicate all non null fields

I'm having simple Book class that contains fields like

private String ISBN;
private String title;
private String author;

I want to create search query, that will take BookDto as criteria, and compare all non nullable fields with elements of my List<Book>. So I wrote few simple Predicates

private Predicate<Book> matchingAuthor(Book another) {
    return book -> book.getAuthor() != null && book.getAuthor().equals(another.getAuthor());
}

private Predicate<Book> matchingTitle(Book another) {
    return book -> book.getTitle() != null && book.getTitle().equals(another.getTitle());
}

private Predicate<Book> matchingISBN(Book another) {
    return book -> book.getISBN() != null && book.getISBN().equals(another.getISBN());
}

And I'd like to have 1 search method that will handle all the logic

private List<BookDto> findMatchingBooks(BookDto criteria) {
        return books.stream().map(BookConverter::toEntity).filter(this::matchingBook).map(BookConverter::toDto).collect(Collectors.toList());
}

But this logic is ugly... and it wont work as I want.

private Predicate<Book> matchingBook(Book criteria) {
    if(criteria.getISBN() != null) {
        return matchingISBN(criteria);
    } 
    else if(criteria.getISBN() == null && criteria.getTitle() == null && criteria.getAuthor() != null) {
        return matchingAuthor(criteria);
    }
     else if(criteria.getISBN() == null && criteria.getTitle() != null && criteria.getAuthor() != null) {
        return matchingAuthor(criteria) && matchingTitle(criteria);
    }
}

First two if/else are lets say ok (ugly but working), third one is causing

bad operand types for binary operator '&&' first type: Predicate second type: Predicate

And the question is, how can I achieve this?

Upvotes: 1

Views: 1635

Answers (2)

GBlodgett
GBlodgett

Reputation: 12819

You must use Predicate::and to combine the Predicates:

return matchingAuthor(criteria).and(matchingTitle(criteria));

default Predicate<T> and(Predicate<? super T> other):

Returns a composed predicate that represents a short-circuiting logical AND of this predicate and another. When evaluating the composed predicate, if this predicate is false, then the other predicate is not evaluated. Any exceptions thrown during evaluation of either predicate are relayed to the caller; if evaluation of this predicate throws an exception, the other predicate will not be evaluated.

Upvotes: 1

Marvin
Marvin

Reputation: 14425

You need to combine your predicates using and:

return matchingAuthor(criteria).and(matchingTitle(criteria));

Returns a composed predicate that represents a short-circuiting logical AND of this predicate and another.

Upvotes: 1

Related Questions