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