Class ClassUtils

java.lang.Object
org.daiitech.naftah.utils.reflect.ClassUtils

public final class ClassUtils extends Object
Utility class for working with Java classes, methods, and their qualified names. Provides methods to get qualified names, filter classes and methods, and obtain built-in methods annotated for Naftah.
Author:
Chakib Daii
  • Field Details

    • CLASS_SEPARATORS_REGEX

      public static final String CLASS_SEPARATORS_REGEX
      Regex pattern to split class names by dot '.' or dollar '$' sign.
      See Also:
    • QUALIFIED_NAME_SEPARATOR

      public static final String QUALIFIED_NAME_SEPARATOR
      Separator used to join qualified names.
      See Also:
    • QUALIFIED_CALL_SEPARATOR

      public static final String QUALIFIED_CALL_SEPARATOR
      Separator used to join qualified calls (class::method).
      See Also:
    • QUALIFIED_CALL_REGEX

      public static final Pattern QUALIFIED_CALL_REGEX
      Regex to match strings with at least one ':' and exactly one '::', with '::' before the last segment.
    • FACTORY_NAMES

      private static final Set<String> FACTORY_NAMES
      Commonly recognized factory-style static method names in Java.

      These names are used by hasFactoryMethod(Class<?>) to detect whether a class provides a static creation method that returns instances of itself or its subclasses. This allows Naftah to treat such methods as "constructors" in its interop layer.

      The list includes canonical JDK factories (e.g., of, from), builder-style factories, parser/deserializer names, and provider patterns from the JDK, Guava, Jackson, and Spring ecosystems.

    • FACTORY_PREFIXES

      private static final String[] FACTORY_PREFIXES
      Common prefixes used to identify factory-like methods when scanning class members.

      Unlike FACTORY_NAMES, these are matched as prefixes, so methods such as newBuilder(), createStream(), fromJsonString(), and getInstanceSafe() are also recognized.

      This prefix-based detection is useful for frameworks that generate descriptive factory names dynamically or through code generation.

  • Constructor Details

    • ClassUtils

      private ClassUtils()
      Private constructor to prevent instantiation. Always throws a NaftahBugError when called.
  • Method Details

    • getQualifiedName

      public static String getQualifiedName(String className)
      Returns a qualified name by transliterating each part of the class name to Arabic. For example, "java.lang.String" becomes Arabic transliteration joined by colon.
      Parameters:
      className - the fully qualified Java class name
      Returns:
      the qualified name transliterated to Arabic script
    • getQualifiedCall

      public static String getQualifiedCall(String qualifiedName, Method method)
      Returns a qualified method call string by combining the qualified class name and the method name, transliterated into Arabic script.

      The format of the returned string is: qualifiedName::methodName, where the method name is transliterated.

      Parameters:
      qualifiedName - the fully qualified name of the class (e.g., com.example.MyClass)
      method - the Method instance representing the method
      Returns:
      a string in the form qualifiedName::methodName with the method name in Arabic script
    • getQualifiedCall

      public static String getQualifiedCall(String qualifiedName, String methodName)
      Returns a qualified method call string by combining the qualified class name and the method name, transliterated into Arabic script.

      The format of the returned string is: qualifiedName::methodName, where the method name is transliterated.

      Parameters:
      qualifiedName - the fully qualified name of the class (e.g., com.example.MyClass)
      methodName - the name of the method as a string
      Returns:
      a string in the form qualifiedName::methodName with the method name in Arabic script
    • getClassQualifiers

      public static Map<String,Pair<String,String[]>> getClassQualifiers(Set<String> classNames, boolean flattened)
      Extracts parts of class names and returns a mapping based on the specified mode.

      If flattened is true, the returned map contains each individual class part as a key, mapped to a pair of the original class name and its array of parts. Duplicate keys are resolved by keeping the first occurrence.

      If flattened is false, the returned map uses the fully qualified class name as the key, mapped to a pair of the original class name and its array of parts.

      Parameters:
      classNames - a set of fully qualified class names to process
      flattened - if true, returns a map of individual parts; if false, returns a map keyed by fully qualified names
      Returns:
      a map where keys are either class parts or fully qualified class names, and values are Pair objects containing the original class name and its parts array
    • getArabicClassQualifiers

      public static Set<String> getArabicClassQualifiers(Collection<String[]> classQualifiers)
      Transliterates a collection of class qualifiers parts arrays into Arabic qualified names.
      Parameters:
      classQualifiers - collection of class parts arrays
      Returns:
      set of Arabic transliterated qualified names joined by colon
    • getArabicClassQualifiersMapping

      public static Map<String,String> getArabicClassQualifiersMapping(Collection<Pair<String,String[]>> classQualifiers)
      Generates a mapping from Arabic-transliterated fully qualified class names to the original fully qualified class names.

      Each entry in the returned map uses the Arabic transliteration of the class parts (joined by QUALIFIED_NAME_SEPARATOR) as the key, and the original fully qualified name as the value. If multiple original names transliterate to the same Arabic string, the first occurrence is kept.

      Parameters:
      classQualifiers - a collection of Pair objects, where the left element is the original class name and the right element is an array of class name parts
      Returns:
      a map of Arabic-transliterated qualified names to original qualified names
    • getClassMethods

      public static Map<String,List<JvmFunction>> getClassMethods(Map<String,Class<?>> classes, Predicate<Method> methodPredicate)
      Retrieves methods from given classes filtered by a predicate, grouped by their qualified call strings.

      Usage example:

       Set<Class> classes = ClassUtils.getClasses();
       Predicate<Method> instancePublicMethodPredicate = method ->
       Modifier.isPublic(method.getModifiers());
       Map<Class, Method[]> instancePublicMethods =
       ClassUtils.getClassMethods(classes,
       instancePublicMethodPredicate);
       
      Parameters:
      classes - map of qualified class names to Class objects
      methodPredicate - predicate to filter methods
      Returns:
      map from qualified call string to list of JvmFunction wrappers
    • getClassConstructors

      public static Map<String,List<JvmClassInitializer>> getClassConstructors(Map<String,Class<?>> classes, Predicate<Constructor<?>> constructorPredicate)
      Retrieves and groups constructors from multiple classes, filtered by a specified predicate, mapping each qualified class name to a list of JvmClassInitializer wrappers.

      For each class in the provided map, this method inspects its public constructors (via Class.getConstructors()), applies the given constructorPredicate, and wraps all matching constructors as JvmClassInitializer instances. The results are then grouped by their qualified class names.

      Any classes or constructors that cannot be accessed or processed (e.g., due to security restrictions) are silently skipped.

      Parameters:
      classes - a map where each key is the fully qualified class name (e.g., "com.example.MyClass") and each value is the corresponding Class object
      constructorPredicate - a Predicate used to filter which constructors should be included
      Returns:
      a map where each key is a qualified class name and each value is a list of JvmClassInitializer instances representing all constructors of that class that satisfy the given predicate
      Throws:
      NullPointerException - if classes or constructorPredicate is null
      See Also:
    • getClassMethods

      public static List<JvmFunction> getClassMethods(String qualifiedName, Class<?> clazz)
      Retrieves all methods of the given class, wrapped as JvmFunction instances.

      This variant retrieves all public methods of the class, including inherited methods, without any filtering.

      Parameters:
      qualifiedName - the fully qualified name of the class
      clazz - the Class object to inspect
      Returns:
      a list of JvmFunction instances representing all class methods
    • getClassMethods

      public static List<JvmFunction> getClassMethods(String qualifiedName, Class<?> clazz, Predicate<Method> methodPredicate)
      Retrieves methods of the given class that satisfy a specified predicate, wrapped as JvmFunction instances.

      The provided methodPredicate is applied to each public method of the class to determine whether it should be included in the result.

      Parameters:
      qualifiedName - the fully qualified name of the class
      clazz - the Class object to inspect
      methodPredicate - a Predicate used to filter methods
      Returns:
      a list of JvmFunction instances representing the filtered methods
    • getClassConstructors

      public static List<JvmClassInitializer> getClassConstructors(String qualifiedName, Class<?> clazz)
      Retrieves all public constructors of the specified class and wraps them as JvmClassInitializer instances.

      Each JvmClassInitializer represents a single constructor and includes its qualified name and reflective metadata.

      Parameters:
      qualifiedName - the fully qualified name of the class (e.g., "com.example.MyClass")
      clazz - the Class object representing the class whose constructors should be retrieved
      Returns:
      a list of JvmClassInitializer instances representing all public constructors of the specified class
    • getClassMethods

      public static Map<String,List<JvmFunction>> getClassMethods(Map<String,Class<?>> classes)
      Returns all methods from given classes without filtering.
      Parameters:
      classes - map of qualified class names to Class objects
      Returns:
      map from qualified call string to list of JvmFunction wrappers
    • getClassConstructors

      public static Map<String,List<JvmClassInitializer>> getClassConstructors(Map<String,Class<?>> classes)
      Retrieves all public constructors from the given classes without applying any filtering, mapping each qualified class name to a list of JvmClassInitializer wrappers.

      This method is a convenience overload of getClassConstructors(Map, java.util.function.Predicate) that includes all available constructors by default.

      Parameters:
      classes - a map where each key is the fully qualified class name (e.g., "com.example.MyClass") and each value is the corresponding Class object
      Returns:
      a map from qualified class names to lists of JvmClassInitializer instances representing all public constructors of the given classes
      Throws:
      NullPointerException - if classes is null
      See Also:
    • isAccessibleClass

      public static boolean isAccessibleClass(Class<?> clazz)
      Checks if the class has at least one public static factory method.
      Parameters:
      clazz - the class to check
      Returns:
      true if accessible (has public static method), false otherwise
    • isInstantiableClass

      public static boolean isInstantiableClass(Class<?> clazz)
      Checks if the class is instantiable: public, not abstract/interface, and has a public no-arg constructor.
      Parameters:
      clazz - the class to check
      Returns:
      true if instantiable, false otherwise
    • hasFactoryMethod

      public static boolean hasFactoryMethod(Class<?> clazz)
      Determines whether the specified class defines at least one public static factory method capable of producing an instance of that class (or a subclass of it).

      This method is used by the Naftah Java interop layer to identify Java types that are constructible through factory methods rather than public constructors. Examples include: Optional.of(), LocalDate.parse(), and List.copyOf().

      The detection relies on a curated set of known factory method names and prefixes (see FACTORY_NAMES and FACTORY_PREFIXES). The following conditions must all be satisfied for a method to be recognized as a valid factory:

      • The method must be public static.
      • It must not be a compiler-generated bridge or synthetic method.
      • Its name must either match a known factory name (e.g. of, from, valueOf) or begin with a recognized prefix (e.g. create, new, build).
      • It must return a non-void type assignable to the declaring class, or whose simple name contains the declaring class’s simple name (to support builder/wrapper patterns).

      Example classes detected as factory-capable:

      
       Optional.of("value");
       LocalDate.parse("2025-11-07");
       List.copyOf(existingList);
       EnumSet.noneOf(MyEnum.class);
       HttpRequest.newBuilder().build();
       

      Classes that are primitives, arrays, or void are excluded immediately.

      Parameters:
      clazz - the class to inspect
      Returns:
      true if the class declares at least one public static factory method that produces instances of itself or a compatible type; false otherwise
    • isFactoryName

      private static boolean isFactoryName(String name)
      Determines whether a given method name matches a known factory method pattern.

      This method checks whether the name appears in the FACTORY_NAMES set or begins with one of the FACTORY_PREFIXES. Matching is case-sensitive and uses simple string comparison for efficiency.

      Parameters:
      name - the method name to test
      Returns:
      true if the name matches a known factory name or prefix, false otherwise
    • isStatic

      public static boolean isStatic(Method method)
      Checks if a method is static.
      Parameters:
      method - the method to check
      Returns:
      true if static, false otherwise
    • isInvocable

      public static boolean isInvocable(Executable methodOrConstructor)
      Determines whether a given Executable (method or constructor) can be invoked dynamically.

      A member is considered invocable if it meets all of the following conditions:

      • It is public.
      • It is not synthetic or compiler-generated (e.g., bridge methods).
      • If it is a Method, it is either static or declared in an instantiable class.
      • If it is a Constructor, it belongs to an instantiable class.
      Parameters:
      methodOrConstructor - the Executable (method or constructor) to check
      Returns:
      true if the executable can be invoked via reflection, otherwise false
      See Also:
    • filterClasses

      public static Map<String,Class<?>> filterClasses(Map<String,Class<?>> classes, Predicate<Class<?>> classPredicate)
      Filters a map of classes by applying a predicate on the Class objects.
      Parameters:
      classes - map of qualified class names to Class objects
      classPredicate - predicate to filter classes
      Returns:
      filtered map of classes
    • getBuiltinMethods

      public static Map<String,List<BuiltinFunction>> getBuiltinMethods(Map<String,Class<?>> classes, Predicate<Method> methodPredicate)
      Retrieves built-in methods annotated with @NaftahFn from classes annotated with @NaftahFnProvider, filtered by a method predicate.
      Parameters:
      classes - map of qualified class names to Class objects
      methodPredicate - predicate to filter methods
      Returns:
      map of function names to lists of BuiltinFunction instances
    • getBuiltinFunctionName

      public static String getBuiltinFunctionName(boolean useQualifiedName, String providerName, String functionName, boolean removeNameDiacritics)
      Constructs the canonical name for a built-in function, optionally using a qualified name that includes the provider name.
      Parameters:
      useQualifiedName - whether to qualify the function name with the provider name
      providerName - the name of the function provider (e.g. extension or library name)
      functionName - the actual function name
      removeNameDiacritics - whether to remove Arabic diacritics from both provider and function names
      Returns:
      the cleaned and optionally qualified function name, with spaces replaced by underscores
    • cleanBuiltinFunctionName

      public static String cleanBuiltinFunctionName(String name, String replacement, boolean removeDiacritics)
      Normalizes a function or provider name by optionally removing Arabic diacritics and replacing whitespace with underscores.
      Parameters:
      name - the original name to clean
      removeDiacritics - whether to remove Arabic diacritics from the name
      Returns:
      a sanitized string with optional diacritics removed and spaces replaced with underscores
    • getBuiltinMethods

      public static Map<String,List<BuiltinFunction>> getBuiltinMethods(Map<String,Class<?>> classes)
      Retrieves all built-in methods from classes annotated with @NaftahFnProvider.
      Parameters:
      classes - map of qualified class names to Class objects
      Returns:
      map of function names to lists of BuiltinFunction instances
    • getBuiltinMethods

      public static List<BuiltinFunction> getBuiltinMethods(Class<?> clazz)
      Retrieves built-in methods annotated with @NaftahFn from a single class annotated with @NaftahFnProvider.
      Parameters:
      clazz - the class to inspect
      Returns:
      list of BuiltinFunction instances or empty list if not annotated
    • getBuiltinMethods

      public static List<BuiltinFunction> getBuiltinMethods(Set<Class<?>> classes)
      Retrieves built-in functions from multiple classes annotated with NaftahFnProvider.

      This method aggregates results from all provided classes by invoking getBuiltinMethods(Class) on each one.

      Parameters:
      classes - the set of classes to inspect
      Returns:
      a combined list of BuiltinFunction instances from all classes, or an empty list if none are found
    • classToDetailedString

      public static String classToDetailedString(Class<?> clazz)
      Returns a detailed, Arabic-formatted string representation of the specified Java class.

      The returned string includes the following information about the class:

      • Fully qualified class name (e.g., java.util.ArrayList)
      • Simple class name (e.g., ArrayList)
      • Package name (or "(default)" if the class is in the default package)
      • Class modifiers (whether it's public, abstract, or an interface)
      • The superclass of the class (if any)
      • All interfaces implemented by the class
      • Declaring class (if the class is an inner or nested class)
      • Whether the class is an enum, annotation, record, or primitive type

      Additionally, the method includes Arabic transliteration (phonetic representation in Arabic script) for class names and package names, using getQualifiedName(String) or ScriptUtils.transliterateToArabicScriptDefault(String...). For example, the simple name ArrayList might appear as:

      
       ArrayList - أرَي لِسْتْ
       

      The output is formatted as a multi-line string with Arabic labels for each item. Example output (for java.util.ArrayList):

       تفاصيل الصنف:
       - الاسم الكامل: java.util.ArrayList - جاڤا:يوتِل:أرَي_لِسْتْ
       - الاسم المختصر: ArrayList - أرَي_لِسْتْ
       - الحزمة: java.util - جاڤا:يوتِل
       - عام؟: نعم
       - مجرد؟: لا
       - واجهة؟: لا
       - الصنف الأب: java.util.AbstractList - جاڤا:يوتِل:أَبْسْتْرَكْتْ_لِسْتْ
       - الواجهات:
       - java.util.List - جاڤا:يوتِل:لِسْتْ
       - java.util.RandomAccess - جاڤا:يوتِل:رَانْدُم_أَكْسِسْ
       - java.lang.Cloneable - جاڤا:لانْغ:كْلُونِبْلْ
       - java.io.Serializable - جاڤا:أَي_أُو:سِرِيَالِيزَابْلْ
       - تعداد؟: لا
       - توصيف؟: لا
       - سجل؟: لا
       - نوع بدائي؟: لا
       
      Parameters:
      clazz - the Class object to inspect
      Returns:
      a multi-line, Arabic-formatted string describing the class, including Arabic transliterations
    • normalizePrimitive

      public static Class<?> normalizePrimitive(Class<?> clazz)
      Normalizes a primitive Class to its corresponding wrapper type.

      If the provided class represents a primitive type (e.g., int.class), this method returns the corresponding wrapper class (e.g., Integer). If the class is not primitive, it is returned unchanged.

      This is useful for reflective or generic type comparisons where primitive and wrapper types should be considered equivalent.

      Examples:

      
       normalizePrimitive(int.class);      // returns Integer.class
       normalizePrimitive(boolean.class);  // returns Boolean.class
       normalizePrimitive(String.class);   // returns String.class (unchanged)
       
      Parameters:
      clazz - the class to normalize; must not be null
      Returns:
      the wrapper class for a primitive type, or the original class if not primitive