@Override
    @SuppressWarnings({"rawtypes", "unchecked"})
    default @NonNull CompletableFuture<@NonNull ArgumentParseResult<O>> parseFuture(
            final @NonNull CommandContext<@NonNull C> commandContext,
            final @NonNull CommandInput commandInput
    ) {
        final AggregateParsingContext<C> aggregateParsingContext = AggregateParsingContext.argumentContext(this);
        CompletableFuture<ArgumentParseResult<Object>> future = CompletableFuture.completedFuture(null);
        for (final CommandComponent<C> component : this.components()) {
            future =
                    future.thenCompose(result -> {
                        if (result != null && result.failure().isPresent()) {
                            return ArgumentParseResult.failureFuture(result.failure().get());
                        }
                        // Skip whitespace between arguments.
                        commandInput.skipWhitespace(1);
                        // Fail if there's no remaining input.
                        if (commandInput.isEmpty()) {
                            return ArgumentParseResult.failureFuture(new AggregateParseException(
                                    commandContext,
                                    component
                            ));
                        }
                        return component.parser()
                                .parseFuture(commandContext, commandInput)
                                .thenApply(value -> {
                                    if (value.parsedValue().isPresent()) {
                                        final CloudKey key = CloudKey.of(component.name(), component.valueType());
                                        aggregateParsingContext.store(key, value.parsedValue().get());
                                    } else if (value.failure().isPresent()) {
                                        return ArgumentParseResult.failure(new AggregateParseException(
                                                commandContext,
                                                "",
                                                component,
                                                value.failure().get()
                                        ));
                                    }
                                    return (ArgumentParseResult<Object>) value;
                                });
                    });
        }
        return future.thenCompose(result -> {
            if (result != null && result.failure().isPresent()) {
                return ((ArgumentParseResult<O>) result).asFuture();
            }
            return this.mapper().map(commandContext, aggregateParsingContext);
        });
    }
Returns the result mapper. It will be invoked after parsing to map the intermediate results into the output type.

@return the result mapper
cloud-core/src/main/java/org/incendo/cloud/parser/aggregate/AggregateParser.java