package org.esmerilprogramming.overtown.server.handlers;
import io.undertow.server.HttpHandler;
import org.esmerilprogramming.overtown.annotation.JSONResponse;
import org.esmerilprogramming.overtown.annotation.Page;
import org.esmerilprogramming.overtown.annotation.path.*;
import org.esmerilprogramming.overtown.http.HttpMethod;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* Created by efraimgentil<efraimgentil@gmail.com> on 28/01/15.
*/
public class ControllerMapping {
private Class<?> controllerClass;
private String name;
private String path;
private Set<PathMapping> pathMappings;
private Set<Method> beforeTranslationMethods;
private HttpHandler internalErrorHandler;
public ControllerMapping(String name , String path) {
this.name = name;
this.path = path;
pathMappings = new LinkedHashSet<>();
beforeTranslationMethods = new LinkedHashSet<>();
}
public void addPathMethods(Set<Method> methods) {
for (Method m : methods) {
Annotation[] annotations = m.getAnnotations();
Set<VerbAndPaths> vaps = mountPathMapping(annotations);
for (VerbAndPaths vap : vaps) {
for (String path : vap.paths) {
path = Path.NO_PATH.equals(path) ? m.getName() : path.trim();
if(!Path.NO_TEMPLATE.equalsIgnoreCase( vap.template)) {
if (!vap.template.startsWith("/") && !vap.template.startsWith(name +"/") ) { //Mount template with the controllerName/templateName
vap.template = name + "/" + vap.template;
}
}
pathMappings.add(new PathMapping(path, vap.httpVerb, m, vap.template, vap.jsonResponse));
}
}
}
}
protected Set<VerbAndPaths> mountPathMapping(Annotation[] annotations) {
Set<VerbAndPaths> verbAndPaths = new LinkedHashSet<>();
for (Annotation annotation : annotations) {
Class<? extends Annotation> annotationClass = annotation.annotationType();
if (annotationClass.equals(Get.class)) {
Get get = (Get) annotation;
verbAndPaths.add(new VerbAndPaths(HttpMethod.GET, get.value(), get.template()));
}
if (annotationClass.equals(Post.class)) {
Post post = (Post) annotation;
verbAndPaths.add(new VerbAndPaths(HttpMethod.POST, post.value(), post.template()));
}
if (annotationClass.equals(Put.class)) {
Put post = (Put) annotation;
verbAndPaths.add(new VerbAndPaths(HttpMethod.PUT, post.value(), post.template()));
}
if (annotationClass.equals(Delete.class)) {
Delete post = (Delete) annotation;
verbAndPaths.add(new VerbAndPaths(HttpMethod.DELETE, post.value(), post.template()));
}
if (annotationClass.equals(Path.class)) {
Path path = (Path) annotation;
verbAndPaths.add(new VerbAndPaths(HttpMethod.GET, path.value(), path.template()));
verbAndPaths.add(new VerbAndPaths(HttpMethod.POST, path.value(), path.template()));
}
if (annotationClass.equals(Page.class)) {
Page page = (Page) annotation;
verbAndPaths.add(new VerbAndPaths(HttpMethod.GET, page.value(), page.responseTemplate()));
verbAndPaths.add(new VerbAndPaths(HttpMethod.POST, page.value(), page.responseTemplate()));
}
}
verbAndPaths = checkForResponseMappings(annotations, verbAndPaths);
return verbAndPaths;
}
private Set<VerbAndPaths> checkForResponseMappings(Annotation[] annotations, Set<VerbAndPaths> verbAndPaths) {
for (Annotation annotation : annotations) {
Class<? extends Annotation> annotationClass = annotation.annotationType();
if (annotationClass.equals(JSONResponse.class)) {
for (VerbAndPaths verbAndPath : verbAndPaths) {
verbAndPath.setJsonResponse(true);
}
}
}
return verbAndPaths;
}
public HttpHandler getInternalErrorHandler() {
return internalErrorHandler;
}
public void setInternalErrorHandler(HttpHandler internalErrorHandler) {
this.internalErrorHandler = internalErrorHandler;
}
private class VerbAndPaths {
private String httpVerb;
private String[] paths;
private String template;
private boolean jsonResponse;
VerbAndPaths(String verb, String[] paths, String template) {
this.httpVerb = verb;
this.paths = paths;
this.template = template;
}
public void setJsonResponse(boolean jsonResponse) {
this.jsonResponse = jsonResponse;
}
}
public void addBeforeTranslationMethods(Set<Method> methods) {
beforeTranslationMethods.addAll(methods);
}
public void setControllerClass(Class<?> controllerClass) {
this.controllerClass = controllerClass;
}
public Class<?> getControllerClass() {
return controllerClass;
}
public Set<Method> getBeforeTranslationMethods() {
return beforeTranslationMethods;
}
public String getPath() {
return path;
}
public Set<PathMapping> getPathMappings() {
return pathMappings;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}