001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau;
014
015import static org.apache.juneau.internal.ConsumerUtils.*;
016
017import java.lang.annotation.*;
018import java.lang.reflect.*;
019import java.util.function.*;
020
021import org.apache.juneau.internal.*;
022
023/**
024 * Interface that provides the ability to look up annotations on classes/methods/constructors/fields.
025 *
026 * <h5 class='section'>See Also:</h5><ul>
027 * </ul>
028 */
029public interface AnnotationProvider {
030
031   /**
032    * Disable annotation caching.
033    */
034   boolean DISABLE_ANNOTATION_CACHING = Boolean.getBoolean("juneau.disableAnnotationCaching");
035
036   /**
037    * Default metadata provider.
038    */
039   @SuppressWarnings("unchecked") AnnotationProvider DEFAULT = new AnnotationProvider() {
040
041      private final TwoKeyConcurrentCache<Class<?>,Class<? extends Annotation>,Annotation[]> classAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, Class::getAnnotationsByType);
042      private final TwoKeyConcurrentCache<Class<?>,Class<? extends Annotation>,Annotation[]> declaredClassAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, Class::getDeclaredAnnotationsByType);
043      private final TwoKeyConcurrentCache<Method,Class<? extends Annotation>,Annotation[]> methodAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, Method::getAnnotationsByType);
044      private final TwoKeyConcurrentCache<Field,Class<? extends Annotation>,Annotation[]> fieldAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, Field::getAnnotationsByType);
045      private final TwoKeyConcurrentCache<Constructor<?>,Class<? extends Annotation>,Annotation[]> constructorAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, Constructor::getAnnotationsByType);
046
047      @Override /* MetaProvider */
048      public <A extends Annotation> void forEachAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action) {
049         if (type != null && onClass != null)
050            for (A a : annotations(type, onClass))
051               consume(filter, action, a);
052      }
053
054      @Override /* MetaProvider */
055      public <A extends Annotation> A firstAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
056         if (type != null && onClass != null)
057            for (A a : annotations(type, onClass))
058               if (test(filter, a))
059                  return a;
060         return null;
061      }
062
063      @Override /* MetaProvider */
064      public <A extends Annotation> A lastAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
065         A x = null;
066         if (type != null && onClass != null)
067            for (A a : annotations(type, onClass))
068               if (test(filter, a))
069                  x = a;
070         return x;
071      }
072
073      @Override /* MetaProvider */
074      public <A extends Annotation> void forEachDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action) {
075         if (type != null && onClass != null)
076            for (A a : declaredAnnotations(type, onClass))
077               consume(filter, action, a);
078      }
079
080      @Override /* MetaProvider */
081      public <A extends Annotation> A firstDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
082         if (type != null && onClass != null)
083            for (A a : declaredAnnotations(type, onClass))
084               if (test(filter, a))
085                  return a;
086         return null;
087      }
088
089      @Override /* MetaProvider */
090      public <A extends Annotation> A lastDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
091         A x = null;
092         if (type != null && onClass != null)
093            for (A a : declaredAnnotations(type, onClass))
094               if (test(filter, a))
095                  x = a;
096         return x;
097      }
098
099      @Override /* MetaProvider */
100      public <A extends Annotation> void forEachAnnotation(Class<A> type, Method onMethod, Predicate<A> filter, Consumer<A> action) {
101         if (type != null && onMethod != null)
102            for (A a : annotations(type, onMethod))
103               consume(filter, action, a);
104      }
105
106      @Override /* MetaProvider */
107      public <A extends Annotation> A firstAnnotation(Class<A> type, Method onMethod, Predicate<A> filter) {
108         if (type != null && onMethod != null)
109            for (A a : annotations(type, onMethod))
110               if (test(filter, a))
111                  return a;
112         return null;
113      }
114
115      @Override /* MetaProvider */
116      public <A extends Annotation> A lastAnnotation(Class<A> type, Method onMethod, Predicate<A> filter) {
117         A x = null;
118         if (type != null && onMethod != null)
119            for (A a : annotations(type, onMethod))
120               if (test(filter, a))
121                  x = a;
122         return x;
123      }
124
125      @Override /* MetaProvider */
126      public <A extends Annotation> void forEachAnnotation(Class<A> type, Field onField, Predicate<A> filter, Consumer<A> action) {
127         if (type != null && onField != null)
128            for (A a : annotations(type, onField))
129               consume(filter, action, a);
130      }
131
132      @Override /* MetaProvider */
133      public <A extends Annotation> A firstAnnotation(Class<A> type, Field onField, Predicate<A> filter) {
134         if (type != null && onField != null)
135            for (A a : annotations(type, onField))
136               if (test(filter, a))
137                  return a;
138         return null;
139      }
140
141      @Override /* MetaProvider */
142      public <A extends Annotation> A lastAnnotation(Class<A> type, Field onField, Predicate<A> filter) {
143         A x = null;
144         if (type != null && onField != null)
145            for (A a : annotations(type, onField))
146               if (test(filter, a))
147                  x = a;
148         return x;
149      }
150
151      @Override /* MetaProvider */
152      public <A extends Annotation> void forEachAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter, Consumer<A> action) {
153         if (type != null && onConstructor != null)
154            for (A a : annotations(type, onConstructor))
155               consume(filter, action, a);
156      }
157
158      @Override /* MetaProvider */
159      public <A extends Annotation> A firstAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter) {
160         if (type != null && onConstructor != null)
161            for (A a : annotations(type, onConstructor))
162               if (test(filter, a))
163                  return a;
164         return null;
165      }
166
167      @Override /* MetaProvider */
168      public <A extends Annotation> A lastAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter) {
169         A x = null;
170         if (type != null && onConstructor != null)
171            for (A a : annotations(type, onConstructor))
172               if (test(filter, a))
173                  x = a;
174         return x;
175      }
176
177      private <A extends Annotation> A[] annotations(Class<A> type, Class<?> onClass) {
178         return (A[])classAnnotationCache.get(onClass, type);
179      }
180
181      private <A extends Annotation> A[] declaredAnnotations(Class<A> type, Class<?> onClass) {
182         return (A[])declaredClassAnnotationCache.get(onClass, type);
183      }
184
185      private <A extends Annotation> A[] annotations(Class<A> type, Method onMethod) {
186         return (A[])methodAnnotationCache.get(onMethod, type);
187      }
188
189      private <A extends Annotation> A[] annotations(Class<A> type, Field onField) {
190         return (A[])fieldAnnotationCache.get(onField, type);
191      }
192
193      private <A extends Annotation> A[] annotations(Class<A> type, Constructor<?> onConstructor) {
194         return (A[])constructorAnnotationCache.get(onConstructor, type);
195      }
196   };
197
198   /**
199    * Performs an action on the matching annotations on the specified class.
200    *
201    * @param <A> The annotation type to find.
202    * @param type The annotation type to find.
203    * @param onClass The class to search on.
204    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
205    * @param action An action to perform on the entry.
206    */
207   <A extends Annotation> void forEachAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action);
208
209   /**
210    * Finds the first matching annotation on the specified class.
211    *
212    * @param <A> The annotation type to find.
213    * @param type The annotation type to find.
214    * @param onClass The class to search on.
215    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
216    * @return The matched annotation, or <jk>null</jk> if not found.
217    */
218   <A extends Annotation> A firstAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter);
219
220   /**
221    * Finds the last matching annotation on the specified class.
222    *
223    * @param <A> The annotation type to find.
224    * @param type The annotation type to find.
225    * @param onClass The class to search on.
226    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
227    * @return The matched annotation, or <jk>null</jk> if not found.
228    */
229   <A extends Annotation> A lastAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter);
230
231   /**
232    * Performs an action on the matching declared annotations on the specified class.
233    *
234    * @param <A> The annotation type to find.
235    * @param type The annotation type to find.
236    * @param onClass The class to search on.
237    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
238    * @param action An action to perform on the entry.
239    */
240   <A extends Annotation> void forEachDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action);
241
242   /**
243    * Finds the first matching declared annotations on the specified class.
244    *
245    * @param <A> The annotation type to find.
246    * @param type The annotation type to find.
247    * @param onClass The class to search on.
248    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
249    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
250    */
251   <A extends Annotation> A firstDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter);
252
253   /**
254    * Finds the last matching declared annotations on the specified class.
255    *
256    * @param <A> The annotation type to find.
257    * @param type The annotation type to find.
258    * @param onClass The class to search on.
259    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
260    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
261    */
262   <A extends Annotation> A lastDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter);
263
264   /**
265    * Performs an action on the matching annotations on the specified method.
266    *
267    * @param <A> The annotation type to find.
268    * @param type The annotation type to find.
269    * @param onMethod The method to search on.
270    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
271    * @param action An action to perform on the entry.
272    */
273   <A extends Annotation> void forEachAnnotation(Class<A> type, Method onMethod, Predicate<A> filter, Consumer<A> action);
274
275   /**
276    * Finds the first matching annotation on the specified method.
277    *
278    * @param <A> The annotation type to find.
279    * @param type The annotation type to find.
280    * @param onMethod The method to search on.
281    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
282    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
283    */
284   <A extends Annotation> A firstAnnotation(Class<A> type, Method onMethod, Predicate<A> filter);
285
286   /**
287    * Finds the last matching annotation on the specified method.
288    *
289    * @param <A> The annotation type to find.
290    * @param type The annotation type to find.
291    * @param onMethod The method to search on.
292    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
293    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
294    */
295   <A extends Annotation> A lastAnnotation(Class<A> type, Method onMethod, Predicate<A> filter);
296
297   /**
298    * Performs an action on the matching annotations on the specified field.
299    *
300    * @param <A> The annotation type to find.
301    * @param type The annotation type to find.
302    * @param onField The field to search on.
303    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
304    * @param action An action to perform on the entry.
305    */
306   <A extends Annotation> void forEachAnnotation(Class<A> type, Field onField, Predicate<A> filter, Consumer<A> action);
307
308   /**
309    * Finds the first matching annotation on the specified field.
310    *
311    * @param <A> The annotation type to find.
312    * @param type The annotation type to find.
313    * @param onField The field to search on.
314    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
315    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
316    */
317   <A extends Annotation> A firstAnnotation(Class<A> type, Field onField, Predicate<A> filter);
318
319   /**
320    * Finds the last matching annotation on the specified field.
321    *
322    * @param <A> The annotation type to find.
323    * @param type The annotation type to find.
324    * @param onField The field to search on.
325    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
326    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
327    */
328   <A extends Annotation> A lastAnnotation(Class<A> type, Field onField, Predicate<A> filter);
329
330   /**
331    * Performs an action on the matching annotations on the specified constructor.
332    *
333    * @param <A> The annotation type to find.
334    * @param type The annotation type to find.
335    * @param onConstructor The constructor to search on.
336    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
337    * @param action An action to perform on the entry.
338    */
339   <A extends Annotation> void forEachAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter, Consumer<A> action);
340
341   /**
342    * Finds the first matching annotation on the specified constructor.
343    *
344    * @param <A> The annotation type to find.
345    * @param type The annotation type to find.
346    * @param onConstructor The constructor to search on.
347    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
348    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
349    */
350   <A extends Annotation> A firstAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter);
351
352   /**
353    * Finds the last matching annotation on the specified constructor.
354    *
355    * @param <A> The annotation type to find.
356    * @param type The annotation type to find.
357    * @param onConstructor The constructor to search on.
358    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
359    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
360    */
361   <A extends Annotation> A lastAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter);
362}