/*
 * Copyright 2017-2020 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.micronaut.core.type;

import io.micronaut.core.annotation.AnnotationMetadata;
import io.micronaut.core.annotation.AnnotationMetadataProvider;
import io.micronaut.core.async.annotation.SingleResult;
import io.micronaut.core.async.publisher.Publishers;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletionStage;

Models a return type of an Executable method in Micronaut.
Author:Graeme Rocher
Type parameters:
  • <T> – The concrete type
Since:1.0
/** * Models a return type of an {@link Executable} method in Micronaut. * * @param <T> The concrete type * @author Graeme Rocher * @since 1.0 */
public interface ReturnType<T> extends TypeVariableResolver, AnnotationMetadataProvider {
Returns:The type of the argument
/** * @return The type of the argument */
Class<T> getType();
Returns:The return type as an argument
/** * @return The return type as an argument */
default Argument<T> asArgument() { Collection<Argument<?>> values = getTypeVariables().values(); return Argument.of(getType(), values.toArray(new Argument[0])); }
Returns:Is the return type suspended function (Kotlin).
Since:2.0.0
/** * @return Is the return type suspended function (Kotlin). * @since 2.0.0 */
default boolean isSuspended() { return false; }
Returns:Is the return type reactive.
Since:2.0.0
/** * @return Is the return type reactive. * @since 2.0.0 */
default boolean isReactive() { return Publishers.isConvertibleToPublisher(getType()); }
Returns:Is the return the return type a reactive completable type.
Since:2.0.0
/** * @return Is the return the return type a reactive completable type. * @since 2.0.0 */
default boolean isCompletable() { return Publishers.isCompletable(getType()); }
Returns:Is the return type a single result or multiple results
Since:2.0
/** * @return Is the return type a single result or multiple results * @since 2.0 */
default boolean isSingleResult() { if (isSpecifiedSingle()) { return true; } else { if (isReactive()) { Class<T> returnType = getType(); return Publishers.isSingle(returnType); } else { return true; } } }
Returns:Has the return type been specified to emit a single result with SingleResult.
Since:2.0
/** * @return Has the return type been specified to emit a single result with {@link SingleResult}. * @since 2.0 */
default boolean isSpecifiedSingle() { AnnotationMetadata annotationMetadata = getAnnotationMetadata(); return annotationMetadata.hasStereotype(SingleResult.class) && annotationMetadata.booleanValue(SingleResult.NAME).orElse(true); }
Returns:Is the return type asynchronous.
Since:2.0.0
/** * @return Is the return type asynchronous. * @since 2.0.0 */
default boolean isAsync() { Class<T> type = getType(); return CompletionStage.class.isAssignableFrom(type); }
Returns:Is the return type either async or reactive.
Since:2.0.0
/** * @return Is the return type either async or reactive. * @since 2.0.0 */
default boolean isAsyncOrReactive() { return isAsync() || isReactive(); }
Returns whether the return type is logically void. This includes reactive times that emit nothing (such as Completable) and asynchronous types that emit Void.
Returns:Is the return type logically void.
Since:2.0.0
/** * Returns whether the return type is logically void. This includes * reactive times that emit nothing (such as {@link io.micronaut.core.async.subscriber.Completable}) * and asynchronous types that emit {@link Void}. * * @return Is the return type logically void. * @since 2.0.0 */
default boolean isVoid() { Class<T> javaReturnType = getType(); if (javaReturnType == void.class) { return true; } else { if (isCompletable()) { return true; } if (isReactive() || isAsync()) { return getFirstTypeVariable().filter(arg -> arg.getType() == Void.class).isPresent(); } } return false; }
Returns:Is the return type Optional.
Since:2.0.1
/** * @return Is the return type {@link java.util.Optional}. * @since 2.0.1 */
default boolean isOptional() { Class<T> type = getType(); return type == Optional.class; }
Create a new return type from the given type and arguments.
Params:
  • type – The type
  • typeArguments – The type arguments
Type parameters:
  • <T1> – The return type
Returns:A ReturnType
/** * Create a new return type from the given type and arguments. * * @param type The type * @param typeArguments The type arguments * @param <T1> The return type * @return A {@link ReturnType} */
static <T1> ReturnType<T1> of(Class<T1> type, Argument<?>... typeArguments) { Map<String, Argument<?>> argumentMap = new LinkedHashMap<>(typeArguments.length); for (Argument<?> argument : typeArguments) { argumentMap.put(argument.getName(), argument); } return new ReturnType<T1>() { @Override public Class<T1> getType() { return type; } @Override public Argument[] getTypeParameters() { return typeArguments; } @Override public Map<String, Argument<?>> getTypeVariables() { return argumentMap; } }; } }