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

com.github.nill14.utils.init.inject.ReflectionUtils Maven / Gradle / Ivy

package com.github.nill14.utils.init.inject;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import javax.inject.Provider;

import com.github.nill14.utils.init.api.BindingKey;
import com.github.nill14.utils.init.api.IScope;
import com.github.nill14.utils.init.binding.Binder;
import com.github.nill14.utils.init.binding.impl.BindingImpl;
import com.github.nill14.utils.init.binding.target.ProvidesMethodBindingTarget;
import com.github.nill14.utils.init.meta.AnnotationScanner;
import com.github.nill14.utils.init.meta.Provides;
import com.github.nill14.utils.init.scope.PrototypeScope;
import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken;
import com.google.common.reflect.TypeToken.TypeSet;

public enum ReflectionUtils {
	;
	
	@SuppressWarnings({ "unchecked" })
	public static  TypeToken getProviderReturnTypeToken(Class> providerClass) {
		try {
			return (TypeToken) TypeToken.of(providerClass.getMethod("get").getGenericReturnType());
		} catch (ReflectiveOperationException e) {
			throw new RuntimeException(e);
		}
	}
	
	@SuppressWarnings({ "unchecked" })
	public static  TypeToken getProviderReturnTypeToken(Provider provider) {
		return getProviderReturnTypeToken((Class>) provider.getClass());
	}
	
	@SuppressWarnings({ "unchecked" })
	public static  TypeToken getProviderReturnTypeToken(TypeToken> providerType) {
		return getProviderReturnTypeToken((Class>)providerType.getRawType());
	}
	
	public static boolean isClassPresent(String name) {
		try {
			Class.forName(name);
			return true;
		} catch(ClassNotFoundException e) {
			return false;
		}
		
	}
	
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List> scanProvidesBindings(Binder binder, Object module) {
		
		List> result = Lists.newArrayList();
		Class moduleClass = module.getClass();
		for (Method m : moduleClass.getDeclaredMethods()) {
			
			if (m.isAnnotationPresent(Provides.class)) {
				TypeToken typeToken = TypeToken.of(m.getGenericReturnType());
				ProvidesMethodBindingTarget target = new ProvidesMethodBindingTarget<>(m, module);
				
				Annotation qualifier = AnnotationScanner.findQualifier(m).orElse(null);
				Optional scopeAnnotation = AnnotationScanner.findScope(m);
				
				
				BindingKey type = BindingKey.of(typeToken, qualifier);
				IScope scope = scopeAnnotation.map(a -> binder.getScope(a.annotationType())).orElse(PrototypeScope.instance());
				
				BindingImpl binding = new BindingImpl(type, target, scope, module);				
				result.add(binding);
			}
		}
		
		return result;
	}
	
	/**
	 * 
	 * @param clazz
	 * @return All classes including self, excluding interfaces and Object.class
	 */
	public static  Stream> getSuperClasses(Class clazz) {
		return TypeToken.of(clazz)
				.getTypes()
				.stream()
				.filter(t -> !t.getRawType().isInterface())
				.filter(t -> !Object.class.equals(t.getRawType()))
				.map(t -> t.getRawType());
	}
}