package com.github.ggeorgovassilis.springjsonmapper.spring;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import com.github.ggeorgovassilis.springjsonmapper.model.Header;
import com.github.ggeorgovassilis.springjsonmapper.model.MappingDeclarationException;
import com.github.ggeorgovassilis.springjsonmapper.model.MethodParameterDescriptor;
import com.github.ggeorgovassilis.springjsonmapper.model.UrlMapping;
import com.github.ggeorgovassilis.springjsonmapper.model.MethodParameterDescriptor.Type;
import com.github.ggeorgovassilis.springjsonmapper.utils.Utils;
/**
* Looks at methods and extracts {@link RequestParam}, {@link PathVariable},
* {@link RequestBody} and {@link RequestMapping} annotations
*
* @author george georgovassilis
*
*/
public class SpringAnnotationMethodInspector extends BaseAnnotationMethodInspector{
@Override
public UrlMapping inspect(Method method, Object[] args) {
UrlMapping urlMapping = new UrlMapping();
RequestMapping rm = AnnotationUtils.findAnnotation(method,
RequestMapping.class);
if (rm == null)
return null;
if (!Utils.hasValue(rm.value()))
throw new MappingDeclarationException("Path missing from @RequestMapping on "+method.toGenericString(), method, rm, -1);
urlMapping.setUrl(resolveExpression(rm.value()[0]));
urlMapping.setHeaders(rm.headers());
urlMapping.setConsumes(rm.consumes());
urlMapping.setProduces(rm.produces());
if (Utils.hasValue(rm.method())) {
if (rm.method().length!=1)
throw new MappingDeclarationException("Multiple HTTP methods on @RequestMapping on "+method.toGenericString(), method, rm, -1);
urlMapping.setHttpMethod(HttpMethod.valueOf(rm.method()[0].name()));
}
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations.length != method.getParameterTypes().length)
throw new MappingDeclarationException(
String.format(
"Annotation mismatch: method has %d parameters but %d have been annotated on %s",
parameterAnnotations.length,
method.getParameterTypes().length,
method.toString()), method, rm, -1);
int i = 0;
for (Annotation[] annotations : parameterAnnotations) {
Object value = args[i];
i++;
String parameterName = "";
Type parameterType = null;
boolean parameterFound = false;
boolean parameterNameRequired = false;
for (Annotation annotation : annotations) {
if (PathVariable.class.isAssignableFrom(annotation
.annotationType())) {
PathVariable pv = (PathVariable) annotation;
parameterName = pv.value();
parameterType = Type.pathVariable;
parameterFound = true;
parameterNameRequired = true;
}
if (RequestParam.class.isAssignableFrom(annotation
.annotationType())) {
RequestParam pv = (RequestParam) annotation;
parameterName = pv.value();
urlMapping.addDescriptor(new MethodParameterDescriptor(
Type.httpParameter, parameterName, value, method, i));
parameterFound = true;
parameterNameRequired = true;
}
if (Header.class.isAssignableFrom(annotation
.annotationType())) {
Header h = (Header) annotation;
parameterName = h.value();
parameterType = Type.httpHeader;
parameterFound = true;
parameterNameRequired = true;
}
if (RequestBody.class.isAssignableFrom(annotation
.annotationType())) {
parameterType = Type.requestBody;
parameterFound = true;
}
if (RequestPart.class.isAssignableFrom(annotation
.annotationType())) {
parameterType = Type.requestPart;
parameterFound = true;
}
if (CookieValue.class.isAssignableFrom(annotation
.annotationType())) {
parameterType = Type.cookie;
parameterFound = true;
CookieValue cv = (CookieValue) annotation;
parameterName = cv.value();
parameterNameRequired = true;
}
}
if (!parameterFound)
throw new MappingDeclarationException(
String.format(
"Couldn't find mapping annotation on parameter %d of method %s",
i, method.toGenericString()), method, null, i);
if (parameterType != null) {
if (parameterNameRequired & !Utils.hasValue(parameterName))
throw new MappingDeclarationException(String.format("No name specified for parameter %d on method %s", i, method.toGenericString()), method, null, i);
urlMapping.addDescriptor(new MethodParameterDescriptor(
parameterType, parameterName, value, method, i));
}
}
return urlMapping;
}
}