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

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

There is a newer version: 0.4.0
Show newest version
/******************************************************************************
 * Copyright (C) 2016 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 com.github.ykrasik.jaci.util.function.Spplr;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * Suppliers that supply through reflection, usually by invoking a method.
 *
 * @author Yevgeny Krasik
 */
public final class ReflectionSuppliers {
    private ReflectionSuppliers() { }

    /**
     * Create a supplier that will invoke the method specified by the give method name
     * on the given object instance through reflection.
     * The method must be no-args and must return a value of the specified type.
     * The method may be private, in which case it will be made accessible outside it's class.
     *
     * @param instance Instance to invoke the method one.
     * @param methodName Method name to invoke. Method must be no-args and return a value of the specified type.
     * @param suppliedClass Expected return type of the method.
     * @param  Supplier return type.
     * @return A {@link Spplr} that will invoke the no-args method specified by the given name on the given instance.
     */
    public static  Spplr reflectionSupplier(Object instance,
                                                  String methodName,
                                                  Class suppliedClass) {
        final ReflectionMethod method = ReflectionUtils.getNoArgsMethod(instance.getClass(), methodName);
        ReflectionUtils.assertReturnValue(method, suppliedClass);
        return new ReflectionSupplier<>(instance, method);
    }

    /**
     * Similar to {@link #reflectionSupplier(Object, String, Class)}, except allows for an alternative return type.
     * Will first try to create a reflection supplier using the primary class, but if that fails (the method doesn't
     * return the primary class), will re-try with the secondary class.
     * Useful for cases where the return type could be either a primitive or the primitive's boxed version
     * (i.e. Integer.type or Integer.class).
     *
     * @param instance Instance to invoke the method one.
     * @param methodName Method name to invoke. Method must be no-args and return a value of
     *                   either the primary class or the secondary type.
     * @param primaryClass Primary return type of the method. Will be tried first.
     * @param secondaryClass Secondary return type of the method.
     *                       Will be tried if the method doesn't return the primary type.
     * @param  Supplier return type.
     * @return A {@link Spplr} that will invoke the no-args method specified by the given name on the given instance.
     */
    public static  Spplr reflectionSupplier(Object instance,
                                                  String methodName,
                                                  Class primaryClass,
                                                  Class secondaryClass) {
        try {
            return reflectionSupplier(instance, methodName, primaryClass);
        } catch (IllegalArgumentException e) {
            // Try the alternative return value.
            return reflectionSupplier(instance, methodName, secondaryClass);
        }
    }

    /**
     * A {@link Spplr} that invokes a (possibly private) no-args method through reflection.
     *
     * @author Yevgeny Krasik
     */
    private static class ReflectionSupplier implements Spplr {
        private final Object instance;
        private final ReflectionMethod method;

        private ReflectionSupplier(Object instance, ReflectionMethod method) {
            this.instance = Objects.requireNonNull(instance, "instance");
            this.method = Objects.requireNonNull(method, "method");
        }

        @Override
        public T get() {
            return ReflectionUtils.invokeNoArgs(instance, method);
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("ReflectionSupplier{");
            sb.append("instance=").append(instance);
            sb.append(", method=").append(method);
            sb.append('}');
            return sb.toString();
        }
    }

    /**
     * Create a supplier that will invoke the method specified by the give method name
     * on the given object instance through reflection.
     * The created supplier will supply a {@link List} of values.
     * The method must be no-args and must return an array of the specified type.
     * The method may be private, in which case it will be made accessible outside it's class.
     *
     * @param instance Instance to invoke the method one.
     * @param methodName Method name to invoke. Method must be no-args and return an array of the specified type.
     * @param suppliedClass Expected array return type of the method.
     * @param  Supplier return type.
     * @return A {@link Spplr} that will invoke the no-args method specified by the given name on the given instance.
     */
    public static  Spplr> reflectionListSupplier(Object instance, String methodName, Class suppliedClass) {
        final Spplr supplier = reflectionSupplier(instance, methodName, suppliedClass);
        return new ArrayListSupplier<>(supplier);
    }

    /**
     * A {@link Spplr} that wraps another {@link Spplr} that returns an array of {@code T}, delegates to that supplier
     * and instead wraps the returned array in a {@link List} of {@code T}.
     *
     * @author Yevgeny Krasik
     */
    private static class ArrayListSupplier implements Spplr> {
        private final Spplr supplier;

        private ArrayListSupplier(Spplr supplier) {
            this.supplier = Objects.requireNonNull(supplier);
        }

        @Override
        public List get() {
            return Arrays.asList(supplier.get());
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("ReflectionListSupplier{");
            sb.append("supplier=").append(supplier);
            sb.append('}');
            return sb.toString();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy