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

com.github.ykrasik.jaci.reflection.ReflectionUtils Maven / Gradle / Ivy

There is a newer version: 0.4.0
Show newest version
/******************************************************************************
 * Copyright (C) 2014 Yevgeny Krasik                                          *
 *                                                                            *
 * 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 com.github.ykrasik.jaci.reflection;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Objects;

/**
 * Utilities for dealing with reflection.
 *
 * @author Yevgeny Krasik
 */
public final class ReflectionUtils {
    private static final Class[] NO_ARGS_TYPE = {};
    private static final Object[] NO_ARGS = {};

    private ReflectionUtils() { }

    private static ReflectionAccessor accessor;

    /**
     * Set the current instance of a {@link ReflectionAccessor} to be used for all reflection calls.
     * Must be called for any reflection operations to become possible.
     *
     * @param accessor {@link ReflectionAccessor} to be used.
     */
    public static void setReflectionAccessor(ReflectionAccessor accessor) {
        ReflectionUtils.accessor = Objects.requireNonNull(accessor, "accessor");
    }

    /**
     * Creates an instance of this class through reflection. Class must have a no-args constructor.
     * Bypasses any checked exceptions that could be throw and throws them at runtime.
     *
     * @param clazz Class to instantiate.
     * @return An instance of the provided class.
     * @throws RuntimeException If an error occurred while instantiating an object of the class (for example, if the
     *                          class doesn't have a no-args constructor).
     */
    public static Object createInstanceNoArgs(Class clazz) {
        assertReflectionAccessor();
        try {
            return accessor.newInstance(clazz);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns a method with the provided name that takes no-args.
     *
     * @param clazz Class to search.
     * @param methodName Method name.
     * @return A method with the provided name that takes no-args.
     * @throws RuntimeException If the class doesn't contain a no-args method with the given name.
     */
    public static ReflectionMethod getNoArgsMethod(Class clazz, String methodName) {
        assertReflectionAccessor();
        try {
            // TODO: Support inheritance?
            return accessor.getDeclaredMethod(clazz, methodName, NO_ARGS_TYPE);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns an array containing {@code ReflectionMethod} objects reflecting all the
     * public methods of the class or interface represented by this {@code
     * Class} object, including those declared by the class or interface and
     * those inherited from superclasses and superinterfaces.
     *
     * @param clazz Class to get methods from
     * @return the array of {@code ReflectionMethod} objects representing the
     *         public methods of this class
     */
    public static ReflectionMethod[] getMethods(Class clazz) {
        assertReflectionAccessor();
        return accessor.getMethods(clazz);
    }

    /**
     * Returns an array of {@code Field} objects reflecting all the fields
     * declared by the class or interface represented by this
     * {@code Class} object. This includes public, protected, default
     * (package) access, and private fields, but excludes inherited fields.
     *
     * @param clazz Class to get fields from
     * @return  the array of {@code Field} objects representing all the
     *          declared fields of this class
     */
    public static ReflectionField[] getDeclaredFields(Class clazz) {
        assertReflectionAccessor();
        return accessor.getDeclaredFields(clazz);
    }

    /**
     * Returns this element's annotation for the specified type if
     * such an annotation is present, else null.
     *
     * @param  the type of the annotation to query for and return if present
     * @param clazz Class to get annotation from
     * @param annotationClass the Class object corresponding to the
     *        annotation type
     * @return this element's annotation for the specified annotation type if
     *     present on this element, else null
     * @throws NullPointerException if the given annotation class is null
     * @since 1.5
     */
    public static  T getAnnotation(Class clazz, Class annotationClass) {
        assertReflectionAccessor();
        return accessor.getAnnotation(clazz, annotationClass);
    }

    /**
     * Invokes the method, using the provided instance as 'this'.
     * Method must be no-args and have a return value of type {@code T}.
     * If the method is private, it will be made accessible outside of it's class.
     *
     * @param instance Instance to use as 'this' for invocation.
     * @param method Method to invoke.
     * @param  Return type.
     * @return Result of invoking the no-args method.
     * @throws RuntimeException If an error occurred invoking the method.
     */
    @SuppressWarnings("unchecked")
    public static  T invokeNoArgs(Object instance, ReflectionMethod method) {
        method.setAccessible(true);
        try {
            return (T) method.invoke(instance, NO_ARGS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Assert that the given method returns the expected return type.
     *
     * @param method Method to assert.
     * @param expectedReturnType Expected return type of the method.
     * @throws IllegalArgumentException If the method's return type doesn't match the expected type.
     */
    public static void assertReturnValue(ReflectionMethod method, Class expectedReturnType) {
        final Class returnType = method.getReturnType();
        if (returnType != expectedReturnType) {
            final String message = "Class='"+method.getDeclaringClass()+"', method='"+method.getName()+"': Must return a value of type '"+expectedReturnType+"'!";
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * Assert that the given method takes no parameters.
     *
     * @param method Method to assert.
     * @throws IllegalArgumentException If the method takes any parameters.
     */
    public static void assertNoParameters(ReflectionMethod method) {
        final List parameters = method.getParameters();
        if (!parameters.isEmpty()) {
            final String message = "Class='"+method.getDeclaringClass()+"', method='"+method.getName()+"': Must take no parameters!";
            throw new IllegalArgumentException(message);
        }
    }

    private static void assertReflectionAccessor() {
        Objects.requireNonNull(accessor, "ReflectionAccessor hasn't been set!");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy