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

dev.soffa.foundation.commons.ClassUtil Maven / Gradle / Ivy

There is a newer version: 0.17.31
Show newest version
package dev.soffa.foundation.commons;


import com.google.gson.internal.Primitives;
import dev.soffa.foundation.error.TechnicalException;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfo;
import io.github.classgraph.ScanResult;
import lombok.SneakyThrows;
import org.checkerframework.checker.nullness.qual.NonNull;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Collectors;

public class ClassUtil {

    public static List getDeclaredFields(Class type) {
        return Arrays.stream(type.getDeclaredFields()).filter(field -> {
            // EL
            return !Modifier.isTransient(field.getModifiers());
        }).collect(Collectors.toList());
    }


    public static Set> findInterfacesAnnotatedWith(String basePackage, Class annotationClass) {
        return findInterfacesAnnotatedWith(basePackage, annotationClass, null);
    }

    public static Set> findInterfacesAnnotatedWith(String basePackage, Class annotationClass,
                                                            Class parentInterface) {
        Set> resources = new HashSet<>();
        try (ScanResult scanResult =
                 new ClassGraph()
                     .enableClassInfo()
                     .enableAnnotationInfo()
                     .acceptPackages(basePackage)
                     .addClassLoader(Thread.currentThread().getContextClassLoader())
                     .scan()) {
            for (ClassInfo ci : scanResult.getClassesWithAnnotation(annotationClass)) {
                if (ci.isInterface()) {
                    Class clazz = ci.loadClass();
                    if (parentInterface == null || parentInterface.isAssignableFrom(clazz)) {
                        resources.add(clazz);
                    }
                }
            }
        }
        return resources;
    }


    public static Type[] lookupGeneric(Class type, @NonNull Class genericClass) {
        if (type == null || type == Object.class) {
            return null;
        }

        Type[] result = null;

        final List candidates = new ArrayList<>();
        Optional.of(type.getGenericInterfaces()).ifPresent(types -> candidates.addAll(Arrays.asList(types)));
        Optional.ofNullable(type.getGenericSuperclass()).ifPresent(candidates::add);

        for (Type candidate : candidates) {
            if (candidate instanceof ParameterizedType) {
                ParameterizedType ptype = (ParameterizedType) candidate;
                result = lookupGeneric(ptype, genericClass);
            } else if (candidate instanceof Class) {
                result = lookupGeneric((Class) candidate, genericClass);
            } else {
                throw new TechnicalException("Unsupported type: " + candidate);
            }
            if (result.length > 0) {
                break;
            }
        }

        return result;
    }

    public static Type[] lookupGeneric(ParameterizedType candidate, @NonNull Type genericClass) {
        boolean matches = genericClass.equals(candidate.getRawType());
        if (matches) {
            return candidate.getActualTypeArguments();
        }
        if (candidate.getRawType() instanceof Class) {
            Class rawType = (Class) candidate.getRawType();
            if (((Class) genericClass).isAssignableFrom(rawType)) {
                return new Type[]{candidate};
            }
        }
        return new Type[]{};
    }


    public static boolean isCollection(Class type) {
        return Collection.class.isAssignableFrom(type) || type.isArray();
    }

    public static boolean isGenericCollection(Class type) {
        if (type == null) return false;
        return isCollection(type) && type.getTypeParameters().length > 0;
    }

    public static Class getGenericType(Type type) {
        if (type instanceof ParameterizedType) {
            ParameterizedType ptype = (ParameterizedType) type;
            return (Class) ptype.getActualTypeArguments()[0];
        } else {
            throw new TechnicalException("getGenericType failed");
        }
    }

    @SneakyThrows
    public static  E newInstance(Class clazz) {
        return clazz.getConstructor().newInstance();
    }

    public static boolean isBaseType(@NonNull Type type) {
        if (Primitives.isPrimitive(type) || Primitives.isWrapperType(type)) {
            return true;
        }
        if (type instanceof Class) {
            Class clazz = (Class) type;
            if (clazz.isEnum()) {
                return true;
            }
        }
        return type.getTypeName().startsWith("java.") || type.getTypeName().startsWith("javax.");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy