All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.tonivade.zeromock.api.HttpServiceK Maven / Gradle / Ivy
/*
* Copyright (c) 2018-2024, Antonio Gabriel Muñoz Conejo
* Distributed under the terms of the MIT License
*/
package com.github.tonivade.zeromock.api;
import static com.github.tonivade.purefun.core.Function1.fail;
import static com.github.tonivade.purefun.core.Matcher1.never;
import static com.github.tonivade.purefun.core.Precondition.checkNonNull;
import static com.github.tonivade.zeromock.api.Matchers.all;
import static com.github.tonivade.zeromock.api.Matchers.startsWith;
import static com.github.tonivade.zeromock.api.PreFilterK.filter;
import static com.github.tonivade.zeromock.api.Responses.notFound;
import com.github.tonivade.purefun.Kind;
import com.github.tonivade.purefun.core.Function1;
import com.github.tonivade.purefun.core.Matcher1;
import com.github.tonivade.purefun.core.PartialFunction1;
import com.github.tonivade.purefun.type.Either;
import com.github.tonivade.purefun.type.Option;
import com.github.tonivade.purefun.type.OptionOf;
import com.github.tonivade.purefun.typeclasses.For;
import com.github.tonivade.purefun.typeclasses.Instances;
import com.github.tonivade.purefun.typeclasses.Monad;
public final class HttpServiceK> implements HttpRouteBuilderK> {
private final String name;
private final Monad monad;
private final PartialFunction1> mappings;
private final Function1>> preFilters;
private final Function1> postFilters;
public HttpServiceK(String name, Monad monad) {
this(name, monad,
PartialFunction1.of(never(), fail(IllegalStateException::new)),
request -> monad.pure(Either.right(request)),
monad::pure);
}
private HttpServiceK(String name, Monad monad,
PartialFunction1> mappings,
Function1>> preFilters,
Function1> postFilters) {
this.name = checkNonNull(name);
this.monad = checkNonNull(monad);
this.mappings = checkNonNull(mappings);
this.preFilters = checkNonNull(preFilters);
this.postFilters = checkNonNull(postFilters);
}
public String name() {
return name;
}
Monad monad() {
return monad;
}
public HttpServiceK mount(String path, HttpServiceK other) {
checkNonNull(path);
checkNonNull(other);
return addMapping(
startsWith(path).and(req -> other.mappings.isDefinedAt(req.dropOneLevel())),
req -> monad.map(other.execute(req.dropOneLevel()), option -> option.getOrElse(notFound())));
}
public HttpServiceK exec(RequestHandlerK handler) {
return addMapping(all(), handler);
}
@Override
public ThenStepK> when(Matcher1 matcher) {
return new ThenStepK<>(monad, handler -> addMapping(matcher, handler));
}
public ThenStepK> preFilter(Matcher1 matcher) {
return new ThenStepK<>(monad, handler -> addPreFilter(matcher, handler));
}
public HttpServiceK preFilter(PreFilterK filter) {
return addPreFilter(checkNonNull(filter));
}
public HttpServiceK postFilter(PostFilterK filter) {
return addPostFilter(checkNonNull(filter));
}
public Kind> execute(HttpRequest request) {
Function1>> mappingsWithPostFilters =
mappings.andThen(value -> monad.flatMap(value, postFilters::apply)).lift();
return For.with(monad)
.then(preFilters.apply(request))
.flatMap(either -> either.fold(
res -> monad.pure(Option.some(res)),
mappingsWithPostFilters.andThen(option -> Instances.>traverse().sequence(monad, option))))
.map(OptionOf::toOption)
.run();
}
public HttpServiceK combine(HttpServiceK other) {
checkNonNull(other);
return new HttpServiceK<>(
this.name + "+" + other.name,
this.monad,
this.mappings.orElse(other.mappings),
this.preFilters.andThen(
value -> monad.flatMap(value,
either -> either.fold(
response -> monad.pure(Either.left(response)), other.preFilters))),
this.postFilters.andThen(value -> monad.flatMap(value, other.postFilters))::apply
);
}
public HttpServiceK addMapping(Matcher1 matcher, RequestHandlerK handler) {
checkNonNull(matcher);
checkNonNull(handler);
return new HttpServiceK<>(
this.name,
this.monad,
this.mappings.orElse(PartialFunction1.of(matcher, handler::apply)),
this.preFilters,
this.postFilters
);
}
public HttpServiceK addPreFilter(Matcher1 matcher, RequestHandlerK handler) {
return addPreFilter(filter(monad, matcher, handler));
}
private HttpServiceK addPreFilter(PreFilterK filter) {
checkNonNull(filter);
return new HttpServiceK<>(
this.name,
this.monad,
this.mappings,
this.preFilters.andThen(
value -> monad.flatMap(value,
either -> either.fold(
response -> monad.pure(Either.left(response)), filter))),
this.postFilters
);
}
private HttpServiceK addPostFilter(PostFilterK filter) {
checkNonNull(filter);
return new HttpServiceK<>(
this.name,
this.monad,
this.mappings,
this.preFilters,
this.postFilters.andThen(value -> monad.flatMap(value, filter))::apply
);
}
}