/*
* #%L
* restdoc-doclet
* %%
* Copyright (C) 2012 IG Group
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package com.iggroup.oss.restdoclet.doclet.util;
import static com.iggroup.oss.restdoclet.doclet.util.UrlUtils.parseMultiUri;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.AnnotationDesc.ElementValuePair;
import com.sun.javadoc.AnnotationValue;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.ProgramElementDoc;
/**
* This is an utility class for processing annotations.
*/
public final class AnnotationUtils {
private static final Logger LOG = Logger.getLogger(AnnotationUtils.class);
/**
* Configurable annotation to ignore attributes or methods
*/
private final static String RESTDOCLET_IGNORE_ANNOTATION =
"RESTDOCLET_IGNORE_ANNOTATION";
/**
* Private constructor to "silence" PMD.
*/
private AnnotationUtils() {
super();
}
/**
* Gets the annotations an argument of a method is annotated with.
*
* @param param the method's argument to look for annotations.
* @return the annotations the argument is annotated with or an empty array
* if the argument is not annotated.
*/
public static AnnotationDesc[] annotations(final Parameter param) {
AnnotationDesc[] annotations = param.annotations();
if (annotations == null) {
annotations = new AnnotationDesc[0];
}
return annotations;
}
/**
* Checks if an argument of a method is annotated with an annotation.
*
* @param param the argument to check for annotations.
* @param type the type of annotation to look for.
* @return <code>true</code> if the argument is annotated,
* <code>false</code> otherwise.
*/
public static boolean isAnnotated(final Parameter param, final Class<?> type) {
boolean result = false;
for (final AnnotationDesc annotation : annotations(param)) {
final String name = annotation.annotationType().qualifiedName();
if (StringUtils.equals(type.getName(), name)) {
result = true;
break;
}
}
return result;
}
/**
* Finds the annotation the argument of a method is annotated with.
*
* @param param the argument to check for annotations.
* @param type the type of annotation to look for.
* @return the annotation the argument is annotated with or
* <code>null</code> if the annotation is not found.
*/
public static AnnotationDesc annotation(final Parameter param,
final Class<?> type) {
AnnotationDesc result = null;
for (final AnnotationDesc annotation : annotations(param)) {
final String name = annotation.annotationType().qualifiedName();
if (StringUtils.equals(type.getName(), name)) {
result = annotation;
break;
}
}
return result;
}
/**
* Gets the element-value pairs of an annotation an argument of a method is
* annotated with.
*
* @param param the argument to check for annotations.
* @param type the type of annotation to look for.
* @return the element-value pairs of the annotation or an empty array if
* the annotation is not found.
*/
public static ElementValuePair[] elementValues(final Parameter param,
final Class<?> type) {
return elementValues(annotation(param, type));
}
/**
* Gets the element-value pairs of an annotation an argument of a method is
* annotated with.
*
* @param annotation annotations
* @return the element-value pairs of the annotation or an empty array if
* the annotation is not found.
*/
private static ElementValuePair[] elementValues(final AnnotationDesc annotation) {
ElementValuePair[] result;
if (annotation == null) {
result = new ElementValuePair[0];
} else {
if (annotation.elementValues() == null) {
result = new ElementValuePair[0];
} else {
result = annotation.elementValues();
}
}
return result;
}
/**
* Gets an element-value pair of an annotation an argument of a method is
* annotated with.
*
* @param param the argument to check for annotations.
* @param type the type of annotation to look for.
* @param elementName the name of the element in the annotation to look for.
* @return the value of the element in the annotation or <code>null</code>
* if the annotation is not found or the name of the element is not
* found.
*/
public static AnnotationValue elementValue(final Parameter param,
final Class<?> type,
final String elementName) {
AnnotationValue value = null;
final ElementValuePair[] pairs = elementValues(param, type);
for (final ElementValuePair pair : pairs) {
if (StringUtils.equals(elementName, pair.element().name())) {
value = pair.value();
break;
}
}
return value;
}
/**
* Gets the annotations an element (class or method) is annotated with.
*
* @param element the element to look for annotations.
* @return the annotations the element is annotated with or an empty array
* if the element is not annotated.
*/
public static AnnotationDesc[] annotations(final ProgramElementDoc element) {
AnnotationDesc[] annotations = element.annotations();
if (annotations == null) {
annotations = new AnnotationDesc[0];
}
return annotations;
}
/**
* Checks if an element (class or method) is annotated with an annotation.
*
* @param element the element to check for annotations.
* @param type the type of annotation to look for.
* @return <code>true</code> if the element is annotated, <code>false</code>
* otherwise.
*/
public static boolean isAnnotated(final ProgramElementDoc element,
final Class<?> type) {
boolean result = false;
for (final AnnotationDesc annotation : annotations(element)) {
final String name = annotation.annotationType().qualifiedName();
if (StringUtils.equals(type.getName(), name)) {
result = true;
break;
}
}
return result;
}
/**
* Check if the element is annotated with the configured
* RESTDOCLET_IGNORE_ANNOTATION system property
*
* @param element the element to check
* @return true if the element is annotated with the configured
* RESTDOCLET_IGNORE_ANNOTATION property
*/
public static boolean ignore(ProgramElementDoc element) {
LOG.debug(" IGNORE " + element.name());
String ignoreAnnotation =
System.getProperty(RESTDOCLET_IGNORE_ANNOTATION);
if (ignoreAnnotation != null && !ignoreAnnotation.isEmpty()) {
for (final AnnotationDesc annotation : annotations(element)) {
final String name = annotation.annotationType().qualifiedName();
LOG.debug(" ? " + name);
if (StringUtils.equals(ignoreAnnotation, name)) {
LOG.debug(" Ignoring : " + name);
return true;
}
}
}
return false;
}
/**
* Finds the annotation an element (class or method) is annotated with.
*
* @param element the element to check for annotations.
* @param type the type of annotation to look for.
* @return the annotation the element is annotated with or <code>null</code>
* if the annotation is not found.
*/
public static AnnotationDesc annotation(final ProgramElementDoc element,
final Class<?> type) {
AnnotationDesc result = null;
for (final AnnotationDesc annotation : annotations(element)) {
final String name = annotation.annotationType().qualifiedName();
if (StringUtils.equals(type.getName(), name)) {
result = annotation;
break;
}
}
return result;
}
/**
* Gets the element-value pairs of an annotation an element (class or
* method) is annotated with.
*
* @param element the element to check for annotations.
* @param type the type of annotation to look for.
* @return the element-value pairs of the annotation or an empty array if
* the annotation is not found.
*/
public static ElementValuePair[] elementValues(final ProgramElementDoc element,
final Class<?> type) {
return elementValues(annotation(element, type));
}
/**
* Gets an element-value pair of an annotation an element (class or method)
* is annotated with.
*
* @param element the element to check for annotations.
* @param type the type of annotation to look for.
* @param elementName the name of the element in the annotation to look for.
* @return the value of the element in the annotation or <code>null</code>
* if the annotation is not found or the name of the element is not
* found.
*/
public static AnnotationValue elementValue(final ProgramElementDoc element,
final Class<?> type,
final String elementName) {
AnnotationValue value = null;
final ElementValuePair[] pairs = elementValues(element, type);
for (ElementValuePair pair : pairs) {
if (StringUtils.equals(elementName, pair.element().name())) {
value = pair.value();
break;
}
}
return value;
}
/**
* Parse @RequestMapping value annotation
*
* @param av value of form "xxx" or {"xx","yy",...}
* @return String array of URIs
*/
public static String[] parseValueAnnotation(final AnnotationValue av) {
return parseMultiUri(av.toString().trim());
}
}