package org.vertexium.util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.vertexium.Element;
import org.vertexium.VertexiumException;
import org.vertexium.query.Query;
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 java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class StreamUtils {
private StreamUtils() {
}
/**
* Create a {@link java.util.stream.Stream} containing the results of executing the queries, in order. The results
* are not loaded into memory first.
*/
public static Stream<Element> stream(Query... queries) {
return Arrays.stream(queries)
.map(query -> StreamSupport.stream(query.elements().spliterator(), false))
.reduce(Stream::concat)
.orElseGet(Stream::empty);
}
/**
* Create a {@link java.util.stream.Stream} over the elements of the iterables, in order. A list of iterators
* is first created from the iterables, and passed to {@link #stream(Iterator[])}. The iterable elements are not
* loaded into memory first.
*/
@SafeVarargs
@SuppressWarnings("unchecked")
public static <T> Stream<T> stream(Iterable<T>... iterables) {
List<Iterator<T>> iterators = Arrays.stream(iterables)
.map(Iterable::iterator)
.collect(Collectors.toList());
return stream(iterators.toArray(new Iterator[iterables.length]));
}
/**
* Create a {@link java.util.stream.Stream} over the elements of the iterators, in order. The iterator elements
* are not loaded into memory first.
*/
@SafeVarargs
public static <T> Stream<T> stream(Iterator<T>... iterators) {
return withCloseHandler(
Arrays.stream(iterators)
.map(StreamUtils::streamForIterator)
.reduce(Stream::concat)
.orElseGet(Stream::empty),
iterators
);
}
@SafeVarargs
private static <T> Stream<T> withCloseHandler(Stream<T> stream, Iterator<T>... iterators) {
return stream.onClose(() -> {
for (Iterator<T> iterator : iterators) {
if (iterator instanceof AutoCloseable) {
try {
((AutoCloseable) iterator).close();
} catch (Exception ex) {
throw new VertexiumException(
String.format("exception occurred when closing %s", iterator.getClass().getName()),
ex
);
}
}
}
});
}
private static <T> Stream<T> streamForIterator(Iterator<T> iterator) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
}
public static <T> Collector<T, ImmutableList.Builder<T>, ImmutableList<T>> toImmutableList() {
return Collector.of(
ImmutableList.Builder<T>::new,
ImmutableList.Builder<T>::add,
(l, r) -> l.addAll(r.build()),
ImmutableList.Builder<T>::build
);
}
public static <T> Collector<T, ImmutableSet.Builder<T>, ImmutableSet<T>> toImmutableSet() {
return Collector.of(
ImmutableSet.Builder::new,
ImmutableSet.Builder::add,
(l, r) -> l.addAll(r.build()),
ImmutableSet.Builder<T>::build,
Collector.Characteristics.UNORDERED
);
}
public static <T, K, V> Collector<T, ImmutableMap.Builder<K, V>, ImmutableMap<K, V>> toImmutableMap(
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper
) {
return Collector.of(
ImmutableMap.Builder<K, V>::new,
(r, t) -> r.put(keyMapper.apply(t), valueMapper.apply(t)),
(l, r) -> l.putAll(r.build()),
ImmutableMap.Builder::build,
Collector.Characteristics.UNORDERED
);
}
public static <T> Collector<T, LinkedHashSet<T>, LinkedHashSet<T>> toLinkedHashSet() {
return Collector.of(
LinkedHashSet::new,
HashSet::add,
(a1, a2) -> {
LinkedHashSet<T> results = new LinkedHashSet<T>();
results.addAll(a1);
results.addAll(a2);
return results;
},
ts -> ts
);
}
}