### Question:
RecordJoiner { public Stream<Record> manyToOne(Collection<? extends Record> rights) { return manyToOne(rights.stream()); } RecordJoiner(Index<K, Record> leftIndex, JoinKey<Record, K> primaryKey); Stream<Record> manyToOne(Collection<? extends Record> rights); Stream<Record> manyToOne(Fetcher<K, Record> fetcher); Stream<Record> manyToOne(Stream<? extends Record> rights); Stream<Record> strictManyToOne(Collection<? extends Record> rights); Stream<Record> strictManyToOne(Fetcher<K, Record> fetcher); Stream<Record> strictManyToOne(Stream<? extends Record> rights); Stream<Record> oneToMany(Collection<? extends Record> rights, ListKey<Record> manyKey); Stream<Record> oneToMany(Fetcher<K, Record> fetcher, ListKey<Record> manyKey); Stream<Record> oneToMany(Stream<? extends Record> rights, ListKey<Record> manyKey); Stream<Record> strictOneToMany(Collection<? extends Record> rights, ListKey<Record> manyKey); Stream<Record> strictOneToMany(Fetcher<K, Record> fetcher, ListKey<Record> manyKey); Stream<Record> strictOneToMany(Stream<? extends Record> rights, ListKey<Record> manyKey); Stream<Record> strictOneToOne(Collection<? extends Record> rights); Stream<Record> strictOneToOne(Fetcher<K, Record> fetcher); Stream<Record> strictOneToOne(Stream<? extends Record> rights);  }### Answer:
@Test public void three_way_join() { List<Record> joined = RecordJoins.join( RecordJoins.join(books) .on(authorId) .to(id) .manyToOne(authors)) .on(publisherId) .to(id) .manyToOne(publishers) .map(r -> r.select(publisherName, authorName, bookName)) .filter(authorName.is("Alan Goodyear")) .collect(Collectors.toList()); assertThat(joined, CoreMatchers.hasItems( $$(bookName.of("Amorous Encounters"), authorName.of("Alan Goodyear"), publisherName.of("Bills And Moon")), $$(bookName.of("The Cromulence Of Truths"), authorName.of("Alan Goodyear"), publisherName.of("Servo")) ) ); }