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.camel.util;
018
019import java.lang.annotation.Annotation;
020import java.lang.reflect.AnnotatedElement;
021import java.lang.reflect.Field;
022import java.lang.reflect.Method;
023import java.util.ArrayList;
024import java.util.List;
025
026public final class AnnotationHelper {
027
028    /**
029     * Returns a list of methods which are annotated with the given annotation
030     *
031     * @param  type           the type to reflect on
032     * @param  annotationType the annotation type
033     * @return                a list of the methods found
034     */
035    public static List<Method> findMethodsWithAnnotation(
036            Class<?> type,
037            Class<? extends Annotation> annotationType) {
038        return findMethodsWithAnnotation(type, annotationType, false);
039    }
040
041    /**
042     * Returns a list of methods which are annotated with the given annotation
043     *
044     * @param  type                 the type to reflect on
045     * @param  annotationType       the annotation type
046     * @param  checkMetaAnnotations check for meta annotations
047     * @return                      a list of the methods found
048     */
049    public static List<Method> findMethodsWithAnnotation(
050            Class<?> type,
051            Class<? extends Annotation> annotationType,
052            boolean checkMetaAnnotations) {
053        List<Method> answer = new ArrayList<>();
054        do {
055            Method[] methods = type.getDeclaredMethods();
056            for (Method method : methods) {
057                if (hasAnnotation(method, annotationType, checkMetaAnnotations)) {
058                    answer.add(method);
059                }
060            }
061            type = type.getSuperclass();
062        } while (type != null);
063        return answer;
064    }
065
066    /**
067     * Checks if a Class or Method are annotated with the given annotation
068     *
069     * @param  elem                 the Class or Method to reflect on
070     * @param  annotationType       the annotation type
071     * @param  checkMetaAnnotations check for meta annotations
072     * @return                      true if annotations is present
073     */
074    public static boolean hasAnnotation(
075            AnnotatedElement elem, Class<? extends Annotation> annotationType,
076            boolean checkMetaAnnotations) {
077        if (elem.isAnnotationPresent(annotationType)) {
078            return true;
079        }
080        if (checkMetaAnnotations) {
081            for (Annotation a : elem.getAnnotations()) {
082                for (Annotation meta : a.annotationType().getAnnotations()) {
083                    if (meta.annotationType().getName().equals(annotationType.getName())) {
084                        return true;
085                    }
086                }
087            }
088        }
089        return false;
090    }
091
092    /**
093     * Checks if the class has been annotated with the given annotation (FQN class name) and if present, then returns
094     * the value attribute.
095     *
096     * @param  clazz             the class
097     * @param  fqnAnnotationName the FQN of the annotation
098     * @return                   null if not annotated, otherwise the value, an empty string means annotation but has no
099     *                           value
100     */
101    public static String getAnnotationValue(Class<?> clazz, String fqnAnnotationName) {
102        for (Annotation ann : clazz.getAnnotations()) {
103            if (ann.annotationType().getName().equals(fqnAnnotationName)) {
104                String s = ann.toString();
105                return StringHelper.between(s, "\"", "\"");
106            }
107        }
108        return null;
109    }
110
111    /**
112     * Checks if the class has been annotated with the given annotation (FQN class name).
113     *
114     * @param  clazz             the class
115     * @param  fqnAnnotationName the FQN of the annotation
116     * @return                   true if annotated or false if not
117     */
118    public static boolean hasAnnotation(Class<?> clazz, String fqnAnnotationName) {
119        for (Annotation ann : clazz.getAnnotations()) {
120            if (ann.annotationType().getName().equals(fqnAnnotationName)) {
121                return true;
122            }
123        }
124        return false;
125    }
126
127    /**
128     * Checks if the method has been annotated with the given annotation (FQN class name).
129     *
130     * @param  method            the method
131     * @param  fqnAnnotationName the FQN of the annotation
132     * @return                   true if annotated or false if not
133     */
134    public static boolean hasAnnotation(Method method, String fqnAnnotationName) {
135        for (Annotation ann : method.getAnnotations()) {
136            if (ann.annotationType().getName().equals(fqnAnnotationName)) {
137                return true;
138            }
139        }
140        return false;
141    }
142
143    /**
144     * Checks if the method has been annotated with the given annotation (FQN class name) and if present, then returns
145     * the value attribute.
146     *
147     * @param  method            the method
148     * @param  fqnAnnotationName the FQN of the annotation
149     * @return                   null if not annotated, otherwise the value, an empty string means annotation but has no
150     *                           value
151     */
152    public static String getAnnotationValue(Method method, String fqnAnnotationName) {
153        return (String) getAnnotationValue(method, fqnAnnotationName, "value");
154    }
155
156    /**
157     * Checks if the method has been annotated with the given annotation (FQN class name) and if present, then returns
158     * the value attribute.
159     *
160     * @param  method            the field
161     * @param  key               the annotation key
162     * @param  fqnAnnotationName the FQN of the annotation
163     * @return                   null if not annotated, otherwise the value, an empty string means annotation but has no
164     *                           value
165     */
166    public static Object getAnnotationValue(Method method, String fqnAnnotationName, String key) {
167        for (Annotation ann : method.getAnnotations()) {
168            if (ann.annotationType().getName().equals(fqnAnnotationName)) {
169                try {
170                    Method m = ann.getClass().getDeclaredMethod(key);
171                    return m.invoke(ann);
172                } catch (Exception e) {
173                    return null;
174                }
175            }
176        }
177        return null;
178    }
179
180    /**
181     * Checks if the field has been annotated with the given annotation (FQN class name).
182     *
183     * @param  field             the field
184     * @param  fqnAnnotationName the FQN of the annotation
185     * @return                   true if annotated or false if not
186     */
187    public static boolean hasAnnotation(Field field, String fqnAnnotationName) {
188        for (Annotation ann : field.getAnnotations()) {
189            if (ann.annotationType().getName().equals(fqnAnnotationName)) {
190                return true;
191            }
192        }
193        return false;
194    }
195
196    /**
197     * Checks if the field has been annotated with the given annotation (FQN class name) and if present, then returns
198     * the value attribute.
199     *
200     * @param  field             the field
201     * @param  fqnAnnotationName the FQN of the annotation
202     * @return                   null if not annotated, otherwise the value, an empty string means annotation but has no
203     *                           value
204     */
205    public static String getAnnotationValue(Field field, String fqnAnnotationName) {
206        return (String) getAnnotationValue(field, fqnAnnotationName, "value");
207    }
208
209    /**
210     * Checks if the field has been annotated with the given annotation (FQN class name) and if present, then returns
211     * the value attribute.
212     *
213     * @param  field             the field
214     * @param  key               the annotation key
215     * @param  fqnAnnotationName the FQN of the annotation
216     * @return                   null if not annotated, otherwise the value, an empty string means annotation but has no
217     *                           value
218     */
219    public static Object getAnnotationValue(Field field, String fqnAnnotationName, String key) {
220        for (Annotation ann : field.getAnnotations()) {
221            if (ann.annotationType().getName().equals(fqnAnnotationName)) {
222                try {
223                    Method m = ann.getClass().getDeclaredMethod(key);
224                    return m.invoke(ann);
225                } catch (Exception e) {
226                    return null;
227                }
228            }
229        }
230        return null;
231    }
232
233}