package com.github.aesteve.vertx.nubes.reflections; import com.github.aesteve.vertx.nubes.Config; import com.github.aesteve.vertx.nubes.annotations.Controller; import com.github.aesteve.vertx.nubes.annotations.File; import com.github.aesteve.vertx.nubes.annotations.View; import com.github.aesteve.vertx.nubes.context.FileResolver; import com.github.aesteve.vertx.nubes.context.ViewResolver; import com.github.aesteve.vertx.nubes.reflections.factories.AuthenticationFactory; import com.github.aesteve.vertx.nubes.reflections.visitors.ControllerVisitor; import com.github.aesteve.vertx.nubes.routing.MVCRoute; import io.vertx.core.VertxException; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import org.reflections.Reflections; import java.lang.annotation.Annotation; import java.util.*; import java.util.function.BiConsumer; public class RouteFactory implements HandlerFactory { private final Router router; private final Config config; private final AuthenticationFactory authFactory; private final RouteRegistry routeRegistry; private Map<Class<? extends Annotation>, BiConsumer<RoutingContext, ?>> returnHandlers; public RouteFactory(Router router, Config config) { this.router = router; this.config = config; routeRegistry = new RouteRegistry(); authFactory = new AuthenticationFactory(config); createReturnHandlers(); } private void createReturnHandlers() { returnHandlers = new HashMap<>(); returnHandlers.put(View.class, (context, res) -> { if (res instanceof String) { ViewResolver.resolve(context, (String) res); } else if (res instanceof Map) { @SuppressWarnings("unchecked") // we have to... Map<? extends String, ?> mapRes = (Map<? extends String, ?>) res; context.data().putAll(mapRes); } }); returnHandlers.put(File.class, (context, res) -> FileResolver.resolve(context, (String) res)); } @Override public void createHandlers() { List<MVCRoute> routes = extractRoutesFromControllers(); routes.stream().filter(MVCRoute::isEnabled).forEach(route -> route.attachHandlersToRouter(router)); } private List<MVCRoute> extractRoutesFromControllers() { List<MVCRoute> routes = new ArrayList<>(); config.forEachControllerPackage(controllerPackage -> { Reflections reflections = new Reflections(controllerPackage); Set<Class<?>> controllers = reflections.getTypesAnnotatedWith(Controller.class); controllers.forEach(controller -> routes.addAll(extractRoutesFromController(controller))); }); return routes; } private List<MVCRoute> extractRoutesFromController(Class<?> controller) { try { ControllerVisitor<?> visitor = new ControllerVisitor<>(controller, config, router, authFactory, routeRegistry, returnHandlers); return visitor.visit(); } catch (IllegalAccessException | InstantiationException e) { throw new VertxException(e); } } }