ReflectionsUtility.java

package it.cnr.iit.utility;

import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

import it.cnr.iit.ucs.properties.base.CommonProperties;
import it.cnr.iit.utility.errorhandling.Reject;

public class ReflectionsUtility {

    private static final Logger log = Logger.getLogger( ReflectionsUtility.class.getName() );

    private ReflectionsUtility() {}

    private static <T> Set<Class<? extends T>> getSubTypesOf( String packageName, Class<T> clazz ) {
        Collection<URL> classLoadersList = ClasspathHelper.forPackage(
            packageName, ClasspathHelper.contextClassLoader(), ClasspathHelper.staticClassLoader() );

        Reflections reflections = new Reflections( new ConfigurationBuilder()
            .setScanners( new SubTypesScanner( false ) )
            .setUrls( classLoadersList )
            .filterInputsBy( new FilterBuilder().include( FilterBuilder.prefix( packageName ) ) ) );
        return reflections.getSubTypesOf( clazz );
    }

    public static <T> Optional<Class<T>> getClassFromPackageName( String name ) {
        try {
            return Optional.of( (Class<T>) Class.forName( name ) );
        } catch( ClassNotFoundException e ) {
            log.warning( e.getMessage() );
        }
        return Optional.empty();
    }

    private static <T> Optional<Class<T>> getClassFromSimpleName( String name, Class<T> clazz ) {
        Set<Class<? extends T>> classList = getSubTypesOf( "", clazz );
        for( Class<?> c : classList ) {
            if( c.getSimpleName().equalsIgnoreCase( name ) ) {
                log.log( Level.INFO, () -> "Match found for " + name + " : " + c.getName() );
                return Optional.of( (Class<T>) c );
            }
        }
        return Optional.empty();
    }

    public static <T> Optional<Class<T>> getClass( String name, Class<T> clazz ) {
        if( name.contains( "." ) ) {
            return getClassFromPackageName( name );
        }
        return getClassFromSimpleName( name, clazz );
    }

    public static <T> Optional<T> buildComponent( CommonProperties properties, Class<T> clazz ) {
        Reject.ifBlank( properties.getName() );
        try {
            Class<?> propClazz = properties.getClass().getInterfaces()[0]; // TODO UCS-32 NOSONAR
            Optional<Class<T>> actualClass = getClass( properties.getName(), clazz );
            if( actualClass.isPresent() ) {
                Constructor<?> constructor = actualClass.get().getConstructor( propClazz );
                T obj = (T) constructor.newInstance( properties );
                return Optional.of( obj );
            }
        } catch( Exception e ) {
            log.severe( () -> "Failed building " + properties.getName() + " : " + e.getMessage() );
        }
        return Optional.empty();
    }

}