Class InvocationUtils
Naftah.
This class provides methods to:
- Invoke Java
MethodandConstructorinstances reflectively. - Handle named and positional arguments, including conversion between Java types and Naftah types such as
NaftahObjectandDynamicNumber. - Support automatic handling of
null,None.get(), andNaNvalues used in Naftah. - Perform deep conversions for arrays, collections, and maps to match expected Java method parameter types .
- Merge or convert arguments back to their original Naftah representations after method execution.
Typical usage scenarios:
- Invoking a Java constructor or method from Naftah code, where argument types may not exactly match Java parameter types.
- Interfacing between Naftah and Java, handling automatic type adaptation for Naftah objects.
- Performing post-invocation conversion or merging of results back into Naftah objects, arrays, or collections.
This class is designed for internal utility use in reflective invocation workflows, especially when integrating Java APIs with the Naftah programming language.
-
Constructor Summary
ConstructorsModifierConstructorDescriptionprivatePrivate constructor to prevent instantiation. -
Method Summary
Modifier and TypeMethodDescriptionstatic ObjectconvertArgument(Object value, Class<?> targetType, Type genericType, boolean useNaftahTypes) Converts a single argument to the target type expected by a reflective method or constructor parameter.static ObjectconvertArgumentBack(Object original, Object converted) Merges a converted argument value back into its original representation.static voidUpdates the original argument list with values from the executed arguments array.static <T extends JvmExecutable>
Pair<T,Object[]> findBestExecutable(Collection<T> candidates, List<Pair<String, Object>> args) Attempts to find the most suitableJvmExecutable(method or constructor) from a collection of candidates, based on the provided argument list.static <T extends JvmExecutable>
Pair<T,Object[]> findBestExecutable(Collection<T> candidates, List<Pair<String, Object>> args, boolean removeInstanceArg) Determines the best-matchingJvmExecutable(method or constructor) from a given collection of candidates based on argument compatibility.private static ObjectgetConvertedElementAt(Object converted, Class<?> convertedType, int i) Retrieves the element at the specified index from a converted composite value.private static <T extends Executable>
TypegetGenericType(T executable, int index) Retrieves the generic parameter type for the specified parameter index of a givenExecutable.private static ObjectCreates a varargs array from a list of arguments if the method parameters indicate a varargs parameter.static <T extends Executable>
ObjectinvokeJvmConstructor(T methodOrConstructor, Object[] executableArgs, List<Pair<String, Object>> naftahArgs, Class<?> returnType) Invokes a JavaConstructorreflectively using the specified argument array.static <T extends Executable>
ObjectinvokeJvmConstructor(T methodOrConstructor, List<Pair<String, Object>> args, Class<?> returnType, boolean useNaftahTypes) Convenience method to invoke aConstructorreflectively using a list of arguments.static <T extends Executable>
ObjectinvokeJvmExecutable(Object instance, T methodOrConstructor, Object[] executableArgs, List<Pair<String, Object>> naftahArgs, Class<?> returnType) Invokes a givenMethodorConstructorreflectively with specified argument values.static <T extends Executable>
ObjectinvokeJvmExecutable(Object instance, T methodOrConstructor, List<Pair<String, Object>> naftahArgs, Class<?> returnType, boolean useNaftahTypes) Dynamically invokes a JVMMethodorConstructorusing reflection.private static <T extends Executable>
Pair<Integer,Object[]> Computes a compatibility score describing how well a set of provided arguments matches the parameter types of a givenExecutable.
-
Constructor Details
-
InvocationUtils
private InvocationUtils()Private constructor to prevent instantiation. Always throws aNaftahBugErrorwhen called.
-
-
Method Details
-
invokeJvmExecutable
public static <T extends Executable> Object invokeJvmExecutable(Object instance, T methodOrConstructor, List<Pair<String, Object>> naftahArgs, Class<?> returnType, boolean useNaftahTypes) throws InvocationTargetException, InstantiationException, IllegalAccessExceptionDynamically invokes a JVMMethodorConstructorusing reflection.This unified utility abstracts the complexity of calling either a
MethodorConstructorat runtime by automatically handling:- Argument conversion to match JVM parameter types, including primitives, arrays, collections, and generic types
- Primitive boxing and unboxing
- Naftah-specific type handling and conversions (when enabled)
- Varargs executables, including automatic construction of the trailing vararg array when possible
This method is designed for runtime environments that need to dynamically invoke JVM executables without compile-time type information.
Supported executable types
- Instance methods: invoked via
Method.invoke(Object, Object...) - Static methods: invoked with a
nullinstance - Constructors: invoked via
Constructor.newInstance(Object...)
Argument handling
- The number of provided arguments must match the executable’s parameter count
- If the executable is
varargs, a missing final array argument may be synthesized automatically - Arguments are converted before invocation and may be converted back
into
naftahArgsafter invocation
Return handling
The raw result of the underlying reflective call is returned. Any Naftah-specific wrapping or post-processing is handled by the delegated invocation logic.
- Type Parameters:
T- the type of executable being invoked- Parameters:
instance- the target object for instance method calls, ornullfor static methods or constructorsmethodOrConstructor- theExecutableto invoke (either aMethodor aConstructor)naftahArgs- a list ofPair<String, Object> representing argument names and values; this list may be mutated during invocation (e.g. for varargs handling or argument back-conversion)returnType- the expected return type; useVoid.TYPEorVoidforvoidexecutablesuseNaftahTypes- whether Naftah-specific type semantics and conversions should be applied- Returns:
- the result of the invocation
- Throws:
InvocationTargetException- if the underlying executable throws an exceptionInstantiationException- if a constructor fails to create a new instanceIllegalAccessException- if the executable cannot be accessed due to Java access controlIllegalArgumentException- if argument count or types do not match the executable signature- See Also:
-
getVarargArrayIfPossible
private static Object getVarargArrayIfPossible(List<Pair<String, Object>> naftahArgs, Class<?>[] paramTypes) Creates a varargs array from a list of arguments if the method parameters indicate a varargs parameter.This method checks if the last parameter in the
paramTypesarray is an array (indicating a varargs parameter) and if there are enough arguments innaftahArgsto populate the normal parameters. If so, it creates a new array for the varargs portion.Example usage:
List<Pair<String, Object>> args = List.of(Pair.of("arg1", value1), Pair.of("arg2", value2)); Class<?>[] paramTypes = { String.class, Integer.class, String[].class }; // last is varargs Object varargsArray = getVarargArrayIfPossible(args, paramTypes); // varargsArray will be a String[0] if no extra arguments, or filled with remaining args otherwise- Parameters:
naftahArgs- the list of arguments as pairs of name and valueparamTypes- the array of parameter types for the target method, where the last element may be a varargs array- Returns:
- a newly instantiated array of the varargs component type containing the extra arguments,
or
nullif there are not enough arguments to reach the varargs parameter - Throws:
NullPointerException- ifnaftahArgsorparamTypesisnull- See Also:
-
invokeJvmExecutable
public static <T extends Executable> Object invokeJvmExecutable(Object instance, T methodOrConstructor, Object[] executableArgs, List<Pair<String, Object>> naftahArgs, Class<?> returnType) throws InvocationTargetException, InstantiationException, IllegalAccessExceptionInvokes a givenMethodorConstructorreflectively with specified argument values.This low-level helper performs:
- Access override via
AccessibleObject.setAccessible(boolean) - Unwrapping of
NaftahObjectinstances when necessary - Automatic conversion of
voidornullresults toNone.get()
- Type Parameters:
T- the type of executable- Parameters:
instance- the target object for instance methods, ornullfor static methods or constructorsmethodOrConstructor- theExecutableto invokeexecutableArgs- the argument values in declared parameter ordernaftahArgs- the original argument name/value pairs (used for back-conversion)returnType- the expected return type- Returns:
- the invocation result, or
None.get()if the result isnullorvoid - Throws:
InvocationTargetException- if the underlying executable throws an exceptionInstantiationException- if a constructor fails to instantiate a new objectIllegalAccessException- if the executable cannot be accessed- See Also:
- Access override via
-
invokeJvmConstructor
public static <T extends Executable> Object invokeJvmConstructor(T methodOrConstructor, List<Pair<String, Object>> args, Class<?> returnType, boolean useNaftahTypes) throws InvocationTargetException, InstantiationException, IllegalAccessExceptionConvenience method to invoke aConstructorreflectively using a list of arguments.This method is a thin wrapper around
invokeJvmExecutable(Object, Executable, List, Class, boolean)that automatically supplies anullinstance, as constructors do not require one.Constructor arguments are converted automatically to match the constructor’s parameter types, including primitives, arrays, collections, and generic types. Naftah-specific type semantics and conversions are applied when enabled.
The provided argument list may be mutated during invocation (for example, to support varargs handling or argument back-conversion).
- Type Parameters:
T- the type of executable (constructor) being invoked- Parameters:
methodOrConstructor- theConstructorto invokeargs- the constructor arguments as a list ofPair<String, Object>returnType- the expected type of the constructed objectuseNaftahTypes- whether Naftah-specific type semantics and conversions should be applied- Returns:
- the newly created instance
- Throws:
InvocationTargetException- if the constructor throws an exceptionInstantiationException- if the constructor fails to instantiate a new objectIllegalAccessException- if reflective access is not allowedIllegalArgumentException- if the argument count or types do not match the constructor signature- See Also:
-
invokeJvmConstructor
public static <T extends Executable> Object invokeJvmConstructor(T methodOrConstructor, Object[] executableArgs, List<Pair<String, Object>> naftahArgs, Class<?> returnType) throws InvocationTargetException, InstantiationException, IllegalAccessExceptionInvokes a JavaConstructorreflectively using the specified argument array.This is a convenience wrapper around
invokeJvmExecutable(Object, Executable, Object[], List, Class)that specifically targets constructors. Since constructors do not require a target object, this method automatically suppliesnullfor theinstanceparameter.Behavior overview
- Invokes the provided
ConstructorusingConstructor.newInstance(Object...). - Delegates argument handling, type checking, and
None.get()substitution toinvokeJvmExecutable(Object, Executable, Object[], List, Class). - Returns
None.get()if the constructor result isnull.
Note: This method assumes that all arguments in
executableArgsare already type-compatible with the constructor’s parameter types. For automatic type conversion, named arguments, or more complex argument handling, use theinvokeJvmConstructor(Executable, List, Class, boolean)variant.- Type Parameters:
T- the type ofExecutable(usuallyConstructor).- Parameters:
methodOrConstructor- theConstructorto invoke reflectively.executableArgs- an array of argument values to pass to the constructor.naftahArgs- a list of named argument pairs, for optional post-processing.returnType- the expected type of the constructed object.- Returns:
- the newly constructed instance, or
None.get()if the result isnull. - Throws:
InvocationTargetException- if the underlying constructor throws an exception.InstantiationException- if the constructor cannot instantiate a new object.IllegalAccessException- if reflective access is not permitted.- See Also:
- Invokes the provided
-
convertArgument
public static Object convertArgument(Object value, Class<?> targetType, Type genericType, boolean useNaftahTypes) Converts a single argument to the target type expected by a reflective method or constructor parameter.This method attempts to adapt the supplied
valueto the specifiedtargetType. When available,genericTypeinformation is used to guide recursive, element-wise conversion of arrays, collections, tuples, and maps.Supported conversions
- Primitive types and their boxed equivalents
DynamicNumberto standard JVM numeric typesNaNtoDouble.NaN- Arrays (recursive element conversion)
Collections(recursive element conversion)Maps(recursive key and value conversion)NTuple,Pair, andTriple(recursive element conversion)NaftahObjectunwrapping when Naftah types are disabled
Naftah-specific semantics
- If
valueisnullor representsNone, the result depends onuseNaftahTypes:- when
true,None.get()is returned - when
false,nullis returned
- when
- When
useNaftahTypesisfalse,NaftahObjectvalues are automatically unwrapped unless the target type isNaftahObject
If
valueis already assignable totargetType, it is returned unchanged.- Parameters:
value- the original argument value to convert; may benullorNonetargetType- the target class expected by the executable parametergenericType- generic type information used to guide recursive conversion of collections, arrays, and maps; may benulluseNaftahTypes- whether Naftah-specific type semantics and wrappers should be preserved- Returns:
- a value compatible with
targetType, ornullifvalueisnulland Naftah types are disabled - Throws:
ClassCastException- if the value cannot be converted or cast totargetType- See Also:
-
convertArgumentsBack
public static void convertArgumentsBack(Object[] executableArgs, List<Pair<String, Object>> naftahArgs) Updates the original argument list with values from the executed arguments array.This method iterates through the provided
executableArgsarray and compares each element with the corresponding element innaftahArgs. If the original argument and the converted value differ (either by reference or logical equality), the method attempts to merge the changes back into the original object usingconvertArgumentBack(Object, Object).This is useful when invoking a method or constructor reflectively and wanting to propagate modifications of mutable arguments (like arrays, collections, or maps) back to the original argument references.
- Parameters:
executableArgs- the array of argument values used during the reflective call.naftahArgs- the list of original named arguments asPair<String, Object>, where the value part may be updated with the converted value.- See Also:
-
convertArgumentBack
Merges a converted argument value back into its original representation.This method reconciles a value produced by a reflective invocation (
converted) with the original argument value (original). Where possible, mutable objects are updated in place; otherwise, the original value or a replacement object is returned.Supported merge behaviors
nullorNone— returnsNone.get()NaN— preserved unchangedNaftahObject— rewrapped with the converted valueDynamicNumber— updated in place- Primitive wrappers and
Numbertypes — merged viaDynamicNumber - Arrays — elements copied into the original array
Collections— elements updated in placeMaps— contents replacedNTuple,Pair,Triple,Tuple— elements merged reflectively
If
convertedis already assignable to the runtime type oforiginal, it is returned directly.This method is primarily intended to propagate argument mutations made during reflective method or constructor execution back to the original argument objects.
- Parameters:
original- the original argument value supplied to the executableconverted- the value produced by the reflective invocation- Returns:
- the merged value, either the updated original instance or a suitable replacement object
- Throws:
NaftahBugError- if reflective field updates fail- See Also:
-
getConvertedElementAt
Retrieves the element at the specified index from a converted composite value.Supports both array and
Collectionrepresentations. IfconvertedTyperepresents an array, the element is obtained viaArray.get(Object, int); otherwise the value is retrieved from the collection using index-based access.- Parameters:
converted- the converted composite value (array orCollection)convertedType- the runtime type ofconverted, used to distinguish arrays from collectionsi- the zero-based index of the element to retrieve- Returns:
- the element at the specified index
- Throws:
IndexOutOfBoundsException- if the index is out of rangeClassCastException- ifconvertedis not compatible withconvertedType
-
findBestExecutable
public static <T extends JvmExecutable> Pair<T,Object[]> findBestExecutable(Collection<T> candidates, List<Pair<String, Object>> args) throws NoSuchMethodExceptionAttempts to find the most suitableJvmExecutable(method or constructor) from a collection of candidates, based on the provided argument list.This overload delegates to
findBestExecutable(Collection, List, boolean)withremoveInstanceArg = false.- Type Parameters:
T- the type ofJvmExecutable(e.g.JvmFunction,BuiltinFunction).- Parameters:
candidates- the collection of availableJvmExecutableinstances to evaluate.args- the argument list to match, represented asPair<String, Object>where each pair contains the argument name and its value.- Returns:
- a
Paircontaining the best-matchingJvmExecutableand its prepared argument array; ornullif no suitable match is found. - Throws:
NoSuchMethodException- See Also:
-
findBestExecutable
public static <T extends JvmExecutable> Pair<T,Object[]> findBestExecutable(Collection<T> candidates, List<Pair<String, Object>> args, boolean removeInstanceArg) throws NoSuchMethodExceptionDetermines the best-matchingJvmExecutable(method or constructor) from a given collection of candidates based on argument compatibility.The matching process computes a “score” for each executable using
matchScore(Executable, Class[], List, boolean), where lower scores indicate a closer match. The executable with the lowest non-negative score is returned along with its converted argument array.If
removeInstanceArgistrue, and the executable represents a non-staticJvmFunction, the first argument inargsis removed, as it corresponds to the instance already passed during invocation.- Type Parameters:
T- the type ofJvmExecutable.- Parameters:
candidates- the collection ofJvmExecutablecandidates to search through.args- the argument list asPair<String, Object>entries.removeInstanceArg- whether to remove the first argument when matching non-static functions (useful when the instance is already supplied).- Returns:
- a
Paircontaining:- the best-matching
JvmExecutable, and - the prepared and type-converted argument array for invocation.
nullif no compatible executable is found. - the best-matching
- Throws:
NoSuchMethodException- See Also:
-
matchScore
private static <T extends Executable> Pair<Integer,Object[]> matchScore(T executable, Class<?>[] params, List<Pair<String, Object>> args, boolean useNaftahTypes) Computes a compatibility score describing how well a set of provided arguments matches the parameter types of a givenExecutable.Each argument is tentatively converted to the corresponding parameter type using
convertArgument(Object, Class, Type, boolean). If any argument fails conversion, the executable is considered incompatible and a score of-1is returned.Scoring semantics
Lower scores indicate a better match. The total score is the sum of per-parameter penalties based on how closely the converted argument matches the target parameter type:
nullargument: +10- Exact runtime type match: +0
- Assignable match (after conversion): +1
- Boxed numeric to boxed numeric: +2
- Boxed numeric to matching primitive: +3
- Numeric or character primitive mismatch: +4
- Other non-null compatible conversions: +5
- Converted value is
null: +6
If a converted argument is
nullbut the corresponding parameter is primitive, the match fails immediately.Naftah-specific behavior
The
useNaftahTypesflag controls whetherNoneandNaftahObjectvalues are preserved or unwrapped during argument conversion.- Type Parameters:
T- the type ofExecutable- Parameters:
executable- the method or constructor being evaluatedparams- the raw parameter types of the executableargs- the provided arguments as a list ofPair<String, Object>useNaftahTypes- whether Naftah-specific type semantics should be applied during conversion- Returns:
- a
Paircontaining:- the computed compatibility score (lower is better,
-1indicates incompatibility) - an array of converted argument values suitable for invocation
- the computed compatibility score (lower is better,
-
getGenericType
Retrieves the generic parameter type for the specified parameter index of a givenExecutable.If the executable declares generic parameter types, the corresponding one is returned; otherwise, the raw parameter type is used as a fallback.
- Type Parameters:
T- the type of theExecutable.- Parameters:
executable- theExecutablewhose parameter type should be retrieved.index- the parameter index.- Returns:
- the
Typerepresenting the parameter’s declared or generic type.
-