♻️ Reformat + Update .editorconfig

This commit is contained in:
Alexander Söderberg 2020-10-06 22:48:30 +02:00 committed by Alexander Söderberg
parent 8bdec87a74
commit 2aac3980d5
169 changed files with 4261 additions and 2448 deletions

View file

@ -40,58 +40,61 @@ class AnnotatedMethodService<Context, Result> implements Service<Context, Result
private final Method method;
private final Object instance;
AnnotatedMethodService(final @NonNull Object instance,
final @NonNull Method method)
throws Exception {
ExecutionOrder executionOrder = ExecutionOrder.SOON;
try {
final Order order = method.getAnnotation(Order.class);
if (order != null) {
executionOrder = order.value();
AnnotatedMethodService(
final @NonNull Object instance,
final @NonNull Method method
)
throws Exception {
ExecutionOrder executionOrder = ExecutionOrder.SOON;
try {
final Order order = method.getAnnotation(Order.class);
if (order != null) {
executionOrder = order.value();
}
} catch (final Exception ignored) {
}
} catch (final Exception ignored) {
}
this.instance = instance;
this.executionOrder = executionOrder;
method.setAccessible(true);
this.methodHandle = MethodHandles.lookup().unreflect(method);
this.method = method;
this.instance = instance;
this.executionOrder = executionOrder;
method.setAccessible(true);
this.methodHandle = MethodHandles.lookup().unreflect(method);
this.method = method;
}
@Override
@SuppressWarnings("unchecked")
public @Nullable Result handle(final @NonNull Context context) {
try {
return (Result) this.methodHandle.invoke(this.instance, context);
} catch (final Throwable throwable) {
new IllegalStateException(String
.format("Failed to call method service implementation '%s' in class '%s'",
method.getName(), instance.getClass().getCanonicalName()), throwable)
.printStackTrace();
@Override
@SuppressWarnings("unchecked")
public @Nullable Result handle(final @NonNull Context context) {
try {
return (Result) this.methodHandle.invoke(this.instance, context);
} catch (final Throwable throwable) {
new IllegalStateException(String
.format("Failed to call method service implementation '%s' in class '%s'",
method.getName(), instance.getClass().getCanonicalName()
), throwable)
.printStackTrace();
}
return null;
}
return null;
}
@Override
public @NonNull ExecutionOrder order() {
return this.executionOrder;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
@Override
public @NonNull ExecutionOrder order() {
return this.executionOrder;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final AnnotatedMethodService<?, ?> that = (AnnotatedMethodService<?, ?>) o;
return Objects.equals(this.methodHandle, that.methodHandle);
}
@Override
public int hashCode() {
return Objects.hash(this.methodHandle);
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final AnnotatedMethodService<?, ?> that = (AnnotatedMethodService<?, ?>) o;
return Objects.equals(this.methodHandle, that.methodHandle);
}
@Override
public int hashCode() {
return Objects.hash(this.methodHandle);
}
}

View file

@ -36,24 +36,28 @@ enum AnnotatedMethodServiceFactory {
INSTANCE;
@NonNull Map<? extends Service<?, ?>, TypeToken<? extends Service<?, ?>>> lookupServices(
final @NonNull Object instance) throws Exception {
final Map<Service<?, ?>, TypeToken<? extends Service<?, ?>>> map = new HashMap<>();
final Class<?> clazz = instance.getClass();
for (final Method method : clazz.getDeclaredMethods()) {
final ServiceImplementation serviceImplementation =
method.getAnnotation(ServiceImplementation.class);
if (serviceImplementation == null) {
continue;
}
if (method.getParameterCount() != 1) {
throw new IllegalArgumentException(String.format(
"Method '%s' in class '%s'" + " has wrong parameter count. Expected 1, got %d",
method.getName(), instance.getClass().getCanonicalName(),
method.getParameterCount()));
final @NonNull Object instance
) throws Exception {
final Map<Service<?, ?>, TypeToken<? extends Service<?, ?>>> map = new HashMap<>();
final Class<?> clazz = instance.getClass();
for (final Method method : clazz.getDeclaredMethods()) {
final ServiceImplementation serviceImplementation =
method.getAnnotation(ServiceImplementation.class);
if (serviceImplementation == null) {
continue;
}
if (method.getParameterCount() != 1) {
throw new IllegalArgumentException(String.format(
"Method '%s' in class '%s'" + " has wrong parameter count. Expected 1, got %d",
method.getName(), instance.getClass().getCanonicalName(),
method.getParameterCount()
));
}
map.put(new AnnotatedMethodService<>(instance, method),
TypeToken.get(serviceImplementation.value()));
map.put(
new AnnotatedMethodService<>(instance, method),
TypeToken.get(serviceImplementation.value())
);
}
return map;
}

View file

@ -55,27 +55,27 @@ public abstract class ChunkedRequestContext<@NonNull Context, @NonNull Result> {
this.results = new HashMap<>(requests.size());
}
/**
* Get a view of the (currently) available results
*
* @return Unmodifiable map of results
*/
public final @NonNull Map<@NonNull Context, @NonNull Result> getAvailableResults() {
synchronized (this.lock) {
return Collections.unmodifiableMap(this.results);
/**
* Get a view of the (currently) available results
*
* @return Unmodifiable map of results
*/
public final @NonNull Map<@NonNull Context, @NonNull Result> getAvailableResults() {
synchronized (this.lock) {
return Collections.unmodifiableMap(this.results);
}
}
}
/**
* Get all remaining requests
*
* @return Unmodifiable list of remaining requests
*/
public final @NonNull List<@NonNull Context> getRemaining() {
synchronized (this.lock) {
return Collections.unmodifiableList(this.requests);
/**
* Get all remaining requests
*
* @return Unmodifiable list of remaining requests
*/
public final @NonNull List<@NonNull Context> getRemaining() {
synchronized (this.lock) {
return Collections.unmodifiableList(this.requests);
}
}
}
/**
* Store a result for a specific context
@ -90,11 +90,11 @@ public abstract class ChunkedRequestContext<@NonNull Context, @NonNull Result> {
}
}
/**
* Check if the request has been completed
*
* @return {@code true} if the request has been completed, {@code false} if not
*/
/**
* Check if the request has been completed
*
* @return {@code true} if the request has been completed, {@code false} if not
*/
public final boolean isCompleted() {
synchronized (this.lock) {
return this.requests.isEmpty();

View file

@ -28,5 +28,10 @@ package cloud.commandframework.services;
*/
@SuppressWarnings("unused")
public enum ExecutionOrder {
LAST, LATER, LATE, SOON, SOONER, FIRST
LAST,
LATER,
LATE,
SOON,
SOONER,
FIRST
}

View file

@ -33,7 +33,8 @@ enum ServiceFilterHandler {
<Context> boolean passes(
final @NonNull ServiceRepository<Context, ?>.ServiceWrapper<? extends Service<Context, ?>> service,
final @NonNull Context context) {
final @NonNull Context context
) {
if (!service.isDefaultImplementation()) {
for (final Predicate<Context> predicate : service.getFilters()) {
try {
@ -43,7 +44,8 @@ enum ServiceFilterHandler {
} catch (final Exception e) {
throw new PipelineException(String
.format("Failed to evaluate filter '%s' for '%s'",
predicate.getClass().getCanonicalName(), service.toString()), e);
predicate.getClass().getCanonicalName(), service.toString()
), e);
}
}
}

View file

@ -73,11 +73,15 @@ public final class ServicePipeline {
*/
public <Context, Result> @NonNull ServicePipeline registerServiceType(
final @NonNull TypeToken<? extends Service<@NonNull Context, @NonNull Result>> type,
final @NonNull Service<@NonNull Context, @NonNull Result> defaultImplementation) {
final @NonNull Service<@NonNull Context, @NonNull Result> defaultImplementation
) {
synchronized (this.lock) {
if (repositories.containsKey(type.getType())) {
throw new IllegalArgumentException(String
.format("Service of type '%s' has already been registered", type.toString()));
.format(
"Service of type '%s' has already been registered",
type.toString()
));
}
final ServiceRepository<Context, Result> repository = new ServiceRepository<>(type);
repository.registerImplementation(defaultImplementation, Collections.emptyList());
@ -106,7 +110,8 @@ public final class ServicePipeline {
*/
@SuppressWarnings("unchecked")
public <T> @NonNull ServicePipeline registerMethods(
final @NonNull T instance) throws Exception {
final @NonNull T instance
) throws Exception {
synchronized (this.lock) {
final Map<? extends Service<?, ?>, TypeToken<? extends Service<?, ?>>> services =
AnnotatedMethodServiceFactory.INSTANCE.lookupServices(instance);
@ -118,8 +123,10 @@ public final class ServicePipeline {
throw new IllegalArgumentException(
String.format("No service registered for type '%s'", type.toString()));
}
repository.<Service>registerImplementation(serviceEntry.getKey(),
Collections.emptyList());
repository.<Service>registerImplementation(
serviceEntry.getKey(),
Collections.emptyList()
);
}
}
return this;
@ -141,7 +148,8 @@ public final class ServicePipeline {
public <Context, Result> ServicePipeline registerServiceImplementation(
final @NonNull TypeToken<? extends Service<Context, Result>> type,
final @NonNull Service<Context, Result> implementation,
final @NonNull Collection<Predicate<Context>> filters) {
final @NonNull Collection<Predicate<Context>> filters
) {
synchronized (this.lock) {
final ServiceRepository<Context, Result> repository = getRepository(type);
repository.registerImplementation(implementation, filters);
@ -165,7 +173,8 @@ public final class ServicePipeline {
public <Context, Result> ServicePipeline registerServiceImplementation(
final @NonNull Class<? extends Service<Context, Result>> type,
final @NonNull Service<Context, Result> implementation,
final @NonNull Collection<Predicate<Context>> filters) {
final @NonNull Collection<Predicate<Context>> filters
) {
return registerServiceImplementation(TypeToken.get(type), implementation, filters);
}
@ -183,9 +192,9 @@ public final class ServicePipeline {
}
@SuppressWarnings("unchecked")
@NonNull
<Context, Result> ServiceRepository<Context, Result> getRepository(
final @NonNull TypeToken<? extends Service<Context, Result>> type) {
@NonNull <Context, Result> ServiceRepository<Context, Result> getRepository(
final @NonNull TypeToken<? extends Service<Context, Result>> type
) {
final ServiceRepository<Context, Result> repository =
(ServiceRepository<Context, Result>) this.repositories.get(type.getType());
if (repository == null) {
@ -213,12 +222,13 @@ public final class ServicePipeline {
* @param <Result> The result type.
* @param <S> The service type.
* @return Returns an collection of the {@link TypeToken}s of the implementations for a given
* service. Iterator order matches the priority when pumping contexts through the pipeline
* service. Iterator order matches the priority when pumping contexts through the pipeline
*/
@NonNull
@SuppressWarnings("unchecked")
public <Context, Result, S extends Service<Context, Result>> Collection<TypeToken<? extends S>> getImplementations(
final @NonNull TypeToken<S> type) {
final @NonNull TypeToken<S> type
) {
ServiceRepository<Context, Result> repository = getRepository(type);
List<TypeToken<? extends S>> collection = new LinkedList<>();
final LinkedList<? extends ServiceRepository<Context, Result>.ServiceWrapper<? extends Service<Context, Result>>>

View file

@ -37,8 +37,10 @@ public final class ServicePump<Context> {
private final ServicePipeline servicePipeline;
private final Context context;
ServicePump(final @NonNull ServicePipeline servicePipeline,
final @NonNull Context context) {
ServicePump(
final @NonNull ServicePipeline servicePipeline,
final @NonNull Context context
) {
this.servicePipeline = servicePipeline;
this.context = context;
}
@ -51,7 +53,8 @@ public final class ServicePump<Context> {
* @return Service spigot instance
*/
public <Result> @NonNull ServiceSpigot<@NonNull Context, @NonNull Result> through(
final @NonNull TypeToken<? extends Service<@NonNull Context, @NonNull Result>> type) {
final @NonNull TypeToken<? extends Service<@NonNull Context, @NonNull Result>> type
) {
return new ServiceSpigot<>(this.servicePipeline, this.context, type);
}
@ -63,7 +66,8 @@ public final class ServicePump<Context> {
* @return Service spigot instance
*/
public <Result> @NonNull ServiceSpigot<@NonNull Context, @NonNull Result> through(
final @NonNull Class<? extends Service<@NonNull Context, @NonNull Result>> clazz) {
final @NonNull Class<? extends Service<@NonNull Context, @NonNull Result>> clazz
) {
return this.through(TypeToken.get(clazz));
}

View file

@ -23,9 +23,9 @@
//
package cloud.commandframework.services;
import io.leangen.geantyref.TypeToken;
import cloud.commandframework.services.annotations.Order;
import cloud.commandframework.services.types.Service;
import io.leangen.geantyref.TypeToken;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Collection;
@ -66,8 +66,10 @@ public final class ServiceRepository<Context, Response> {
* @param filters Filters that will be used to determine whether or not the service gets used
* @param <T> Type of the implementation
*/
<T extends Service<Context, Response>> void registerImplementation(final @NonNull T service,
final @NonNull Collection<Predicate<Context>> filters) {
<T extends Service<Context, Response>> void registerImplementation(
final @NonNull T service,
final @NonNull Collection<Predicate<Context>> filters
) {
synchronized (this.lock) {
this.implementations.add(new ServiceWrapper<>(service, filters));
}
@ -101,8 +103,10 @@ public final class ServiceRepository<Context, Response> {
private final int registrationOrder = ServiceRepository.this.registrationOrder++;
private final ExecutionOrder executionOrder;
private ServiceWrapper(final @NonNull T implementation,
final @NonNull Collection<Predicate<Context>> filters) {
private ServiceWrapper(
final @NonNull T implementation,
final @NonNull Collection<Predicate<Context>> filters
) {
this.defaultImplementation = implementations.isEmpty();
this.implementation = implementation;
this.filters = filters;
@ -136,15 +140,16 @@ public final class ServiceRepository<Context, Response> {
public String toString() {
return String
.format("ServiceWrapper{type=%s,implementation=%s}", serviceType.toString(),
TypeToken.get(implementation.getClass()).toString());
TypeToken.get(implementation.getClass()).toString()
);
}
@Override
public int compareTo(final @NonNull ServiceWrapper<T> other) {
return Comparator.<ServiceWrapper<T>>comparingInt(
wrapper -> wrapper.isDefaultImplementation()
? Integer.MIN_VALUE
: Integer.MAX_VALUE).thenComparingInt(wrapper -> wrapper.executionOrder.ordinal())
? Integer.MIN_VALUE
: Integer.MAX_VALUE).thenComparingInt(wrapper -> wrapper.executionOrder.ordinal())
.thenComparingInt(wrapper -> wrapper.registrationOrder).compare(this, other);
}

View file

@ -23,10 +23,10 @@
//
package cloud.commandframework.services;
import io.leangen.geantyref.TypeToken;
import cloud.commandframework.services.types.ConsumerService;
import cloud.commandframework.services.types.Service;
import cloud.commandframework.services.types.SideEffectService;
import io.leangen.geantyref.TypeToken;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.LinkedList;
@ -45,9 +45,11 @@ public final class ServiceSpigot<Context, Result> {
private final ServicePipeline pipeline;
private final ServiceRepository<Context, Result> repository;
ServiceSpigot(final @NonNull ServicePipeline pipeline,
final @NonNull Context context,
final @NonNull TypeToken<? extends Service<@NonNull Context, @NonNull Result>> type) {
ServiceSpigot(
final @NonNull ServicePipeline pipeline,
final @NonNull Context context,
final @NonNull TypeToken<? extends Service<@NonNull Context, @NonNull Result>> type
) {
this.context = context;
this.pipeline = pipeline;
this.repository = pipeline.getRepository(type);
@ -71,7 +73,7 @@ public final class ServiceSpigot<Context, Result> {
* PipelineException}. Use {@link PipelineException#getCause()} to
* get the exception that was thrown.
* @see PipelineException PipelineException wraps exceptions thrown during filtering and result
* retrieval
* retrieval
*/
@SuppressWarnings("unchecked")
public @NonNull Result getResult()

View file

@ -43,4 +43,5 @@ public @interface Order {
* @return Priority
*/
ExecutionOrder value() default ExecutionOrder.SOON;
}

View file

@ -45,10 +45,11 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceImplementation {
/**
/**
* The service class that the method implements
*
* @return Service to implement
*/
Class<? extends Service<?, ?>> value();
}

View file

@ -38,52 +38,52 @@ import java.util.function.Consumer;
*/
@FunctionalInterface
public interface ConsumerService<Context>
extends SideEffectService<Context>, Consumer<Context> {
extends SideEffectService<Context>, Consumer<Context> {
/**
* Immediately terminate the execution and return {@link State#ACCEPTED}
*
* @throws PipeBurst Pipe burst
*/
static void interrupt() throws PipeBurst {
throw new PipeBurst();
}
@Override
default @NonNull State handle(final @NonNull Context context) {
try {
this.accept(context);
} catch (final PipeBurst burst) {
return State.ACCEPTED;
}
return State.REJECTED;
}
/**
* Accept the context. Call {@link #interrupt()} to interrupt the entire pipeline and immediately
* return {@link State#ACCEPTED} to the sink
*
* @param context Context to consume
*/
@Override
void accept(@NonNull Context context);
class PipeBurst extends RuntimeException {
private PipeBurst() {
/**
* Immediately terminate the execution and return {@link State#ACCEPTED}
*
* @throws PipeBurst Pipe burst
*/
static void interrupt() throws PipeBurst {
throw new PipeBurst();
}
@Override
public synchronized Throwable fillInStackTrace() {
return this;
default @NonNull State handle(final @NonNull Context context) {
try {
this.accept(context);
} catch (final PipeBurst burst) {
return State.ACCEPTED;
}
return State.REJECTED;
}
/**
* Accept the context. Call {@link #interrupt()} to interrupt the entire pipeline and immediately
* return {@link State#ACCEPTED} to the sink
*
* @param context Context to consume
*/
@Override
public synchronized Throwable initCause(final Throwable cause) {
return this;
}
void accept(@NonNull Context context);
}
class PipeBurst extends RuntimeException {
private PipeBurst() {
}
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
@Override
public synchronized Throwable initCause(final Throwable cause) {
return this;
}
}
}

View file

@ -38,26 +38,26 @@ import java.util.Map;
* @param <Chunked> Chunk request context
*/
public interface PartialResultService<Context, Result, Chunked extends ChunkedRequestContext<Context, Result>>
extends Service<Chunked, @Nullable Map<@NonNull Context, @NonNull Result>> {
extends Service<Chunked, @Nullable Map<@NonNull Context, @NonNull Result>> {
@Override
default @Nullable Map<@NonNull Context, @NonNull Result> handle(final @NonNull Chunked context) {
if (!context.isCompleted()) {
this.handleRequests(context.getRemaining()).forEach(context::storeResult);
@Override
default @Nullable Map<@NonNull Context, @NonNull Result> handle(final @NonNull Chunked context) {
if (!context.isCompleted()) {
this.handleRequests(context.getRemaining()).forEach(context::storeResult);
}
if (context.isCompleted()) {
return context.getAvailableResults();
}
return null;
}
if (context.isCompleted()) {
return context.getAvailableResults();
}
return null;
}
/**
* Attempt to generate results for a list of requests, and return a map of all successful
* requests
*
* @param requests Requests
* @return Map of request-result pairs
*/
@NonNull Map<@NonNull Context, @NonNull Result> handleRequests(@NonNull List<Context> requests);
/**
* Attempt to generate results for a list of requests, and return a map of all successful
* requests
*
* @param requests Requests
* @return Map of request-result pairs
*/
@NonNull Map<@NonNull Context, @NonNull Result> handleRequests(@NonNull List<Context> requests);
}

View file

@ -41,36 +41,36 @@ import java.util.function.Function;
@FunctionalInterface
public interface Service<Context, Result> extends Function<@NonNull Context, @Nullable Result> {
/**
* Provide a response for the given context. If the service implementation cannot provide a
* response for the given context, it should return {@code null}
*
* @param context Context used in the generation of the response
* @return Response. If the response isn't {@code null}, the next service in the service chain
* will get to act on the context. Otherwise the execution halts, and the provided response is the
* final response.
* @throws Exception Any exception that occurs during the handling can be thrown, and will be
* wrapped by a {@link PipelineException}
*/
@Nullable Result handle(@NonNull Context context) throws Exception;
/**
* Provide a response for the given context. If the service implementation cannot provide a
* response for the given context, it should return {@code null}
*
* @param context Context used in the generation of the response
* @return Response. If the response isn't {@code null}, the next service in the service chain
* will get to act on the context. Otherwise the execution halts, and the provided response is the
* final response.
* @throws Exception Any exception that occurs during the handling can be thrown, and will be
* wrapped by a {@link PipelineException}
*/
@Nullable Result handle(@NonNull Context context) throws Exception;
@Override
default @Nullable Result apply(@NonNull Context context) {
try {
return this.handle(context);
} catch (final Exception exception) {
throw new PipelineException(exception);
@Override
default @Nullable Result apply(@NonNull Context context) {
try {
return this.handle(context);
} catch (final Exception exception) {
throw new PipelineException(exception);
}
}
}
/**
* Get the execution order of the service. This should not be overridden, unless you know what you
* are doing
*
* @return Execution order
*/
default @Nullable ExecutionOrder order() {
return null;
}
/**
* Get the execution order of the service. This should not be overridden, unless you know what you
* are doing
*
* @return Execution order
*/
default @Nullable ExecutionOrder order() {
return null;
}
}

View file

@ -36,18 +36,18 @@ import org.checkerframework.checker.nullness.qual.NonNull;
@FunctionalInterface
public interface SideEffectService<Context> extends Service<Context, State> {
/**
* Consumes the context, if possible. Returns {@link State#ACCEPTED} if the input was consumed,
* else {@link State#REJECTED}
*
* @param context context used in the generation of the response
* @return Response. If the response isn't {@link State#ACCEPTED}, the next service in the service
* chain will get to act on the context. Otherwise the execution halts, and the provided response
* is the final response.
* @throws Exception Any exception that occurs during the handling can be thrown, and will be
* wrapped by a {@link cloud.commandframework.services.PipelineException}
*/
@Override
@NonNull State handle(@NonNull Context context) throws Exception;
/**
* Consumes the context, if possible. Returns {@link State#ACCEPTED} if the input was consumed,
* else {@link State#REJECTED}
*
* @param context context used in the generation of the response
* @return Response. If the response isn't {@link State#ACCEPTED}, the next service in the service
* chain will get to act on the context. Otherwise the execution halts, and the provided response
* is the final response.
* @throws Exception Any exception that occurs during the handling can be thrown, and will be
* wrapped by a {@link cloud.commandframework.services.PipelineException}
*/
@Override
@NonNull State handle(@NonNull Context context) throws Exception;
}

View file

@ -67,22 +67,31 @@ public class ServicesTest {
final SecondaryMockService secondaryMockService = new SecondaryMockService();
servicePipeline
.registerServiceImplementation(TypeToken.get(MockService.class), secondaryMockService,
Collections.singleton(secondaryMockService));
servicePipeline.registerServiceImplementation(MockService.class,
Collections.singleton(secondaryMockService)
);
servicePipeline.registerServiceImplementation(
MockService.class,
mockContext -> new MockService.MockResult(-91),
Collections.singleton(mockContext -> mockContext.getString().startsWith("-91")));
Assertions.assertEquals(32,
Collections.singleton(mockContext -> mockContext.getString().startsWith("-91"))
);
Assertions.assertEquals(
32,
servicePipeline.pump(new MockService.MockContext("Hello")).through(MockService.class)
.getResult().getInteger());
.getResult().getInteger()
);
servicePipeline.pump(new MockService.MockContext("Hello")).through(MockService.class)
.getResult(
(mockResult, throwable) -> Assertions.assertEquals(32, mockResult.getInteger()));
Assertions.assertEquals(999,
Assertions.assertEquals(
999,
servicePipeline.pump(new MockService.MockContext("potato")).through(MockService.class)
.getResult().getInteger());
Assertions.assertEquals(-91,
.getResult().getInteger()
);
Assertions.assertEquals(
-91,
servicePipeline.pump(new MockService.MockContext("-91")).through(MockService.class)
.getResult().getInteger());
.getResult().getInteger()
);
Assertions.assertNotNull(
servicePipeline.pump(new MockService.MockContext("oi")).through(MockService.class)
.getResultAsynchronously().get());
@ -92,66 +101,98 @@ public class ServicesTest {
@Test
public void testSideEffectServices() {
final ServicePipeline servicePipeline = ServicePipeline.builder().build();
servicePipeline.registerServiceType(TypeToken.get(MockSideEffectService.class),
new DefaultSideEffectService());
servicePipeline.registerServiceType(
TypeToken.get(MockSideEffectService.class),
new DefaultSideEffectService()
);
final MockSideEffectService.MockPlayer mockPlayer =
new MockSideEffectService.MockPlayer(20);
Assertions.assertEquals(20, mockPlayer.getHealth());
Assertions.assertEquals(State.ACCEPTED,
servicePipeline.pump(mockPlayer).through(MockSideEffectService.class).getResult());
Assertions.assertEquals(
State.ACCEPTED,
servicePipeline.pump(mockPlayer).through(MockSideEffectService.class).getResult()
);
Assertions.assertEquals(0, mockPlayer.getHealth());
mockPlayer.setHealth(20);
servicePipeline.registerServiceImplementation(MockSideEffectService.class,
new SecondaryMockSideEffectService(), Collections.emptyList());
Assertions.assertThrows(IllegalStateException.class,
new SecondaryMockSideEffectService(), Collections.emptyList()
);
Assertions.assertThrows(
IllegalStateException.class,
() -> servicePipeline.pump(mockPlayer).through(MockSideEffectService.class)
.getResult());
.getResult()
);
}
@Test
public void testForwarding() throws Exception {
final ServicePipeline servicePipeline = ServicePipeline.builder().build()
.registerServiceType(TypeToken.get(MockService.class), new DefaultMockService())
.registerServiceType(TypeToken.get(MockResultConsumer.class), new MockResultConsumer());
Assertions.assertEquals(State.ACCEPTED,
.registerServiceType(
TypeToken.get(MockService.class),
new DefaultMockService()
)
.registerServiceType(
TypeToken.get(MockResultConsumer.class),
new MockResultConsumer()
);
Assertions.assertEquals(
State.ACCEPTED,
servicePipeline.pump(new MockService.MockContext("huh")).through(MockService.class)
.forward().through(MockResultConsumer.class).getResult());
Assertions.assertEquals(State.ACCEPTED,
.forward().through(MockResultConsumer.class).getResult()
);
Assertions.assertEquals(
State.ACCEPTED,
servicePipeline.pump(new MockService.MockContext("Something"))
.through(MockService.class).forwardAsynchronously()
.thenApply(pump -> pump.through(MockResultConsumer.class))
.thenApply(ServiceSpigot::getResult).get());
.thenApply(ServiceSpigot::getResult).get()
);
}
@Test
public void testSorting() {
final ServicePipeline servicePipeline = ServicePipeline.builder().build()
.registerServiceType(TypeToken.get(MockService.class), new DefaultMockService());
.registerServiceType(
TypeToken.get(MockService.class),
new DefaultMockService()
);
servicePipeline.registerServiceImplementation(MockService.class, new MockOrderedFirst(),
Collections.emptyList());
Collections.emptyList()
);
servicePipeline.registerServiceImplementation(MockService.class, new MockOrderedLast(),
Collections.emptyList());
Collections.emptyList()
);
// Test that the annotations worked
Assertions.assertEquals(1,
Assertions.assertEquals(
1,
servicePipeline.pump(new MockService.MockContext("")).through(MockService.class)
.getResult().getInteger());
.getResult().getInteger()
);
}
@Test
public void testRecognisedTypes() {
final ServicePipeline servicePipeline = ServicePipeline.builder().build()
.registerServiceType(TypeToken.get(MockService.class), new DefaultMockService());
.registerServiceType(
TypeToken.get(MockService.class),
new DefaultMockService()
);
Assertions.assertEquals(1, servicePipeline.getRecognizedTypes().size());
}
@Test
public void testImplementationGetters() {
final ServicePipeline servicePipeline = ServicePipeline.builder().build()
.registerServiceType(TypeToken.get(MockService.class), new DefaultMockService());
.registerServiceType(
TypeToken.get(MockService.class),
new DefaultMockService()
);
servicePipeline.registerServiceImplementation(MockService.class, new MockOrderedFirst(),
Collections.emptyList());
Collections.emptyList()
);
servicePipeline.registerServiceImplementation(MockService.class, new MockOrderedLast(),
Collections.emptyList());
Collections.emptyList()
);
final TypeToken<? extends Service<?, ?>> first = TypeToken.get(MockOrderedFirst.class),
last = TypeToken.get(MockOrderedLast.class);
final TypeToken<MockService> mockServiceType = TypeToken.get(MockService.class);
@ -171,21 +212,31 @@ public class ServicesTest {
@Test
public void testAnnotatedMethods() throws Exception {
final ServicePipeline servicePipeline = ServicePipeline.builder().build()
.registerServiceType(TypeToken.get(MockService.class), new DefaultMockService())
.registerServiceType(
TypeToken.get(MockService.class),
new DefaultMockService()
)
.registerMethods(new AnnotatedMethodTest());
final String testString = UUID.randomUUID().toString();
Assertions.assertEquals(testString.length(),
Assertions.assertEquals(
testString.length(),
servicePipeline.pump(new MockService.MockContext(testString)).through(MockService.class)
.getResult().getInteger());
.getResult().getInteger()
);
}
@Test
public void testConsumerServices() {
final ServicePipeline servicePipeline = ServicePipeline.builder().build()
.registerServiceType(TypeToken.get(MockConsumerService.class),
new StateSettingConsumerService())
.registerServiceImplementation(MockConsumerService.class,
new InterruptingMockConsumer(), Collections.emptyList());
.registerServiceType(
TypeToken.get(MockConsumerService.class),
new StateSettingConsumerService()
)
.registerServiceImplementation(
MockConsumerService.class,
new InterruptingMockConsumer(),
Collections.emptyList()
);
final MockService.MockContext context = new MockService.MockContext("");
servicePipeline.pump(context).through(MockConsumerService.class).getResult();
Assertions.assertEquals("", context.getState());
@ -194,10 +245,15 @@ public class ServicesTest {
@Test
public void testPartialResultServices() {
final ServicePipeline servicePipeline = ServicePipeline.builder().build()
.registerServiceType(TypeToken.get(MockPartialResultService.class),
new DefaultPartialRequestService())
.registerServiceImplementation(MockPartialResultService.class,
new CompletingPartialResultService(), Collections.emptyList());
.registerServiceType(
TypeToken.get(MockPartialResultService.class),
new DefaultPartialRequestService()
)
.registerServiceImplementation(
MockPartialResultService.class,
new CompletingPartialResultService(),
Collections.emptyList()
);
final MockChunkedRequest.Animal cow = new MockChunkedRequest.Animal("cow");
final MockChunkedRequest.Animal dog = new MockChunkedRequest.Animal("dog");
final MockChunkedRequest.Animal cat = new MockChunkedRequest.Animal("cat");
@ -215,16 +271,22 @@ public class ServicesTest {
Assertions.assertNotNull(servicePipeline);
servicePipeline
.registerServiceType(TypeToken.get(MockService.class), new DefaultMockService());
final PipelineException pipelineException = Assertions.assertThrows(PipelineException.class,
final PipelineException pipelineException = Assertions.assertThrows(
PipelineException.class,
() -> servicePipeline.pump(new MockService.MockContext("pls throw exception"))
.through(MockService.class).getResult());
Assertions.assertEquals(DefaultMockService.TotallyIntentionalException.class,
pipelineException.getCause().getClass());
.through(MockService.class).getResult()
);
Assertions.assertEquals(
DefaultMockService.TotallyIntentionalException.class,
pipelineException.getCause().getClass()
);
servicePipeline.pump(new MockService.MockContext("pls throw exception"))
.through(MockService.class).getResult((result, throwable) -> {
Assertions.assertNotNull(throwable);
Assertions.assertEquals(DefaultMockService.TotallyIntentionalException.class,
throwable.getClass());
Assertions.assertEquals(
DefaultMockService.TotallyIntentionalException.class,
throwable.getClass()
);
Assertions.assertNull(result);
});
}

View file

@ -29,17 +29,17 @@ import java.util.Map;
public class CompletingPartialResultService implements MockPartialResultService {
@Override
public Map<MockChunkedRequest.Animal, MockChunkedRequest.Sound> handleRequests(List<MockChunkedRequest.Animal> requests) {
final Map<MockChunkedRequest.Animal, MockChunkedRequest.Sound> map = new HashMap<>();
for (final MockChunkedRequest.Animal animal : requests) {
if (animal.getName().equals("cow")) {
map.put(animal, new MockChunkedRequest.Sound("moo"));
} else if (animal.getName().equals("dog")) {
map.put(animal, new MockChunkedRequest.Sound("woof"));
}
@Override
public Map<MockChunkedRequest.Animal, MockChunkedRequest.Sound> handleRequests(List<MockChunkedRequest.Animal> requests) {
final Map<MockChunkedRequest.Animal, MockChunkedRequest.Sound> map = new HashMap<>();
for (final MockChunkedRequest.Animal animal : requests) {
if (animal.getName().equals("cow")) {
map.put(animal, new MockChunkedRequest.Sound("moo"));
} else if (animal.getName().equals("dog")) {
map.put(animal, new MockChunkedRequest.Sound("woof"));
}
}
return map;
}
return map;
}
}

View file

@ -25,19 +25,19 @@ package cloud.commandframework.services.mock;
public class DefaultMockService implements MockService {
@Override
public MockResult handle(final MockContext mockContext)
throws Exception {
if (mockContext.getString().equals("pls throw exception")) {
throw new TotallyIntentionalException();
@Override
public MockResult handle(final MockContext mockContext)
throws Exception {
if (mockContext.getString().equals("pls throw exception")) {
throw new TotallyIntentionalException();
}
return new MockResult(32);
}
return new MockResult(32);
}
public static class TotallyIntentionalException extends Exception {
public static class TotallyIntentionalException extends Exception {
}
}
}

View file

@ -29,14 +29,14 @@ import java.util.Map;
public class DefaultPartialRequestService implements MockPartialResultService {
@Override
public Map<MockChunkedRequest.Animal, MockChunkedRequest.Sound> handleRequests(final List<MockChunkedRequest.Animal> requests) {
final Map<MockChunkedRequest.Animal, MockChunkedRequest.Sound> map =
new HashMap<>(requests.size());
for (final MockChunkedRequest.Animal animal : requests) {
map.put(animal, new MockChunkedRequest.Sound("unknown"));
@Override
public Map<MockChunkedRequest.Animal, MockChunkedRequest.Sound> handleRequests(final List<MockChunkedRequest.Animal> requests) {
final Map<MockChunkedRequest.Animal, MockChunkedRequest.Sound> map =
new HashMap<>(requests.size());
for (final MockChunkedRequest.Animal animal : requests) {
map.put(animal, new MockChunkedRequest.Sound("unknown"));
}
return map;
}
return map;
}
}

View file

@ -27,10 +27,10 @@ import cloud.commandframework.services.State;
public class DefaultSideEffectService implements MockSideEffectService {
@Override
public State handle(final MockPlayer mockPlayer) {
mockPlayer.setHealth(0);
return State.ACCEPTED;
}
@Override
public State handle(final MockPlayer mockPlayer) {
mockPlayer.setHealth(0);
return State.ACCEPTED;
}
}

View file

@ -27,9 +27,9 @@ import cloud.commandframework.services.types.ConsumerService;
public class InterruptingMockConsumer implements MockConsumerService {
@Override
public void accept(final MockService.MockContext mockContext) {
ConsumerService.interrupt();
}
@Override
public void accept(final MockService.MockContext mockContext) {
ConsumerService.interrupt();
}
}

View file

@ -28,37 +28,39 @@ import cloud.commandframework.services.ChunkedRequestContext;
import java.util.Collection;
public class MockChunkedRequest
extends ChunkedRequestContext<MockChunkedRequest.Animal, MockChunkedRequest.Sound> {
extends ChunkedRequestContext<MockChunkedRequest.Animal, MockChunkedRequest.Sound> {
public MockChunkedRequest(final Collection<Animal> requests) {
super(requests);
}
public static class Animal {
private final String name;
public Animal(final String name) {
this.name = name;
public MockChunkedRequest(final Collection<Animal> requests) {
super(requests);
}
public String getName() {
return this.name;
}
}
public static class Animal {
private final String name;
public static class Sound {
public Animal(final String name) {
this.name = name;
}
private final String sound;
public String getName() {
return this.name;
}
public Sound(final String sound) {
this.sound = sound;
}
public String getSound() {
return this.sound;
public static class Sound {
private final String sound;
public Sound(final String sound) {
this.sound = sound;
}
public String getSound() {
return this.sound;
}
}
}
}

View file

@ -29,9 +29,9 @@ import cloud.commandframework.services.annotations.Order;
@Order(ExecutionOrder.FIRST)
public class MockOrderedFirst implements MockService {
@Override
public MockResult handle(final MockContext mockContext) {
return new MockResult(1);
}
@Override
public MockResult handle(final MockContext mockContext) {
return new MockResult(1);
}
}

View file

@ -29,9 +29,9 @@ import cloud.commandframework.services.annotations.Order;
@Order(ExecutionOrder.LAST)
public class MockOrderedLast implements MockService {
@Override
public MockResult handle(final MockContext mockContext) {
return new MockResult(2);
}
@Override
public MockResult handle(final MockContext mockContext) {
return new MockResult(2);
}
}

View file

@ -26,6 +26,6 @@ package cloud.commandframework.services.mock;
import cloud.commandframework.services.types.PartialResultService;
public interface MockPartialResultService extends
PartialResultService<MockChunkedRequest.Animal, MockChunkedRequest.Sound, MockChunkedRequest> {
PartialResultService<MockChunkedRequest.Animal, MockChunkedRequest.Sound, MockChunkedRequest> {
}

View file

@ -28,9 +28,9 @@ import cloud.commandframework.services.types.SideEffectService;
public class MockResultConsumer implements SideEffectService<MockService.MockResult> {
@Override
public State handle(final MockService.MockResult mockResultConsumer) {
return State.ACCEPTED;
}
@Override
public State handle(final MockService.MockResult mockResultConsumer) {
return State.ACCEPTED;
}
}

View file

@ -29,24 +29,24 @@ public interface MockService extends Service<MockService.MockContext, MockServic
class MockContext {
private final String string;
private String state = "";
private final String string;
private String state = "";
public MockContext( final String string) {
this.string = string;
}
public MockContext(final String string) {
this.string = string;
}
public String getString() {
return this.string;
}
public String getString() {
return this.string;
}
public String getState() {
return this.state;
}
public String getState() {
return this.state;
}
public void setState( final String state) {
this.state = state;
}
public void setState(final String state) {
this.state = state;
}
}

View file

@ -27,14 +27,14 @@ import java.util.function.Predicate;
public class SecondaryMockService implements MockService, Predicate<MockService.MockContext> {
@Override
public MockResult handle(final MockContext mockContext) {
return new MockResult(999);
}
@Override
public MockResult handle(final MockContext mockContext) {
return new MockResult(999);
}
@Override
public boolean test(final MockContext mockContext) {
return mockContext.getString().equalsIgnoreCase("potato");
}
@Override
public boolean test(final MockContext mockContext) {
return mockContext.getString().equalsIgnoreCase("potato");
}
}

View file

@ -27,9 +27,9 @@ import cloud.commandframework.services.State;
public class SecondaryMockSideEffectService implements MockSideEffectService {
@Override
public State handle(final MockPlayer mockPlayer) {
return null;
}
@Override
public State handle(final MockPlayer mockPlayer) {
return null;
}
}

View file

@ -25,9 +25,9 @@ package cloud.commandframework.services.mock;
public class StateSettingConsumerService implements MockConsumerService {
@Override
public void accept(final MockService.MockContext mockContext) {
mockContext.setState("");
}
@Override
public void accept(final MockService.MockContext mockContext) {
mockContext.setState("");
}
}