001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.core.annotation;
018
019import java.lang.reflect.AnnotatedElement;
020import java.lang.reflect.Method;
021import java.util.Arrays;
022import java.util.Collections;
023import java.util.List;
024
025import org.springframework.core.DecoratingProxy;
026import org.springframework.core.OrderComparator;
027
028/**
029 * {@code AnnotationAwareOrderComparator} is an extension of
030 * {@link OrderComparator} that supports Spring's
031 * {@link org.springframework.core.Ordered} interface as well as the
032 * {@link Order @Order} and {@link javax.annotation.Priority @Priority}
033 * annotations, with an order value provided by an {@code Ordered}
034 * instance overriding a statically defined annotation value (if any).
035 *
036 * <p>Consult the Javadoc for {@link OrderComparator} for details on the
037 * sort semantics for non-ordered objects.
038 *
039 * @author Juergen Hoeller
040 * @author Oliver Gierke
041 * @author Stephane Nicoll
042 * @since 2.0.1
043 * @see org.springframework.core.Ordered
044 * @see org.springframework.core.annotation.Order
045 * @see javax.annotation.Priority
046 */
047public class AnnotationAwareOrderComparator extends OrderComparator {
048
049        /**
050         * Shared default instance of {@code AnnotationAwareOrderComparator}.
051         */
052        public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
053
054
055        /**
056         * This implementation checks for {@link Order @Order} or
057         * {@link javax.annotation.Priority @Priority} on various kinds of
058         * elements, in addition to the {@link org.springframework.core.Ordered}
059         * check in the superclass.
060         */
061        @Override
062        protected Integer findOrder(Object obj) {
063                // Check for regular Ordered interface
064                Integer order = super.findOrder(obj);
065                if (order != null) {
066                        return order;
067                }
068
069                // Check for @Order and @Priority on various kinds of elements
070                if (obj instanceof Class) {
071                        return OrderUtils.getOrder((Class<?>) obj);
072                }
073                else if (obj instanceof Method) {
074                        Order ann = AnnotationUtils.findAnnotation((Method) obj, Order.class);
075                        if (ann != null) {
076                                return ann.value();
077                        }
078                }
079                else if (obj instanceof AnnotatedElement) {
080                        Order ann = AnnotationUtils.getAnnotation((AnnotatedElement) obj, Order.class);
081                        if (ann != null) {
082                                return ann.value();
083                        }
084                }
085                else if (obj != null) {
086                        order = OrderUtils.getOrder(obj.getClass());
087                        if (order == null && obj instanceof DecoratingProxy) {
088                                order = OrderUtils.getOrder(((DecoratingProxy) obj).getDecoratedClass());
089                        }
090                }
091
092                return order;
093        }
094
095        /**
096         * This implementation retrieves an @{@link javax.annotation.Priority}
097         * value, allowing for additional semantics over the regular @{@link Order}
098         * annotation: typically, selecting one object over another in case of
099         * multiple matches but only one object to be returned.
100         */
101        @Override
102        public Integer getPriority(Object obj) {
103                Integer priority = null;
104                if (obj instanceof Class) {
105                        priority = OrderUtils.getPriority((Class<?>) obj);
106                }
107                else if (obj != null) {
108                        priority = OrderUtils.getPriority(obj.getClass());
109                        if (priority == null && obj instanceof DecoratingProxy) {
110                                priority = OrderUtils.getPriority(((DecoratingProxy) obj).getDecoratedClass());
111                        }
112                }
113                return priority;
114        }
115
116
117        /**
118         * Sort the given List with a default AnnotationAwareOrderComparator.
119         * <p>Optimized to skip sorting for lists with size 0 or 1,
120         * in order to avoid unnecessary array extraction.
121         * @param list the List to sort
122         * @see java.util.Collections#sort(java.util.List, java.util.Comparator)
123         */
124        public static void sort(List<?> list) {
125                if (list.size() > 1) {
126                        Collections.sort(list, INSTANCE);
127                }
128        }
129
130        /**
131         * Sort the given array with a default AnnotationAwareOrderComparator.
132         * <p>Optimized to skip sorting for lists with size 0 or 1,
133         * in order to avoid unnecessary array extraction.
134         * @param array the array to sort
135         * @see java.util.Arrays#sort(Object[], java.util.Comparator)
136         */
137        public static void sort(Object[] array) {
138                if (array.length > 1) {
139                        Arrays.sort(array, INSTANCE);
140                }
141        }
142
143        /**
144         * Sort the given array or List with a default AnnotationAwareOrderComparator,
145         * if necessary. Simply skips sorting when given any other value.
146         * <p>Optimized to skip sorting for lists with size 0 or 1,
147         * in order to avoid unnecessary array extraction.
148         * @param value the array or List to sort
149         * @see java.util.Arrays#sort(Object[], java.util.Comparator)
150         */
151        public static void sortIfNecessary(Object value) {
152                if (value instanceof Object[]) {
153                        sort((Object[]) value);
154                }
155                else if (value instanceof List) {
156                        sort((List<?>) value);
157                }
158        }
159
160}