/*
* Copyright 2002-2017 the original author or authors.
*
* 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.springframework.web.method;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.function.Predicate;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.ValueConstants;
/**
* Predicates for {@code @MVC} annotations.
*
* @author Rossen Stoyanchev
* @since 5.0
*
* @see ResolvableMethod#annot(Predicate[])
* @see ResolvableMethod.Builder#annot(Predicate[])
*/
public class MvcAnnotationPredicates {
// Method parameter predicates
public static ModelAttributePredicate modelAttribute() {
return new ModelAttributePredicate();
}
public static RequestBodyPredicate requestBody() {
return new RequestBodyPredicate();
}
public static RequestParamPredicate requestParam() {
return new RequestParamPredicate();
}
public static RequestPartPredicate requestPart() {
return new RequestPartPredicate();
}
// Method predicates
public static ModelAttributeMethodPredicate modelMethod() {
return new ModelAttributeMethodPredicate();
}
public static ResponseStatusPredicate responseStatus() {
return new ResponseStatusPredicate();
}
public static ResponseStatusPredicate responseStatus(HttpStatus code) {
return new ResponseStatusPredicate(code);
}
public static RequestMappingPredicate requestMapping(String... path) {
return new RequestMappingPredicate(path);
}
public static RequestMappingPredicate getMapping(String... path) {
return new RequestMappingPredicate(path).method(RequestMethod.GET);
}
public static RequestMappingPredicate postMapping(String... path) {
return new RequestMappingPredicate(path).method(RequestMethod.POST);
}
public static RequestMappingPredicate putMapping(String... path) {
return new RequestMappingPredicate(path).method(RequestMethod.PUT);
}
public static RequestMappingPredicate deleteMapping(String... path) {
return new RequestMappingPredicate(path).method(RequestMethod.DELETE);
}
public static RequestMappingPredicate optionsMapping(String... path) {
return new RequestMappingPredicate(path).method(RequestMethod.OPTIONS);
}
public static RequestMappingPredicate headMapping(String... path) {
return new RequestMappingPredicate(path).method(RequestMethod.HEAD);
}
public static class ModelAttributePredicate implements Predicate<MethodParameter> {
private String name;
private boolean binding = true;
public ModelAttributePredicate name(String name) {
this.name = name;
return this;
}
public ModelAttributePredicate noName() {
this.name = "";
return this;
}
public ModelAttributePredicate noBinding() {
this.binding = false;
return this;
}
@Override
public boolean test(MethodParameter parameter) {
ModelAttribute annotation = parameter.getParameterAnnotation(ModelAttribute.class);
return annotation != null &&
(this.name == null || annotation.name().equals(this.name)) &&
annotation.binding() == this.binding;
}
}
public static class RequestBodyPredicate implements Predicate<MethodParameter> {
private boolean required = true;
public RequestBodyPredicate notRequired() {
this.required = false;
return this;
}
@Override
public boolean test(MethodParameter parameter) {
RequestBody annotation = parameter.getParameterAnnotation(RequestBody.class);
return annotation != null && annotation.required() == this.required;
}
}
public static class RequestParamPredicate implements Predicate<MethodParameter> {
private String name;
private boolean required = true;
private String defaultValue = ValueConstants.DEFAULT_NONE;
public RequestParamPredicate name(String name) {
this.name = name;
return this;
}
public RequestParamPredicate noName() {
this.name = "";
return this;
}
public RequestParamPredicate notRequired() {
this.required = false;
return this;
}
public RequestParamPredicate notRequired(String defaultValue) {
this.defaultValue = defaultValue;
return this;
}
@Override
public boolean test(MethodParameter parameter) {
RequestParam annotation = parameter.getParameterAnnotation(RequestParam.class);
return annotation != null &&
(this.name == null || annotation.name().equals(this.name)) &&
annotation.required() == this.required &&
annotation.defaultValue().equals(this.defaultValue);
}
}
public static class RequestPartPredicate implements Predicate<MethodParameter> {
private String name;
private boolean required = true;
public RequestPartPredicate name(String name) {
this.name = name;
return this;
}
public RequestPartPredicate noName() {
this.name = "";
return this;
}
public RequestPartPredicate notRequired() {
this.required = false;
return this;
}
@Override
public boolean test(MethodParameter parameter) {
RequestPart annotation = parameter.getParameterAnnotation(RequestPart.class);
return annotation != null &&
(this.name == null || annotation.name().equals(this.name)) &&
annotation.required() == this.required;
}
}
public static class ModelAttributeMethodPredicate implements Predicate<Method> {
private String name;
public ModelAttributeMethodPredicate name(String name) {
this.name = name;
return this;
}
public ModelAttributeMethodPredicate noName() {
this.name = "";
return this;
}
@Override
public boolean test(Method method) {
ModelAttribute annot = AnnotatedElementUtils.findMergedAnnotation(method, ModelAttribute.class);
return annot != null && (this.name == null || annot.name().equals(this.name));
}
}
public static class ResponseStatusPredicate implements Predicate<Method> {
private HttpStatus code = HttpStatus.INTERNAL_SERVER_ERROR;
private ResponseStatusPredicate() {
}
private ResponseStatusPredicate(HttpStatus code) {
this.code = code;
}
@Override
public boolean test(Method method) {
ResponseStatus annot = AnnotatedElementUtils.findMergedAnnotation(method, ResponseStatus.class);
return annot != null && annot.code().equals(this.code);
}
}
public static class RequestMappingPredicate implements Predicate<Method> {
private String[] path;
private RequestMethod[] method = {};
private String[] params;
private RequestMappingPredicate(String... path) {
this.path = path;
}
public RequestMappingPredicate method(RequestMethod... methods) {
this.method = methods;
return this;
}
public RequestMappingPredicate params(String... params) {
this.params = params;
return this;
}
@Override
public boolean test(Method method) {
RequestMapping annot = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
return annot != null &&
Arrays.equals(this.path, annot.path()) &&
Arrays.equals(this.method, annot.method()) &&
(this.params == null || Arrays.equals(this.params, annot.params()));
}
}
}