/*
* Copyright 2015 the original author or 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
*
* http://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 org.springframework.cloud.stream.binding;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.cloud.stream.annotation.Bindings;
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.MethodCallback;
import org.springframework.util.StringUtils;
/**
* Utility class for registering bean definitions for binding targets.
*
* @author Marius Bogoevici
* @author Dave Syer
*/
public abstract class BindingBeanDefinitionRegistryUtils {
public static void registerInputBindingTargetBeanDefinition(String qualifierValue, String name,
String bindingTargetInterfaceBeanName, String bindingTargetInterfaceMethodName,
BeanDefinitionRegistry registry) {
registerBindingTargetBeanDefinition(Input.class, qualifierValue, name, bindingTargetInterfaceBeanName,
bindingTargetInterfaceMethodName, registry);
}
public static void registerOutputBindingTargetBeanDefinition(String qualifierValue, String name,
String bindingTargetInterfaceBeanName, String bindingTargetInterfaceMethodName,
BeanDefinitionRegistry registry) {
registerBindingTargetBeanDefinition(Output.class, qualifierValue, name, bindingTargetInterfaceBeanName,
bindingTargetInterfaceMethodName, registry);
}
private static void registerBindingTargetBeanDefinition(Class<? extends Annotation> qualifier,
String qualifierValue, String name, String bindingTargetInterfaceBeanName,
String bindingTargetInterfaceMethodName, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setFactoryBeanName(bindingTargetInterfaceBeanName);
rootBeanDefinition.setUniqueFactoryMethodName(bindingTargetInterfaceMethodName);
rootBeanDefinition.addQualifier(new AutowireCandidateQualifier(qualifier, qualifierValue));
registry.registerBeanDefinition(name, rootBeanDefinition);
}
public static void registerBindingTargetBeanDefinitions(Class<?> type, final String bindingTargetInterfaceBeanName,
final BeanDefinitionRegistry registry) {
ReflectionUtils.doWithMethods(type, new MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
Input input = AnnotationUtils.findAnnotation(method, Input.class);
if (input != null) {
String name = getBindingTargetName(input, method);
registerInputBindingTargetBeanDefinition(input.value(), name, bindingTargetInterfaceBeanName,
method.getName(), registry);
}
Output output = AnnotationUtils.findAnnotation(method, Output.class);
if (output != null) {
String name = getBindingTargetName(output, method);
registerOutputBindingTargetBeanDefinition(output.value(), name, bindingTargetInterfaceBeanName,
method.getName(), registry);
}
}
});
}
public static void registerBindingTargetsQualifiedBeanDefinitions(Class<?> parent, Class<?> type,
final BeanDefinitionRegistry registry) {
if (type.isInterface()) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(BindableProxyFactory.class);
rootBeanDefinition.addQualifier(new AutowireCandidateQualifier(Bindings.class, parent));
rootBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue(type);
registry.registerBeanDefinition(type.getName(), rootBeanDefinition);
}
else {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(type);
rootBeanDefinition.addQualifier(new AutowireCandidateQualifier(Bindings.class, parent));
registry.registerBeanDefinition(type.getName(), rootBeanDefinition);
}
}
public static String getBindingTargetName(Annotation annotation, Method method) {
Map<String, Object> attrs = AnnotationUtils.getAnnotationAttributes(annotation, false);
if (attrs.containsKey("value") && StringUtils.hasText((CharSequence) attrs.get("value"))) {
return (String) attrs.get("value");
}
return method.getName();
}
}