001/* 002 * Copyright 2002-2019 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.annotation.Annotation; 020import java.util.function.Predicate; 021 022/** 023 * {@link MergedAnnotationSelector} implementations that provide various options 024 * for {@link MergedAnnotation} instances. 025 * 026 * @author Phillip Webb 027 * @since 5.2 028 * @see MergedAnnotations#get(Class, Predicate, MergedAnnotationSelector) 029 * @see MergedAnnotations#get(String, Predicate, MergedAnnotationSelector) 030 */ 031public abstract class MergedAnnotationSelectors { 032 033 private static final MergedAnnotationSelector<?> NEAREST = new Nearest(); 034 035 private static final MergedAnnotationSelector<?> FIRST_DIRECTLY_DECLARED = new FirstDirectlyDeclared(); 036 037 038 private MergedAnnotationSelectors() { 039 } 040 041 042 /** 043 * Select the nearest annotation, i.e. the one with the lowest distance. 044 * @return a selector that picks the annotation with the lowest distance 045 */ 046 @SuppressWarnings("unchecked") 047 public static <A extends Annotation> MergedAnnotationSelector<A> nearest() { 048 return (MergedAnnotationSelector<A>) NEAREST; 049 } 050 051 /** 052 * Select the first directly declared annotation when possible. If no direct 053 * annotations are declared then the nearest annotation is selected. 054 * @return a selector that picks the first directly declared annotation whenever possible 055 */ 056 @SuppressWarnings("unchecked") 057 public static <A extends Annotation> MergedAnnotationSelector<A> firstDirectlyDeclared() { 058 return (MergedAnnotationSelector<A>) FIRST_DIRECTLY_DECLARED; 059 } 060 061 062 /** 063 * {@link MergedAnnotationSelector} to select the nearest annotation. 064 */ 065 private static class Nearest implements MergedAnnotationSelector<Annotation> { 066 067 @Override 068 public boolean isBestCandidate(MergedAnnotation<Annotation> annotation) { 069 return annotation.getDistance() == 0; 070 } 071 072 @Override 073 public MergedAnnotation<Annotation> select( 074 MergedAnnotation<Annotation> existing, MergedAnnotation<Annotation> candidate) { 075 076 if (candidate.getDistance() < existing.getDistance()) { 077 return candidate; 078 } 079 return existing; 080 } 081 082 } 083 084 085 /** 086 * {@link MergedAnnotationSelector} to select the first directly declared 087 * annotation. 088 */ 089 private static class FirstDirectlyDeclared implements MergedAnnotationSelector<Annotation> { 090 091 @Override 092 public boolean isBestCandidate(MergedAnnotation<Annotation> annotation) { 093 return annotation.getDistance() == 0; 094 } 095 096 @Override 097 public MergedAnnotation<Annotation> select( 098 MergedAnnotation<Annotation> existing, MergedAnnotation<Annotation> candidate) { 099 100 if (existing.getDistance() > 0 && candidate.getDistance() == 0) { 101 return candidate; 102 } 103 return existing; 104 } 105 106 } 107 108}