package nouritsu; import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD.Response.Status; import io.vavr.Tuple2; import io.vavr.collection.HashMap; import io.vavr.collection.List; import io.vavr.collection.Map; import io.vavr.control.Either; import io.vavr.control.Try; import nouritsu.types.Message; import java.io.IOException; import java.util.function.Function; public class Nouritsu extends NanoHTTPD { private final Dao dao; public Nouritsu(int port, Dao dao) throws IOException { super(port); start(10_000, false); this.dao = dao; } @Override public Response serve(IHTTPSession session) { return Try.of(() -> processRequest(session, dao)) .fold( err -> newFixedLengthResponse(Status.INTERNAL_ERROR, MIME_PLAINTEXT, err.getMessage()), response -> newFixedLengthResponse(response.status(), MIME_PLAINTEXT, response.text()) ); } private static final String HELP = """ Valid endpoints are (not case sensitive): /addStore/?name=storeName§ions=first,second,third /addItem/?name=itemName&category=itemCategory /addToList/?user=userId&itemName /getList/?user=userId&store=optionalStoreName /clearList/?user=userId """; private static Message processRequest(IHTTPSession session, Dao dao) { var params = extractParams(session); return switch (session.getUri().replaceAll("/", "").toLowerCase()) { case "", "index.html" -> new Message(HELP, Status.OK); case "addstore" -> addStore(params, dao); case "additem" -> addItem(params, dao); case "addtolist" -> addToList(params, dao); case "getlist" -> getList(params, dao); case "clearlist" -> clearList(params, dao); default -> new Message(HELP, Status.NOT_FOUND); }; } // Repack the parameters into vavr collections. private static Map> extractParams(IHTTPSession session) { return session.getParameters() .entrySet() .stream() .map(e -> new Tuple2<>(e.getKey(), List.ofAll(e.getValue()))) .collect(HashMap.collector()); } private static Message clearList(Map> params, Dao dao) { return getFromParams(params, "user") .map(List::head) // save, the list can’t be empty .flatMap(dao::clearList) .fold(Function.identity(), Message.OK); } private static Message getList(Map> params, Dao dao) { return getFromParams(params, "user") .map(List::head) // save, the list can’t be empty .flatMap(dao::getList) .fold(Function.identity(), Message.OK); } private static Message addToList(Map> params, Dao dao) { return new Message("", Status.NOT_IMPLEMENTED); } private static Message addItem(Map> params, Dao dao) { return new Message("", Status.NOT_IMPLEMENTED); } private static Message addStore(Map> params, Dao dao) { return new Message("", Status.NOT_IMPLEMENTED); } private static Either> getFromParams(Map> params, String key) { return params.get(key).toEither(new Message("Parameter “%s” not found".formatted(key), Status.NOT_FOUND)); } public static void main(String[] args) { try { new Nouritsu(14523, new Dao()); } catch (IOException e) { e.printStackTrace(); } } }