package example.spring;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.ObjectUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.view.RedirectView;
import org.springframework.web.util.UriTemplate;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class PathBuilder {
private Class handler;
private String methodName;
private RequestMethod method;
private Map<String, String> pathVariables = new HashMap<String, String>();
private PathBuilder(Class handler) {
this.handler = handler;
}
public static PathBuilder pathTo(Class handler) {
return new PathBuilder(handler).withMethod(RequestMethod.GET);
}
public PathBuilder POST() {
return withMethod(RequestMethod.POST);
}
public PathBuilder withMethod(RequestMethod method) {
this.method = method;
return this;
}
public PathBuilder withMethodName(String methodName) {
this.methodName = methodName;
return this;
}
public PathBuilder withVar(String name, Object value) {
pathVariables.put(name, ObjectUtils.toString(value));
return this;
}
public String build() {
return expandPathVariables(findHandlerClassMapping() + findHandlerMethodMapping());
}
public RedirectView redirect() {
return new ServletRelativeRedirectView(build());
}
private String findHandlerClassMapping() {
RequestMapping mapping = AnnotationUtils.findAnnotation(handler, RequestMapping.class);
return (mapping != null) ? getFirstPath(mapping) : "";
}
private String findHandlerMethodMapping() {
return (methodName != null) ? findMappingForMethodName() : findMappingForRequestMethod();
}
private String findMappingForMethodName() {
for (Method classMethod : handler.getMethods()) {
if (classMethod.getName().equals(methodName)) {
RequestMapping mapping = AnnotationUtils.findAnnotation(classMethod, RequestMapping.class);
if (mapping != null) {
return getFirstPath(mapping);
}
}
}
throw new IllegalArgumentException(handler.getName() +
" does not contain an annotated method named '" + methodName + "'");
}
private String findMappingForRequestMethod() {
for (Method classMethod : handler.getMethods()) {
RequestMapping mapping = AnnotationUtils.findAnnotation(classMethod, RequestMapping.class);
if (mapping != null && ArrayUtils.contains(mapping.method(), method)) {
return getFirstPath(mapping);
}
}
throw new IllegalArgumentException(handler.getName() + " cannot handle " + method + " requests");
}
private String getFirstPath(RequestMapping mapping) {
String[] paths = mapping.value();
return (paths.length > 0) ? paths[0] : "";
}
private String expandPathVariables(String url) {
UriTemplate template = new UriTemplate(url);
return template.expand(pathVariables).toString();
}
}