package com.sebastian_daschner.jaxrs_analyzer.analysis.results;
import com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;
import com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;
import com.sun.javadoc.*;
import java.util.Optional;
import java.util.stream.Stream;
import static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.toReadableType;
import static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;
/**
* Resolves the actual {@code *Param} parameters analyzed by both the JavaDoc and Bytecode analysis.
*
* @author Sebastian Daschner
*/
final class JavaDocParameterResolver {
private static final String[] KNOWN_ANNOTATIONS = {PATH_PARAM, QUERY_PARAM, HEADER_PARAM, FORM_PARAM, COOKIE_PARAM, MATRIX_PARAM, DEFAULT_VALUE, SUSPENDED, CONTEXT};
private JavaDocParameterResolver() {
throw new UnsupportedOperationException();
}
static Optional<ParamTag> findParameterDoc(final MethodParameter parameter, final MethodDoc methodDoc) {
final Optional<String> paramName = Stream.of(methodDoc.parameters())
.filter(p -> hasAnnotation(parameter, p.annotations()))
.map(Parameter::name)
.findAny();
if (!paramName.isPresent())
return Optional.empty();
return Stream.of(methodDoc.paramTags())
.filter(t -> t.parameterName().equals(paramName.get()))
.findAny();
}
static Optional<FieldDoc> findFieldDoc(final MethodParameter parameter, final ClassDoc classDoc) {
if (classDoc == null)
return Optional.empty();
return Stream.of(classDoc.fields(false))
.filter(f -> hasAnnotation(parameter, f.annotations()))
.findAny();
}
static Optional<ParamTag> findRequestBodyDoc(final MethodDoc methodDoc) {
final Optional<String> paramName = Stream.of(methodDoc.parameters())
.filter(p -> isRequestBody(p.annotations()))
.map(Parameter::name)
.findAny();
return Stream.of(methodDoc.paramTags())
.filter(t -> t.parameterName().equals(paramName.get()))
.findAny();
}
private static boolean hasAnnotation(final MethodParameter parameter, final AnnotationDesc... annotations) {
return Stream.of(annotations)
.filter(a -> annotationTypeMatches(a.annotationType().qualifiedTypeName(), parameter.getParameterType()))
.anyMatch(a -> annotationValueMatches(a.elementValues(), parameter.getName()));
}
private static boolean isRequestBody(final AnnotationDesc... annotations) {
return Stream.of(annotations)
.map(AnnotationDesc::annotationType)
.map(AnnotationTypeDoc::qualifiedTypeName)
.noneMatch(t -> Stream.of(KNOWN_ANNOTATIONS).anyMatch(a -> t.equals(toReadableType(a))));
}
private static boolean annotationTypeMatches(final String qualifiedTypeName, final ParameterType parameterType) {
return qualifiedTypeName.equals(getJavaType(parameterType));
}
private static boolean annotationValueMatches(final AnnotationDesc.ElementValuePair[] elementValuePairs, final String name) {
return Stream.of(elementValuePairs)
.anyMatch(p -> "value".equals(p.element().name()) && name.equals(p.value().value()));
}
private static String getJavaType(final ParameterType parameterType) {
switch (parameterType) {
case PATH:
return toReadableType(PATH_PARAM);
case QUERY:
return toReadableType(QUERY_PARAM);
case HEADER:
return toReadableType(HEADER_PARAM);
case FORM:
return toReadableType(FORM_PARAM);
case MATRIX:
return toReadableType(MATRIX_PARAM);
case COOKIE:
return toReadableType(COOKIE_PARAM);
default:
return null;
}
}
}