public static <T> FluentFutureStream<T> unboxStream(FluentFutureStream<Stream<T>> streams) { return FluentFutureStream.of( streams.completableFuture() .thenApply(StreamUtils::flatten)); }
@Override public List<Mailbox> findNonPersonalMailboxes(String userName, Right right) { return FluentFutureStream.of(userMailboxRightsDAO.listRightsForUser(userName) .thenApply(map -> toAuthorizedMailboxIds(map, right))) .map(this::retrieveMailbox, FluentFutureStream::unboxFutureOptional) .join() .collect(Guavate.toImmutableList()); }
private CompletableFuture<Stream<SimpleMailboxMessage>> expungeUidChunk(CassandraId mailboxId, Collection<MessageUid> uidChunk) { return FluentFutureStream.of( uidChunk.stream().map(uid -> retrieveComposedId(mailboxId, uid)), FluentFutureStream::unboxOptional) .performOnAll(this::deleteUsingMailboxId) .map(idWithMetadata -> FluentFutureStream.of( messageDAO.retrieveMessages(ImmutableList.of(idWithMetadata), FetchType.Metadata, Limit.unlimited())), FluentFutureStream::unboxFluentFuture) .filter(CassandraMessageDAO.MessageResult::isFound) .map(CassandraMessageDAO.MessageResult::message) .map(pair -> pair.getKey().toMailboxMessage(ImmutableList.of())) .completableFuture(); }
public static <T> FluentFutureStream<T> unboxFluentFuture(FluentFutureStream<FluentFutureStream<T>> futures) { return unboxStream( unboxFuture( futures.map(FluentFutureStream::completableFuture))); }
public static <T> FluentFutureStream<T> unboxOptional(FluentFutureStream<Optional<T>> optionals) { return unboxStream(optionals.map(OptionalUtils::toStream)); }
private List<Mailbox> toMailboxes(MailboxPath path, CompletableFuture<Stream<CassandraIdAndPath>> listUserMailboxes) { Pattern regex = Pattern.compile(constructEscapedRegexForMailboxNameMatching(path)); return FluentFutureStream.of(listUserMailboxes) .filter(idAndPath -> regex.matcher(idAndPath.getMailboxPath().getName()).matches()) .map(this::retrieveMailbox, FluentFutureStream::unboxFutureOptional) .join() .collect(Guavate.toImmutableList()); }
@Test void thenPerformOnAllShouldGenerateASynchronousSideEffectForAllElementsOfTheUnderlyingStream() { ConcurrentLinkedDeque<Integer> sideEffects = new ConcurrentLinkedDeque<>(); FluentFutureStream.of( CompletableFuture.completedFuture( Stream.of(1, 2, 3))) .performOnAll(i -> { sideEffects.addLast(i); return CompletableFuture.completedFuture(null); }) .join() .collect(Guavate.toImmutableList()); assertThat(sideEffects).containsOnly(1, 2, 3); }
private CompletableFuture<FlagsUpdateStageResult> performUpdatesForChunk(CassandraId mailboxId, FlagsUpdateCalculator flagsUpdateCalculator, Long newModSeq, Collection<ComposedMessageIdWithMetaData> uidChunk) { Stream<CompletableFuture<FlagsUpdateStageResult>> updateMetaDataFuture = uidChunk.stream().map(oldMetadata -> tryFlagsUpdate(flagsUpdateCalculator, newModSeq, oldMetadata)); return FluentFutureStream.of(updateMetaDataFuture) .reduce(FlagsUpdateStageResult.none(), FlagsUpdateStageResult::merge) .thenCompose(result -> updateIndexesForUpdatesResult(mailboxId, result)); }
public CompletableFuture<ImmutableList<Attachment>> getAttachmentsAsFuture(Collection<AttachmentId> attachmentIds) { Preconditions.checkArgument(attachmentIds != null); Stream<CompletableFuture<Optional<Attachment>>> attachments = attachmentIds .stream() .distinct() .map(id -> getAttachmentInternal(id) .thenApply(finalValue -> logNotFound(id, finalValue))); return FluentFutureStream.of(attachments, FluentFutureStream::unboxOptional) .collect(Guavate.toImmutableList()); }
/** * Apply a transformation to all value of the underlying stream. * * As the supplied transformation produces futures of stream, we need to compose then flatMap the returned values. */ public <U> FluentFutureStream<U> thenFlatCompose(Function<T, CompletableFuture<Stream<U>>> function) { return FluentFutureStream.of( CompletableFutureUtil.thenComposeOnAll(completableFuture(), function)) .flatMap(Function.identity()); }
/** * Apply a transformation to all value of the underlying stream. * * As the supplied transformation produces futures of optionals, we need to compose then unbox the returned values. */ public <U> FluentFutureStream<U> thenFlatComposeOnOptional(Function<T, CompletableFuture<Optional<U>>> function) { return FluentFutureStream.of( CompletableFutureUtil.thenComposeOnAll(completableFuture(), function)) .flatMapOptional(Function.identity()); }
@Test public void flatMapOptionalShouldTransformUnderlyingValuesAndUnboxResult() { assertThat( FluentFutureStream.of( CompletableFuture.completedFuture( Stream.of(1, 2, 3))) .flatMapOptional(i -> Optional.of(i + 1) .filter(j -> j % 2 == 0)) .join() .collect(Guavate.toImmutableList())) .containsExactly(2, 4); }
@Test public void thenComposeOnAllShouldTransformUnderlyingValuesAndComposeFutures() { assertThat( FluentFutureStream.of( CompletableFuture.completedFuture( Stream.of(1, 2, 3))) .thenComposeOnAll(i -> CompletableFuture.completedFuture(i + 1)) .join() .collect(Guavate.toImmutableList())) .containsExactly(2, 3, 4); }
@Test public void thenFlatComposeShouldTransformUnderlyingValuesAndComposeFuturesWithStreamUnboxing() { assertThat( FluentFutureStream.of( CompletableFuture.completedFuture( Stream.of(1, 2, 3))) .thenFlatCompose(i -> CompletableFuture.completedFuture(Stream.of(i, i + 1))) .join() .collect(Guavate.toImmutableList())) .containsExactly(1, 2, 2, 3, 3, 4); }
@Test public void thenFlatComposeOnOptionalShouldTransformUnderlyingValuesAndComposeFuturesWithOptionalUnboxing() { assertThat( FluentFutureStream.of( CompletableFuture.completedFuture( Stream.of(1, 2, 3))) .thenFlatComposeOnOptional(i -> CompletableFuture.completedFuture(Optional.of(i + 1) .filter(j -> j % 2 == 0))) .join() .collect(Guavate.toImmutableList())) .containsExactly(2, 4); }