package net.exoego.function.helper;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.stream.Collector;
import net.exoego.function.Func1;
import net.exoego.function.Funcs;
/**
* Utility class consists exclusively of static methods that operate on or return collectors.
*/
public final class MoreCollectors {
private MoreCollectors() {}
/**
* <p>Returns a {@code Collector} that joins the input elements into a{@code String}.</p>
* <p>The returned string representation consists of the elements in the order they are returned,
* enclosed between the {@code prefix} and {@code suffix}. Adjacent elements are delimited by the {@code separator}.
* </p>
* <p>Each element is mapped to string by the given {@code toStringMapper}.</p>
*
* @param delimiter the sequence of characters to be used between adjacent elements
* @param prefix the sequence of characters to be used at the beginning
* @param suffix the sequence of characters to be used at the end
* @param toStringMapper a function that maps element into its string representation
* @return a {@code Collector} that joins the input elements into a{@code String}
* @throws NullPointerException if {@code toStringMapper} is null.
*/
public static <T> Collector<T, ?, String> toJoinedString(
final CharSequence delimiter,
final CharSequence prefix,
final CharSequence suffix,
final Func1<? super T, String> toStringMapper) {
Objects.requireNonNull(toStringMapper);
return toJoinedString(alt(delimiter), alt(prefix), alt(suffix), toStringMapper);
}
/**
* <p>Returns a {@code Collector} that joins the input elements into a{@code String}.</p>
* <p>The returned string representation consists of the elements in the order they are returned,
* enclosed between the {@code prefix} and {@code suffix}. Adjacent elements are delimited by the {@code separator}.
* </p>
* <p>If an element is an array, it is converted to strings by toString or deepToString of {@link java.util.Arrays}.
* Otherwise elements are converted to strings by {@link String#valueOf(Object)}.</p>
*
* @param delimiter the sequence of characters to be used between adjacent elements
* @param prefix the sequence of characters to be used at the beginning
* @param suffix the sequence of characters to be used at the end
* @return a {@code Collector} that joins the input elements into a{@code String}
*/
public static <T> Collector<T, ?, String> toJoinedString(
final CharSequence delimiter, final CharSequence prefix, final CharSequence suffix) {
return toJoinedString(delimiter, prefix, suffix, Funcs.toStringCall());
}
private static String alt(final CharSequence seq) {
return seq == null ? "null" : seq.toString();
}
private static <T> Collector<T, StringJoiner, String> toJoinedString(
final String delimiter,
final String prefix,
final String suffix,
final Func1<? super T, String> toStringMapper) {
return Collector.of(() -> new StringJoiner(delimiter, prefix, suffix),
(joiner, element) -> joiner.add(toStringMapper.apply(element)),
(joiner1, joiner2) -> joiner1.merge(joiner2),
joiner -> joiner.toString());
}
}