Java21 and some refactoring.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Manuel Friedli 2024-05-18 02:20:31 +02:00
parent ba85f54b16
commit dbdfb0c8a4
Signed by: manuel
GPG key ID: 41D08ABA75634DA1
14 changed files with 101 additions and 87 deletions

View file

@ -3,7 +3,7 @@ type: docker
name: default name: default
steps: steps:
- name: build - name: build
image: maven:3.8-openjdk-18-slim image: maven:3.9-eclipse-temurin-21
commands: commands:
- mvn clean install -DskipTests=true -Dmaven.javadoc.skip=true -B -V - mvn clean install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
when: when:
@ -13,7 +13,7 @@ steps:
- refs/head/feature/** - refs/head/feature/**
- refs/tags/** - refs/tags/**
- name: test - name: test
image: maven:3.8-openjdk-18-slim image: maven:3.9-eclipse-temurin-21
commands: commands:
- mvn test -B - mvn test -B
when: when:
@ -22,7 +22,7 @@ steps:
- master - master
- feature/* - feature/*
- name: deploy - name: deploy
image: maven:3.8-openjdk-18-slim image: maven:3.9-eclipse-temurin-21
environment: environment:
REPO_TOKEN: REPO_TOKEN:
from_secret: repo-token from_secret: repo-token

View file

@ -1,4 +1,4 @@
FROM openjdk:17-slim FROM eclipse-temurin:21-jre
COPY target/maze-server-*.jar /app/ COPY target/maze-server-*.jar /app/
RUN rm /app/*-sources.jar RUN rm /app/*-sources.jar

View file

@ -10,7 +10,7 @@
</server> </server>
<server> <server>
<id>ossrh</id> <id>ossrh</id>
<username>fritteli</username> <username>4etdRvZF</username>
<password>${env.REPO_TOKEN_OSSRH}</password> <password>${env.REPO_TOKEN_OSSRH}</password>
</server> </server>
</servers> </servers>

View file

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ch.fritteli</groupId> <groupId>ch.fritteli</groupId>
<artifactId>fritteli-build-parent</artifactId> <artifactId>fritteli-build-parent</artifactId>
<version>5.0.0</version> <version>5.1.0</version>
</parent> </parent>
<groupId>ch.fritteli.a-maze-r</groupId> <groupId>ch.fritteli.a-maze-r</groupId>
@ -55,9 +55,9 @@
</distributionManagement> </distributionManagement>
<properties> <properties>
<maze-generator.version>0.1.0</maze-generator.version> <maze-generator.version>0.2.1</maze-generator.version>
<maven-site-plugin.version>4.0.0-M8</maven-site-plugin.version> <maven-site-plugin.version>4.0.0-M8</maven-site-plugin.version>
<undertow.version>2.3.5.Final</undertow.version> <undertow.version>2.3.13.Final</undertow.version>
</properties> </properties>
<dependencies> <dependencies>

View file

@ -0,0 +1,9 @@
package ch.fritteli.maze.server;
import org.wildfly.common.annotation.NotNull;
public class InvalidRequestParameterException extends RuntimeException {
public InvalidRequestParameterException(@NotNull final String s) {
super(s);
}
}

View file

@ -6,17 +6,18 @@ import ch.fritteli.maze.server.handler.RenderV2Handler;
import io.undertow.Undertow; import io.undertow.Undertow;
import io.undertow.server.RoutingHandler; import io.undertow.server.RoutingHandler;
import io.vavr.control.Try; import io.vavr.control.Try;
import java.net.InetSocketAddress;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.wildfly.common.annotation.NotNull;
import java.net.InetSocketAddress;
@Slf4j @Slf4j
public class MazeServer { public class MazeServer {
@NonNull @NotNull
private final Undertow undertow; private final Undertow undertow;
private MazeServer(@NonNull final ServerConfig config) { private MazeServer(@NotNull final ServerConfig config) {
final String hostAddress = config.getAddress().getHostAddress(); final String hostAddress = config.getAddress().getHostAddress();
final int port = config.getPort(); final int port = config.getPort();
log.info("Starting Server at http://{}:{}/", hostAddress, port); log.info("Starting Server at http://{}:{}/", hostAddress, port);
@ -31,14 +32,14 @@ public class MazeServer {
.build(); .build();
} }
@NonNull @NotNull
public static Try<MazeServer> createAndStartServer() { public static Try<MazeServer> createAndStartServer() {
return Try.of(ServerConfig::init) return Try.of(ServerConfig::init)
.flatMapTry(MazeServer::createAndStartServer); .flatMapTry(MazeServer::createAndStartServer);
} }
@NonNull @NotNull
public static Try<MazeServer> createAndStartServer(@NonNull final ServerConfig config) { public static Try<MazeServer> createAndStartServer(@NotNull final ServerConfig config) {
return Try.of(() -> new MazeServer(config)) return Try.of(() -> new MazeServer(config))
.peek(MazeServer::start); .peek(MazeServer::start);
} }

View file

@ -1,17 +1,17 @@
package ch.fritteli.maze.server; package ch.fritteli.maze.server;
import ch.fritteli.maze.generator.model.Maze;
import ch.fritteli.maze.generator.renderer.html.HTMLRenderer; import ch.fritteli.maze.generator.renderer.html.HTMLRenderer;
import ch.fritteli.maze.generator.renderer.json.JsonRenderer; import ch.fritteli.maze.generator.renderer.json.JsonRenderer;
import ch.fritteli.maze.generator.renderer.pdf.PDFRenderer; import ch.fritteli.maze.generator.renderer.pdf.PDFRenderer;
import ch.fritteli.maze.generator.renderer.text.TextRenderer; import ch.fritteli.maze.generator.renderer.text.TextRenderer;
import ch.fritteli.maze.generator.serialization.v1.SerializerDeserializerV1; import ch.fritteli.maze.generator.serialization.v1.SerializerDeserializerV1;
import ch.fritteli.maze.generator.serialization.v2.SerializerDeserializerV2; import ch.fritteli.maze.generator.serialization.v2.SerializerDeserializerV2;
import ch.fritteli.maze.generator.model.Maze;
import io.vavr.collection.List; import io.vavr.collection.List;
import io.vavr.collection.Stream; import io.vavr.collection.Stream;
import io.vavr.control.Option; import io.vavr.control.Option;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -67,24 +67,24 @@ public enum OutputType {
"v", "v",
"binaryv2"); "binaryv2");
@Getter @Getter
@NonNull @NotNull
private final String contentType; private final String contentType;
@Getter @Getter
@NonNull @NotNull
private final String fileExtension; private final String fileExtension;
@NonNull @NotNull
private final Function<Maze, byte[]> render; private final Function<Maze, byte[]> render;
@Getter @Getter
private final boolean attachment; private final boolean attachment;
@Getter @Getter
@NonNull @NotNull
private final List<String> names; private final List<String> names;
OutputType(@NonNull final String contentType, OutputType(@NotNull final String contentType,
@NonNull final String fileExtension, @NotNull final String fileExtension,
@NonNull final Function<Maze, byte[]> render, @NotNull final Function<Maze, byte[]> render,
final boolean attachment, final boolean attachment,
@NonNull final String... names) { @NotNull final String... names) {
this.contentType = contentType; this.contentType = contentType;
this.render = render; this.render = render;
this.fileExtension = fileExtension; this.fileExtension = fileExtension;
@ -92,7 +92,7 @@ public enum OutputType {
this.names = List.of(names); this.names = List.of(names);
} }
@NonNull @NotNull
public static Option<OutputType> ofString(@Nullable final String name) { public static Option<OutputType> ofString(@Nullable final String name) {
return Option.of(name) return Option.of(name)
.map(String::toLowerCase) .map(String::toLowerCase)
@ -101,14 +101,14 @@ public enum OutputType {
} }
@NonNull @NotNull
@Override @Override
public String toString() { public String toString() {
return this.names.last(); return this.names.last();
} }
@NonNull @NotNull
public byte[] render(@NonNull final Maze maze) { public byte[] render(@NotNull final Maze maze) {
return this.render.apply(maze); return this.render.apply(maze);
} }
} }

View file

@ -3,10 +3,10 @@ package ch.fritteli.maze.server;
import io.vavr.control.Try; import io.vavr.control.Try;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.Value; import lombok.Value;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.wildfly.common.annotation.NotNull;
import java.net.InetAddress; import java.net.InetAddress;
@ -17,7 +17,7 @@ public class ServerConfig {
public static final String SYSPROP_HOST = "fritteli.maze.server.host"; public static final String SYSPROP_HOST = "fritteli.maze.server.host";
public static final String SYSPROP_PORT = "fritteli.maze.server.port"; public static final String SYSPROP_PORT = "fritteli.maze.server.port";
@NonNull @NotNull
InetAddress address; InetAddress address;
int port; int port;
@ -27,7 +27,7 @@ public class ServerConfig {
log.debug("host={}, port={}", this.address, this.port); log.debug("host={}, port={}", this.address, this.port);
} }
@NonNull @NotNull
public static ServerConfig init() throws ConfigurationException { public static ServerConfig init() throws ConfigurationException {
final String host = System.getProperty(SYSPROP_HOST); final String host = System.getProperty(SYSPROP_HOST);
final String portString = System.getProperty(SYSPROP_PORT); final String portString = System.getProperty(SYSPROP_PORT);
@ -35,7 +35,7 @@ public class ServerConfig {
return new ServerConfig(host, port); return new ServerConfig(host, port);
} }
@NonNull @NotNull
private static InetAddress validateAddress(@Nullable final String address) { private static InetAddress validateAddress(@Nullable final String address) {
return Try.of(() -> InetAddress.getByName(address)) return Try.of(() -> InetAddress.getByName(address))
.getOrElseThrow(cause -> new ConfigurationException( .getOrElseThrow(cause -> new ConfigurationException(

View file

@ -3,8 +3,8 @@ package ch.fritteli.maze.server.handler;
import io.undertow.server.HttpHandler; import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange; import io.undertow.server.HttpServerExchange;
import io.undertow.util.StatusCodes; import io.undertow.util.StatusCodes;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.slf4j.MDC; import org.slf4j.MDC;
import java.time.Instant; import java.time.Instant;
@ -14,7 +14,7 @@ import java.util.UUID;
@Slf4j @Slf4j
public abstract class AbstractHttpHandler implements HttpHandler { public abstract class AbstractHttpHandler implements HttpHandler {
@Override @Override
public final void handleRequest(@NonNull final HttpServerExchange exchange) { public final void handleRequest(@NotNull final HttpServerExchange exchange) {
final Instant start = Instant.now(); final Instant start = Instant.now();
try (final MDC.MDCCloseable closeable = MDC.putCloseable("correlationId", UUID.randomUUID().toString())) { try (final MDC.MDCCloseable closeable = MDC.putCloseable("correlationId", UUID.randomUUID().toString())) {
@ -25,7 +25,7 @@ public abstract class AbstractHttpHandler implements HttpHandler {
} }
try { try {
this.handle(exchange); this.handle(exchange);
} catch (@NonNull final Exception e) { } catch (final Exception e) {
log.error("Error handling request", e); log.error("Error handling request", e);
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR) exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR)
.getResponseSender() .getResponseSender()
@ -35,5 +35,5 @@ public abstract class AbstractHttpHandler implements HttpHandler {
} }
} }
protected abstract void handle(@NonNull final HttpServerExchange exchange) throws Exception; protected abstract void handle(@NotNull final HttpServerExchange exchange) throws Exception;
} }

View file

@ -1,21 +1,22 @@
package ch.fritteli.maze.server.handler; package ch.fritteli.maze.server.handler;
import ch.fritteli.maze.server.OutputType;
import ch.fritteli.maze.generator.model.Maze; import ch.fritteli.maze.generator.model.Maze;
import ch.fritteli.maze.server.InvalidRequestParameterException;
import ch.fritteli.maze.server.OutputType;
import io.undertow.server.HttpServerExchange; import io.undertow.server.HttpServerExchange;
import io.undertow.util.Headers; import io.undertow.util.Headers;
import io.undertow.util.HttpString; import io.undertow.util.HttpString;
import io.undertow.util.StatusCodes; import io.undertow.util.StatusCodes;
import io.vavr.Tuple2;
import io.vavr.control.Try; import io.vavr.control.Try;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.slf4j.MDC;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Deque; import java.util.Deque;
import java.util.Map; import java.util.Map;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
@Slf4j @Slf4j
public class CreateHandler extends AbstractHttpHandler { public class CreateHandler extends AbstractHttpHandler {
@ -23,27 +24,29 @@ public class CreateHandler extends AbstractHttpHandler {
public static final String PATH_TEMPLATE = "/create/{output}"; public static final String PATH_TEMPLATE = "/create/{output}";
@Override @Override
protected void handle(@NonNull final HttpServerExchange exchange) { protected void handle(@NotNull final HttpServerExchange exchange) {
final Instant start = Instant.now(); final Instant start = Instant.now();
log.debug("Handling create request"); log.debug("Handling create request");
this.createMazeFromRequestParameters(exchange.getQueryParameters()) this.createMazeFromRequestParameters(exchange.getQueryParameters())
.onFailure(e -> { .onFailure(e -> {
log.error("Error creating maze from request", e); log.error("Error creating maze from request", e);
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR) if (e instanceof InvalidRequestParameterException) {
.setReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR_STRING) exchange.setStatusCode(StatusCodes.BAD_REQUEST);
.getResponseSender() } else {
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
}
exchange.getResponseSender()
.send(e.getMessage()); .send(e.getMessage());
}) })
.forEach(tuple -> { .forEach(generatedMaze -> {
final OutputType outputType = tuple._1(); final OutputType outputType = generatedMaze.outputType();
final Maze maze = tuple._2(); final Maze maze = generatedMaze.maze();
final byte[] bytes; final byte[] bytes;
try { try {
bytes = outputType.render(maze); bytes = outputType.render(maze);
} catch (@NonNull final Exception e) { } catch (final Exception e) {
log.error("Error rendering Maze", e); log.error("Error rendering Maze", e);
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR) exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR)
.setReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR_STRING)
.getResponseSender() .getResponseSender()
.send("Error creating the maze. Please contact the administrator. Request id=%s".formatted(MDC.get("correlationId"))); .send("Error creating the maze. Please contact the administrator. Request id=%s".formatted(MDC.get("correlationId")));
return; return;
@ -54,8 +57,7 @@ public class CreateHandler extends AbstractHttpHandler {
.put(HttpString.tryFromString("X-Maze-ID"), String.valueOf(maze.getRandomSeed())) .put(HttpString.tryFromString("X-Maze-ID"), String.valueOf(maze.getRandomSeed()))
.put(HttpString.tryFromString("X-Maze-Width"), String.valueOf(maze.getWidth())) .put(HttpString.tryFromString("X-Maze-Width"), String.valueOf(maze.getWidth()))
.put(HttpString.tryFromString("X-Maze-Height"), String.valueOf(maze.getHeight())) .put(HttpString.tryFromString("X-Maze-Height"), String.valueOf(maze.getHeight()))
// TODO read the algorithm from the maze once this is supported. .put(HttpString.tryFromString("X-Maze-Algorithm"), generatedMaze.generatorName())
.put(HttpString.tryFromString("X-Maze-Algorithm"), "RandomDepthFirst")
.put(HttpString.tryFromString("X-Maze-Generation-Duration-millis"), String.valueOf(durationMillis)); .put(HttpString.tryFromString("X-Maze-Generation-Duration-millis"), String.valueOf(durationMillis));
if (outputType.isAttachment()) { if (outputType.isAttachment()) {
exchange.getResponseHeaders() exchange.getResponseHeaders()
@ -71,8 +73,8 @@ public class CreateHandler extends AbstractHttpHandler {
}); });
} }
@NonNull @NotNull
private Try<Tuple2<OutputType, Maze>> createMazeFromRequestParameters(final Map<String, Deque<String>> queryParameters) { private Try<ParametersToMazeExtractor.GeneratedMaze> createMazeFromRequestParameters(final Map<String, Deque<String>> queryParameters) {
return new ParametersToMazeExtractor(queryParameters).createMaze(); return new ParametersToMazeExtractor(queryParameters).createMaze();
} }
} }

View file

@ -1,16 +1,15 @@
package ch.fritteli.maze.server.handler; package ch.fritteli.maze.server.handler;
import ch.fritteli.maze.server.OutputType;
import ch.fritteli.maze.generator.algorithm.RandomDepthFirst; import ch.fritteli.maze.generator.algorithm.RandomDepthFirst;
import ch.fritteli.maze.generator.model.Maze; import ch.fritteli.maze.generator.model.Maze;
import ch.fritteli.maze.generator.model.Position; import ch.fritteli.maze.generator.model.Position;
import io.vavr.Tuple; import ch.fritteli.maze.server.InvalidRequestParameterException;
import io.vavr.Tuple2; import ch.fritteli.maze.server.OutputType;
import io.vavr.collection.Stream; import io.vavr.collection.Stream;
import io.vavr.control.Option; import io.vavr.control.Option;
import io.vavr.control.Try; import io.vavr.control.Try;
import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import java.util.Deque; import java.util.Deque;
import java.util.Map; import java.util.Map;
@ -19,11 +18,11 @@ import java.util.Random;
@RequiredArgsConstructor @RequiredArgsConstructor
class ParametersToMazeExtractor { class ParametersToMazeExtractor {
@NonNull @NotNull
private final Map<String, Deque<String>> queryParameters; private final Map<String, Deque<String>> queryParameters;
@NonNull @NotNull
Try<Tuple2<OutputType, Maze>> createMaze() { Try<GeneratedMaze> createMaze() {
final Option<OutputType> output = getParameterValue(RequestParameter.OUTPUT); final Option<OutputType> output = getParameterValue(RequestParameter.OUTPUT);
final Option<Integer> width = getParameterValue(RequestParameter.WIDTH); final Option<Integer> width = getParameterValue(RequestParameter.WIDTH);
final Option<Integer> height = getParameterValue(RequestParameter.HEIGHT); final Option<Integer> height = getParameterValue(RequestParameter.HEIGHT);
@ -32,7 +31,7 @@ class ParametersToMazeExtractor {
final Option<Position> end = getParameterValue(RequestParameter.END); final Option<Position> end = getParameterValue(RequestParameter.END);
if (output.isEmpty()) { if (output.isEmpty()) {
return Try.failure(new IllegalArgumentException("Path parameter %s is required and must be one of: %s".formatted( return Try.failure(new InvalidRequestParameterException("Path parameter %s is required and must be one of: %s".formatted(
RequestParameter.OUTPUT.getNames().mkString("'", " / ", "'"), RequestParameter.OUTPUT.getNames().mkString("'", " / ", "'"),
Stream.of(OutputType.values()) Stream.of(OutputType.values())
.flatMap(OutputType::getNames) .flatMap(OutputType::getNames)
@ -40,12 +39,12 @@ class ParametersToMazeExtractor {
))); )));
} }
if (width.isEmpty()) { if (width.isEmpty()) {
return Try.failure(new IllegalArgumentException("Query parameter %s is required and must be a positive integer value".formatted( return Try.failure(new InvalidRequestParameterException("Query parameter %s is required and must be a positive integer value".formatted(
RequestParameter.WIDTH.getNames().mkString("'", " / ", "'") RequestParameter.WIDTH.getNames().mkString("'", " / ", "'")
))); )));
} }
if (height.isEmpty()) { if (height.isEmpty()) {
return Try.failure(new IllegalArgumentException("Query parameter %s is required and must be a positive integer value".formatted( return Try.failure(new InvalidRequestParameterException("Query parameter %s is required and must be a positive integer value".formatted(
RequestParameter.HEIGHT.getNames().mkString("'", " / ", "'") RequestParameter.HEIGHT.getNames().mkString("'", " / ", "'")
))); )));
} }
@ -58,12 +57,15 @@ class ParametersToMazeExtractor {
maze = new Maze(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong())); maze = new Maze(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong()));
} }
new RandomDepthFirst(maze).run(); new RandomDepthFirst(maze).run();
return Tuple.of(output.get(), maze); return new GeneratedMaze(maze, output.get(), RandomDepthFirst.class.getSimpleName());
}); });
} }
@NonNull @NotNull
private <T> Option<T> getParameterValue(@NonNull final RequestParameter parameter) { private <T> Option<T> getParameterValue(@NotNull final RequestParameter parameter) {
return parameter.getParameterValue(this.queryParameters); return parameter.getParameterValue(this.queryParameters);
} }
public record GeneratedMaze(@NotNull Maze maze, @NotNull OutputType outputType, @NotNull String generatorName) {
}
} }

View file

@ -1,14 +1,14 @@
package ch.fritteli.maze.server.handler; package ch.fritteli.maze.server.handler;
import ch.fritteli.maze.server.OutputType;
import ch.fritteli.maze.generator.model.Maze; import ch.fritteli.maze.generator.model.Maze;
import ch.fritteli.maze.generator.serialization.v1.SerializerDeserializerV1; import ch.fritteli.maze.generator.serialization.v1.SerializerDeserializerV1;
import ch.fritteli.maze.server.OutputType;
import io.undertow.server.HttpServerExchange; import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderValues; import io.undertow.util.HeaderValues;
import io.undertow.util.Headers; import io.undertow.util.Headers;
import io.undertow.util.StatusCodes; import io.undertow.util.StatusCodes;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -18,7 +18,7 @@ public class RenderV1Handler extends AbstractHttpHandler {
public static final String PATH_TEMPLATE = "/render/v1/{output}"; public static final String PATH_TEMPLATE = "/render/v1/{output}";
@Override @Override
public void handle(final HttpServerExchange exchange) { public void handle(@NotNull final HttpServerExchange exchange) {
log.debug("Handling render request"); log.debug("Handling render request");
if (exchange.isInIoThread()) { if (exchange.isInIoThread()) {
@ -47,8 +47,8 @@ public class RenderV1Handler extends AbstractHttpHandler {
}); });
} }
@NonNull @NotNull
private OutputType getOutputType(@NonNull final HttpServerExchange httpServerExchange) { private OutputType getOutputType(@NotNull final HttpServerExchange httpServerExchange) {
return RequestParameter.OUTPUT.<OutputType>getParameterValue(httpServerExchange.getQueryParameters()) return RequestParameter.OUTPUT.<OutputType>getParameterValue(httpServerExchange.getQueryParameters())
.getOrElse(() -> { .getOrElse(() -> {
final HeaderValues accept = httpServerExchange.getRequestHeaders().get(Headers.ACCEPT); final HeaderValues accept = httpServerExchange.getRequestHeaders().get(Headers.ACCEPT);

View file

@ -1,14 +1,14 @@
package ch.fritteli.maze.server.handler; package ch.fritteli.maze.server.handler;
import ch.fritteli.maze.server.OutputType;
import ch.fritteli.maze.generator.model.Maze; import ch.fritteli.maze.generator.model.Maze;
import ch.fritteli.maze.generator.serialization.v2.SerializerDeserializerV2; import ch.fritteli.maze.generator.serialization.v2.SerializerDeserializerV2;
import ch.fritteli.maze.server.OutputType;
import io.undertow.server.HttpServerExchange; import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderValues; import io.undertow.util.HeaderValues;
import io.undertow.util.Headers; import io.undertow.util.Headers;
import io.undertow.util.StatusCodes; import io.undertow.util.StatusCodes;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -18,7 +18,7 @@ public class RenderV2Handler extends AbstractHttpHandler {
public static final String PATH_TEMPLATE = "/render/v2/{output}"; public static final String PATH_TEMPLATE = "/render/v2/{output}";
@Override @Override
public void handle(final HttpServerExchange exchange) { public void handle(@NotNull final HttpServerExchange exchange) {
log.debug("Handling render request"); log.debug("Handling render request");
if (exchange.isInIoThread()) { if (exchange.isInIoThread()) {
@ -47,8 +47,8 @@ public class RenderV2Handler extends AbstractHttpHandler {
}); });
} }
@NonNull @NotNull
private OutputType getOutputType(@NonNull final HttpServerExchange httpServerExchange) { private OutputType getOutputType(@NotNull final HttpServerExchange httpServerExchange) {
return RequestParameter.OUTPUT.<OutputType>getParameterValue(httpServerExchange.getQueryParameters()) return RequestParameter.OUTPUT.<OutputType>getParameterValue(httpServerExchange.getQueryParameters())
.getOrElse(() -> { .getOrElse(() -> {
final HeaderValues accept = httpServerExchange.getRequestHeaders().get(Headers.ACCEPT); final HeaderValues accept = httpServerExchange.getRequestHeaders().get(Headers.ACCEPT);

View file

@ -1,7 +1,7 @@
package ch.fritteli.maze.server.handler; package ch.fritteli.maze.server.handler;
import ch.fritteli.maze.server.OutputType;
import ch.fritteli.maze.generator.model.Position; import ch.fritteli.maze.generator.model.Position;
import ch.fritteli.maze.server.OutputType;
import io.vavr.Tuple2; import io.vavr.Tuple2;
import io.vavr.collection.HashMap; import io.vavr.collection.HashMap;
import io.vavr.collection.HashSet; import io.vavr.collection.HashSet;
@ -9,8 +9,8 @@ import io.vavr.collection.Set;
import io.vavr.control.Option; import io.vavr.control.Option;
import io.vavr.control.Try; import io.vavr.control.Try;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import java.util.Deque; import java.util.Deque;
import java.util.Map; import java.util.Map;
@ -45,24 +45,24 @@ enum RequestParameter {
}) })
.toOption() .toOption()
.onEmpty(() -> log.debug("Unparseable value for parameter 'end': '{}'", p)), "e", "end"); .onEmpty(() -> log.debug("Unparseable value for parameter 'end': '{}'", p)), "e", "end");
@NonNull @NotNull
private final Function<String, Option<?>> extractor; private final Function<String, Option<?>> extractor;
@Getter @Getter
@NonNull @NotNull
private final Set<String> names; private final Set<String> names;
RequestParameter(@NonNull final Function<String, Option<?>> extractor, @NonNull final String... names) { RequestParameter(@NotNull final Function<String, Option<?>> extractor, @NotNull final String... names) {
this.extractor = extractor; this.extractor = extractor;
this.names = HashSet.of(names); this.names = HashSet.of(names);
} }
@NonNull @NotNull
Option<?> extractParameterValue(@NonNull final String parameter) { Option<?> extractParameterValue(@NotNull final String parameter) {
return this.extractor.apply(parameter); return this.extractor.apply(parameter);
} }
@NonNull @NotNull
public <T> Option<T> getParameterValue(@NonNull final Map<String, Deque<String>> queryParameters) { public <T> Option<T> getParameterValue(@NotNull final Map<String, Deque<String>> queryParameters) {
return (Option<T>) HashMap.ofAll(queryParameters) return (Option<T>) HashMap.ofAll(queryParameters)
.filterKeys(this.names::contains) .filterKeys(this.names::contains)
.flatMap(Tuple2::_2) .flatMap(Tuple2::_2)