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   static final boolean DISABLE_ANNOTATION_CACHING = Boolean.getBoolean("juneau.disableAnnotationCaching");
035
036   /**
037    * Default metadata provider.
038    */
039   @SuppressWarnings("unchecked")
040   public static final AnnotationProvider DEFAULT = new AnnotationProvider() {
041
042      private final TwoKeyConcurrentCache<Class<?>,Class<? extends Annotation>,Annotation[]> classAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, (k1,k2) -> k1.getAnnotationsByType(k2));
043      private final TwoKeyConcurrentCache<Class<?>,Class<? extends Annotation>,Annotation[]> declaredClassAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, (k1,k2) -> k1.getDeclaredAnnotationsByType(k2));
044      private final TwoKeyConcurrentCache<Method,Class<? extends Annotation>,Annotation[]> methodAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, (k1,k2) -> k1.getAnnotationsByType(k2));
045      private final TwoKeyConcurrentCache<Field,Class<? extends Annotation>,Annotation[]> fieldAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, (k1,k2) -> k1.getAnnotationsByType(k2));
046      private final TwoKeyConcurrentCache<Constructor<?>,Class<? extends Annotation>,Annotation[]> constructorAnnotationCache = new TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING, (k1,k2) -> k1.getAnnotationsByType(k2));
047
048      @Override /* MetaProvider */
049      public <A extends Annotation> void forEachAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action) {
050         if (type != null && onClass != null)
051            for (A a : annotations(type, onClass))
052               consume(filter, action, a);
053      }
054
055      @Override /* MetaProvider */
056      public <A extends Annotation> A firstAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
057         if (type != null && onClass != null)
058            for (A a : annotations(type, onClass))
059               if (test(filter, a))
060                  return a;
061         return null;
062      }
063
064      @Override /* MetaProvider */
065      public <A extends Annotation> A lastAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
066         A x = null;
067         if (type != null && onClass != null)
068            for (A a : annotations(type, onClass))
069               if (test(filter, a))
070                  x = a;
071         return x;
072      }
073
074      @Override /* MetaProvider */
075      public <A extends Annotation> void forEachDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action) {
076         if (type != null && onClass != null)
077            for (A a : declaredAnnotations(type, onClass))
078               consume(filter, action, a);
079      }
080
081      @Override /* MetaProvider */
082      public <A extends Annotation> A firstDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
083         if (type != null && onClass != null)
084            for (A a : declaredAnnotations(type, onClass))
085               if (test(filter, a))
086                  return a;
087         return null;
088      }
089
090      @Override /* MetaProvider */
091      public <A extends Annotation> A lastDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
092         A x = null;
093         if (type != null && onClass != null)
094            for (A a : declaredAnnotations(type, onClass))
095               if (test(filter, a))
096                  x = a;
097         return x;
098      }
099
100      @Override /* MetaProvider */
101      public <A extends Annotation> void forEachAnnotation(Class<A> type, Method onMethod, Predicate<A> filter, Consumer<A> action) {
102         if (type != null && onMethod != null)
103            for (A a : annotations(type, onMethod))
104               consume(filter, action, a);
105      }
106
107      @Override /* MetaProvider */
108      public <A extends Annotation> A firstAnnotation(Class<A> type, Method onMethod, Predicate<A> filter) {
109         if (type != null && onMethod != null)
110            for (A a : annotations(type, onMethod))
111               if (test(filter, a))
112                  return a;
113         return null;
114      }
115
116      @Override /* MetaProvider */
117      public <A extends Annotation> A lastAnnotation(Class<A> type, Method onMethod, Predicate<A> filter) {
118         A x = null;
119         if (type != null && onMethod != null)
120            for (A a : annotations(type, onMethod))
121               if (test(filter, a))
122                  x = a;
123         return x;
124      }
125
126      @Override /* MetaProvider */
127      public <A extends Annotation> void forEachAnnotation(Class<A> type, Field onField, Predicate<A> filter, Consumer<A> action) {
128         if (type != null && onField != null)
129            for (A a : annotations(type, onField))
130               consume(filter, action, a);
131      }
132
133      @Override /* MetaProvider */
134      public <A extends Annotation> A firstAnnotation(Class<A> type, Field onField, Predicate<A> filter) {
135         if (type != null && onField != null)
136            for (A a : annotations(type, onField))
137               if (test(filter, a))
138                  return a;
139         return null;
140      }
141
142      @Override /* MetaProvider */
143      public <A extends Annotation> A lastAnnotation(Class<A> type, Field onField, Predicate<A> filter) {
144         A x = null;
145         if (type != null && onField != null)
146            for (A a : annotations(type, onField))
147               if (test(filter, a))
148                  x = a;
149         return x;
150      }
151
152      @Override /* MetaProvider */
153      public <A extends Annotation> void forEachAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter, Consumer<A> action) {
154         if (type != null && onConstructor != null)
155            for (A a : annotations(type, onConstructor))
156               consume(filter, action, a);
157      }
158
159      @Override /* MetaProvider */
160      public <A extends Annotation> A firstAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter) {
161         if (type != null && onConstructor != null)
162            for (A a : annotations(type, onConstructor))
163               if (test(filter, a))
164                  return a;
165         return null;
166      }
167
168      @Override /* MetaProvider */
169      public <A extends Annotation> A lastAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter) {
170         A x = null;
171         if (type != null && onConstructor != null)
172            for (A a : annotations(type, onConstructor))
173               if (test(filter, a))
174                  x = a;
175         return x;
176      }
177
178      private <A extends Annotation> A[] annotations(Class<A> type, Class<?> onClass) {
179         return (A[])classAnnotationCache.get(onClass, type);
180      }
181
182      private <A extends Annotation> A[] declaredAnnotations(Class<A> type, Class<?> onClass) {
183         return (A[])declaredClassAnnotationCache.get(onClass, type);
184      }
185
186      private <A extends Annotation> A[] annotations(Class<A> type, Method onMethod) {
187         return (A[])methodAnnotationCache.get(onMethod, type);
188      }
189
190      private <A extends Annotation> A[] annotations(Class<A> type, Field onField) {
191         return (A[])fieldAnnotationCache.get(onField, type);
192      }
193
194      private <A extends Annotation> A[] annotations(Class<A> type, Constructor<?> onConstructor) {
195         return (A[])constructorAnnotationCache.get(onConstructor, type);
196      }
197   };
198
199   /**
200    * Performs an action on the matching annotations on the specified class.
201    *
202    * @param <A> The annotation type to find.
203    * @param type The annotation type to find.
204    * @param onClass The class to search on.
205    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
206    * @param action An action to perform on the entry.
207    */
208   <A extends Annotation> void forEachAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action);
209
210   /**
211    * Finds the first matching annotation on the specified class.
212    *
213    * @param <A> The annotation type to find.
214    * @param type The annotation type to find.
215    * @param onClass The class to search on.
216    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
217    * @return The matched annotation, or <jk>null</jk> if not found.
218    */
219   <A extends Annotation> A firstAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter);
220
221   /**
222    * Finds the last matching annotation on the specified class.
223    *
224    * @param <A> The annotation type to find.
225    * @param type The annotation type to find.
226    * @param onClass The class to search on.
227    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
228    * @return The matched annotation, or <jk>null</jk> if not found.
229    */
230   <A extends Annotation> A lastAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter);
231
232   /**
233    * Performs an action on the matching declared annotations on the specified class.
234    *
235    * @param <A> The annotation type to find.
236    * @param type The annotation type to find.
237    * @param onClass The class to search on.
238    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
239    * @param action An action to perform on the entry.
240    */
241   <A extends Annotation> void forEachDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action);
242
243   /**
244    * Finds the first matching declared annotations on the specified class.
245    *
246    * @param <A> The annotation type to find.
247    * @param type The annotation type to find.
248    * @param onClass The class to search on.
249    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
250    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
251    */
252   <A extends Annotation> A firstDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter);
253
254   /**
255    * Finds the last matching declared annotations on the specified class.
256    *
257    * @param <A> The annotation type to find.
258    * @param type The annotation type to find.
259    * @param onClass The class to search on.
260    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
261    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
262    */
263   <A extends Annotation> A lastDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter);
264
265   /**
266    * Performs an action on the matching annotations on the specified method.
267    *
268    * @param <A> The annotation type to find.
269    * @param type The annotation type to find.
270    * @param onMethod The method to search on.
271    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
272    * @param action An action to perform on the entry.
273    */
274   <A extends Annotation> void forEachAnnotation(Class<A> type, Method onMethod, Predicate<A> filter, Consumer<A> action);
275
276   /**
277    * Finds the first matching annotation on the specified method.
278    *
279    * @param <A> The annotation type to find.
280    * @param type The annotation type to find.
281    * @param onMethod The method to search on.
282    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
283    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
284    */
285   <A extends Annotation> A firstAnnotation(Class<A> type, Method onMethod, Predicate<A> filter);
286
287   /**
288    * Finds the last matching annotation on the specified method.
289    *
290    * @param <A> The annotation type to find.
291    * @param type The annotation type to find.
292    * @param onMethod The method to search on.
293    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
294    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
295    */
296   <A extends Annotation> A lastAnnotation(Class<A> type, Method onMethod, Predicate<A> filter);
297
298   /**
299    * Performs an action on the matching annotations on the specified field.
300    *
301    * @param <A> The annotation type to find.
302    * @param type The annotation type to find.
303    * @param onField The field to search on.
304    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
305    * @param action An action to perform on the entry.
306    */
307   <A extends Annotation> void forEachAnnotation(Class<A> type, Field onField, Predicate<A> filter, Consumer<A> action);
308
309   /**
310    * Finds the first matching annotation on the specified field.
311    *
312    * @param <A> The annotation type to find.
313    * @param type The annotation type to find.
314    * @param onField The field to search on.
315    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
316    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
317    */
318   <A extends Annotation> A firstAnnotation(Class<A> type, Field onField, Predicate<A> filter);
319
320   /**
321    * Finds the last matching annotation on the specified field.
322    *
323    * @param <A> The annotation type to find.
324    * @param type The annotation type to find.
325    * @param onField The field to search on.
326    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
327    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
328    */
329   <A extends Annotation> A lastAnnotation(Class<A> type, Field onField, Predicate<A> filter);
330
331   /**
332    * Performs an action on the matching annotations on the specified constructor.
333    *
334    * @param <A> The annotation type to find.
335    * @param type The annotation type to find.
336    * @param onConstructor The constructor to search on.
337    * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
338    * @param action An action to perform on the entry.
339    */
340   <A extends Annotation> void forEachAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter, Consumer<A> action);
341
342   /**
343    * Finds the first matching annotation on the specified constructor.
344    *
345    * @param <A> The annotation type to find.
346    * @param type The annotation type to find.
347    * @param onConstructor The constructor to search on.
348    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
349    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
350    */
351   <A extends Annotation> A firstAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter);
352
353   /**
354    * Finds the last matching annotation on the specified constructor.
355    *
356    * @param <A> The annotation type to find.
357    * @param type The annotation type to find.
358    * @param onConstructor The constructor to search on.
359    * @param filter A predicate to apply to the entries to determine if value should be used.  Can be <jk>null</jk>.
360    * @return The matched annotation, or <jk>null</jk> if no annotations matched.
361    */
362   <A extends Annotation> A lastAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter);
363}