initial commit
This commit is contained in:
commit
c2b3bc4515
|
@ -0,0 +1,2 @@
|
|||
build/
|
||||
.gradle/
|
|
@ -0,0 +1,3 @@
|
|||
# 能率
|
||||
I’m trying to prove a point by implementing something in Java.
|
||||
More details will follow on [my blog](https://ruru.moe).
|
|
@ -0,0 +1,39 @@
|
|||
plugins {
|
||||
java
|
||||
application
|
||||
}
|
||||
|
||||
group = "moe.kageru"
|
||||
version = "0.1.0"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_15
|
||||
targetCompatibility = JavaVersion.VERSION_15
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
options.compilerArgs.add("--enable-preview")
|
||||
}
|
||||
|
||||
tasks.run {
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
jvmArgs("--enable-preview")
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set("nouritsu.Nouritsu")
|
||||
applicationDefaultJvmArgs = listOf("--enable-preview")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.nanohttpd:nanohttpd:2.3.1")
|
||||
implementation("io.vavr:vavr:1.0.0-alpha-3")
|
||||
testImplementation("junit", "junit", "4.12")
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
rootProject.name = "nouritsu"
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package nouritsu;
|
||||
|
||||
import io.vavr.collection.List;
|
||||
import io.vavr.control.Either;
|
||||
import nouritsu.types.Message;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Dao {
|
||||
public Either<Message, String> clearList(String id) {
|
||||
return Either.right("Cleared list of user “%s“".formatted(id));
|
||||
}
|
||||
|
||||
public Either<Message, String> getList(String id) {
|
||||
return Either.right(List.of("first", "second", "third")
|
||||
.collect(Collectors.joining(",")));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
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<String, List<String>> 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<String, List<String>> 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<String, List<String>> 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<String, List<String>> params, Dao dao) {
|
||||
return new Message("", Status.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
private static Message addItem(Map<String, List<String>> params, Dao dao) {
|
||||
return new Message("", Status.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
private static Message addStore(Map<String, List<String>> params, Dao dao) {
|
||||
return new Message("", Status.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
private static Either<Message, List<String>> getFromParams(Map<String, List<String>> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package nouritsu.types;
|
||||
|
||||
public enum Category {
|
||||
CANS,
|
||||
FRUITS,
|
||||
VEGETABLES,
|
||||
PASTA,
|
||||
RICE,
|
||||
MEAT,
|
||||
DAIRY,
|
||||
HYGIENE,
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package nouritsu.types;
|
||||
|
||||
import fi.iki.elonen.NanoHTTPD.Response.Status;
|
||||
import io.vavr.Function1;
|
||||
|
||||
public record Message(String text, Status status) {
|
||||
public static Function1<String, Message> OK = Function1.of(s -> new Message(s, Status.OK));
|
||||
public static Function1<String, Message> BAD_REQUEST = Function1.of(s -> new Message(s, Status.BAD_REQUEST));
|
||||
public static Function1<String, Message> CREATED = Function1.of(s -> new Message(s, Status.CREATED));
|
||||
public static Function1<String, Message> NOT_FOUND = Function1.of(s -> new Message(s, Status.NOT_FOUND));
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package nouritsu.types;
|
||||
|
||||
public record ShoppingItem(String name, Category category) {
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package nouritsu.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A store with an ordered list of sections from entrance to exit.
|
||||
*/
|
||||
public record Store(String name, List<Category> sections) {
|
||||
}
|
Loading…
Reference in New Issue
Block a user