[jOOQ/jOOQ#12341] Add a Records::intoHierarchy Collector to turn Result into tree representations
This commit is contained in:
parent
d7ffb56ad6
commit
d6dcaa3762
@ -42,12 +42,16 @@ import static java.util.stream.Collectors.toCollection;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -573,6 +577,109 @@ public final class Records {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collector that can collect {@link Record} resulting from a
|
||||
* {@link ResultQuery} into a hierarchy of custom data types.
|
||||
* <p>
|
||||
* For example:
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* record File(String name, List<File> contents) {}
|
||||
*
|
||||
* List<File> files =
|
||||
* ctx.select(FILE.ID, FILE.PARENT_ID, FILE.NAME)
|
||||
* .from(FILE)
|
||||
* .collect(intoHierarchy(
|
||||
* r -> r.value1(),
|
||||
* r -> r.value2(),
|
||||
* (r, l) -> new File(r.value3(), l)
|
||||
* ));
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* @param <K> The key type (e.g. an <code>ID</code>)
|
||||
* @param <E> The value type (e.g. a POJO)
|
||||
* @param <R> The record type
|
||||
* @param keyMapper A function that extract a key from a record
|
||||
* @param parentKeyMapper A function that extracts the parent key from a
|
||||
* record.
|
||||
* @param recordMapper A function that maps a record and a list of child
|
||||
* values to a new value type.
|
||||
*/
|
||||
public static final <K, E, R extends Record> Collector<R, ?, List<E>> intoHierarchy(
|
||||
Function<? super R, ? extends K> keyMapper,
|
||||
Function<? super R, ? extends K> parentKeyMapper,
|
||||
BiFunction<? super R, ? super List<E>, ? extends E> recordMapper
|
||||
) {
|
||||
return intoHierarchy(keyMapper, parentKeyMapper, recordMapper, ArrayList::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collector that can collect {@link Record} resulting from a
|
||||
* {@link ResultQuery} into a hierarchy of custom data types.
|
||||
* <p>
|
||||
* For example:
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* record File(String name, List<File> contents) {}
|
||||
*
|
||||
* List<File> files =
|
||||
* ctx.select(FILE.ID, FILE.PARENT_ID, FILE.NAME)
|
||||
* .from(FILE)
|
||||
* .collect(intoHierarchy(
|
||||
* r -> r.value1(),
|
||||
* r -> r.value2(),
|
||||
* (r, l) -> new File(r.value3(), l),
|
||||
* ArrayList::new
|
||||
* ));
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* @param <K> The key type (e.g. an <code>ID</code>)
|
||||
* @param <E> The value type (e.g. a POJO)
|
||||
* @param <R> The record type
|
||||
* @param keyMapper A function that extract a key from a record
|
||||
* @param parentKeyMapper A function that extracts the parent key from a
|
||||
* record.
|
||||
* @param collectionFactory A supplier for new child value collections.
|
||||
* @param recordMapper A function that maps a record and a list of child
|
||||
* values to a new value type.
|
||||
*/
|
||||
public static final <K, E, C extends Collection<E>, R extends Record> Collector<R, ?, List<E>> intoHierarchy(
|
||||
Function<? super R, ? extends K> keyMapper,
|
||||
Function<? super R, ? extends K> parentKeyMapper,
|
||||
BiFunction<? super R, ? super C, ? extends E> recordMapper,
|
||||
Supplier<? extends C> collectionFactory
|
||||
) {
|
||||
return collectingAndThen(
|
||||
intoMap(keyMapper, r -> {
|
||||
C e = collectionFactory.get();
|
||||
return new Tuple3<R, C, E>(r, e, recordMapper.apply(r, e));
|
||||
}),
|
||||
m -> {
|
||||
List<E> r = new ArrayList<>();
|
||||
|
||||
m.forEach((k, v) -> {
|
||||
K parent = parentKeyMapper.apply(v.t1());
|
||||
E child = v.t3();
|
||||
|
||||
if (m.containsKey(parent))
|
||||
m.get(parent).t2().add(child);
|
||||
else
|
||||
r.add(child);
|
||||
});
|
||||
|
||||
return r;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static final record Tuple3<T1, T2, T3>(T1 t1, T2 t2, T3 t3) {}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user