package com.vtence.molecule; import com.vtence.molecule.middlewares.URLMap; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; import java.util.function.Consumer; public class MiddlewareStack implements Application { private final Deque<Middleware> stack = new ArrayDeque<>(); private URLMap map; private Application runner; private Application pipeline = (request, response) -> boot().handle(request, response); private Consumer<Application> warmup; public MiddlewareStack() {} public MiddlewareStack use(Middleware middleware) { if (map != null) { stack.add(map); map = null; } stack.add(middleware); return this; } public MiddlewareStack mount(String path, Application app) { if (map == null) { map = new URLMap(); } map.mount(path, app); return this; } public MiddlewareStack warmup(Consumer<Application> warmup) { this.warmup = warmup; return this; } public MiddlewareStack run(Application runner) { this.runner = runner; return this; } public void handle(Request request, Response response) throws Exception { pipeline.handle(request, response); } public Application boot() { if (map == null && runner == null) { throw new IllegalStateException("No app or mount points defined"); } if (map != null) { runner = runner != null ? map.mount("/", runner) : map; } pipeline = assemble(); if (warmup != null) warmup.accept(pipeline); return pipeline; } private Application assemble() { Application chain = runner; for (Iterator<Middleware> middlewares = stack.descendingIterator(); middlewares.hasNext(); ) { Middleware previous = middlewares.next(); previous.connectTo(chain); chain = previous; } return chain; } }