diff --git a/README.md b/README.md index 69ebbd7..f1f3e0b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# labyrinth +# labyrinth-generator diff --git a/pom.xml b/pom.xml index 6648fc4..2ad3f6d 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 diff --git a/src/main/java/ch/fritteli/labyrinth/generator/Main.java b/src/main/java/ch/fritteli/labyrinth/generator/Main.java index 1541519..1acf787 100644 --- a/src/main/java/ch/fritteli/labyrinth/generator/Main.java +++ b/src/main/java/ch/fritteli/labyrinth/generator/Main.java @@ -1,13 +1,11 @@ package ch.fritteli.labyrinth.generator; import ch.fritteli.labyrinth.generator.model.Labyrinth; -import ch.fritteli.labyrinth.generator.net.TheListener; import ch.fritteli.labyrinth.generator.renderer.html.HTMLRenderer; import ch.fritteli.labyrinth.generator.renderer.htmlfile.HTMLFileRenderer; import ch.fritteli.labyrinth.generator.renderer.pdffile.PDFFileRenderer; import ch.fritteli.labyrinth.generator.renderer.text.TextRenderer; import ch.fritteli.labyrinth.generator.renderer.textfile.TextFileRenderer; -import io.vavr.control.Option; import lombok.NonNull; import java.nio.file.Path; @@ -15,38 +13,34 @@ import java.nio.file.Paths; public class Main { public static void main(@NonNull final String[] args) { - final Option listener = TheListener.createListener(); - if (listener.isEmpty()) { - System.out.println("In order to start the webserver, specify the port to listen to via the system property 'fritteli.labyrinth.listenerport', i.e.: -Dfritteli.labyrinth.listenerport=12345"); - int width = 100; - int height = 100; - final Labyrinth labyrinth = new Labyrinth(width, height/*, 0*/); - final TextRenderer textRenderer = TextRenderer.newInstance(); - final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance(); - final Path userHome = Paths.get(System.getProperty("user.home")); - final String baseFilename = getBaseFilename(labyrinth); - final TextFileRenderer textFileRenderer = TextFileRenderer.newInstance() - .setTargetLabyrinthFile(userHome.resolve(baseFilename + ".txt")) - .setTargetSolutionFile(userHome.resolve(baseFilename + "-solution.txt")); - final HTMLFileRenderer htmlFileRenderer = HTMLFileRenderer.newInstance() - .setTargetFile(userHome.resolve(baseFilename + ".html")); - final PDFFileRenderer pdfFileRenderer = PDFFileRenderer.newInstance() - .setTargetFile(userHome.resolve(baseFilename + ".pdf")); + int width = 100; + int height = 100; + final Labyrinth labyrinth = new Labyrinth(width, height/*, 0*/); + final TextRenderer textRenderer = TextRenderer.newInstance(); + final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance(); + final Path userHome = Paths.get(System.getProperty("user.home")); + final String baseFilename = getBaseFilename(labyrinth); + final TextFileRenderer textFileRenderer = TextFileRenderer.newInstance() + .setTargetLabyrinthFile(userHome.resolve(baseFilename + ".txt")) + .setTargetSolutionFile(userHome.resolve(baseFilename + "-solution.txt")); + final HTMLFileRenderer htmlFileRenderer = HTMLFileRenderer.newInstance() + .setTargetFile(userHome.resolve(baseFilename + ".html")); + final PDFFileRenderer pdfFileRenderer = PDFFileRenderer.newInstance() + .setTargetFile(userHome.resolve(baseFilename + ".pdf")); - System.out.println("Labyrinth-ID: " + labyrinth.getRandomSeed()); - // Render Labyrinth to stdout - System.out.println(textRenderer.render(labyrinth)); - // Render Labyrinth solution to stdout - System.out.println(textRenderer.setRenderSolution(true).render(labyrinth)); - // Render HTML to stdout - System.out.println(htmlRenderer.render(labyrinth)); - // Render Labyrinth and solution to (separate) files - System.out.println(textFileRenderer.render(labyrinth)); - // Render HTML to file - System.out.println(htmlFileRenderer.render(labyrinth)); - // Render PDF to file - System.out.println(pdfFileRenderer.render(labyrinth)); - } + System.out.println("Labyrinth-ID: " + labyrinth.getRandomSeed()); + // Render Labyrinth to stdout + System.out.println(textRenderer.render(labyrinth)); + // Render Labyrinth solution to stdout + System.out.println(textRenderer.setRenderSolution(true).render(labyrinth)); + // Render HTML to stdout + System.out.println(htmlRenderer.render(labyrinth)); + // Render Labyrinth and solution to (separate) files + System.out.println(textFileRenderer.render(labyrinth)); + // Render HTML to file + System.out.println(htmlFileRenderer.render(labyrinth)); + // Render PDF to file + System.out.println(pdfFileRenderer.render(labyrinth)); } private static String getBaseFilename(@NonNull final Labyrinth labyrinth) { diff --git a/src/main/java/ch/fritteli/labyrinth/generator/net/TheListener.java b/src/main/java/ch/fritteli/labyrinth/generator/net/TheListener.java deleted file mode 100644 index df898ae..0000000 --- a/src/main/java/ch/fritteli/labyrinth/generator/net/TheListener.java +++ /dev/null @@ -1,198 +0,0 @@ -package ch.fritteli.labyrinth.generator.net; - -import ch.fritteli.labyrinth.generator.model.Labyrinth; -import ch.fritteli.labyrinth.generator.renderer.html.HTMLRenderer; -import ch.fritteli.labyrinth.generator.renderer.pdf.PDFRenderer; -import ch.fritteli.labyrinth.generator.renderer.text.TextRenderer; -import com.sun.net.httpserver.Headers; -import com.sun.net.httpserver.HttpServer; -import io.vavr.collection.HashMap; -import io.vavr.collection.HashSet; -import io.vavr.collection.List; -import io.vavr.collection.Map; -import io.vavr.collection.Set; -import io.vavr.collection.Stream; -import io.vavr.control.Option; -import io.vavr.control.Try; -import lombok.Getter; -import lombok.NonNull; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.function.Function; - -public class TheListener { - - private final HttpServer httpServer; - - public TheListener(final int port) throws IOException { - this.httpServer = HttpServer.create(new InetSocketAddress(port), 0); - this.httpServer.createContext("/create", exchange -> { - final String requestMethod = exchange.getRequestMethod(); - if (!requestMethod.equals("GET")) { - exchange.getResponseBody().close(); - exchange.sendResponseHeaders(405, -1); - exchange.close(); - return; - } - final Map requestParams = this.parseQueryString(exchange.getRequestURI().getQuery()); - final int width = this.getOrDefault(requestParams.get(RequestParameter.WIDTH), Integer::valueOf, 1); - final int height = this.getOrDefault(requestParams.get(RequestParameter.HEIGHT), Integer::valueOf, 1); - final Option seedOption = requestParams.get(RequestParameter.ID).toTry().map(Long::valueOf).toOption(); - final long seed; - final Option outputOption = requestParams.get(RequestParameter.OUTPUT).flatMap(OutputType::ofString); - final OutputType output; - final Headers responseHeaders = exchange.getResponseHeaders(); - boolean needsRedirect = false; - if (seedOption.isEmpty()) { - needsRedirect = true; - seed = System.nanoTime(); - } else { - seed = seedOption.get(); - } - if (outputOption.isEmpty()) { - needsRedirect = true; - output = OutputType.HTML; - } else { - output = outputOption.get(); - } - if (needsRedirect) { - responseHeaders.add("Location", "/create?width=" + width + "&height=" + height + "&output=" + output.toString() + "&id=" + seed); - exchange.sendResponseHeaders(302, -1); - exchange.close(); - return; - } - responseHeaders.add("Content-type", output.getContentType()); - exchange.sendResponseHeaders(200, 0); - final Labyrinth labyrinth = new Labyrinth(width, height, seed); - final byte[] render = output.render(labyrinth); - final OutputStream responseBody = exchange.getResponseBody(); - responseBody.write(render); - responseBody.flush(); - exchange.close(); - }); - } - - public static Option createListener() { - final String listenerPort = System.getProperty("fritteli.labyrinth.listenerport"); - final Option listenerOption = Option.of(listenerPort) - .toTry() - .map(Integer::valueOf) - .onFailure(cause -> System.err.println("Invalid port specified via system property 'fritteli.labyrinth.listenerport': " - + listenerPort - + ". Not starting webserver.")) - .mapTry(TheListener::new) - .onFailure(cause -> System.err.println("Failed to create Listener: " + cause)) - .toOption(); - listenerOption.forEach(TheListener::start); - return listenerOption; - } - - private T getOrDefault(@NonNull final Option input, @NonNull final Function mapper, @Nullable final T defaultValue) { - return input.toTry().map(mapper).getOrElse(defaultValue); - } - - @NonNull - private Map parseQueryString(@Nullable final String query) { - if (query == null) { - return HashMap.empty(); - } - HashMap result = HashMap.empty(); - final String[] parts = query.split("&"); - for (final String part : parts) { - final int split = part.indexOf('='); - if (split == -1) { - final Try tryKey = Try.of(() -> this.normalizeParameterName(part)); - if (tryKey.isSuccess()) { - result = result.put(tryKey.get(), null); - } - } else { - final String key = part.substring(0, split); - final String value = part.substring(split + 1); - final Try tryKey = Try.of(() -> this.normalizeParameterName(key)); - if (tryKey.isSuccess()) { - result = result.put(tryKey.get(), value); - } - } - } - return result; - } - - private RequestParameter normalizeParameterName(final String paramName) { - return RequestParameter.parseName(paramName).get(); - } - - public void start() { - Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "listener-stopper")); - this.httpServer.start(); - System.out.println("Listening on " + this.httpServer.getAddress()); - } - - public void stop() { - System.out.println("Stopping listener ..."); - this.httpServer.stop(5); - System.out.println("Listener stopped."); - } - - private enum RequestParameter { - WIDTH("w", "width"), - HEIGHT("h", "height"), - ID("i", "id"), - OUTPUT("o", "output"); - private final Set names; - - RequestParameter(@NonNull final String... names) { - this.names = HashSet.of(names); - } - - static Option parseName(@Nullable final String name) { - if (name == null) { - return Option.none(); - } - final String nameLC = name.toLowerCase(); - return Stream.of(values()) - .find(param -> param.names.contains(nameLC)); - } - } - - private enum OutputType { - TEXT_PLAIN("text/plain; charset=UTF-8", labyrinth -> TextRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8), "t", "text"), - HTML("text/html", labyrinth -> HTMLRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8), "h", "html"), - PDF("application/pdf", labyrinth -> PDFRenderer.newInstance().render(labyrinth), "p", "pdf"); - @Getter - @NonNull - private final String contentType; - @NonNull - private final List names; - @NonNull - private final Function render; - - OutputType(@NonNull final String contentType, @NonNull final Function render, @NonNull final String... names) { - this.contentType = contentType; - this.render = render; - this.names = List.of(names); - } - - static Option ofString(@Nullable final String name) { - if (name == null) { - return Option.none(); - } - final String nameLC = name.toLowerCase(); - return Stream.of(values()) - .find(param -> param.names.contains(nameLC)); - - } - - @Override - public String toString() { - return this.names.last(); - } - - byte[] render(@NonNull final Labyrinth labyrinth) { - return this.render.apply(labyrinth); - } - } -}