diff --git a/.github/FUNDING.yaml b/.github/FUNDING.yaml new file mode 100644 index 00000000..c093a181 --- /dev/null +++ b/.github/FUNDING.yaml @@ -0,0 +1,4 @@ +ko_fi: progrm_jarvis +custom: + - 'https://qiwi.com/n/PROgrammerJARvis' + - 'https://yoomoney.ru/to/410013423232443' diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 2a0f4faf..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -ko_fi: progrm_jarvis -custom: ['http://qiwi.com/n/PROgrammerJARvis', 'https://yoomoney.ru/to/410013423232443'] diff --git a/.github/dependabot.yml b/.github/dependabot.yaml similarity index 100% rename from .github/dependabot.yml rename to .github/dependabot.yaml diff --git a/.github/workflows/deploy-release.yml b/.github/workflows/deploy-release.yaml similarity index 93% rename from .github/workflows/deploy-release.yml rename to .github/workflows/deploy-release.yaml index 0f30ce5b..2907a20e 100644 --- a/.github/workflows/deploy-release.yml +++ b/.github/workflows/deploy-release.yaml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.4.0 - name: Set up Java 17 & Deployment credentials - uses: actions/setup-java@main + uses: actions/setup-java@v2.3.1 with: distribution: 'zulu' java-version: '17' diff --git a/.github/workflows/deploy-snapshot.yml b/.github/workflows/deploy-snapshot.yaml similarity index 93% rename from .github/workflows/deploy-snapshot.yml rename to .github/workflows/deploy-snapshot.yaml index 9eb45076..2ea037ba 100644 --- a/.github/workflows/deploy-snapshot.yml +++ b/.github/workflows/deploy-snapshot.yaml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.4.0 - name: Set up Java 17 & Deployment credentials - uses: actions/setup-java@main + uses: actions/setup-java@v2.3.1 with: distribution: 'zulu' java-version: '17' diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 00000000..272b9454 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,41 @@ +name: Test + +on: [ pull_request ] + +jobs: + run-tests: + name: Run Tests + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2.4.0 + + - name: Set up Java 17 + uses: actions/setup-java@v2.3.1 + with: + distribution: 'zulu' + java-version: '17' + cache: 'maven' + + - name: Run tests + run: mvn -B test + + check-javadocs: + name: Check Javadocs + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2.4.0 + + - name: Set up Java 17 + uses: actions/setup-java@v2.3.1 + with: + distribution: 'zulu' + java-version: '17' + cache: 'maven' + + - name: Install artifacts + run: mvn -B install -Dmaven.test.skip=true + + - name: Try to generate Javadocs + run: mvn -B javadoc:javadoc diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 85f24193..00000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Test - -on: [ pull_request ] - -jobs: - test: - name: Test - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2.3.4 - - - name: Set up Java 17 - uses: actions/setup-java@main - with: - distribution: 'zulu' - java-version: 17 - cache: 'maven' - - - name: Run tests - run: mvn -B test diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/collection/LazyIteratorToCollectionWrapper.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/collection/LazyIteratorToCollectionWrapper.java index 892d9eb2..0c2e39fc 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/collection/LazyIteratorToCollectionWrapper.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/collection/LazyIteratorToCollectionWrapper.java @@ -53,7 +53,7 @@ public class LazyIteratorToCollectionWrapper> impleme } /** - * Checks whether or not the wrapped iterator contains the specified element. + * Checks whether the wrapped iterator contains the specified element. * * @param element element to check for containment * @return {@code true} if the element is contained in the wrapped iterator and {@code false} otherwise diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/data/DataSerializer.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/data/DataSerializer.java index 08448b83..34c618ed 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/data/DataSerializer.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/data/DataSerializer.java @@ -36,8 +36,9 @@ public interface DataSerializer { * @implNote delegates to {@link #write(DataOutputStream, Object)} * @implSpec should not be overridden */ + @SneakyThrows(IOException.class) default void writeUnchecked(final @NotNull DataOutputStream output, final T object) { - writeUnchecked(output, object); + write(output, object); } /** diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/data/DataSerializers.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/data/DataSerializers.java index cf46c22a..fe9a7ae1 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/data/DataSerializers.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/data/DataSerializers.java @@ -62,32 +62,32 @@ public class DataSerializers { /* ************************************************ Collections ************************************************ */ - public , T> @NotNull DataSerializer collectionDataSerializer( - final @NonNull DataSerializers.SizeAwareFactory<@NotNull C> collectionFactory, + public , T> @NotNull DataSerializer<@NotNull C> collectionDataSerializer( + final DataSerializers.@NonNull SizeAwareFactory collectionFactory, final @NonNull DataSerializer elementSerializer ) { return new CollectionDataSerializer<>(collectionFactory, elementSerializer); } - public @NotNull DataSerializer> collectionDataSerializer( + public @NotNull DataSerializer<@NotNull Collection> collectionDataSerializer( final @NonNull DataSerializer elementSerializer) { return collectionDataSerializer(ArrayList::new, elementSerializer); } - public @NotNull DataSerializer> listDataSerializer( + public @NotNull DataSerializer<@NotNull List> listDataSerializer( final @NonNull DataSerializer elementSerializer ) { return collectionDataSerializer(ArrayList::new, elementSerializer); } - public @NotNull DataSerializer> setDataSerializer( + public @NotNull DataSerializer<@NotNull Set> setDataSerializer( final @NonNull DataSerializer elementSerializer ) { return collectionDataSerializer(HashSet::new, elementSerializer); } - public , K, V> @NotNull DataSerializer mapDataSerializer( - final @NonNull DataSerializers.SizeAwareFactory<@NotNull M> mapFactory, + public , K, V> @NotNull DataSerializer<@NotNull M> mapDataSerializer( + final DataSerializers.@NonNull SizeAwareFactory mapFactory, final @NonNull DataSerializer keySerializer, final @NonNull DataSerializer valueSerializer ) { @@ -473,7 +473,7 @@ public void write(final @NotNull DataOutputStream out, final @NotNull UUID uuid) @Override public @NotNull UUID fromByteArray(final byte @NotNull [] byteArray) throws IOException { - if (byteArray.length != 16) throw new IOException("Byte array should be of length 16"); + if (byteArray.length != UuidUtil.UUID_BYTES) throw new IOException("Byte array should be of length 16"); return UuidUtil.uuidFromBytes(byteArray); } @@ -493,19 +493,20 @@ public void write(final @NotNull DataOutputStream out, final @NotNull UUID uuid) @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) - private static final class CollectionDataSerializer, T> implements DataSerializer { + private static final class CollectionDataSerializer, T> + implements DataSerializer<@NotNull C> { - @NotNull DataSerializers.SizeAwareFactory<@NotNull C> collectionFactory; + DataSerializers.@NotNull SizeAwareFactory collectionFactory; @NotNull DataSerializer elementSerializer; @Override - public void write(final @NotNull DataOutputStream out, final C collection) throws IOException { + public void write(final @NotNull DataOutputStream out, final @NotNull C collection) throws IOException { out.writeInt(collection.size()); for (val element : collection) elementSerializer.write(out, element); } @Override - public C read(final @NotNull DataInputStream in) throws IOException { + public @NotNull C read(final @NotNull DataInputStream in) throws IOException { final int size; val collection = collectionFactory.create(size = in.readInt()); for (var i = 0; i < size; i++) collection.add(elementSerializer.read(in)); @@ -516,14 +517,14 @@ public C read(final @NotNull DataInputStream in) throws IOException { @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) - private static final class MapDataSerializer, K, V> implements DataSerializer { + private static final class MapDataSerializer, K, V> implements DataSerializer<@NotNull M> { - @NotNull DataSerializers.SizeAwareFactory<@NotNull M> mapFactory; + DataSerializers.@NotNull SizeAwareFactory mapFactory; @NotNull DataSerializer keySerializer; @NotNull DataSerializer valueSerializer; @Override - public void write(final @NotNull DataOutputStream out, final M map) throws IOException { + public void write(final @NotNull DataOutputStream out, final @NotNull M map) throws IOException { final Set> entries; out.writeInt((entries = map.entrySet()).size()); for (val entry : entries) { @@ -533,7 +534,7 @@ public void write(final @NotNull DataOutputStream out, final M map) throws IOExc } @Override - public M read(final @NotNull DataInputStream in) throws IOException { + public @NotNull M read(final @NotNull DataInputStream in) throws IOException { final int size; val map = mapFactory.create(size = in.readInt()); for (var i = 0; i < size; i++) map.put(keySerializer.read(in), valueSerializer.read(in)); diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/object/Result.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/object/Result.java index 4cbbdc94..e7e26f0f 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/object/Result.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/object/Result.java @@ -8,12 +8,15 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import ru.progrm_jarvis.javacommons.annotation.Any; +import ru.progrm_jarvis.javacommons.util.function.ThrowingRunnable; +import ru.progrm_jarvis.javacommons.util.function.ThrowingSupplier; import java.util.Optional; import java.util.concurrent.Callable; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Stream; /** * A tagged union representing either a successful result or an error. @@ -74,6 +77,32 @@ public interface Result extends Supplier { return (Result) NullError.INSTANCE; } + /** + * Creates a new {@link #success(Object) successful result} if the value is not {@code null}. + * + * @param value value which should be non-{@code null} to be considered a successful value + * @param type of the successful value + * @param any formal type of the error value + * @return a {@link #success(Object) successful result} if the {@code value} is not {@code null} + * or a {@link #nullError() null error} otherwise + */ + static @NotNull Result<@NotNull T, @Nullable E> nonNullSuccess(final @Nullable T value) { + return value == null ? nullError() : success(value); + } + + /** + * Creates a new {@link #error(Object) error result} if the value is not {@code null}. + * + * @param error value which should be non-{@code null} to be considered an error value + * @param any formal type of the successful value + * @param type of the error value + * @return a {@link #error(Object) error result} if the {@code value} is not {@code null} + * or a {@link #nullSuccess() null success} otherwise + */ + static @NotNull Result<@Nullable T, @NotNull E> nonNullError(final @Nullable E error) { + return error == null ? nullSuccess() : error(error); + } + /** * Converts the given {@link Optional} into a {@link #nullError() null-error result}. * @@ -109,15 +138,54 @@ public interface Result extends Supplier { return optional.>map(Result::success).orElseGet(() -> error(errorSupplier.get())); } + /** + * Creates a result by running the specified runnable. + * + * @param runnable function whose failure indicates the {@link #error(Object) error result} + * @return {@link #nullSuccess() successful void-result} if the runnable runs unexceptionally + * or an {@link #error(Object) error result} containing the thrown {@link Throwable throwable} otherwise + */ + static @NotNull Result<@Nullable Void, ? extends @NotNull Throwable> tryRun( + final @NonNull ThrowingRunnable runnable + ) { + try { + runnable.runChecked(); + } catch (final Throwable x) { + return error(x); + } + + return nullSuccess(); + } + + /** + * Creates a result by getting the value of the specified supplier. + * + * @param supplier provider of the result whose failure indicates the {@link #error(Object) error result} + * @return {@link #success(Object) successful result} if the supplier provides the value unexceptionally + * or an {@link #error(Object) error result} containing the thrown {@link Throwable throwable} otherwise + */ + static Result tryGet( + final @NonNull ThrowingSupplier supplier + ) { + final T value; + try { + value = supplier.get(); + } catch (final Exception x) { + return error(x); + } + + return success(value); + } + /** * Creates a result by calling the specified callable. * - * @param callable provider of the result + * @param callable provider of the result whose failure indicates the {@link #error(Object) error result} * @param type of the result provided by the given callable - * @return {@link #success(Object) successful result} if the callable ran unexceptionally - * and {@link #error(Object) error result} containing the thrown {@link Exception exception} otherwise + * @return {@link #success(Object) successful result} if the callable completes unexceptionally + * or an {@link #error(Object) error result} containing the thrown {@link Exception exception} otherwise */ - static Result tryFrom(final @NonNull Callable callable) { + static @NotNull Result tryCall(final @NonNull Callable callable) { final T value; try { value = callable.call(); @@ -128,6 +196,20 @@ public interface Result extends Supplier { return success(value); } + /** + * Creates a result by calling the specified callable. + * + * @param callable provider of the result whose failure indicates the {@link #error(Object) error result} + * @param type of the result provided by the given callable + * @return {@link #success(Object) successful result} if the callable completes unexceptionally + * or an {@link #error(Object) error result} containing the thrown {@link Exception exception} otherwise + * @deprecated in favor of {@link #tryCall(Callable)} + */ + @Deprecated + static @NotNull Result tryFrom(final @NonNull Callable callable) { + return tryCall(callable); + } + /* ********************************************** Checking methods ********************************************** */ /** @@ -228,10 +310,20 @@ default T orElseSneakyThrow( * * @param defaultValueSupplier supplier of the default value * to be returned if this is an {@link #isError()} error value} - * @return successful value if this a {@link #isSuccess() successful result} or {@code defaultValue} otherwise + * @return successful value if this a {@link #isSuccess() successful result} or got default otherwise */ T orGetDefault(@NonNull Supplier defaultValueSupplier); + /** + * Gets the value of this result if this is a {@link #isSuccess() successful} + * otherwise returning the value computed by applying the given function to the {@link #unwrapError() error value}. + * + * @param defaultValueFactory factory used for creation of the default value + * to be returned if this is an {@link #isError()} error value} + * @return successful value if this a {@link #isSuccess() successful result} or the computed default otherwise + */ + T orComputeDefault(@NonNull Function defaultValueFactory); + /** * Gets the error of this result throwing a {@link NotErrorException} * if this is a {@link #isSuccess() successful result}. @@ -418,41 +510,59 @@ default E errorOrElseSneakyThrow( /* ********************************************* Conversion methods ********************************************* */ /** - * Converts this result to an {@link Optional} of its successful value. + * Converts this result into an {@link Optional} of its successful value. * - * @return {@link Optional optional} containing the successful result's value + * @return {@link Optional optional} containing the value * if this is a {@link #isSuccess() successful result} - * and an {@link Optional#empty() empty optional} otherwise + * or an {@link Optional#empty() empty optional} otherwise */ @NotNull Optional asOptional(); /** - * Converts this result to an {@link Optional} of its error. + * Converts this result into an {@link Optional} of its error. * - * @return {@link Optional optional} containing the error result's error + * @return {@link Optional optional} containing the error * if this is an {@link #isError() error result} - * and an {@link Optional#empty() empty optional} otherwise + * or an {@link Optional#empty() empty optional} otherwise */ @NotNull Optional asErrorOptional(); /** - * Converts this result to a {@link ValueContainer} of its successful value. + * Converts this result into a {@link ValueContainer} of its successful value. * - * @return {@link ValueContainer value container} containing the successful result's value + * @return {@link ValueContainer value container} containing the value * if this is a {@link #isSuccess() successful result} * or an {@link ValueContainer#empty() empty value-container} otherwise */ @NotNull ValueContainer asValueContainer(); /** - * Converts this result to a {@link ValueContainer} of its error value. + * Converts this result into a {@link ValueContainer} of its error value. * - * @return {@link ValueContainer value container} containing the error result's error + * @return {@link ValueContainer value container} containing the error * if this is an {@link #isError() error result} * or an {@link ValueContainer#empty() empty value-container} otherwise */ @NotNull ValueContainer asErrorValueContainer(); + /** + * Converts this result into a {@link Stream} of its successful value. + * + * @return {@link Stream stream} of the value + * if this is a {@link #isSuccess() successful result} + * or an {@link Stream#empty() empty stream} otherwise + */ + @NotNull Stream asStream(); + + /** + * Converts this result into a {@link Stream} of its error value. + * + * @return {@link Stream stream} containing the error + * if this is an {@link #isError() error result} + * or an {@link Stream#empty() empty stream} otherwise + */ + @NotNull Stream asErrorStream(); + /** * Representation of a {@link #isSuccess() successful} {@link Result result}. * @@ -519,6 +629,11 @@ public T orGetDefault(final @NonNull Supplier defaultValueSupplier) return value; } + @Override + public T orComputeDefault(@NonNull final Function defaultValueFactory) { + return value; + } + @Override public E unwrapError() { throw new NotErrorException("This is not an error result"); @@ -633,6 +748,16 @@ public void handle( return ValueContainer.empty(); } + @Override + public @NotNull Stream asStream() { + return Stream.of(value); + } + + @Override + public @NotNull Stream asErrorStream() { + return Stream.empty(); + } + // } @@ -704,6 +829,11 @@ public T orGetDefault(final @NonNull Supplier defaultValueSupplier) return defaultValueSupplier.get(); } + @Override + public T orComputeDefault(final @NonNull Function defaultValueFactory) { + return defaultValueFactory.apply(error); + } + @Override public E unwrapError() { return error; @@ -815,6 +945,16 @@ public void handle( return ValueContainer.of(error); } + @Override + public @NotNull Stream asStream() { + return Stream.empty(); + } + + @Override + public @NotNull Stream asErrorStream() { + return Stream.of(error); + } + // } @@ -822,7 +962,7 @@ public void handle( * Holder of a {@code null}-success result. */ @UtilityClass - final class NullSuccess { + class NullSuccess { /** * Instance of a {@code null}-error @@ -834,7 +974,7 @@ final class NullSuccess { * Holder of a {@code null}-error result. */ @UtilityClass - final class NullError { + class NullError { /** * Instance of a {@code null}-error @@ -883,9 +1023,9 @@ public NotSuccessException(final Throwable cause) { * * @param message message describing the exception cause * @param cause cause of this exception - * @param enableSuppression flag indicating whether or not suppression + * @param enableSuppression flag indicating whether suppression * is enabled or disabled for this exception - * @param writableStackTrace flag indicating whether or not not the stack trace + * @param writableStackTrace flag indicating whether not the stack trace * should be writable for this exception */ public NotSuccessException(final String message, final Throwable cause, final boolean enableSuppression, @@ -937,9 +1077,9 @@ public NotErrorException(final Throwable cause) { * * @param message message describing the exception cause * @param cause cause of this exception - * @param enableSuppression flag indicating whether or not suppression + * @param enableSuppression flag indicating whether suppression * is enabled or disabled for this exception - * @param writableStackTrace flag indicating whether or not not the stack trace + * @param writableStackTrace flag indicating whether not the stack trace * should be writable for this exception */ public NotErrorException(final String message, final Throwable cause, final boolean enableSuppression, @@ -970,5 +1110,38 @@ public T rethrow( ) throws X { return result.orElseThrow(Function.identity()); } + + /** + *

Converts the result to another result whose types are super-types of its current types.

+ *

This is equivalent to the following:

+ *
{@code
+         * result
+         *         .map(Function.identity())
+         *         .mapError(Function.identity())
+         * }
+ * + * @param result result whose type should be upcasted + * @param new (super-) type of the successful result + * @param new (super-) type of the error result + * @return upcasted result + * + * @apiNote this method could have been an instance method but its type cannot be described due to the absence + * of the ability to specify {@code super}-bounds on generic parameters relative to the other ones + */ + @SuppressWarnings("unchecked") // Results are immutable so they are always safe to upcast + public Result upcast(final @NotNull Result result) { + return (Result) result; + } + + /** + * Either returns the successful result's value ot the error result's value depending on what is present. + * + * @param result given result + * @param type of the resulting value common for the success and error values + * @return either the success or the error value + */ + public T any(final @NotNull Result result) { + return Extensions.upcast(result).orComputeDefault(Function.identity()); + } } } diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/object/ValueContainer.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/object/ValueContainer.java index 4a91286f..e3b64f92 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/object/ValueContainer.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/object/ValueContainer.java @@ -392,9 +392,9 @@ public EmptyValueException(final Throwable cause) { * * @param message message describing the exception cause * @param cause cause of this exception - * @param enableSuppression flag indicating whether or not suppression + * @param enableSuppression flag indicating whether suppression * is enabled or disabled for this exception - * @param writableStackTrace flag indicating whether or not not the stack trace + * @param writableStackTrace flag indicating whether not the stack trace * should be writable for this exception */ public EmptyValueException(final String message, final Throwable cause, final boolean enableSuppression, diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/ownership/annotation/Own.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/ownership/annotation/Own.java index ecd8bfee..60a4d346 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/ownership/annotation/Own.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/ownership/annotation/Own.java @@ -5,7 +5,7 @@ /** *

Marker indicating the owner of a mutable object. * It is intended only for use with mutable types - * for which it will indicate whether or not the operated object should be cloned for modification

+ * for which it will indicate whether the operated object should be cloned for modification

*

Owner depends on the target:

*
*
parameter
diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/ownership/annotation/Ref.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/ownership/annotation/Ref.java index 231f1b9e..1d8ae283 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/ownership/annotation/Ref.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/ownership/annotation/Ref.java @@ -5,7 +5,7 @@ /** *

Marker indicating the non-owner of a mutable object. * It is intended only for use with mutable types - * for which it will indicate whether or not the operated object should be cloned for modification

+ * for which it will indicate whether the operated object should be cloned for modification

*

Owner depends on the target:

*
*
parameter
diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/service/AbstractManagedPendingService.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/service/AbstractManagedPendingService.java index b520ed15..a1012421 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/service/AbstractManagedPendingService.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/service/AbstractManagedPendingService.java @@ -184,11 +184,11 @@ protected enum State { STARTED(false, false); /** - * Flag indicating whether or not new {@link #request(Object) own-requests} can happen + * Flag indicating whether new {@link #request(Object) own-requests} can happen */ boolean canRequest, /** - * Flag indicating whether or not owned services can still be {@link OwnedService#close() closed} + * Flag indicating whether owned services can still be {@link OwnedService#close() closed} */ canClose; } @@ -210,7 +210,7 @@ protected class SafeOwnedService implements OwnedService { S service; /** - * Flag indicating whether or not this service can no longer be used. + * Flag indicating whether this service can no longer be used. */ @NotNull AtomicBoolean closed; diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/SneakyThrower.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/SneakyThrower.java new file mode 100644 index 00000000..1c0b3c38 --- /dev/null +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/SneakyThrower.java @@ -0,0 +1,28 @@ +package ru.progrm_jarvis.javacommons.util; + +import lombok.NonNull; +import lombok.SneakyThrows; +import lombok.experimental.UtilityClass; +import ru.progrm_jarvis.javacommons.annotation.Any; + +/** + * Utility used for rethrowing checked exceptions as unchecked. + */ +@UtilityClass +public class SneakyThrower { + + /** + * Rethrows the provided throwable without the need to handle it. + * This always throws {@code X} never returning any value. + * + * @param exception rethrown exception + * @param type of the returned exception + * @param any formal return type of this expression + * + * @return never + */ + @SneakyThrows + public R sneakyThrow(final @NonNull X exception) { + throw exception; + } +} diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/UuidUtil.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/UuidUtil.java index 055eaeba..490976e6 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/UuidUtil.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/UuidUtil.java @@ -16,7 +16,7 @@ public class UuidUtil { /** * Amount of bytes from which the {@link UUID} consists. */ - private final int UUID_BYTES = Long.BYTES << 1; + public final int UUID_BYTES = Long.BYTES << 1; /** * Converts {@link UUID} into an array of 16 {@code byte}s. diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/Predicates.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/Predicates.java index 46b69059..88116513 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/Predicates.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/Predicates.java @@ -15,6 +15,7 @@ public class Predicates { /** * Creates a predicate which is always {@code true}. * + * @param any formal type of the input parameter * @return predicate which is always {@code true} */ public <@Any T> @NotNull Predicate alwaysTrue() { @@ -24,6 +25,7 @@ public class Predicates { /** * Creates a predicate which is always {@code false}. * + * @param any formal type of the input parameter * @return predicate which is always {@code false} */ public <@Any T> @NotNull Predicate alwaysFalse() { diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingBiFunction.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingBiFunction.java index 8c86035b..3e7ad2a9 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingBiFunction.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingBiFunction.java @@ -14,6 +14,16 @@ @FunctionalInterface public interface ThrowingBiFunction extends BiFunction { + /** + * Applies this function to the given arguments. + * + * @param t the first function argument + * @param u the second function argument + * @return the function result + * @throws X if an exception happens + */ + R applyChecked(T t, U u) throws X; + /** * Applies this function to the given arguments. * @@ -22,12 +32,16 @@ public interface ThrowingBiFunction extends BiFunc * @return the function result * @throws X if an exception happens * + * @deprecated in favor of {@link #applyChecked(Object, Object)} */ - R invoke(T t, U u) throws X; + @Deprecated + default R invoke(final T t, final U u) throws X { + return applyChecked(t, u); + } @Override @SneakyThrows default R apply(final T t, final U u) { - return invoke(t, u); + return applyChecked(t, u); } } diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingFunction.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingFunction.java index ee2330b3..48bf8dc2 100644 --- a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingFunction.java +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingFunction.java @@ -21,11 +21,25 @@ public interface ThrowingFunction extends Function the type of the exception thrown by the function + */ +@FunctionalInterface +public interface ThrowingRunnable extends Runnable{ + + /** + * Runs an action. + * + * @throws X if an exception happens + */ + void runChecked() throws X; + + @Override + @SneakyThrows + default void run() { + runChecked(); + } + + /** + * Creates an empty (no-op) throwing runnable. + * + * @param any formal type of the (never thrown) exception + * @return empty throwing runnable + */ + static <@Any X extends Throwable> @NotNull ThrowingRunnable empty() { + return () -> {}; + } + + /** + * Creates a throwing runnable which always throws an exception produced by using the factory. + * + * @param exceptionFactory factory used for creation of the exception + * @param the type of the exception thrown by the function + * @return throwing runnable which always throws {@code X} by creating it via the provided factory + * @throws NullPointerException if {@code exceptionFactory} is {@code null} + * + * @apiNote if the {@code exceptionFactory} produces {@code null} + * then {@link NullPointerException} will be thrown when attempting to throw the expected exception + */ + static <@Any X extends Throwable> @NotNull ThrowingRunnable throwing( + final @NonNull Supplier exceptionFactory + ) { + return () -> { + throw exceptionFactory.get(); + }; + } +} diff --git a/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingSupplier.java b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingSupplier.java new file mode 100644 index 00000000..1fdb5750 --- /dev/null +++ b/java-commons/src/main/java/ru/progrm_jarvis/javacommons/util/function/ThrowingSupplier.java @@ -0,0 +1,64 @@ +package ru.progrm_jarvis.javacommons.util.function; + +import lombok.NonNull; +import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; +import ru.progrm_jarvis.javacommons.annotation.Any; + +import java.util.function.Supplier; + +/** + * An extension of {@link Supplier} allowing throwing calls in its body. + * + * @param the type of results supplied by this supplier + * @param the type of the exception thrown by the function + */ +@FunctionalInterface +public interface ThrowingSupplier extends Supplier { + + /** + * Gets a result. + * + * @return a result + * @throws X if an exception happens + */ + T getChecked() throws X; + + @Override + @SneakyThrows + default T get() { + return getChecked(); + } + + /** + * Creates throwing supplier which always returns the provided value. + * + * @param value the value always returned by this factory + * @param the type of the supplied result + * @param any formal type of the (never thrown) exception + * @return created throwing supplier + */ + static @NotNull ThrowingSupplier returning(final T value) { + return () -> value; + } + + /** + * Creates a throwing supplier which always throws an exception produced by using the factory. + * + * @param exceptionFactory factory used for creation of the exception + * @param any formal type of the (never returned) value + * @param the type of the exception thrown by the function + * @return throwing runnable which always throws {@code X} by creating it via the provided factory + * @throws NullPointerException if {@code exceptionFactory} is {@code null} + * + * @apiNote if the {@code exceptionFactory} produces {@code null} + * then {@link NullPointerException} will be thrown when attempting to throw the expected exception + */ + static <@Any T, X extends Throwable> @NotNull ThrowingSupplier throwing( + final @NonNull Supplier exceptionFactory + ) { + return () -> { + throw exceptionFactory.get(); + }; + } +} diff --git a/java-commons/src/main/java9/ru/progrm_jarvis/javacommons/util/UuidUtil.java b/java-commons/src/main/java9/ru/progrm_jarvis/javacommons/util/UuidUtil.java deleted file mode 100644 index c0224ce0..00000000 --- a/java-commons/src/main/java9/ru/progrm_jarvis/javacommons/util/UuidUtil.java +++ /dev/null @@ -1,64 +0,0 @@ -package ru.progrm_jarvis.javacommons.util; - -import lombok.NonNull; -import lombok.experimental.UtilityClass; -import org.jetbrains.annotations.NotNull; - -import java.lang.invoke.MethodHandles; -import java.lang.invoke.VarHandle; -import java.nio.ByteOrder; -import java.util.UUID; - -/** - * Utility for {@link UUID}-related functionality. - */ -@UtilityClass -public class UuidUtil { - - /** - * Amount of bytes from which the {@link UUID} consists. - */ - private final int UUID_BYTES = Long.BYTES << 1; - - /** - * VarHandle representing a {@code long[]}-view to a {@code byte[]} using {@link ByteOrder#BIG_ENDIAN big-endian}. - */ - private final @NotNull VarHandle BYTE_ARRAY_LONG_VIEW_BIG_ENDIAN - = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN); - - /** - * Converts {@link UUID} into an array of 16 {@code byte}s. - * - * @param uuid UUID to convert - * @return result of conversion as array of 16 bytes - * - * @see #uuidFromBytes(byte[]) for backward conversion - */ - public byte[] uuidToBytes(final @NonNull UUID uuid) { - // note: there is an Unsafe method for allocating a non-zeroed array, but it is hard to access it - final byte[] bytes; - BYTE_ARRAY_LONG_VIEW_BIG_ENDIAN.set(bytes = new byte[UUID_BYTES], 0, uuid.getMostSignificantBits()); - BYTE_ARRAY_LONG_VIEW_BIG_ENDIAN.set(bytes, Long.BYTES, uuid.getLeastSignificantBits()); - - return bytes; - } - - /** - * Converts a 16-{@code byte}s array into a {@link UUID}. - * - * @param bytes array of 16 bytes to convert - * @return result of conversion as UUID - * - * @see #uuidToBytes(UUID) for backward conversion - */ - public UUID uuidFromBytes(final byte @NonNull [] bytes) { - if (bytes.length != UUID_BYTES) throw new IllegalArgumentException( - "Length of bytes length should be " + UUID_BYTES - ); - - return new UUID( - (long) BYTE_ARRAY_LONG_VIEW_BIG_ENDIAN.get(bytes, 0), - (long) BYTE_ARRAY_LONG_VIEW_BIG_ENDIAN.get(bytes, Long.BYTES) - ); - } -} diff --git a/pom.xml b/pom.xml index 4127032b..23274c32 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ UTF-8 8 - 3.12.4 + 4.0.0 PADLA for Java @@ -83,14 +83,27 @@ 3.8.1 - java-9 + java-11 compile - 9 + 11 - ${project.basedir}/src/main/java9 + ${project.basedir}/src/main/java11 + + true + + + + java-17 + + compile + + + 17 + + ${project.basedir}/src/main/java17 true @@ -184,6 +197,15 @@ org.sonatype.plugins nexus-staging-maven-plugin 1.6.8 + true + + + + com.thoughtworks.xstream + xstream + 1.4.18 + + @@ -241,7 +263,7 @@ org.projectlombok lombok - 1.18.20 + 1.18.22 provided true diff --git a/tools/pom.xml b/tools/pom.xml index ba3d6bba..78c34e50 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -41,7 +41,7 @@ commons-cli commons-cli - 1.4 + 1.5.0 org.apache.velocity diff --git a/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/AbstractGeneratingTextModelFactoryBuilder.java b/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/AbstractGeneratingTextModelFactoryBuilder.java index 670905a9..a3b7d046 100644 --- a/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/AbstractGeneratingTextModelFactoryBuilder.java +++ b/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/AbstractGeneratingTextModelFactoryBuilder.java @@ -5,6 +5,7 @@ import lombok.experimental.NonFinal; import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Range; import java.util.ArrayList; import java.util.List; @@ -24,7 +25,7 @@ @FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) public abstract class AbstractGeneratingTextModelFactoryBuilder, - SN extends AbstractGeneratingTextModelFactoryBuilder.StaticNode, + SN extends AbstractGeneratingTextModelFactoryBuilder.StaticNode, DN extends AbstractGeneratingTextModelFactoryBuilder.DynamicNode> extends AbstractCachingTextModelFactoryBuilder { @@ -169,8 +170,7 @@ protected void endLastNodeModification() { /** * {@inheritDoc} - *

- * Attempts to create a fast implementation if there is no dynamic content in this text model builder. + *

Attempts to create a fast implementation if there is no dynamic content in this text model builder.

* * @param release {@inheritDoc} * @return {@inheritDoc} @@ -208,7 +208,7 @@ protected void endLastNodeModification() { * @param type of static node wrapped * @param type of dynamic node wrapped */ - protected interface Node, D extends DynamicNode> { + protected interface Node> { /** * Marker indicating whether this element is dynamic. @@ -241,12 +241,10 @@ protected interface Node, D extends DynamicNode> { /** * Static {@link Node node}. * - * @param type of object according to which the created text models are formatted - * * @apiNote this interface does not extend {@link Node} but it is a common practice to have a class implement both * in order to decrease the amount of allocated objects */ - protected interface StaticNode { + protected interface StaticNode { /** * Gets this element's static content. @@ -257,7 +255,12 @@ protected interface StaticNode { */ @NotNull String getText(); - int getTextLength(); + /** + * Gets the length of the static text's content. + * + * @return length of the static text's content + */ + @Range(from = 0, to = Integer.MAX_VALUE) int getTextLength(); /** * Appends a static element to this element's content. @@ -298,7 +301,7 @@ protected interface DynamicNode { @Value @RequiredArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE) - protected static class SimpleStaticNode implements Node, DynamicNode>, StaticNode { + protected static class SimpleStaticNode implements Node>, StaticNode { /** * Text of this node @@ -315,7 +318,7 @@ public boolean isDynamic() { } @Override - public @NotNull StaticNode asStatic() { + public @NotNull StaticNode asStatic() { return this; } @@ -325,7 +328,7 @@ public boolean isDynamic() { } @Override - public int getTextLength() { + public @Range(from = 0, to = Integer.MAX_VALUE) int getTextLength() { return text.length(); } @@ -347,7 +350,7 @@ public void appendText(final @NotNull String text) { */ @Value @FieldDefaults(level = AccessLevel.PRIVATE) - protected static class SimpleDynamicNode implements Node, DynamicNode>, DynamicNode { + protected static class SimpleDynamicNode implements Node>, DynamicNode { /** * Dynamic content of this node @@ -365,7 +368,7 @@ public boolean isDynamic() { } @Override - public @NotNull StaticNode asStatic() { + public @NotNull StaticNode asStatic() { throw new UnsupportedOperationException("This is not a static node"); } } diff --git a/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/AsmTextModelFactory.java b/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/AsmTextModelFactory.java index 3ccd26e1..ab7df2d6 100644 --- a/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/AsmTextModelFactory.java +++ b/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/AsmTextModelFactory.java @@ -5,10 +5,7 @@ import lombok.experimental.FieldDefaults; import lombok.experimental.NonFinal; import lombok.extern.java.Log; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; +import org.jetbrains.annotations.*; import org.objectweb.asm.*; import ru.progrm_jarvis.javacommons.annotation.Internal; import ru.progrm_jarvis.javacommons.bytecode.CommonBytecodeLibrary; @@ -1269,7 +1266,7 @@ private interface AsmNode * * @param type of object according to which the created text models are formatted */ - private interface StaticAsmNode extends AbstractGeneratingTextModelFactoryBuilder.StaticNode, AsmNode { + private interface StaticAsmNode extends AbstractGeneratingTextModelFactoryBuilder.StaticNode, AsmNode { /** * Checks if this node's text cannot be passed as a raw part @@ -1346,7 +1343,7 @@ public boolean isDynamic() { } @Override - public int getTextLength() { + public @Range(from = 0, to = Integer.MAX_VALUE) int getTextLength() { return text.length(); } diff --git a/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/JavassistTextModelFactory.java b/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/JavassistTextModelFactory.java index 025aca96..ebff9cf1 100644 --- a/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/JavassistTextModelFactory.java +++ b/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/format/model/JavassistTextModelFactory.java @@ -69,7 +69,7 @@ public final class JavassistTextModelFactory implements TextModelFactory { @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) protected static final class JavassistTextModelBuilder extends AbstractGeneratingTextModelFactoryBuilder< - T, Node, DynamicNode>, StaticNode, DynamicNode + T, Node>, StaticNode, DynamicNode > { /** @@ -78,12 +78,12 @@ protected static final class JavassistTextModelBuilder private static final @NotNull MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); @Override - protected @NotNull Node, DynamicNode> newStaticNode(final @NotNull String text) { + protected @NotNull Node> newStaticNode(final @NotNull String text) { return new SimpleStaticNode<>(text); } @Override - protected @NotNull Node, DynamicNode> newDynamicNode(final @NotNull TextModel content) { + protected @NotNull Node> newDynamicNode(final @NotNull TextModel content) { return new SimpleDynamicNode<>(content); } diff --git a/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/message/Message.java b/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/message/Message.java index 12b0b7fb..951aa0e8 100644 --- a/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/message/Message.java +++ b/ultimate-messenger/src/main/java/ru/progrm_jarvis/ultimatemessenger/message/Message.java @@ -34,7 +34,7 @@ public interface Message { * @param receivers receivers of the message */ @SuppressWarnings("unchecked") // generic vararg - default void send(@NotNull C context, @NotNull R... receivers) { + default void send(final @NotNull C context, final @NotNull R... receivers) { for (val receiver : receivers) send(context, receiver); } @@ -44,11 +44,17 @@ default void send(@NotNull C context, @NotNull R... receivers) { * @param context context of the message * @param receivers receivers of the message */ - default void send(@NotNull C context, @NotNull Iterator<@NotNull R> receivers) { + default void send(final @NotNull C context, final @NotNull Iterator<@NotNull R> receivers) { while (receivers.hasNext()) send(context, receivers.next()); } - default void send(@NotNull C context, @NotNull Spliterator<@NotNull R> receivers) { + /** + * Sends a message in the given context to each of the receivers. + * + * @param context context of the message + * @param receivers receivers of the message + */ + default void send(final @NotNull C context, final @NotNull Spliterator<@NotNull R> receivers) { receivers.forEachRemaining(receiver -> send(context, receiver)); } @@ -58,7 +64,7 @@ default void send(@NotNull C context, @NotNull Spliterator<@NotNull R> receivers * @param context context of the message * @param receivers receivers of the message */ - default void send(@NotNull C context, @NotNull Iterable<@NotNull R> receivers) { + default void send(final @NotNull C context, final @NotNull Iterable<@NotNull R> receivers) { for (val receiver : receivers) send(context, receiver); } @@ -68,7 +74,7 @@ default void send(@NotNull C context, @NotNull Iterable<@NotNull R> receivers) { * @param context context of the message * @param receivers receivers of the message */ - default void send(@NotNull C context, @NotNull Collection<@NotNull R> receivers) { + default void send(final @NotNull C context, final @NotNull Collection<@NotNull R> receivers) { for (val receiver : receivers) send(context, receiver); } @@ -78,7 +84,7 @@ default void send(@NotNull C context, @NotNull Collection<@NotNull R> receivers) * @param context context of the message * @param receivers receivers of the message */ - default void send(@NotNull C context, @NotNull List<@NotNull R> receivers) { + default void send(final @NotNull C context, final @NotNull List<@NotNull R> receivers) { for (val receiver : receivers) send(context, receiver); } }