All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.androidannotations.rest.spring.helper.RestSpringValidatorHelper Maven / Gradle / Ivy

There is a newer version: 4.8.0
Show newest version
/**
 * Copyright (C) 2010-2016 eBusiness Information, Excilys 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.
 */
package org.androidannotations.rest.spring.helper;

import static java.util.Arrays.asList;
import static org.androidannotations.rest.spring.helper.RestSpringClasses.CLIENT_HTTP_REQUEST_FACTORY;
import static org.androidannotations.rest.spring.helper.RestSpringClasses.CLIENT_HTTP_REQUEST_INTERCEPTOR;
import static org.androidannotations.rest.spring.helper.RestSpringClasses.FORM_HTTP_MESSAGE_CONVERTER;
import static org.androidannotations.rest.spring.helper.RestSpringClasses.HTTP_MESSAGE_CONVERTER;
import static org.androidannotations.rest.spring.helper.RestSpringClasses.REST_CLIENT_EXCEPTION;
import static org.androidannotations.rest.spring.helper.RestSpringClasses.REST_TEMPLATE;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;

import org.androidannotations.AndroidAnnotationsEnvironment;
import org.androidannotations.ElementValidation;
import org.androidannotations.annotations.EBean;
import org.androidannotations.helper.CanonicalNameConstants;
import org.androidannotations.helper.TargetAnnotationHelper;
import org.androidannotations.helper.ValidatorHelper;
import org.androidannotations.rest.spring.annotations.Body;
import org.androidannotations.rest.spring.annotations.Delete;
import org.androidannotations.rest.spring.annotations.Field;
import org.androidannotations.rest.spring.annotations.Get;
import org.androidannotations.rest.spring.annotations.Head;
import org.androidannotations.rest.spring.annotations.Options;
import org.androidannotations.rest.spring.annotations.Part;
import org.androidannotations.rest.spring.annotations.Patch;
import org.androidannotations.rest.spring.annotations.Path;
import org.androidannotations.rest.spring.annotations.Post;
import org.androidannotations.rest.spring.annotations.Put;
import org.androidannotations.rest.spring.annotations.Rest;
import org.androidannotations.rest.spring.api.RestClientErrorHandling;
import org.androidannotations.rest.spring.api.RestClientHeaders;
import org.androidannotations.rest.spring.api.RestClientRootUrl;
import org.androidannotations.rest.spring.api.RestClientSupport;

public class RestSpringValidatorHelper extends ValidatorHelper {

	private static final List VALID_REST_INTERFACES = asList(RestClientHeaders.class.getName(), RestClientErrorHandling.class.getName(),
			RestClientRootUrl.class.getName(), RestClientSupport.class.getName());
	private static final List> REST_ANNOTATION_CLASSES = Arrays.asList(Get.class, Head.class, Options.class, Post.class, Put.class, Patch.class, Delete.class);

	private static final String METHOD_NAME_SET_ROOT_URL = "setRootUrl";
	private static final String METHOD_NAME_SET_AUTHENTICATION = "setAuthentication";
	private static final String METHOD_NAME_SET_BEARER_AUTH = "setBearerAuth";
	private static final String METHOD_NAME_GET_COOKIE = "getCookie";
	private static final String METHOD_NAME_GET_HEADER = "getHeader";

	private static final String METHOD_NAME_GET_ROOT_URL = "getRootUrl";

	private final RestAnnotationHelper restAnnotationHelper;

	public RestSpringValidatorHelper(AndroidAnnotationsEnvironment environment, String target) {
		super(new TargetAnnotationHelper(environment, target));
		restAnnotationHelper = new RestAnnotationHelper(environment, target);
	}

	public void doesNotExtendInvalidInterfaces(TypeElement element, ElementValidation valid) {
		if (element.getInterfaces().size() > 0) {
			boolean isValid = true;

			for (TypeMirror iface : element.getInterfaces()) {
				if (!VALID_REST_INTERFACES.contains(iface.toString())) {
					isValid = false;
					break;
				}
			}

			if (!isValid) {
				valid.addError("%s interfaces can only extend the following interfaces: " + VALID_REST_INTERFACES);
			}
		}
	}

	public void enclosingElementHasRestAnnotation(Element element, ElementValidation valid) {
		String error = "can only be used in an interface annotated with";
		enclosingElementHasAnnotation(Rest.class, element, valid, error);
	}

	public void enclosingElementHasOneOfRestMethodAnnotations(Element element, ElementValidation validation) {
		enclosingElementHasOneOfAnnotations(element, REST_ANNOTATION_CLASSES, validation);
	}

	public void unannotatedMethodReturnsRestTemplate(TypeElement typeElement, ElementValidation valid) {
		List enclosedElements = typeElement.getEnclosedElements();
		boolean foundGetRestTemplateMethod = false;
		boolean foundSetRestTemplateMethod = false;
		boolean foundSetAuthenticationMethod = false;
		boolean foundSetBearerAuthMethod = false;
		boolean foundSetRootUrlMethod = false;
		boolean foundGetCookieMethod = false;
		boolean foundGetHeaderMethod = false;
		boolean foundGetRootUrlMethod = false;

		for (Element enclosedElement : enclosedElements) {
			if (enclosedElement.getKind() != ElementKind.METHOD) {
				valid.addError(enclosedElement, "Only methods are allowed in a %s annotated interface");
			} else {

				boolean hasRestAnnotation = false;
				for (Class annotationClass : REST_ANNOTATION_CLASSES) {
					if (enclosedElement.getAnnotation(annotationClass) != null) {
						hasRestAnnotation = true;
						break;
					}
				}

				if (!hasRestAnnotation) {

					ExecutableElement executableElement = (ExecutableElement) enclosedElement;
					TypeMirror returnType = executableElement.getReturnType();
					String simpleName = executableElement.getSimpleName().toString();

					if (returnType.toString().equals(REST_TEMPLATE)) {
						if (executableElement.getParameters().size() > 0) {
							valid.addError(enclosedElement,
									"The method returning a RestTemplate should not declare any parameter in a " + TargetAnnotationHelper.annotationName(Rest.class) + " annotated interface");
						} else {
							if (foundGetRestTemplateMethod) {
								valid.addError(enclosedElement, "Only one method should declare returning a RestTemplate in a " + TargetAnnotationHelper.annotationName(Rest.class)
										+ " annotated interface");
							} else {
								foundGetRestTemplateMethod = true;
							}
						}
					} else if (simpleName.equals(METHOD_NAME_GET_ROOT_URL)) {
						if (!returnType.toString().equals(CanonicalNameConstants.STRING)) {
							valid.addError(enclosedElement, "The method getRootUrl must return String on a %s annotated interface");
						}

						if (executableElement.getParameters().size() != 0) {
							valid.addError(enclosedElement, "The method getRootUrl cannot have parameters on a " + TargetAnnotationHelper.annotationName(Rest.class)
									+ " annotated interface");
						}

						if (!foundGetRootUrlMethod) {
							foundGetRootUrlMethod = true;
						} else {
							valid.addError(enclosedElement, "The can be only one getRootUrl method on a %s annotated interface");
						}
					} else if (returnType.getKind() == TypeKind.VOID) {
						List parameters = executableElement.getParameters();
						if (parameters.size() == 1) {
							VariableElement firstParameter = parameters.get(0);
							if (firstParameter.asType().toString().equals(REST_TEMPLATE)) {
								if (!foundSetRestTemplateMethod) {
									foundSetRestTemplateMethod = true;
								} else {
									valid.addError(enclosedElement, "You can only have oneRestTemplate setter method on a " + TargetAnnotationHelper.annotationName(Rest.class)
											+ " annotated interface");
								}
							} else if (executableElement.getSimpleName().toString().equals(METHOD_NAME_SET_ROOT_URL) && !foundSetRootUrlMethod) {
								foundSetRootUrlMethod = true;
							} else if (executableElement.getSimpleName().toString().equals(METHOD_NAME_SET_AUTHENTICATION) && !foundSetAuthenticationMethod) {
								foundSetAuthenticationMethod = true;
							} else if (executableElement.getSimpleName().toString().equals(METHOD_NAME_SET_BEARER_AUTH) && !foundSetBearerAuthMethod) {
								foundSetBearerAuthMethod = true;
							} else {
								valid.addError(enclosedElement,
										"The method to set a RestTemplate should have only one RestTemplate parameter on a " + TargetAnnotationHelper.annotationName(Rest.class)
												+ " annotated interface");

							}
						} else if (parameters.size() == 2) {
							VariableElement firstParameter = parameters.get(0);
							VariableElement secondParameter = parameters.get(1);
							if (!(firstParameter.asType().toString().equals(CanonicalNameConstants.STRING) && secondParameter.asType().toString().equals(CanonicalNameConstants.STRING))) {
								valid.addError(enclosedElement,
										"The method to set headers, cookies, or HTTP Basic Auth should have only String parameters on a " + TargetAnnotationHelper.annotationName(Rest.class)
												+ " annotated interface");
							}
						} else {
							valid.addError(enclosedElement,
									"The method to set a RestTemplate should have only one RestTemplate parameter on a " + TargetAnnotationHelper.annotationName(Rest.class) + " annotated interface");
						}
					} else if (returnType.toString().equals(CanonicalNameConstants.STRING)) {
						List parameters = executableElement.getParameters();
						if (parameters.size() == 1) {
							VariableElement firstParameter = parameters.get(0);
							if (firstParameter.asType().toString().equals(CanonicalNameConstants.STRING)) {
								if (executableElement.getSimpleName().toString().equals(METHOD_NAME_GET_COOKIE) && !foundGetCookieMethod) {
									foundGetCookieMethod = true;
								} else if (executableElement.getSimpleName().toString().equals(METHOD_NAME_GET_HEADER) && !foundGetHeaderMethod) {
									foundGetHeaderMethod = true;
								} else {
									valid.addError(enclosedElement,
											"Only one getCookie(String) and one getHeader(String) method are allowed on a " + TargetAnnotationHelper.annotationName(Rest.class)
													+ " annotated interface");
								}
							} else {
								valid.addError(enclosedElement,
										"Only getCookie(String) and getHeader(String) can return a String on a " + TargetAnnotationHelper.annotationName(Rest.class) + " annotated interface");
							}

						} else {
							valid.addError(enclosedElement, "The only methods that can return a String on a " + TargetAnnotationHelper.annotationName(Rest.class)
									+ " annotated interface are getCookie(String) and getHeader(String)");
						}
					} else {
						valid.addError(enclosedElement, "All methods should be annotated in a " + TargetAnnotationHelper.annotationName(Rest.class)
								+ " annotated interface, except the ones that returns or set a RestTemplate");
					}
				}
			}
		}
	}

	public void validateConverters(Element element, ElementValidation valid) {
		TypeMirror httpMessageConverterType = annotationHelper.typeElementFromQualifiedName(HTTP_MESSAGE_CONVERTER).asType();
		TypeMirror httpMessageConverterTypeErased = annotationHelper.getTypeUtils().erasure(httpMessageConverterType);
		List converters = annotationHelper.extractAnnotationClassArrayParameter(element, annotationHelper.getTarget(), "converters");

		if (converters == null || converters.isEmpty()) {
			valid.addError(element, "At least one converter is required");
			return;
		}

		for (DeclaredType converterType : converters) {
			TypeMirror erasedConverterType = annotationHelper.getTypeUtils().erasure(converterType);
			if (annotationHelper.isSubtype(erasedConverterType, httpMessageConverterTypeErased)) {
				Element converterElement = converterType.asElement();
				if (converterElement.getKind().isClass()) {
					if (!annotationHelper.isAbstract(converterElement)) {
						if (converterElement.getAnnotation(EBean.class) == null) {
							List constructors = ElementFilter.constructorsIn(converterElement.getEnclosedElements());
							boolean hasPublicWithNoArgumentConstructor = false;
							for (ExecutableElement constructor : constructors) {
								if (annotationHelper.isPublic(constructor) && constructor.getParameters().isEmpty()) {
									hasPublicWithNoArgumentConstructor = true;
								}
							}
							if (!hasPublicWithNoArgumentConstructor) {
								valid.addError("The converter class must have a public no argument constructor");
							}
						}
					} else {
						valid.addError("The converter class must not be abstract");
					}
				} else {
					valid.addError("The converter class must be a class");
				}
			} else {
				valid.addError("The converter class must be a subtype of " + HTTP_MESSAGE_CONVERTER);
			}
		}
	}

	public void validateInterceptors(Element element, ElementValidation valid) {
		TypeMirror clientHttpRequestInterceptorType = annotationHelper.typeElementFromQualifiedName(CLIENT_HTTP_REQUEST_INTERCEPTOR).asType();
		TypeMirror clientHttpRequestInterceptorTypeErased = annotationHelper.getTypeUtils().erasure(clientHttpRequestInterceptorType);
		List interceptors = annotationHelper.extractAnnotationClassArrayParameter(element, annotationHelper.getTarget(), "interceptors");
		if (interceptors == null) {
			return;
		}
		for (DeclaredType interceptorType : interceptors) {
			TypeMirror erasedInterceptorType = annotationHelper.getTypeUtils().erasure(interceptorType);
			if (annotationHelper.isSubtype(erasedInterceptorType, clientHttpRequestInterceptorTypeErased)) {
				Element interceptorElement = interceptorType.asElement();
				if (interceptorElement.getKind().isClass()) {
					if (!annotationHelper.isAbstract(interceptorElement)) {
						if (interceptorElement.getAnnotation(EBean.class) == null) {
							List constructors = ElementFilter.constructorsIn(interceptorElement.getEnclosedElements());
							boolean hasPublicWithNoArgumentConstructor = false;
							for (ExecutableElement constructor : constructors) {
								if (annotationHelper.isPublic(constructor) && constructor.getParameters().isEmpty()) {
									hasPublicWithNoArgumentConstructor = true;
								}
							}
							if (!hasPublicWithNoArgumentConstructor) {
								valid.addError("The interceptor class must have a public no argument constructor or be annotated with @EBean");
							}
						}
					} else {
						valid.addError("The interceptor class must not be abstract");
					}
				} else {
					valid.addError("The interceptor class must be a class");
				}
			} else {
				valid.addError("The interceptor class must be a subtype of " + CLIENT_HTTP_REQUEST_INTERCEPTOR);
			}
		}
	}

	public void validateRestSimpleParameter(Element element, String requiredClass, String parameterName, ElementValidation validation) {
		TypeMirror requiredType = annotationHelper.typeElementFromQualifiedName(requiredClass).asType();
		DeclaredType paramterType = annotationHelper.extractAnnotationClassParameter(element, annotationHelper.getTarget(), parameterName);
		if (paramterType != null) {
			if (annotationHelper.isSubtype(paramterType, requiredType)) {
				Element parameterElement = paramterType.asElement();
				if (parameterElement.getKind().isClass()) {
					if (!annotationHelper.isAbstract(parameterElement)) {
						if (parameterElement.getAnnotation(EBean.class) != null) {
							return;
						}
						List constructors = ElementFilter.constructorsIn(parameterElement.getEnclosedElements());
						for (ExecutableElement constructor : constructors) {
							if (annotationHelper.isPublic(constructor) && constructor.getParameters().isEmpty()) {
								return;
							}
						}
						validation.addError(element, "The " + parameterName + " class must have a public no argument constructor or must be annotated with @EBean");
					} else {
						validation.addError(element, "The " + parameterName + " class must not be abstract");
					}
				} else {
					validation.addError(element, "The " + parameterName + " class must be a class");
				}
			} else {
				validation.addError(element, "The " + parameterName + " class must be a subtype of " + requiredClass);
			}
		}
	}

	public void validateRequestFactory(Element element, ElementValidation validation) {
		validateRestSimpleParameter(element, CLIENT_HTTP_REQUEST_FACTORY, "requestFactory", validation);
	}

	public void validateResponseErrorHandler(Element element, ElementValidation validation) {
		validateRestSimpleParameter(element, RestSpringClasses.RESPONSE_ERROR_HANDLER, "responseErrorHandler", validation);
	}

	public void throwsOnlyRestClientException(ExecutableElement element, ElementValidation valid) {
		List thrownTypes = element.getThrownTypes();
		if (thrownTypes.size() > 0) {
			if (thrownTypes.size() > 1 || !thrownTypes.get(0).toString().equals(REST_CLIENT_EXCEPTION)) {
				valid.addError("%s annotated methods can only declare throwing a RestClientException");
			}
		}
	}

	public void urlVariableNamesExistInParameters(ExecutableElement element, Set variableNames, ElementValidation valid) {

		List parameters = element.getParameters();

		Set parametersName = new HashSet<>();
		for (VariableElement parameter : parameters) {
			if (parameter.getAnnotation(Path.class) == null) {
				continue;
			}

			String nameToAdd = restAnnotationHelper.getUrlVariableCorrespondingTo(parameter);

			if (parametersName.contains(nameToAdd)) {
				valid.addError(element, "%s has multiple method parameters which correspond to the same url variable");
				return;
			}
			parametersName.add(nameToAdd);
		}

		String[] cookiesToUrl = restAnnotationHelper.requiredUrlCookies(element);
		if (cookiesToUrl != null) {
			Collections.addAll(parametersName, cookiesToUrl);
		}

		for (String variableName : variableNames) {
			if (!parametersName.contains(variableName)) {
				valid.addError("%s annotated method has an url variable which name could not be found in the method parameters: " + variableName);
				return;
			}
		}
	}

	public void doesNotMixRequestEntityAnnotations(ExecutableElement element, ElementValidation validation) {
		int numberOfRequestEntityFound = 0;
		boolean partFound = false;
		boolean fieldFound = false;
		boolean bodyFound = false;

		for (VariableElement parameter : element.getParameters()) {
			Part part = parameter.getAnnotation(Part.class);
			if (part != null && !partFound) {
				partFound = true;
				numberOfRequestEntityFound++;
			}

			Field field = parameter.getAnnotation(Field.class);
			if (field != null && !fieldFound) {
				fieldFound = true;
				numberOfRequestEntityFound++;
			}

			Body body = parameter.getAnnotation(Body.class);
			if (body != null && !bodyFound) {
				bodyFound = true;
				numberOfRequestEntityFound++;
			}
		}

		if (numberOfRequestEntityFound > 1) {
			validation.addError(element, "Only one of @Part, @Field and @Body annotations can be used on the same method's parameters, not both.");
		}
	}

	public void urlVariableNameExistsInEnclosingAnnotation(Element element, ElementValidation validation) {
		Set validRestMethodAnnotationNames = new HashSet<>();

		for (Class validAnnotation : REST_ANNOTATION_CLASSES) {
			validRestMethodAnnotationNames.add(validAnnotation.getCanonicalName());
		}

		String url = null;

		for (AnnotationMirror annotationMirror : element.getEnclosingElement().getAnnotationMirrors()) {
			if (validRestMethodAnnotationNames.contains(annotationMirror.getAnnotationType().toString())) {
				url = restAnnotationHelper.extractAnnotationParameter(element.getEnclosingElement(), annotationMirror.getAnnotationType().toString(), "value");
				break;
			}
		}

		Set urlVariableNames = restAnnotationHelper.extractUrlVariableNames(url);

		String expectedUrlVariableName = restAnnotationHelper.getUrlVariableCorrespondingTo((VariableElement) element);

		if (!urlVariableNames.contains(expectedUrlVariableName)) {
			validation.addError(element, "%s annotated parameter is has no corresponding url variable");
		}
	}

	public void hasSpringAndroidJars(ElementValidation valid) {
		Elements elementUtils = annotationHelper.getElementUtils();
		if (elementUtils.getTypeElement(REST_TEMPLATE) == null) {
			valid.addError("Could not find the SpringAndroid framework in the classpath, the following class is missing: " + REST_TEMPLATE);
		}
	}

	public void hasHttpHeadersReturnType(ExecutableElement element, ElementValidation valid) {
		String returnType = element.getReturnType().toString();
		if (!returnType.equals("org.springframework.http.HttpHeaders")) {
			valid.addError("%s annotated methods can only return a HttpHeaders, not " + returnType);
		}
	}

	public void hasSetOfHttpMethodReturnType(ExecutableElement element, ElementValidation valid) {
		TypeMirror returnType = element.getReturnType();
		String returnTypeString = returnType.toString();
		if (!returnTypeString.equals("java.util.Set")) {
			valid.addError("%s annotated methods can only return a Set of HttpMethod, not " + returnTypeString);
		} else {
			DeclaredType declaredType = (DeclaredType) returnType;
			List typeArguments = declaredType.getTypeArguments();
			if (typeArguments.size() != 1) {
				valid.addError("%s annotated methods can only return a parameterized Set (with HttpMethod)");
			} else {
				TypeMirror typeArgument = typeArguments.get(0);
				if (!typeArgument.toString().equals("org.springframework.http.HttpMethod")) {
					valid.addError("%s annotated methods can only return a parameterized Set of HttpMethod, not " + typeArgument.toString());
				}
			}
		}
	}

	public int numberOfBodyAnnotatedParameter(ExecutableElement element) {
		return numberOfElementParameterHasAnnotation(element, Body.class);
	}

	public int numberOfPathAnnotatedParameter(ExecutableElement element) {
		return numberOfElementParameterHasAnnotation(element, Path.class);
	}

	public int numberOfRequiresCookieInUrl(ExecutableElement element) {
		String[] cookiesToUrl = restAnnotationHelper.requiredUrlCookies(element);
		if (cookiesToUrl == null) {
			return 0;
		} else {
			return cookiesToUrl.length;
		}
	}

	public int numberOfPartAnnotatedParameter(ExecutableElement element) {
		return numberOfElementParameterHasAnnotation(element, Part.class);
	}

	public int numberOfFieldAnnotatedParameter(ExecutableElement element) {
		return numberOfElementParameterHasAnnotation(element, Field.class);
	}

	public void doesNotHaveDuplicateFieldAndPartName(ExecutableElement element, ElementValidation validation) {
		if (restAnnotationHelper.extractFieldAndPartParameters(element) == null) {
			validation.addError(element, "%s annotated method has multiple form parameters with the same name");
		}
	}

	public void doesNotHaveBodyAnnotatedParameter(ExecutableElement element, ElementValidation validation) {
		if (numberOfBodyAnnotatedParameter(element) != 0) {
			validation.addError(element, "%s parameters must not have @Body parameter");
		}
	}

	public void doesNotHavePartAnnotatedParameter(ExecutableElement element, ElementValidation validation) {
		if (numberOfPartAnnotatedParameter(element) != 0) {
			validation.addError(element, "%s parameters must not have @Part parameter");
		}
	}

	public void doesNotHaveFieldAnnotatedParameter(ExecutableElement element, ElementValidation validation) {
		if (numberOfFieldAnnotatedParameter(element) != 0) {
			validation.addError(element, "%s parameters must not have @Field parameter");
		}
	}

	public void doesNotHaveRequestEntityAnnotatedParameters(ExecutableElement element, ElementValidation validation) {
		doesNotHavePartAnnotatedParameter(element, validation);
		doesNotHaveFieldAnnotatedParameter(element, validation);
		doesNotHaveBodyAnnotatedParameter(element, validation);
	}

	public void doesNotHavePathAnnotation(Element element, ElementValidation validation) {
		doesNotHaveAnnotation(element, Path.class, validation);
	}

	public void doesNotHaveFieldAnnotation(Element element, ElementValidation validation) {
		doesNotHaveAnnotation(element, Field.class, validation);
	}

	public void doesNotHavePartAnnotation(Element element, ElementValidation validation) {
		doesNotHaveAnnotation(element, Part.class, validation);
	}

	public void doesNotHaveBodyAnnotation(Element element, ElementValidation validation) {
		doesNotHaveAnnotation(element, Body.class, validation);
	}

	public void restInterfaceHasFormConverter(Element element, ElementValidation validation) {
		Element restInterface = element.getEnclosingElement().getEnclosingElement();

		if (restInterface.getAnnotation(Rest.class) == null) {
			return;
		}

		List converters = annotationHelper.extractAnnotationClassArrayParameter(restInterface, Rest.class.getCanonicalName(), "converters");

		boolean formConverterFound = false;

		TypeElement formConverter = annotationHelper.getElementUtils().getTypeElement(FORM_HTTP_MESSAGE_CONVERTER);

		for (DeclaredType converter : converters) {
			if (formConverter != null && annotationHelper.isSubtype(formConverter.asType(), converter)) {
				formConverterFound = true;
				break;
			}
		}

		if (!formConverterFound) {
			validation.addError(element, "%s annotated method parameter must be in a @Rest annotated interface which uses at least one " //
					+ FORM_HTTP_MESSAGE_CONVERTER + " (or subtype)");
		}
	}

	public void elementHasOneOfRestMethodAnnotations(Element element, ElementValidation validation) {
		hasOneOfAnnotations(element, element, REST_ANNOTATION_CLASSES, validation);
	}

	public void usesSpringAndroid2(Element element, ElementValidation validation) {
		if (environment().getProcessingEnvironment().getElementUtils().getTypeElement(RestSpringClasses.PARAMETERIZED_TYPE_REFERENCE) == null) {
			validation.addError(element, "To use %s annotated method you must add Spring Android Rest Template 2.0 to your classpath");
		}
	}

	public void hasOneOrZeroBodyParameter(ExecutableElement element, ElementValidation validation) {
		if (validation.isValid() && numberOfBodyAnnotatedParameter(element) > 1) {
			validation.addError(element, "%s parameters must not have more than one @Body annotation.");
		}
	}

	public void hasAnnotatedAllParameters(ExecutableElement element, ElementValidation validation) {
		if (!validation.isValid()) {
			return;
		}

		Set urlVariableNames = restAnnotationHelper.extractUrlVariableNames(element);
		if (urlVariableNames.size() != numberOfPathAnnotatedParameter(element) + numberOfRequiresCookieInUrl(element)) {
			validation.addError(element, "%s must have url variables corresponding to the @Path or @RequiresCookieInUrl annotation");
		}

		for (VariableElement variableElement : element.getParameters()) {
			if (!restAnnotationHelper.hasRestApiMethodParameterAnnotation(variableElement)) {
				validation.addError(element, "%s method parameters '" + variableElement + "' must be annotated");
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy