package com.zenika.util;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import static com.zenika.util.Try.Type.FAILURE;
import static com.zenika.util.Try.Type.SUCCESS;
/**
* A Collector implementation processing elements as long as results are success
* @param <E>
*/
public class TryCollector<E> implements Collector<Supplier<Try<E>>, Map<Try.Type, LinkedList<Try<E>>>, Try<List<E>>> {
@Override
public Supplier<Map<Try.Type, LinkedList<Try<E>>>> supplier() {
return () -> {
HashMap<Try.Type, LinkedList<Try<E>>> map = new HashMap<>();
map.put(SUCCESS, new LinkedList<>());
map.put(FAILURE, new LinkedList<>());
return map;
};
}
@Override
public BiConsumer<Map<Try.Type, LinkedList<Try<E>>>, Supplier<Try<E>>> accumulator() {
return (results, supplier) -> {
if(results.get(FAILURE).isEmpty()) {
Try<E> result = supplier.get();
results.get(result.getType()).add(result);
}
};
}
@Override
public BinaryOperator<Map<Try.Type, LinkedList<Try<E>>>> combiner() {
return (left, right) -> {
if(!left.get(FAILURE).isEmpty()) {
return left;
}
if(!right.get(FAILURE).isEmpty()) {
return right;
}
left.get(SUCCESS).addAll(right.get(SUCCESS));
return left;
};
}
@Override
public Function<Map<Try.Type, LinkedList<Try<E>>>, Try<List<E>>> finisher() {
return results -> {
if(results.get(FAILURE).isEmpty()) {
List<E> collect = results.get(SUCCESS).stream().
map(success -> success.asSuccess().getResult()).
collect(Collectors.toList());
return new Success<>(collect);
} else {
return (Failure<List<E>>) results.get(FAILURE).pop();
}
};
}
@Override
public Set<Characteristics> characteristics() {
return new HashSet<>(0);
}
}