io.github.springwolf.plugins.cloudstream.asyncapi.scanners.common.FunctionalChannelBeanBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of springwolf-cloud-stream Show documentation
Show all versions of springwolf-cloud-stream Show documentation
Automated JSON API documentation for Spring Boot cloud stream functions
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.plugins.cloudstream.asyncapi.scanners.common;
import io.github.springwolf.core.asyncapi.scanners.common.payload.TypeToClassConverter;
import lombok.RequiredArgsConstructor;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static java.util.stream.Collectors.toList;
@RequiredArgsConstructor
public class FunctionalChannelBeanBuilder {
private final TypeToClassConverter typeToClassConverter;
public Set build(AnnotatedElement element) {
Class> type = getRawType(element);
if (Consumer.class.isAssignableFrom(type)) {
Class> payloadType = getTypeGenerics(element).get(0);
return Set.of(ofConsumer(element, payloadType));
}
if (Supplier.class.isAssignableFrom(type)) {
Class> payloadType = getTypeGenerics(element).get(0);
return Set.of(ofSupplier(element, payloadType));
}
if (Function.class.isAssignableFrom(type)) {
Class> inputType = getTypeGenerics(element).get(0);
Class> outputType = getTypeGenerics(element).get(1);
return Set.of(ofConsumer(element, inputType), ofSupplier(element, outputType));
}
return Collections.emptySet();
}
private static Class> getRawType(AnnotatedElement element) {
if (element instanceof Method m) {
return m.getReturnType();
}
if (element instanceof Class> c) {
return c;
}
throw new IllegalArgumentException("Must be a Method or Class");
}
private static FunctionalChannelBeanData ofConsumer(AnnotatedElement element, Class> payloadType) {
String name = getElementName(element);
String cloudStreamBinding = firstCharToLowerCase(name) + "-in-0";
return new FunctionalChannelBeanData(
name, element, payloadType, FunctionalChannelBeanData.BeanType.CONSUMER, cloudStreamBinding);
}
private static FunctionalChannelBeanData ofSupplier(AnnotatedElement element, Class> payloadType) {
String name = getElementName(element);
String cloudStreamBinding = firstCharToLowerCase(name) + "-out-0";
return new FunctionalChannelBeanData(
name, element, payloadType, FunctionalChannelBeanData.BeanType.SUPPLIER, cloudStreamBinding);
}
private static String firstCharToLowerCase(String name) {
return name.substring(0, 1).toLowerCase() + name.substring(1);
}
private static String getElementName(AnnotatedElement element) {
if (element instanceof Method m) {
return m.getName();
}
if (element instanceof Class> c) {
return c.getSimpleName();
}
throw new IllegalArgumentException("Must be a Method or Class");
}
private List> getTypeGenerics(AnnotatedElement element) {
if (element instanceof Method m) {
ParameterizedType genericReturnType = (ParameterizedType) m.getGenericReturnType();
return getTypeGenerics(genericReturnType);
}
if (element instanceof Class> c) {
return getTypeGenerics(c);
}
throw new IllegalArgumentException("Must be a Method or Class");
}
private List> getTypeGenerics(Class> c) {
Predicate> isConsumerPredicate = Consumer.class::isAssignableFrom;
Predicate> isSupplierPredicate = Supplier.class::isAssignableFrom;
Predicate> isFunctionPredicate = Function.class::isAssignableFrom;
Predicate> hasFunctionalInterfacePredicate =
isConsumerPredicate.or(isSupplierPredicate).or(isFunctionPredicate);
return Arrays.stream(c.getGenericInterfaces())
.filter(type -> type instanceof ParameterizedType)
.map(type -> (ParameterizedType) type)
.filter(type -> type.getRawType() instanceof Class>)
.filter(type -> hasFunctionalInterfacePredicate.test((Class>) type.getRawType()))
.map(this::getTypeGenerics)
.findFirst()
.orElse(Collections.emptyList());
}
private List> getTypeGenerics(ParameterizedType parameterizedType) {
return Arrays.stream(parameterizedType.getActualTypeArguments())
.map(typeToClassConverter::extractClass)
.collect(toList());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy