/** * Sorts the elements according to their order: * * <ol> * <li>If an {@link Order} annotation is present, its {@link Order#value()} is used * <li>If a {@link Replace} annotation is present, the superclass' order is used * <li>If the object implements {@link IOrdered}, {@link IOrdered#getOrder()} is used * <li>Finally, the index in the original collection is used * </ol> * * @since 3.8.1 */ public static <T> Collection<T> sortByOrder(Collection<T> list) { if (list == null) { return null; } TreeMap<CompositeObject, T> sortMap = new TreeMap<CompositeObject, T>(); int index = 0; for (T element : list) { Class<?> c = element.getClass(); double order; Order orderAnnotation; while ((orderAnnotation = c.getAnnotation(Order.class)) == null && c.isAnnotationPresent(Replace.class)) { c = c.getSuperclass(); } if (orderAnnotation != null) { order = orderAnnotation.value(); } else if (element instanceof IOrdered) { order = ((IOrdered) element).getOrder(); } else { order = (double) index; } sortMap.put(new CompositeObject(order, index), element); index++; } return sortMap.values(); }
/** * Filters the given class array and sorts the remaining elements according to their {@link Order} * annotation. * * <p>By default, the method throws an {@link IllegalArgumentException} if one of the remaining * classes is not annotated by {@link Order}. The behavior can be switched off by setting the * system property <code>bsi.debug.innerclass.order</code> to an arbitrary value. * * @param classes * @param filter * @return * @throws IllegalArgumentException */ @SuppressWarnings("unchecked") public static <T> Class<T>[] sortFilteredClassesByOrderAnnotation( Class[] classes, Class<T> filter) { TreeMap<CompositeObject, Class> orderedClassesMap = new TreeMap<CompositeObject, Class>(); for (int i = 0; i < classes.length; i++) { if (filter.isAssignableFrom(classes[i])) { if (classes[i].isAnnotationPresent(Order.class)) { Order order = (Order) classes[i].getAnnotation(Order.class); orderedClassesMap.put(new CompositeObject(order.value(), i), classes[i]); } else { if (!classes[i].isAnnotationPresent(Replace.class)) { LOG.error("missing @Order annotation: " + classes[i].getName()); } orderedClassesMap.put(new CompositeObject(Double.MAX_VALUE, i), classes[i]); } } } return orderedClassesMap.values().toArray(new Class[orderedClassesMap.size()]); }