
org.javimmutable.collections.util.ReflectionFunctions Maven / Gradle / Ivy
///###////////////////////////////////////////////////////////////////////////
//
// Burton Computer Corporation
// http://www.burton-computer.com
//
// Copyright (c) 2017, Burton Computer Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// Neither the name of the Burton Computer Corporation nor the names
// of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package org.javimmutable.collections.util;
import org.javimmutable.collections.Func0;
import org.javimmutable.collections.Func1;
import org.javimmutable.collections.Func2;
import org.javimmutable.collections.Func3;
import org.javimmutable.collections.Func4;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* Contains static constructors for creating FuncN objects that call methods using reflection.
*/
@SuppressWarnings("unchecked")
public final class ReflectionFunctions
{
private ReflectionFunctions()
{
}
/**
* Encapsulates the various checked exceptions that can be thrown by the java reflection methods.
*/
public static class ReflectionException
extends RuntimeException
{
public ReflectionException(Throwable throwable)
{
super(throwable);
}
}
/**
* Exception thrown if caller requests a static class but reflection finds a non-static class (or vice versa).
*/
public static class StaticMismatchException
extends RuntimeException
{
public StaticMismatchException()
{
super("static modifier on method does not match expected value");
}
}
/**
* Returns a Func0 instance that calls the specified non-static method on the specified java object.
*
* @param obj the object whose method should be invoked
* @param name the name of the method to invoke
* @param the return type of the function
*/
public static Func0 method(final Object obj,
String name)
{
return new ReflectionFunc0<>(findMethod(obj.getClass(), name, false), obj);
}
/**
* Returns a Func1 instance that calls the specified non-static method on the specified java object.
*
* @param obj the object whose method should be invoked
* @param name the name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param parameter 1 type
* @param the return type of the function
*/
public static Func1 method(final Object obj,
String name,
Class arg1Class)
{
return new ReflectionFunc1<>(findMethod(obj.getClass(), name, false, arg1Class), obj);
}
/**
* Returns a Func2 instance that calls the specified non-static method on the specified java object.
*
* @param obj the object whose method should be invoked
* @param name the name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param arg2Class Class of parameter 2 of the method
* @param parameter 1 type
* @param parameter 2 type
*/
public static Func2 method(final Object obj,
String name,
Class arg1Class,
Class arg2Class)
{
return new ReflectionFunc2<>(findMethod(obj.getClass(), name, false, arg1Class, arg2Class), obj);
}
/**
* Returns a Func3 instance that calls the specified non-static method on the specified java object.
*
* @param obj the object whose method should be invoked
* @param name the name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param arg2Class Class of parameter 2 of the method
* @param arg3Class Class of parameter 3 of the method
* @param parameter 1 type
* @param parameter 2 type
* @param parameter 3 type
* @param the return type of the function
*/
public static Func3 method(final Object obj,
String name,
Class arg1Class,
Class arg2Class,
Class arg3Class)
{
return new ReflectionFunc3<>(findMethod(obj.getClass(), name, false, arg1Class, arg2Class, arg3Class), obj);
}
/**
* Returns a Func4 instance that calls the specified non-static method on the specified java object.
*
* @param obj the object whose method should be invoked
* @param name the name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param arg2Class Class of parameter 2 of the method
* @param arg3Class Class of parameter 3 of the method
* @param arg4Class Class of parameter 4 of the method
* @param parameter 1 type
* @param parameter 2 type
* @param parameter 3 type
* @param parameter 4 type
* @param the return type of the function
*/
public static Func4 method(final Object obj,
String name,
Class arg1Class,
Class arg2Class,
Class arg3Class,
Class arg4Class)
{
return new ReflectionFunc4<>(findMethod(obj.getClass(), name, false, arg1Class, arg2Class, arg3Class, arg4Class), obj);
}
/**
* Returns a Func1 instance that calls the specified non-static method on a java object
* passed as the parameter of the function. These functions are useful for invoking
* the same method on all objects returned by a Cursor.
*
* @param name name of the method to invoke
* @param klass class of the instance object parameter
*/
public static Func1 method(String name,
Class klass)
{
return new ParamReflectionFunc1<>(findMethod(klass, name, false));
}
/**
* Returns a Func2 instance that calls the specified non-static method on a java object
* passed as the last parameter of the Func2. These functions are useful for invoking
* the same method with the same arguments on all objects returned by a Cursor. The instance
* object is the last parameter to facilitate the use of Curry.of().
*
* @param name name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param klass class of the instance object parameter
*/
public static Func2 method(String name,
Class arg1Class,
Class klass)
{
return new ParamReflectionFunc2<>(findMethod(klass, name, false, arg1Class));
}
/**
* Returns a Func3 instance that calls the specified non-static method on a java object
* passed as the last parameter of the Func3. These functions are useful for invoking
* the same method with the same arguments on all objects returned by a Cursor. The instance
* object is the last parameter to facilitate the use of Curry.of().
*
* @param name name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param arg2Class Class of parameter 2 of the method
* @param klass class of the instance object parameter
*/
public static Func3 method(String name,
Class arg1Class,
Class arg2Class,
Class klass)
{
return new ParamReflectionFunc3<>(findMethod(klass, name, false, arg1Class, arg2Class));
}
/**
* Returns a Func4 instance that calls the specified non-static method on a java object
* passed as the last parameter of the Func4. These functions are useful for invoking
* the same method with the same arguments on all objects returned by a Cursor. The instance
* object is the last parameter to facilitate the use of Curry.of().
*
* @param name name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param arg2Class Class of parameter 2 of the method
* @param arg3Class Class of parameter 3 of the method
* @param klass class of the instance object parameter
*/
public static Func4 method(String name,
Class arg1Class,
Class arg2Class,
Class arg3Class,
Class klass)
{
return new ParamReflectionFunc4<>(findMethod(klass, name, false, arg1Class, arg2Class, arg3Class));
}
/**
* Returns a Func0 instance that calls the specified static method on the specified java object.
*
* @param name the name of the method to invoke
* @param the return type of the function
*/
public static Func0 staticMethod(final Class klass,
String name)
{
return new ReflectionFunc0<>(findMethod(klass, name, true), null);
}
/**
* Returns a Func3 instance that calls the specified static method on the specified java object.
*
* @param name the name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param parameter 1 type
* @param the return type of the function
*/
public static Func1 staticMethod(final Class klass,
String name,
Class arg1Class)
{
return new ReflectionFunc1<>(findMethod(klass, name, true, arg1Class), null);
}
/**
* Returns a Func2 instance that calls the specified static method on the specified java object.
*
* @param name the name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param arg2Class Class of parameter 2 of the method
* @param parameter 1 type
* @param parameter 2 type
* @param the return type of the function
*/
public static Func2 staticMethod(final Class klass,
String name,
Class arg1Class,
Class arg2Class)
{
return new ReflectionFunc2<>(findMethod(klass, name, true, arg1Class, arg2Class), null);
}
/**
* Returns a Func3 instance that calls the specified static method on the specified java object.
*
* @param name the name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param arg2Class Class of parameter 2 of the method
* @param arg3Class Class of parameter 3 of the method
* @param parameter 1 type
* @param parameter 2 type
* @param parameter 3 type
* @param the return type of the function
*/
public static Func3 staticMethod(final Class klass,
String name,
Class arg1Class,
Class arg2Class,
Class arg3Class)
{
return new ReflectionFunc3<>(findMethod(klass, name, true, arg1Class, arg2Class, arg3Class), null);
}
/**
* Returns a Func4 instance that calls the specified static method on the specified java object.
*
* @param name the name of the method to invoke
* @param arg1Class Class of parameter 1 of the method
* @param arg2Class Class of parameter 2 of the method
* @param arg3Class Class of parameter 3 of the method
* @param arg4Class Class of parameter 4 of the method
* @param parameter 1 type
* @param parameter 2 type
* @param parameter 3 type
* @param parameter 4 type
* @param the return type of the function
*/
public static Func4 staticMethod(final Class klass,
String name,
Class arg1Class,
Class arg2Class,
Class arg3Class,
Class arg4Class)
{
return new ReflectionFunc4<>(findMethod(klass, name, true, arg1Class, arg2Class, arg3Class, arg4Class), null);
}
private static class NoInstanceReflectionBase
{
protected final Method method;
private NoInstanceReflectionBase(Method method)
{
this.method = method;
}
}
private static class ReflectionBase
extends NoInstanceReflectionBase
{
protected final Object obj;
private ReflectionBase(Method method,
Object obj)
{
super(method);
this.obj = obj;
}
}
private static class ReflectionFunc0
extends ReflectionBase
implements Func0
{
private ReflectionFunc0(Method method,
Object obj)
{
super(method, obj);
}
@Override
public R apply()
{
return (R)callMethod(method, obj);
}
}
private static class ReflectionFunc1
extends ReflectionBase
implements Func1
{
private ReflectionFunc1(Method method,
Object obj)
{
super(method, obj);
}
@Override
public R apply(P1 param1)
{
return (R)callMethod(method, obj, param1);
}
}
private static class ReflectionFunc2
extends ReflectionBase
implements Func2
{
private ReflectionFunc2(Method method,
Object obj)
{
super(method, obj);
}
@Override
public R apply(P1 param1,
P2 param2)
{
return (R)callMethod(method, obj, param1, param2);
}
}
private static class ReflectionFunc3
extends ReflectionBase
implements Func3
{
private ReflectionFunc3(Method method,
Object obj)
{
super(method, obj);
}
@Override
public R apply(P1 param1,
P2 param2,
P3 param3)
{
return (R)callMethod(method, obj, param1, param2, param3);
}
}
private static class ReflectionFunc4
extends ReflectionBase
implements Func4
{
private ReflectionFunc4(Method method,
Object obj)
{
super(method, obj);
}
@Override
public R apply(P1 param1,
P2 param2,
P3 param3,
P4 param4)
{
return (R)callMethod(method, obj, param1, param2, param3, param4);
}
}
private static class ParamReflectionFunc1
extends NoInstanceReflectionBase
implements Func1
{
private ParamReflectionFunc1(Method method)
{
super(method);
}
@Override
public R apply(OT obj)
{
return (R)callMethod(method, obj);
}
}
private static class ParamReflectionFunc2
extends NoInstanceReflectionBase
implements Func2
{
private ParamReflectionFunc2(Method method)
{
super(method);
}
@Override
public R apply(P1 param1,
OT obj)
{
return (R)callMethod(method, obj, param1);
}
}
private static class ParamReflectionFunc3
extends NoInstanceReflectionBase
implements Func3
{
private ParamReflectionFunc3(Method method)
{
super(method);
}
@Override
public R apply(P1 param1,
P2 param2,
OT obj)
{
return (R)callMethod(method, obj, param1, param2);
}
}
private static class ParamReflectionFunc4
extends NoInstanceReflectionBase
implements Func4
{
private ParamReflectionFunc4(Method method)
{
super(method);
}
@Override
public R apply(P1 param1,
P2 param2,
P3 param3,
OT obj)
{
return (R)callMethod(method, obj, param1, param2, param3);
}
}
private static Object callMethod(Method method,
Object obj,
Object... params)
{
try {
return method.invoke(obj, params);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new ReflectionException(e);
}
}
private static Method findMethod(Class klass,
String name,
boolean expectStatic,
Class... args)
{
try {
Method method = klass.getMethod(name, args);
boolean isStatic = (method.getModifiers() & Modifier.STATIC) != 0;
if (isStatic != expectStatic) {
throw new StaticMismatchException();
}
return method;
} catch (NoSuchMethodException e) {
throw new ReflectionException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy