package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;
import com.sebastian_daschner.jaxrs_analyzer.LogProvider;
import com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation.*;
import com.sebastian_daschner.jaxrs_analyzer.model.Types;
import com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;
import com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;
import com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;
import com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;
import com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.objectweb.asm.Opcodes.ASM5;
/**
* @author Sebastian Daschner
*/
class JAXRSAnnotatedSuperMethodVisitor extends MethodVisitor {
private final MethodResult methodResult;
private final List<String> parameterTypes;
private final Map<Integer, MethodParameter> methodParameters;
private final BitSet annotatedParameters;
JAXRSAnnotatedSuperMethodVisitor(final MethodResult methodResult) {
super(ASM5);
this.methodResult = methodResult;
parameterTypes = methodResult.getOriginalMethodSignature().getParameters();
annotatedParameters = new BitSet(parameterTypes.size());
methodParameters = new HashMap<>();
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
switch (desc) {
case Types.GET:
methodResult.setHttpMethod(HttpMethod.GET);
break;
case Types.POST:
methodResult.setHttpMethod(HttpMethod.POST);
break;
case Types.PUT:
methodResult.setHttpMethod(HttpMethod.PUT);
break;
case Types.DELETE:
methodResult.setHttpMethod(HttpMethod.DELETE);
break;
case Types.HEAD:
methodResult.setHttpMethod(HttpMethod.HEAD);
break;
case Types.OPTIONS:
methodResult.setHttpMethod(HttpMethod.OPTIONS);
break;
case Types.DEPRECATED:
methodResult.setDeprecated(true);
break;
case Types.PATH:
return new PathAnnotationVisitor(methodResult);
case Types.CONSUMES:
return new ConsumesAnnotationVisitor(methodResult);
case Types.PRODUCES:
return new ProducesAnnotationVisitor(methodResult);
}
return null;
}
@Override
public AnnotationVisitor visitParameterAnnotation(final int index, final String annotationDesc, final boolean visible) {
switch (annotationDesc) {
case Types.PATH_PARAM:
return paramAnnotationVisitor(index, ParameterType.PATH);
case Types.QUERY_PARAM:
return paramAnnotationVisitor(index, ParameterType.QUERY);
case Types.HEADER_PARAM:
return paramAnnotationVisitor(index, ParameterType.HEADER);
case Types.FORM_PARAM:
return paramAnnotationVisitor(index, ParameterType.FORM);
case Types.COOKIE_PARAM:
return paramAnnotationVisitor(index, ParameterType.COOKIE);
case Types.MATRIX_PARAM:
return paramAnnotationVisitor(index, ParameterType.MATRIX);
case Types.DEFAULT_VALUE:
return defaultAnnotationVisitor(index);
case Types.SUSPENDED:
LogProvider.debug("Handling of " + annotationDesc + " not yet implemented");
case Types.CONTEXT:
annotatedParameters.set(index);
default:
return null;
}
}
private AnnotationVisitor paramAnnotationVisitor(final int index, final ParameterType parameterType) {
annotatedParameters.set(index);
final String type = parameterTypes.get(index);
MethodParameter methodParameter = methodParameters.get(index);
if (methodParameter == null) {
methodParameter = new MethodParameter(TypeIdentifier.ofType(type), parameterType);
methodParameters.put(index, methodParameter);
} else {
methodParameter.setParameterType(parameterType);
}
return new ParamAnnotationVisitor(methodParameter);
}
private AnnotationVisitor defaultAnnotationVisitor(final int index) {
final String type = parameterTypes.get(index);
MethodParameter methodParameter = methodParameters.get(index);
if (methodParameter == null) {
methodParameter = new MethodParameter(TypeIdentifier.ofType(type));
methodParameters.put(index, methodParameter);
}
return new DefaultValueAnnotationVisitor(methodParameter);
}
@Override
public void visitEnd() {
if (annotatedParameters.cardinality() != parameterTypes.size()) {
final String requestBodyType = parameterTypes.get(annotatedParameters.nextClearBit(0));
methodResult.setRequestBodyType(requestBodyType);
}
methodResult.getMethodParameters().addAll(methodParameters.values());
}
}