All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.pulumi.core.Output Maven / Gradle / Ivy

There is a newer version: 0.17.0
Show newest version
package com.pulumi.core;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.pulumi.core.Tuples.Tuple2;
import com.pulumi.core.Tuples.Tuple3;
import com.pulumi.core.Tuples.Tuple4;
import com.pulumi.core.Tuples.Tuple5;
import com.pulumi.core.Tuples.Tuple6;
import com.pulumi.core.Tuples.Tuple7;
import com.pulumi.core.Tuples.Tuple8;
import com.pulumi.core.internal.CompletableFutures;
import com.pulumi.core.internal.Copyable;
import com.pulumi.core.internal.Internal;
import com.pulumi.core.internal.OutputData;
import com.pulumi.core.internal.OutputInternal;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.Lists.newArrayList;
import static com.pulumi.core.internal.OutputInternal.TupleZeroOut;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toCollection;

/**
 * {@code Output}{@literal } is a key part of how Pulumi tracks dependencies
 * between {@link com.pulumi.resources.Resource}s.
 * Because the values of outputs are not available until resources are created,
 * these are represented using the special {@code Output}{@literal } type,
 * which internally represents two things:
 * 
    *
  1. An eventually available value of the output
  2. *
  3. The dependency on the source(s) of the output value
  4. *
* In fact, {@code Output}{@literal } is quite similar to {@link CompletableFuture}. * Additionally, they carry along dependency information. *

* The output properties of all resource objects in Pulumi have type {@code Output}{@literal }. */ public interface Output extends Copyable> { /** * Transforms the data of this {@link Output}{@literal } with the provided {@code func}. * The result remains an {@link Output}{@literal } so that dependent resources * can be properly tracked. *

* {@code func} is not allowed to make resources. *

* {@code func} can return other {@link Output}{@literal }s. This can be handy if * you have an Output<SomeType> and you want to get a transitive dependency of it. i.e.: *
* * Output<SomeType> d1 = ...; * Output<OtherType> {@literal d2 = d1.apply(v -> v.otherOutput);} // getting an output off of 'v'. * *

* In this example, taking a dependency on d2 means a resource will depend on all the resources * of d1. It will not depend on the resources of v.x.y.OtherDep. *

* Importantly, the Resources that d2 feels like it will depend on are the same resources * as d1. *

* If you need have multiple {@link Output}{@literal }s and a single {@link Output}{@literal } * is needed that combines both set of resources, then {@link Output#all(Output[])} * or {@link Output#tuple(Output, Output, Output)} should be used instead. *

* This function will only be called during execution of a pulumi up request. * It will not run during pulumi preview * (as the values of resources are of course not known then). * * @param type of the {@link Output} returned by {@code func} * @param func the function to apply to the current value * @return an {@link Output} after applying {@code func} */ Output apply(Function> func); /** * @param type returned by {@code func} * @param func the function to apply to the current value * @return an {@link Output} after applying {@code func} * @see Output#apply(Function) for more details. */ default Output applyValue(Function func) { return apply(t -> Output.ofNullable(func.apply(t))); } /** * Creates a shallow copy (the underlying CompletableFuture is copied) of this {@link Output}{@literal } * * @return a shallow copy of the {@link Output}{@literal } */ Output copy(); /** * Returns a new {@link Output}{@literal } which is a copy of the existing output but marked as * a non-secret. The original output or input is not modified in any way. *

Please use with caution

* * @return this {@link Output} as a non-secret */ Output asPlaintext(); /** * Returns a new {@link Output}{@literal } which is a copy of the existing output but marked as * a secret. The original output or input is not modified in any way. * * @return this {@link Output} as a secret */ Output asSecret(); // Static section ----- /** * Returns an {@code Output}{@literal } describing the given non-{@code null} value. * * @param value the value to describe, which must be non-{@code null} * @param the type of the value * @return an {@code Output}{@literal } with the value present * @throws NullPointerException if value is {@code null} */ static Output of(T value) { requireNonNull(value); return new OutputInternal<>(value); } /** * Returns an {@code Output}{@literal } describing a future value. * * @param future the future to describe, which must be non-{@code null} * @param the type of the value * @return an {@code Output}{@literal } with the value present * @throws NullPointerException if future is {@code null}, but not the future value */ static Output of(CompletableFuture future) { return new OutputInternal<>(future, false); } /** * Returns an {@code Output}{@literal } describing the given non-{@code null} secret value. * * @param value the secret value to describe, which must be non-{@code null} * @param the type of the value * @return an {@code Output}{@literal } with the value present * @throws NullPointerException if value is {@code null} */ static Output ofSecret(T value) { return new OutputInternal<>(value, true); } /** * Returns an {@code Output}{@literal } describing the given value, if * non-{@code null}, otherwise returns an empty {@code Output}{@literal }. * * @param value the possibly-{@code null} value to describe * @param the type of the value * @return an {@code Output}{@literal } with a present value if the specified value * is non-{@code null}, otherwise an empty {@code Output}{@literal } */ static Output ofNullable(@Nullable T value) { return new OutputInternal<>(value); } /** * Combines all the {@link Output}{@literal } values in {@code outputs} * into a single {@link Output}{@literal } with an {@link java.util.List}{@literal } * containing all their underlying values. *

* If any of the {@link Output}{@literal }s are not known, the final result will be not known. * Similarly, if any of the {@link Output}{@literal }s are secrets, then the final result will be a secret. * * @param the type of the value * @param outputs the outputs to be combined * @return an {@link Output} with a list of all values of the given {@code outputs} */ @SafeVarargs // safe because we only call List.of, that is also @SafeVarargs static Output> all(Output... outputs) { return all(Stream.of(outputs)); } /** * @param the type of the value * @param outputs the outputs to be combined * @return an {@link Output} with a list of all values of the given {@code outputs} * @see Output#all(Output[]) for more details. */ static Output> all(Iterable> outputs) { return all(StreamSupport.stream(outputs.spliterator(), /* not parallel */ false)); } private static Output> all(Stream> outputs) { var data = outputs .map(output -> Internal.of(output).getDataAsync()) .collect(toCollection(ArrayList::new)); // ArrayList preserves null var futureResult = CompletableFutures.flatAllOf(data) .thenApply(completed -> completed.stream().map(Output::joinOrThrow)) // already complete at this point .thenApply(Output::accumulateOutputData); return new OutputInternal<>(futureResult); } /** * Takes in a {@code formattableString} with potential {@link Output} or a regular {@link Object}. * in the 'placeholder holes'. * Conceptually, this method unwraps all the underlying values in the holes, * combines them appropriately with the {@code formattableString}, and produces an {@link Output} * containing the final result. *

* If any of the {@link Output}s are not known, the * final result will be not known. *

* Similarly, if any of the {@link Output}s are secrets, * then the final result will be a secret. * * @param formattableString The format string with same syntax as expected by {@link String#format(String, Object...)}, * the behaviour on a {@code null} argument depends on the format conversion. * @param arguments {@link Output}s or regular {@link Object}s that values of will be applied to the format String * @return an {@link Output} with the result of the formatting */ static Output format(String formattableString, @Nullable Object... arguments) { var argumentsOrEmpty = arguments == null ? List.of() : newArrayList(arguments); var outputs = argumentsOrEmpty.stream().map(Output::ensureOutput); return Output.all(outputs).applyValue(objs -> String.format(formattableString, objs.toArray())); } private static Output ensureOutput(@Nullable Object o) { if (o instanceof Output) { //noinspection unchecked return (Output) o; } return Output.ofNullable(o); } private static OutputData joinOrThrow(CompletableFuture> futureData) { var d = futureData.join(); return requireNonNull(d, "unexpected null OutputData from a CompletableFuture"); } private static OutputData> accumulateOutputData(Stream> nullableStream) { return OutputData.builder(new ArrayList()) // ArrayList preserves null .accumulate(nullableStream, (ts, t) -> { ts.add(t); return ts; }) .build(ts -> ts); } // Convenience methods for Either (a.k.a. Union) /** * Represents an {@link Output} value that can be one of two different types. * For example, it might potentially be an "Integer" some time * or a "String" in other cases. * * @param the type contained by the {@link Left} instance * @param the type contained by the {@link Right} instance * @param value the value to create the {@link Left} instance with * @return an {@link Output} holding {@link Left} instance with the given value */ static Output> ofLeft(L value) { return Output.of(Either.ofLeft(value)); } /** * @param the type contained by the {@link Left} instance * @param the type contained by the {@link Right} instance * @param value the value to create the {@link Right} instance with * @return an {@link Output} holding {@link Right} instance with the given value * @see #ofLeft(Object) */ static Output> ofRight(R value) { return Output.of(Either.ofRight(value)); } /** * @param the type contained by the {@link Left} instance * @param the type contained by the {@link Right} instance * @param value an {@link Output} with the value to create the {@link Left} instance with * @return an {@link Output} holding {@link Left} instance with the value of the given {@link Output} * @see #ofLeft(Object) */ static Output> ofLeft(Output value) { return new OutputInternal<>(Internal.of(value).getDataAsync() .thenApply(ioData -> ioData.apply(Either::ofLeft))); } /** * @param the type contained by the {@link Left} instance * @param the type contained by the {@link Right} instance * @param value an {@link Output} with the value to create the {@link Right} instance with * @return an {@link Output} holding {@link Right} instance with the value of the given {@link Output} * @see #ofLeft(Object) */ static Output> ofRight(Output value) { return new OutputInternal<>(Internal.of(value).getDataAsync() .thenApply(ioData -> ioData.apply(Either::ofRight))); } // Convenience methods for JSON /** * @return a {@link JsonNull#INSTANCE} * @see #ofJson(JsonElement) */ static Output ofJson() { return ofJson(JsonNull.INSTANCE); } /** * Represents an {@link Output} value that wraps a {@link JsonElement} * * @param json the {@link JsonElement} to wrap * @return given {@link JsonElement} wrapped in an {@link Output} */ static Output ofJson(JsonElement json) { return Output.of(json); } /** * @param json the json value to wrap * @return given json value as a {@link JsonElement} wrapped in an {@link Output} * @throws com.google.gson.JsonSyntaxException – if json is not valid * @see #ofJson(JsonElement) */ static Output parseJson(String json) { var gson = new Gson(); return ofJson(gson.fromJson(json, JsonElement.class)); } /** * @param json the json value wrapped in an {@link Output}{@literal } * @return given json value as a {@link JsonElement} wrapped in an {@link Output} * @throws com.google.gson.JsonSyntaxException – if json is not valid * @see #ofJson(JsonElement) */ static Output parseJson(Output json) { var gson = new Gson(); return json.applyValue((String j) -> gson.fromJson(j, JsonElement.class)); } // Convenience methods for List /** * Returns a shallow copy of the {@link List} wrapped in an {@link Output} * * @return an {@link Output} holding a copy of the given list */ static Output> copyOfList(List values) { return Output.of(ImmutableList.copyOf(values)); } /** * Concatenates two lists of {@link Output}, can take a {@code null} value that will be treated as an empty list, * always returns {@code non-null}. * * @param type of the list element * @param left fist list to concatenate * @param right second list to concatenate * @return an {@link Output} with {@code left} and {@code right} lists concatenated */ @Nonnull static Output> concatList(@Nullable Output> left, @Nullable Output> right) { return tuple( left == null ? Output.of(List.of()) : left, right == null ? Output.of(List.of()) : right ).applyValue(tuple -> ImmutableList.builder() .addAll(tuple.t1 == null ? List.of() : tuple.t1) .addAll(tuple.t2 == null ? List.of() : tuple.t2) .build()); } /** * @return an {@link Output} with an empty {@link List} * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList() { return Output.of(ImmutableList.of()); } /** * @return an {@link Output} value that wraps a {@link List} with one element. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1) { return Output.of(ImmutableList.of(e1)); } /** * @return an {@link Output} value that wraps a {@link List} with two elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2) { return Output.of(ImmutableList.of(e1, e2)); } /** * @return an {@link Output} value that wraps a {@link List} with three elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3) { return Output.of(ImmutableList.of(e1, e2, e3)); } /** * @return an {@link Output} value that wraps a {@link List} with four elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3, E e4) { return Output.of(ImmutableList.of(e1, e2, e3, e4)); } /** * @return an {@link Output} value that wraps a {@link List} with five elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3, E e4, E e5) { return Output.of(ImmutableList.of(e1, e2, e3, e4, e5)); } /** * @return an {@link Output} value that wraps a {@link List} with six elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3, E e4, E e5, E e6) { return Output.of(ImmutableList.of(e1, e2, e3, e4, e5, e6)); } /** * @return an {@link Output} value that wraps a {@link List} with seven elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { return Output.of(ImmutableList.of(e1, e2, e3, e4, e5, e6, e7)); } /** * @return an {@link Output} value that wraps a {@link List} with eight elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { return Output.of(ImmutableList.of(e1, e2, e3, e4, e5, e6, e7, e8)); } /** * @return an {@link Output} value that wraps a {@link List} with nine elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { return Output.of(ImmutableList.of(e1, e2, e3, e4, e5, e6, e7, e8, e9)); } /** * @return an {@link Output} value that wraps a {@link List} with ten elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { return Output.of(ImmutableList.of(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10)); } /** * @return an {@link Output} value that wraps a {@link List} with eleven elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) { return Output.of(ImmutableList.of(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11)); } /** * @return an {@link Output} value that wraps a {@link List} with twelve elements. * @see #ofList(Object) * @see #listBuilder() */ static Output> ofList(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12) { return Output.of(ImmutableList.of(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12)); } /** * @return an {@link Output} value that wraps a {@link List} with more than twelve elements. * @see #ofList(Object) * @see #listBuilder() */ @SafeVarargs static Output> ofList( E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) { return Output.of(ImmutableList.of(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, others)); } /** * Helps to build an {@link Output} that wraps a {@link List}. * * @return an {@link Output.ListBuilder}{@literal } instance * @see #ofList(Object) */ static Output.ListBuilder listBuilder() { return new Output.ListBuilder<>(); } /** * A {@link List} wrapped in an {@link Output} builder. */ final class ListBuilder { private final CompletableFutures.Builder>> builder; public ListBuilder() { builder = CompletableFutures.builder( CompletableFuture.completedFuture(OutputData.builder(ImmutableList.builder())) ); } @CanIgnoreReturnValue public Output.ListBuilder add(Output value) { this.builder.accumulate( Internal.of(value).getDataAsync(), (dataBuilder, data) -> dataBuilder.accumulate(data, ImmutableList.Builder::add) ); return this; } @CanIgnoreReturnValue public Output.ListBuilder add(E value) { this.builder.accumulate( CompletableFuture.completedFuture(OutputData.of(value)), (dataBuilder, data) -> dataBuilder.accumulate(data, ImmutableList.Builder::add) ); return this; } @SafeVarargs @CanIgnoreReturnValue public final Output.ListBuilder add(E... elements) { return addAll(List.of(elements)); } @CanIgnoreReturnValue public Output.ListBuilder addAll(Iterable elements) { this.builder.accumulate( CompletableFuture.completedFuture(OutputData.of(elements)), (dataBuilder, data) -> dataBuilder.accumulate(data, ImmutableList.Builder::addAll) ); return this; } @CanIgnoreReturnValue public Output.ListBuilder addAll(Iterator elements) { this.builder.accumulate( CompletableFuture.completedFuture(OutputData.of(elements)), (dataBuilder, data) -> dataBuilder.accumulate(data, ImmutableList.Builder::addAll) ); return this; } public Output> build() { return new OutputInternal<>(builder.build(dataBuilder -> dataBuilder.build(ImmutableList.Builder::build))); } } // Convenience methods for Map /** * Returns a shallow copy of the {@link Map} wrapped in an {@link Output} * * @return an {@link Output} holding a copy of the given map */ static Output> copyOfMap(Map values) { return Output.of(ImmutableMap.copyOf(values)); } /** * Concatenates two {@link Map} wrapped in an {@link Output}. * Returns a new instance without modifying any of the arguments. *

* If both maps contain the same key, the value from the second map takes over. *

* {@code null} values in the Output or Map layer are treated as empty maps. * * @param type of the map value * @param left The first @see {@code Output>} to concatenate * @param right The second @see {@code Output>} to concatenate, it has higher priority in case of key clash * @return an {@code Output>} that contains the items from both maps given */ static Output> concatMap(@Nullable Output> left, @Nullable Output> right) { return tuple( left == null ? Output.of(Map.of()) : left, right == null ? Output.of(Map.of()) : right ).applyValue(tuple -> Stream.concat( (tuple.t1 == null ? ImmutableMap.of() : tuple.t1).entrySet().stream(), (tuple.t2 == null ? ImmutableMap.of() : tuple.t2).entrySet().stream() ).collect(toImmutableMap( Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2 // in case of duplicate, ignore the v1 ))); } /** * @return an {@link Output} with an empty {@link Map} * @see #ofMap(String, Object) * @see #mapBuilder() */ static Output> ofMap() { return Output.of(ImmutableMap.of()); } /** * @return an {@link Output} that wraps a {@link Map} with one pair. * @see #mapBuilder() */ static Output> ofMap(String key1, V value1) { return Output.of(ImmutableMap.of(key1, value1)); } /** * @return an {@link Output} that wraps a {@link Map} with two pairs. * @see #ofMap(String, Object) * @see #mapBuilder() */ static Output> ofMap(String key1, V value1, String key2, V value2) { return Output.of(ImmutableMap.of(key1, value1, key2, value2)); } /** * @return an {@link Output} that wraps a {@link Map} with three pairs. * @see #ofMap(String, Object) * @see #mapBuilder() */ static Output> ofMap(String key1, V value1, String key2, V value2, String key3, V value3) { return Output.of(ImmutableMap.of(key1, value1, key2, value2, key3, value3)); } /** * @return an {@link Output} that wraps a {@link Map} with four pairs. * @see #ofMap(String, Object) * @see #mapBuilder() */ static Output> ofMap(String key1, V value1, String key2, V value2, String key3, V value3, String key4, V value4) { return Output.of( ImmutableMap.of(key1, value1, key2, value2, key3, value3, key4, value4)); } /** * @return an {@link Output} that wraps a {@link Map} with five pairs. * @see #ofMap(String, Object) * @see #mapBuilder() */ static Output> ofMap(String key1, V value1, String key2, V value2, String key3, V value3, String key4, V value4, String key5, V value5) { return Output.of( ImmutableMap.of(key1, value1, key2, value2, key3, value3, key4, value4, key5, value5)); } /** * Helps to build a {@link Map} wrapped in an {@link Output}. * * @see #ofMap(String, Object) */ static Output.MapBuilder mapBuilder() { return new Output.MapBuilder<>(); } /** * A {@link Map} wrapped in an {@link Output} builder. */ final class MapBuilder { private final CompletableFutures.Builder>> builder; public MapBuilder() { builder = CompletableFutures.builder( CompletableFuture.completedFuture(OutputData.builder(ImmutableMap.builder())) ); } @CanIgnoreReturnValue public Output.MapBuilder put(String key, Output value) { this.builder.accumulate( Internal.of(value).getDataAsync(), (dataBuilder, data) -> dataBuilder.accumulate(data, (mapBuilder, v) -> mapBuilder.put(key, v)) ); return this; } @CanIgnoreReturnValue public Output.MapBuilder put(String key, V value) { this.builder.accumulate( CompletableFuture.completedFuture(OutputData.of(value)), (dataBuilder, data) -> dataBuilder.accumulate(data, (mapBuilder, v) -> mapBuilder.put(key, v)) ); return this; } @CanIgnoreReturnValue public Output.MapBuilder put(Map.Entry entry) { this.builder.accumulate( CompletableFuture.completedFuture(OutputData.of(entry)), (dataBuilder, data) -> dataBuilder.accumulate(data, ImmutableMap.Builder::put) ); return this; } @CanIgnoreReturnValue public Output.MapBuilder putAll(Map map) { this.builder.accumulate( CompletableFuture.completedFuture(OutputData.of(map)), (dataBuilder, data) -> dataBuilder.accumulate(data, ImmutableMap.Builder::putAll) ); return this; } @SuppressWarnings("UnstableApiUsage") @CanIgnoreReturnValue public Output.MapBuilder putAll(Iterable> entries) { this.builder.accumulate( CompletableFuture.completedFuture(OutputData.of(entries)), (dataBuilder, data) -> dataBuilder.accumulate(data, ImmutableMap.Builder::putAll) ); return this; } public Output> build() { return new OutputInternal<>(builder.build(dataBuilder -> dataBuilder.build(ImmutableMap.Builder::build))); } } // Tuple Overloads that take various number of outputs. /** * @param type of {@code item1} * @param type of {@code item2} * @param item1 the 1st item ot the tuple * @param item2 the 2nd item ot the tuple * @return an {@link Output} holding a {@link Tuple2} with all given items * @see Output#tuple(Output, Output, Output, Output, Output, Output, Output, Output) */ static Output> tuple(Output item1, Output item2) { return tuple(item1, item2, TupleZeroOut, TupleZeroOut, TupleZeroOut, TupleZeroOut, TupleZeroOut, TupleZeroOut) .applyValue(v -> Tuples.of(v.t1, v.t2)); } /** * @param type of {@code item1} * @param type of {@code item2} * @param type of {@code item3} * @param item1 the 1st item ot the tuple * @param item2 the 2nd item ot the tuple * @param item3 the 3rd item ot the tuple * @return an {@link Output} holding a {@link Tuple3} with all given items * @see Output#tuple(Output, Output, Output, Output, Output, Output, Output, Output) */ static Output> tuple( Output item1, Output item2, Output item3 ) { return tuple(item1, item2, item3, TupleZeroOut, TupleZeroOut, TupleZeroOut, TupleZeroOut, TupleZeroOut) .applyValue(v -> Tuples.of(v.t1, v.t2, v.t3)); } /** * @param type of {@code item1} * @param type of {@code item2} * @param type of {@code item3} * @param type of {@code item4} * @param item1 the 1st item ot the tuple * @param item2 the 2nd item ot the tuple * @param item3 the 3rd item ot the tuple * @param item4 the 4th item ot the tuple * @return an {@link Output} holding a {@link Tuple4} with all given items * @see Output#tuple(Output, Output, Output, Output, Output, Output, Output, Output) */ static Output> tuple( Output item1, Output item2, Output item3, Output item4 ) { return tuple(item1, item2, item3, item4, TupleZeroOut, TupleZeroOut, TupleZeroOut, TupleZeroOut) .applyValue(v -> Tuples.of(v.t1, v.t2, v.t3, v.t4)); } /** * @param type of {@code item1} * @param type of {@code item2} * @param type of {@code item3} * @param type of {@code item4} * @param type of {@code item5} * @param item1 the 1st item ot the tuple * @param item2 the 2nd item ot the tuple * @param item3 the 3rd item ot the tuple * @param item4 the 4th item ot the tuple * @param item5 the 5th item ot the tuple * @return an {@link Output} holding a {@link Tuple5} with all given items * @see Output#tuple(Output, Output, Output, Output, Output, Output, Output, Output) */ static Output> tuple( Output item1, Output item2, Output item3, Output item4, Output item5 ) { return tuple(item1, item2, item3, item4, item5, TupleZeroOut, TupleZeroOut, TupleZeroOut) .applyValue(v -> Tuples.of(v.t1, v.t2, v.t3, v.t4, v.t5)); } /** * @param type of {@code item1} * @param type of {@code item2} * @param type of {@code item3} * @param type of {@code item4} * @param type of {@code item5} * @param type of {@code item6} * @param item1 the 1st item ot the tuple * @param item2 the 2nd item ot the tuple * @param item3 the 3rd item ot the tuple * @param item4 the 4th item ot the tuple * @param item5 the 5th item ot the tuple * @param item6 the 6th item ot the tuple * @return an {@link Output} holding a {@link Tuple6} with all given items * @see Output#tuple(Output, Output, Output, Output, Output, Output, Output, Output) */ static Output> tuple( Output item1, Output item2, Output item3, Output item4, Output item5, Output item6 ) { return tuple(item1, item2, item3, item4, item5, item6, TupleZeroOut, TupleZeroOut) .applyValue(v -> Tuples.of(v.t1, v.t2, v.t3, v.t4, v.t5, v.t6)); } /** * @param type of {@code item1} * @param type of {@code item2} * @param type of {@code item3} * @param type of {@code item4} * @param type of {@code item5} * @param type of {@code item6} * @param type of {@code item7} * @param item1 the 1st item ot the tuple * @param item2 the 2nd item ot the tuple * @param item3 the 3rd item ot the tuple * @param item4 the 4th item ot the tuple * @param item5 the 5th item ot the tuple * @param item6 the 6th item ot the tuple * @param item7 the 7th item ot the tuple * @return an {@link Output} holding a {@link Tuple7} with all given items * @see Output#tuple(Output, Output, Output, Output, Output, Output, Output, Output) */ static Output> tuple( Output item1, Output item2, Output item3, Output item4, Output item5, Output item6, Output item7 ) { return tuple(item1, item2, item3, item4, item5, item6, item7, TupleZeroOut) .applyValue(v -> Tuples.of(v.t1, v.t2, v.t3, v.t4, v.t5, v.t6, v.t7)); } /** * Combines all the {@link Output} values in the provided parameters and combines * them all into a single tuple containing each of their underlying values. * If any of the {@link Output}s are not known, the final result will be not known. Similarly, * if any of the {@link Output}s are secrets, then the final result will be a secret. * * @param type of {@code item1} * @param type of {@code item2} * @param type of {@code item3} * @param type of {@code item4} * @param type of {@code item5} * @param type of {@code item6} * @param type of {@code item7} * @param type of {@code item8} * @param item1 the 1st item ot the tuple * @param item2 the 2nd item ot the tuple * @param item3 the 3rd item ot the tuple * @param item4 the 4th item ot the tuple * @param item5 the 5th item ot the tuple * @param item6 the 6th item ot the tuple * @param item7 the 7th item ot the tuple * @param item8 the 8th item ot the tuple * @return an {@link Output} holding a {@link Tuple8} with all given items */ static Output> tuple( Output item1, Output item2, Output item3, Output item4, Output item5, Output item6, Output item7, Output item8 ) { return new OutputInternal<>(OutputData.tuple(item1, item2, item3, item4, item5, item6, item7, item8)); } }