findOrder method

int? findOrder(
  1. Object? obj
)

Finds the order value for the given object using annotation-aware resolution.

This method implements the comprehensive order resolution strategy that makes this comparator unique. It examines various sources of order information in a specific precedence sequence.

Resolution Precedence:

  1. Direct Objects:

    • PriorityOrdered implementations (highest precedence)
    • Ordered implementations
    • Raw integer values
  2. Class Objects:

    • @Order annotation on the class
    • Ordered interface implementation
    • Fallback to Ordered.LOWEST_PRECEDENCE
  3. Source Objects:

    • @Order annotation on the source element
  4. Executable Objects (Methods/Constructors):

    • @Order annotation
    • Parameter count as natural ordering (fewer parameters first)
  5. Fallback Strategy:

    • For unknown types, attempt to get class and recurse
    • Final fallback to Ordered.LOWEST_PRECEDENCE

Parameters:

  • obj: The object to find order for (Class, Source, Executable, or direct object)

Returns:

The resolved order value, or null if no specific order could be determined

Example:

final comparator = AnnotationAwareOrderComparator();

// Check annotated class
@Order(42)
class MyService {}
final order1 = comparator.findOrder(Class<MyService>());
print(order1); // 42

// Check Ordered implementation
class OrderedService implements Ordered {
  @override int get order => 100;
}
final order2 = comparator.findOrder(Class<OrderedService>());
print(order2); // 100

// Check method with @Order annotation
class Component {
  @Order(10)
  void highPriorityMethod() {}
}
final method = Class<Component>().getDeclaredMethod('highPriorityMethod');
final order3 = comparator.findOrder(method);
print(order3); // 10

// Check method without annotation (uses parameter count)
class AnotherComponent {
  void methodWithParams(String a, int b) {} // 2 parameters
}
final method2 = Class<AnotherComponent>().getDeclaredMethod('methodWithParams');
final order4 = comparator.findOrder(method2);
print(order4); // 2

Implementation

int? findOrder(Object? obj) {
  if (obj == null) return Ordered.LOWEST_PRECEDENCE;

  if (obj is Class) {
    final cls = obj;

    // First priority: @Order annotation on class
    if (cls.hasDirectAnnotation<Order>()) {
      final ann = cls.getDirectAnnotation<Order>();
      if (ann != null) return ann.value;
    }

    // Second priority: Ordered interface implementation
    final ordered = Class<Ordered>();
    if (ordered.isAssignableFrom(cls)) {
      final instance = cls.getNoArgConstructor()?.newInstance();
      if (instance != null && instance is PriorityOrdered) {
        return instance.getOrder();
      } else if (instance != null && instance is Ordered) {
        return instance.getOrder();
      }
    }
  } else if (obj is Source) {
    // @Order annotation on source elements
    if (obj.hasDirectAnnotation<Order>()) {
      final ann = obj.getDirectAnnotation<Order>();
      if (ann != null) return ann.value;
    }
  } else if (obj is Executable) {
    // @Order annotation on executables
    if (obj.hasDirectAnnotation<Order>()) {
      final ann = obj.getDirectAnnotation<Order>();
      if (ann != null) return ann.value;
    }

    // Natural ordering for methods based on parameter count
    if (obj is Method) {
      final method = obj;
      return method.getParameters().length;
    }

    // Natural ordering for constructors based on parameter count
    if (obj is Constructor) {
      final constructor = obj;
      return constructor.getParameters().length;
    }
  } else if (obj is PriorityOrdered) {
    // Direct PriorityOrdered implementation (highest precedence)
    return obj.getOrder();
  } else if (obj is Ordered) {
    // Direct Ordered implementation
    return obj.getOrder();
  } else if (obj is int) {
    // Raw integer order value
    return obj;
  } else {
    // Fallback: try to get class and recurse
    return findOrder(obj.getClass());
  }

  return null;
}