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

io.katharsis.utils.ClassUtils Maven / Gradle / Ivy

There is a newer version: 3.0.2
Show newest version
package io.katharsis.utils;

import io.katharsis.resource.annotations.JsonApiResource;
import io.katharsis.resource.exception.ResourceException;
import io.katharsis.utils.java.Optional;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Provides reflection methods for parsing information about a class.
 */
public class ClassUtils {

    private static final ClassUtils INSTANCE = new ClassUtils();

    private ClassUtils() {
    }

    /**
     * Returns a list of class fields. Supports inheritance and doesn't return synthetic fields.
     *
     * @param beanClass class to be searched for
     * @return a list of found fields
     */
    public static List getClassFields(Class beanClass) {
        Map result = new HashMap<>();

        Class currentClass = beanClass;
        while (currentClass != null && currentClass != Object.class) {
            for (Field field : currentClass.getDeclaredFields()) {
                if (!field.isSynthetic()) {
                    Field v = result.get(field.getName());
                    if (v == null) {
                        result.put(field.getName(), field);
                    }
                }
            }
            currentClass = currentClass.getSuperclass();
        }

        return new LinkedList<>(result.values());
    }

    /**
     * Returns an instance of bean's annotation
     *
     * @param beanClass       class to be searched for
     * @param annotationClass type of an annotation
     * @param              type of an annotation
     * @return an instance of an annotation
     */
    public static  Optional getAnnotation(Class beanClass, Class annotationClass) {
        Class currentClass = beanClass;
        while (currentClass != null && currentClass != Object.class) {
            if (currentClass.isAnnotationPresent(annotationClass)) {
                return Optional.of(currentClass.getAnnotation(annotationClass));
            }
            currentClass = currentClass.getSuperclass();
        }

        return Optional.empty();
    }

    /**
     * Tries to find a class fields. Supports inheritance and doesn't return synthetic fields.
     *
     * @param beanClass class to be searched for
     * @param fieldName field name
     * @return a list of found fields
     */
    public static Field findClassField(Class beanClass, String fieldName) {
        Class currentClass = beanClass;
        while (currentClass != null && currentClass != Object.class) {
            for (Field field : currentClass.getDeclaredFields()) {
                if (field.isSynthetic()) {
                    continue;
                }

                if (field.getName().equals(fieldName)) {
                    return field;
                }
            }
            currentClass = currentClass.getSuperclass();
        }

        return null;
    }

    /**
     * 

* Return a list of class getters. Supports inheritance and overriding, that is when a method is found on the * lowest level of inheritance chain, no other method can override it. *

* A getter: *

    *
  • Starts with an is if returns boolean or {@link Boolean} value
  • *
  • Starts with a get if returns non-boolean value
  • *
* * @param beanClass class to be searched for * @return a list of found getters */ public static List getClassGetters(Class beanClass) { Map result = new HashMap<>(); Class currentClass = beanClass; while (currentClass != null && currentClass != Object.class) { for (Method method : currentClass.getDeclaredMethods()) { if (INSTANCE.isGetter(method)) { Method v = result.get(method.getName()); if (v == null) { result.put(method.getName(), method); } } } currentClass = currentClass.getSuperclass(); } return new LinkedList<>(result.values()); } /** * Return a list of class setters. Supports inheritance and overriding, that is when a method is found on the * lowest level of inheritance chain, no other method can override it. * * @param beanClass class to be searched for * @return a list of found getters */ public static List getClassSetters(Class beanClass) { Map result = new HashMap<>(); Class currentClass = beanClass; while (currentClass != null && currentClass != Object.class) { for (Method method : currentClass.getDeclaredMethods()) { if (INSTANCE.isSetter(method)) { Method v = result.get(method.getName()); if (v == null) { result.put(method.getName(), method); } } } currentClass = currentClass.getSuperclass(); } return new LinkedList<>(result.values()); } /** * Return a first occurrence of a method annotated with specified annotation * * @param searchClass class to be searched * @param annotationClass annotation class * @return annotated method or null */ public static Method findMethodWith(Class searchClass, Class annotationClass) { Method foundMethod = null; methodFinder: while (searchClass != null && searchClass != Object.class) { for (Method method : searchClass.getDeclaredMethods()) { if (method.isAnnotationPresent(annotationClass)) { foundMethod = method; break methodFinder; } } searchClass = searchClass.getSuperclass(); } return foundMethod; } /** * Returns the first clazz in the ancestor hierarchy with the JsonApiResource annotation * * @param data instance * @param instance type * @return class or null */ public static Class getJsonApiResourceClass(final T data) { return getJsonApiResourceClass((Class) data.getClass()); } public static Class getJsonApiResourceClass(final Class candidateClass) { Class currentClass = candidateClass; while (currentClass != null && currentClass != Object.class) { if (currentClass.isAnnotationPresent(JsonApiResource.class)) { return currentClass; } currentClass = currentClass.getSuperclass(); } return null; } /** * Create a new instance of a resource using a default constructor * * @param clazz new instance class * @param new instance class * @return new instance */ public static T newInstance(Class clazz) { try { return clazz.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new ResourceException(String.format("couldn't create a new instance of %s", clazz)); } } private boolean isGetter(Method method) { return isBooleanGetter(method) || isNonBooleanGetter(method); } public static boolean isBooleanGetter(Method method) { if (!method.getName().startsWith("is")) return false; if (method.getName().length() < 3) return false; if (method.getParameterTypes().length != 0) { return false; } return boolean.class.equals(method.getReturnType()) || Boolean.class.equals(method.getReturnType()); } private boolean isNonBooleanGetter(Method method) { if (!method.getName().startsWith("get")) return false; if (method.getName().length() < 4) return false; if (method.getParameterTypes().length != 0) return false; return !void.class.equals(method.getReturnType()); } private static boolean isSetter(Method method) { if (!method.getName().startsWith("set")) return false; if (method.getName().length() < 4) return false; return method.getParameterTypes().length == 1; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy