package org.radargun.stages.stream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
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 java.util.stream.Stream;
/**
* @author Roman Macor <rmacor@redhat.com>
*/
public class WordCount implements StreamStage.StreamFunction {
private Map<Object, Object> result;
@Override
public Object apply(Stream stream) {
Object result = stream.map((Serializable & Function<Map.Entry<String, String>, String[]>) e -> e.getValue().split("[\\p{Punct}\\s&&[^'-]]+")).
flatMap((Serializable & Function<String[], Stream<String>>) Arrays::stream).
collect(serializableCollector(() -> Collectors.groupingBy(Function.identity(), Collectors.counting())));
this.result = (Map<Object, Object>) result;
return result;
}
@Override
public String getPrintableResult() {
StringBuilder sb = new StringBuilder();
for (Map.Entry<Object, Object> entry : result.entrySet()) {
sb.append(System.getProperty("line.separator"));
sb.append("key: " + entry.getKey() + " value: " + entry.getValue());
}
return sb.toString();
}
@Override
public long getResultCount() {
return result.keySet().size();
}
@FunctionalInterface
private interface SerializableSupplier<T> extends Supplier<T>, Serializable {
}
public static <T, R> Collector<T, ?, R> serializableCollector(SerializableSupplier<Collector<T, ?, R>> supplier) {
return new CollectorSupplier<>(supplier);
}
private static final class CollectorSupplier<T, R> implements Serializable, Collector<T, Object, R> {
private final Supplier<Collector<T, ?, R>> supplier;
private transient Collector<T, Object, R> collector;
CollectorSupplier(Supplier<Collector<T, ?, R>> supplier) {
this.supplier = supplier;
}
private Collector<T, Object, R> getCollector() {
if (collector == null) {
collector = (Collector<T, Object, R>) supplier.get();
}
return collector;
}
@Override
public Supplier<Object> supplier() {
return getCollector().supplier();
}
@Override
public BiConsumer<Object, T> accumulator() {
return getCollector().accumulator();
}
@Override
public BinaryOperator<Object> combiner() {
return getCollector().combiner();
}
@Override
public Function<Object, R> finisher() {
return getCollector().finisher();
}
@Override
public Set<Characteristics> characteristics() {
return getCollector().characteristics();
}
}
}