Reputation: 399
The scenario is there are different types of filters I have created which filters the list of some objects based on the property of the object.
So for that I have created an AbstractObjectFilter class which inherited by every filter.
AbstractObjectFilter.java
public abstract class AbstractEventFilter
{
protected abstract Predicate<IEvent> isEligible();
public List<IEvent> getFilteredEvents(final List<IEvent> events)
{
return events.stream().filter(isEligible()).collect(Collectors.toList());
}
}
So now every filter extends this class and overrides the isEligible() and in that function it returns the predicate based on its properties.
For eg:- MinNumOfPrizesFilter.java
public class MinimumNumOfPrizesFilter extends AbstractEventFilter
{
private int minimumNumOfPrizes;
public MinimumNumOfPrizesFilter(@NonNull int minimumNumOfPrizes)
{
this.minimumNumOfPrizes = minimumNumOfPrizes;
}
@Override
protected Predicate<IEvent> isEligible()
{
return event -> event.getPrizeCount() >= minimumNumOfPrizes;
}
}
Similarly there are many other filters I have created. There is one applyFilter function which iterate over the list of filter objects and keep applying filter by call getFilteredEvents function.
Now how can i log the fate of each event For example - "x1 event was filtered by MinNumOfPrizesFilter filter. x1's prize count - 10 , required min prize count - 20"
Upvotes: 11
Views: 14907
Reputation: 21004
You can simply add brackets to your lambda expression and add the logging statement right before the validation :
return event -> {
// LOG.info(event.getName() + " was filtered...") or whatever you use for logging.
return event.getPrizeCount() >= minimumNumOfPrizes;
}
Note that there exists a peek
operation which is meant to be used mostly for logging on java streams :
events.stream()
.peek(event -> System.out.println("Filtering event" + event.getName()))
.filter(isEligible())
.collect(Collectors.toList());
but that is not helping here, as you need to log in AbstractEventFilter
implementations.
Upvotes: 12
Reputation: 19471
perhaps not the prettiest solution, but it works and you only change your abstract base class:
abstract class AbstractEventFilter {
private final Logger logger = Logger.getLogger(getClass().getCanonicalName());
private final String filterName = getClass().getSimpleName();
protected abstract Predicate<IEvent> isEligible();
private Predicate<IEvent> internalIsEligible() {
return iEvent -> {
boolean res = isEligible().test(iEvent);
if (!res) {
logger.info("event " + iEvent.toString() + " filtered by " + filterName);
}
return res;
};
}
public List<IEvent> getFilteredEvents(final List<IEvent> events) {
return events.stream().filter(internalIsEligible()).collect(Collectors.toList());
}
}
you keep your derived classes implementing isELigible()
as before, only in your getFilteredEvents
method, you call the internalIsEligibable
method instead.
Upvotes: 3