package com.codepoetics.octarine.joins; import com.codepoetics.octarine.records.Key; import com.codepoetics.octarine.records.Record; import java.util.Collection; import java.util.Comparator; import java.util.function.Function; import java.util.stream.Stream; public final class RecordJoins { private final Stream<? extends Record> lefts; public RecordJoins(Stream<? extends Record> lefts) { this.lefts = lefts; } public static RecordJoins join(Collection<? extends Record> lefts) { return join(lefts.stream()); } public static RecordJoins join(Stream<? extends Record> lefts) { return new RecordJoins(lefts); } public <K extends Comparable<K>> JoinBuilder<K> on(Key<K> foreignKey) { return comparingWith(Comparator.<K>naturalOrder()).on(foreignKey::extract); } public static interface ComparatorCapture<K> { JoinBuilder<K> on(Function<? super Record, ? extends K> foreignKey); } public <K> ComparatorCapture<K> comparingWith(Comparator<? super K> comparator) { return f -> new JoinBuilder<>(comparator, lefts, JoinKey.on(f, comparator)); } public static final class JoinBuilder<K> { private final Comparator<? super K> comparator; private final Stream<? extends Record> lefts; private final JoinKey<Record, K> foreignKey; private JoinBuilder(Comparator<? super K> comparator, Stream<? extends Record> lefts, JoinKey<Record, K> foreignKey) { this.comparator = comparator; this.lefts = lefts; this.foreignKey = foreignKey; } public RecordJoiner<K> to(Key<? extends K> primaryKey) { return new RecordJoiner<K>(foreignKey.index(lefts), JoinKey.<Record, K>on(primaryKey::extract, comparator)); } } }