@SuppressWarnings("unchecked")
	@PublicEvolving
	public static <IN, OUT> TypeInformation<OUT> getUnaryOperatorReturnType(
		Function function,
		Class<?> baseClass,
		int inputTypeArgumentIndex,
		int outputTypeArgumentIndex,
		int[] lambdaOutputTypeArgumentIndices,
		TypeInformation<IN> inType,
		String functionName,
		boolean allowMissing) {

		Preconditions.checkArgument(inType == null || inputTypeArgumentIndex >= 0, "Input type argument index was not provided");
		Preconditions.checkArgument(outputTypeArgumentIndex >= 0, "Output type argument index was not provided");
		Preconditions.checkArgument(
			lambdaOutputTypeArgumentIndices != null,
			"Indices for output type arguments within lambda not provided");

		// explicit result type has highest precedence
		if (function instanceof ResultTypeQueryable) {
			return ((ResultTypeQueryable<OUT>) function).getProducedType();
		}

		// perform extraction
		try {
			final LambdaExecutable exec;
			try {
				exec = checkAndExtractLambda(function);
			} catch (TypeExtractionException e) {
				throw new InvalidTypesException("Internal error occurred.", e);
			}
			if (exec != null) {

				// parameters must be accessed from behind, since JVM can add additional parameters e.g. when using local variables inside lambda function
				// paramLen is the total number of parameters of the provided lambda, it includes parameters added through closure
				final int paramLen = exec.getParameterTypes().length;

				final Method sam = TypeExtractionUtils.getSingleAbstractMethod(baseClass);

				// number of parameters the SAM of implemented interface has; the parameter indexing applies to this range
				final int baseParametersLen = sam.getParameterTypes().length;

				final Type output;
				if (lambdaOutputTypeArgumentIndices.length > 0) {
					output = TypeExtractionUtils.extractTypeFromLambda(
						baseClass,
						exec,
						lambdaOutputTypeArgumentIndices,
						paramLen,
						baseParametersLen);
				} else {
					output = exec.getReturnType();
					TypeExtractionUtils.validateLambdaType(baseClass, output);
				}

				return new TypeExtractor().privateCreateTypeInfo(output, inType, null);
			} else {
				if (inType != null) {
					validateInputType(baseClass, function.getClass(), inputTypeArgumentIndex, inType);
				}
				return new TypeExtractor().privateCreateTypeInfo(baseClass, function.getClass(), outputTypeArgumentIndex, inType, null);
			}
		}
		catch (InvalidTypesException e) {
			if (allowMissing) {
				return (TypeInformation<OUT>) new MissingTypeInfo(functionName != null ? functionName : function.toString(), e);
			} else {
				throw e;
			}
		}
	}
@ SuppressWarnings ( "unchecked" ) @ PublicEvolving public static < IN , OUT > TypeInformation < OUT > getUnaryOperatorReturnType ( Function function , Class < ? > baseClass , int inputTypeArgumentIndex , int outputTypeArgumentIndex , int [ ] lambdaOutputTypeArgumentIndices , TypeInformation < IN > inType , String functionName , boolean allowMissing ) { Preconditions . checkArgument ( inType == null || inputTypeArgumentIndex >= 0 , "Input type argument index was not provided" ) ; Preconditions . checkArgument ( outputTypeArgumentIndex >= 0 , "Output type argument index was not provided" ) ; Preconditions . checkArgument ( lambdaOutputTypeArgumentIndices != null , "Indices for output type arguments within lambda not provided" ) ; if ( function instanceof ResultTypeQueryable ) { return ( ( ResultTypeQueryable < OUT > ) function ) . getProducedType ( ) ; } try { final LambdaExecutable exec ; try { exec = checkAndExtractLambda ( function ) ; } catch ( TypeExtractionException e ) { throw new InvalidTypesException ( "Internal error occurred." , e ) ; } if ( exec != null ) { final int paramLen = exec . getParameterTypes ( ) . length ; final Method sam = TypeExtractionUtils . getSingleAbstractMethod ( baseClass ) ; final int baseParametersLen = sam . getParameterTypes ( ) . length ; final Type output ; if ( lambdaOutputTypeArgumentIndices . length > 0 ) { output = TypeExtractionUtils . extractTypeFromLambda ( baseClass , exec , lambdaOutputTypeArgumentIndices , paramLen , baseParametersLen ) ; } else { output = exec . getReturnType ( ) ; TypeExtractionUtils . validateLambdaType ( baseClass , output ) ; } return new TypeExtractor ( ) . privateCreateTypeInfo ( output , inType , null ) ; } else { if ( inType != null ) { validateInputType ( baseClass , function . getClass ( ) , inputTypeArgumentIndex , inType ) ; } return new TypeExtractor ( ) . privateCreateTypeInfo ( baseClass , function . getClass ( ) , outputTypeArgumentIndex , inType , null ) ; } } catch ( InvalidTypesException e ) { if ( allowMissing ) { return ( TypeInformation < OUT > ) new MissingTypeInfo ( functionName != null ? functionName : function . toString ( ) , e ) ; } else { throw e ; } } }
Returns the unary operator's return type.

<p>This method can extract a type in 4 different ways:

<p>1. By using the generics of the base class like MyFunction<X, Y, Z, IN, OUT>.
This is what outputTypeArgumentIndex (in this example "4") is good for.

<p>2. By using input type inference SubMyFunction<T, String, String, String, T>.
This is what inputTypeArgumentIndex (in this example "0") and inType is good for.

<p>3. By using the static method that a compiler generates for Java lambdas.
This is what lambdaOutputTypeArgumentIndices is good for. Given that MyFunction has
the following single abstract method:

<pre>
<code>
void apply(IN value, Collector<OUT> value)
</code>
</pre>

<p> Lambda type indices allow the extraction of a type from lambdas. To extract the
output type <b>OUT</b> from the function one should pass {@code new int[] {1, 0}}.
"1" for selecting the parameter and 0 for the first generic in this type.
Use {@code TypeExtractor.NO_INDEX} for selecting the return type of the lambda for
extraction or if the class cannot be a lambda because it is not a single abstract
method interface.

<p>4. By using interfaces such as {@link TypeInfoFactory} or {@link ResultTypeQueryable}.

<p>See also comments in the header of this class.

@param function Function to extract the return type from
@param baseClass Base class of the function
@param inputTypeArgumentIndex Index of input generic type in the base class specification (ignored if inType is null)
@param outputTypeArgumentIndex Index of output generic type in the base class specification
@param lambdaOutputTypeArgumentIndices Table of indices of the type argument specifying the input type. See example.
@param inType Type of the input elements (In case of an iterable, it is the element type) or null
@param functionName Function name
@param allowMissing Can the type information be missing (this generates a MissingTypeInfo for postponing an exception)
@param <IN> Input type
@param <OUT> Output type
@return TypeInformation of the return type of the function