From ed69383731aee22b0aef84265863c44099cd5c0b Mon Sep 17 00:00:00 2001 From: siujamo Date: Fri, 29 May 2026 16:31:55 +0800 Subject: [PATCH 1/6] build: bump versions to 3.4.0 for common-toolbox, crypto-toolbox and version-catalogue --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5209411..310f921 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,12 +21,12 @@ # artefactVersion=3.3.0 -commonToolboxVersion=3.3.0 +commonToolboxVersion=3.4.0 tupleVersion=3.3.0 identityGeneratorVersion=3.3.0 -cryptoToolboxVersion=3.3.0 +cryptoToolboxVersion=3.4.0 mathToolboxVersion=3.3.0 -versionCatalogueVersion=3.3.0 +versionCatalogueVersion=3.4.0 projectUrl=https://onixbyte.com/projects/onixbyte-toolbox projectGithubUrl=https://github.com/onixbyte/onixbyte-toolbox licenseName=MIT From 2b781baed96db264942d972d52eda846471596aa Mon Sep 17 00:00:00 2001 From: siujamo Date: Fri, 29 May 2026 16:53:48 +0800 Subject: [PATCH 2/6] build: bump versions to 3.4.0 for common-toolbox, crypto-toolbox and version-catalogue --- .github/workflows/github-packages-publish.yml | 2 +- common-toolbox/build.gradle.kts | 1 + crypto-toolbox/build.gradle.kts | 1 + identity-generator/build.gradle.kts | 1 + math-toolbox/build.gradle.kts | 1 + tuple/build.gradle.kts | 1 + version-catalogue/build.gradle.kts | 1 + 7 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/github-packages-publish.yml b/.github/workflows/github-packages-publish.yml index c083358..9894b8a 100644 --- a/.github/workflows/github-packages-publish.yml +++ b/.github/workflows/github-packages-publish.yml @@ -19,7 +19,7 @@ on: jobs: publish: name: Build and Publish - runs-on: ubuntu-latest + runs-on: self-hosted permissions: contents: read diff --git a/common-toolbox/build.gradle.kts b/common-toolbox/build.gradle.kts index 542f580..40f20e0 100644 --- a/common-toolbox/build.gradle.kts +++ b/common-toolbox/build.gradle.kts @@ -112,6 +112,7 @@ publishing { from(components["java"]) signing { + setRequired(project.hasProperty("signing.keyId")) sign(publishing.publications["commonToolbox"]) } } diff --git a/crypto-toolbox/build.gradle.kts b/crypto-toolbox/build.gradle.kts index ed4b40b..e7b7034 100644 --- a/crypto-toolbox/build.gradle.kts +++ b/crypto-toolbox/build.gradle.kts @@ -116,6 +116,7 @@ publishing { from(components["java"]) signing { + setRequired(project.hasProperty("signing.keyId")) sign(publishing.publications["cryptoToolbox"]) } } diff --git a/identity-generator/build.gradle.kts b/identity-generator/build.gradle.kts index d076fc5..1889597 100644 --- a/identity-generator/build.gradle.kts +++ b/identity-generator/build.gradle.kts @@ -112,6 +112,7 @@ publishing { from(components["java"]) signing { + setRequired(project.hasProperty("signing.keyId")) sign(publishing.publications["identityGenerator"]) } } diff --git a/math-toolbox/build.gradle.kts b/math-toolbox/build.gradle.kts index 3a44116..910e86b 100644 --- a/math-toolbox/build.gradle.kts +++ b/math-toolbox/build.gradle.kts @@ -113,6 +113,7 @@ publishing { from(components["java"]) signing { + setRequired(project.hasProperty("signing.keyId")) sign(publishing.publications["mathToolbox"]) } } diff --git a/tuple/build.gradle.kts b/tuple/build.gradle.kts index 870bd1a..ba5fdda 100644 --- a/tuple/build.gradle.kts +++ b/tuple/build.gradle.kts @@ -113,6 +113,7 @@ publishing { from(components["java"]) signing { + setRequired(project.hasProperty("signing.keyId")) sign(publishing.publications["tuple"]) } } diff --git a/version-catalogue/build.gradle.kts b/version-catalogue/build.gradle.kts index 90f945b..9e90dde 100644 --- a/version-catalogue/build.gradle.kts +++ b/version-catalogue/build.gradle.kts @@ -100,6 +100,7 @@ publishing { from(components["javaPlatform"]) signing { + setRequired(project.hasProperty("signing.keyId")) sign(publishing.publications["versionCatalogue"]) } } From 7e1b7cae85cd9a47b7945595924b66846b597a8d Mon Sep 17 00:00:00 2001 From: siujamo Date: Tue, 2 Jun 2026 13:19:27 +0800 Subject: [PATCH 3/6] refactor: split tuple module to repo onixbyte/onixbyte-tuple --- settings.gradle.kts | 1 - tuple/README.md | 74 -------- tuple/build.gradle.kts | 132 -------------- .../com/onixbyte/tuple/ImmutableTriple.java | 62 ------- .../com/onixbyte/tuple/ImmutableTuple.java | 57 ------ .../main/java/com/onixbyte/tuple/Triple.java | 168 ------------------ .../main/java/com/onixbyte/tuple/Tuple.java | 149 ---------------- 7 files changed, 643 deletions(-) delete mode 100644 tuple/README.md delete mode 100644 tuple/build.gradle.kts delete mode 100644 tuple/src/main/java/com/onixbyte/tuple/ImmutableTriple.java delete mode 100644 tuple/src/main/java/com/onixbyte/tuple/ImmutableTuple.java delete mode 100644 tuple/src/main/java/com/onixbyte/tuple/Triple.java delete mode 100644 tuple/src/main/java/com/onixbyte/tuple/Tuple.java diff --git a/settings.gradle.kts b/settings.gradle.kts index 92c83e6..c64a8fd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,7 +24,6 @@ rootProject.name = "onixbyte-toolbox" include("version-catalogue") include("common-toolbox") -include("tuple") include("identity-generator") include("crypto-toolbox") include("math-toolbox") diff --git a/tuple/README.md b/tuple/README.md deleted file mode 100644 index b0eb7d1..0000000 --- a/tuple/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# Tuple - -## Introduction - -The `tuple` module provides simple and efficient implementations of mutable and immutable bi-tuples and tri-tuples. These tuples allow you to group two or three values together without creating custom classes, supporting convenient usage in various programming scenarios. - -## Features - -- Immutable and mutable versions of bi-tuples (pairs) and tri-tuples (triplets); -- Factory method of() for easy instantiation of all tuple types; -- Simple, lightweight implementation compatible with standard Java usage; -- Clear distinction between mutable and immutable tuples for flexibility. - -## Installation - -### Maven - -Add the following dependency to your `pom.xml`: - -```xml - - com.onixbyte - tuple - $artefactVersion - -``` - -### Gradle - -#### Version Catalogue - -Add the following codes to you `gradle/libs.versions.toml`: - -```toml -[version] -onixbyteToolbox = "$artefactVersion" - -[libraries] -onixbyteToolbox-tuple = { group = "com.onixbyte", name = "tuple", version.ref = "onixbyteToolbox" } -``` - -Then add the following codes to your `build.gradle.kts` or `build.gradle` dependencies block: - -```kotlin -implementation(libs.onixbyteToolbox.tuple) -``` - -```groovy -implementation libs.onixbyteToolbox.tuple -``` - -#### Kotlin DSL - -Add the following line to your `build.gradle.kts` dependencies block: - -```kotlin -implementation("com.onixbyte:tuple:$artefactVersion") -``` - -#### Groovy DSL - -Add the following line to your `build.gradle` dependencies block: - -```groovy -implementation 'com.onixbyte:tuple:${artefactVersion}' -``` - -## Dependencies - -This module has no external dependencies other than the standard Java SDK. - -## Acknowledgement - -Thanks to all contributors who helped develop this module, improving its design, performance, and documentation over time. diff --git a/tuple/build.gradle.kts b/tuple/build.gradle.kts deleted file mode 100644 index ba5fdda..0000000 --- a/tuple/build.gradle.kts +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import java.net.URI - -plugins { - java - id("java-library") - id("maven-publish") - id("signing") -} - -val tupleVersion: String by project - -version = tupleVersion -val projectUrl: String by project -val projectGithubUrl: String by project -val licenseName: String by project -val licenseUrl: String by project - -repositories { - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - withSourcesJar() - withJavadocJar() -} - -tasks.withType { - options.encoding = "UTF-8" -} - -tasks.withType { - exclude("logback.xml") -} - -dependencies { - compileOnly(libs.slf4j) - implementation(libs.logback) - testImplementation(platform(libs.junit.bom)) - testImplementation(libs.junit.jupiter) -} - -tasks.test { - useJUnitPlatform() -} - -publishing { - publications { - create("tuple") { - groupId = group.toString() - artifactId = "tuple" - version = tupleVersion - - pom { - name = "OnixByte Tuple" - description = - "The tuple module is designed to offer a convenient and efficient way to handle grouped data." - url = projectUrl - - licenses { - license { - name = licenseName - url = licenseUrl - } - } - - scm { - connection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - developerConnection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - url = projectGithubUrl - } - - developers { - developer { - id = "zihluwang" - name = "Zihlu Wang" - email = "really@zihlu.wang" - timezone = "Asia/Hong_Kong" - } - - developer { - id = "siujamo" - name = "Siu Jam'o" - email = "jamo.siu@outlook.com" - timezone = "Asia/Shanghai" - } - } - } - - from(components["java"]) - - signing { - setRequired(project.hasProperty("signing.keyId")) - sign(publishing.publications["tuple"]) - } - } - - repositories { - maven { - name = "sonatypeNexus" - url = URI(providers.gradleProperty("repo.maven-central.host").get()) - credentials { - username = providers.gradleProperty("repo.maven-central.username").get() - password = providers.gradleProperty("repo.maven-central.password").get() - } - } - } - } -} diff --git a/tuple/src/main/java/com/onixbyte/tuple/ImmutableTriple.java b/tuple/src/main/java/com/onixbyte/tuple/ImmutableTriple.java deleted file mode 100644 index 26d43ac..0000000 --- a/tuple/src/main/java/com/onixbyte/tuple/ImmutableTriple.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.tuple; - -/** - * Represents an immutable triple of three elements, referred to as 'left', 'middle', and 'right'. - * This class provides a generic way to group three values without the need to create a custom class - * for each specific combination. - *

- * The generic types {@code L}, {@code M}, and {@code R} denote the types of the left, middle, and - * right elements, respectively. Instances of this class are immutable once created. - * - * @param the type of the left element - * @param the type of the middle element - * @param the type of the right element - * @param left the left element of this triple - * @param middle the middle element of this triple - * @param right the right element of this triple - * @author siujamo - * @author zihluwang - */ -public record ImmutableTriple( - L left, - M middle, - R right -) { - - /** - * Creates a new {@code ImmutableTriple} with the specified left, middle, and right elements. - * - * @param the type of the left element - * @param the type of the middle element - * @param the type of the right element - * @param left the left element - * @param middle the middle element - * @param right the right element - * @return a new {@code ImmutableTriple} containing the specified elements - */ - public static ImmutableTriple of(L left, M middle, R right) { - return new ImmutableTriple<>(left, middle, right); - } -} diff --git a/tuple/src/main/java/com/onixbyte/tuple/ImmutableTuple.java b/tuple/src/main/java/com/onixbyte/tuple/ImmutableTuple.java deleted file mode 100644 index 6e31e46..0000000 --- a/tuple/src/main/java/com/onixbyte/tuple/ImmutableTuple.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.tuple; - -/** - * Represents an immutable pair of two elements, referred to as 'left' and 'right'. This class - * provides a simple way to group two values without the need to create a custom class for each - * specific pair. - *

- * The generic types {@code L} and {@code R} denote the types of the left and right elements, - * respectively. Instances of this class are immutable once created. - * - * @param the type of the left element - * @param the type of the right element - * @param left the left element of this tuple - * @param right the right element of this tuple - * @author siujamo - * @author zihluwang - */ -public record ImmutableTuple( - L left, - R right -) { - - /** - * Creates a new {@code ImmutableTuple} with the specified left and right elements. - * - * @param the type of the left element - * @param the type of the right element - * @param left the left element - * @param right the right element - * @return a new {@code ImmutableTuple} containing the specified elements - */ - public static ImmutableTuple of(L left, R right) { - return new ImmutableTuple<>(left, right); - } -} diff --git a/tuple/src/main/java/com/onixbyte/tuple/Triple.java b/tuple/src/main/java/com/onixbyte/tuple/Triple.java deleted file mode 100644 index 531e196..0000000 --- a/tuple/src/main/java/com/onixbyte/tuple/Triple.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.tuple; - -import java.util.Objects; - -/** - * Represents a mutable triple of three elements, referred to as 'left', 'middle' and 'right'. - * This class provides a way to group three values of different types. - *

- * The generic types {@code L}, {@code M} and {@code R} denote the types of the left, middle and - * right elements respectively. - * - * @param the type of the left element - * @param the type of the middle element - * @param the type of the right element - * @author siujamo - * @author zihluwang - */ -public final class Triple { - - private L left; - private M middle; - private R right; - - /** - * Constructs a new {@code Triple} with the given left, middle and right elements. - * - * @param left the left element - * @param middle the middle element - * @param right the right element - */ - public Triple(L left, M middle, R right) { - this.left = left; - this.middle = middle; - this.right = right; - } - - /** - * Retrieves the left element of the triple. - * - * @return the left element - */ - public L getLeft() { - return left; - } - - /** - * Sets the left element of the triple. - * - * @param left the new left element - */ - public void setLeft(L left) { - this.left = left; - } - - /** - * Retrieves the middle element of the triple. - * - * @return the middle element - */ - public M getMiddle() { - return middle; - } - - /** - * Sets the middle element of the triple. - * - * @param middle the new middle element - */ - public void setMiddle(M middle) { - this.middle = middle; - } - - /** - * Retrieves the right element of the triple. - * - * @return the right element - */ - public R getRight() { - return right; - } - - /** - * Sets the right element of the triple. - * - * @param right the new right element - */ - public void setRight(R right) { - this.right = right; - } - - /** - * Checks if this {@code Triple} is equal to the specified object. Two {@code Triple}s are - * considered equal if their left, middle and right elements are equal. - * - * @param object the object to compare with - * @return {@code true} if the objects are equal, {@code false} otherwise - */ - @Override - public boolean equals(Object object) { - if (!(object instanceof Triple triple)) return false; - return Objects.equals(left, triple.left) && - Objects.equals(middle, triple.middle) && - Objects.equals(right, triple.right); - } - - /** - * Calculates the hash code for this {@code Triple} based on its left, middle and - * right elements. - * - * @return the hash code value for this object - */ - @Override - public int hashCode() { - return Objects.hash(left, middle, right); - } - - /** - * Returns a string representation of this {@code Triple}, including its left, middle and - * right elements. - * - * @return a string representation of the object - */ - @Override - public String toString() { - return "Triple{" + - "left=" + left + - ", middle=" + middle + - ", right=" + right + - '}'; - } - - /** - * Factory method to create a new {@code Triple} instance with the given left, middle and right elements. - * - * @param left the left element - * @param middle the middle element - * @param right the right element - * @param the type of the left element - * @param the type of the middle element - * @param the type of the right element - * @return a new {@code Triple} instance - */ - public static Triple of(L left, M middle, R right) { - return new Triple<>(left, middle, right); - } -} diff --git a/tuple/src/main/java/com/onixbyte/tuple/Tuple.java b/tuple/src/main/java/com/onixbyte/tuple/Tuple.java deleted file mode 100644 index 9763941..0000000 --- a/tuple/src/main/java/com/onixbyte/tuple/Tuple.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.tuple; - -import java.util.Objects; - -/** - * Represents an ordered pair of elements, where the first element is of type {@code L} and the - * second is of type {@code R}. This class provides a simple way to group two related - * values together. - *

- * The class is mutable, allowing the values of the left and right elements to be changed - * after creation. It also overrides the {@code equals}, {@code hashCode}, and {@code toString} - * methods to provide meaningful comparisons and string representations. - * - * @param the type of the left element - * @param the type of the right element - * @author siujamo - * @author zihluwang - */ -public final class Tuple { - - private L left; - private R right; - - /** - * Constructs a new {@code Tuple} with the specified left and right elements. - * - * @param left the left element to be stored in the tuple - * @param right the right element to be stored in the tuple - */ - public Tuple(L left, R right) { - this.left = left; - this.right = right; - } - - /** - * Retrieves the left element of the tuple. - * - * @return the left element of the tuple - */ - public L getLeft() { - return left; - } - - /** - * Sets the left element of the tuple to the specified value. - * - * @param left the new value for the left element of the tuple - */ - public void setLeft(L left) { - this.left = left; - } - - /** - * Retrieves the right element of the tuple. - * - * @return the right element of the tuple - */ - public R getRight() { - return right; - } - - /** - * Sets the right element of the tuple to the specified value. - * - * @param right the new value for the right element of the tuple - */ - public void setRight(R right) { - this.right = right; - } - - /** - * Compares this {@code Tuple} with the specified object for equality. - *

- * Two {@code Tuple}s are considered equal if they are of the same type and their left and - * right elements are equal according to their respective {@code equals} methods. - * - * @param object the object to compare with this {@code Tuple} - * @return {@code true} if the specified object is equal to this {@code Tuple}, - * {@code false} otherwise - */ - @Override - public boolean equals(Object object) { - if (!(object instanceof Tuple tuple)) return false; - return Objects.equals(left, tuple.left) && Objects.equals(right, tuple.right); - } - - /** - * Returns a hash code value for the {@code Tuple}. - *

- * The hash code is calculated based on the hash codes of the left and right elements. - * - * @return a hash code value for this {@code Tuple} - */ - @Override - public int hashCode() { - return Objects.hash(left, right); - } - - /** - * Returns a string representation of the {@code Tuple}. - *

- * The string representation consists of the class name, followed by the values of - * the left and right elements in the format {@code "Tuple{left=value1, right=value2}"}. - * - * @return a string representation of the {@code Tuple} - */ - @Override - public String toString() { - return "Tuple{" + - "left=" + left + - ", right=" + right + - '}'; - } - - /** - * Creates a new {@code Tuple} with the specified left and right elements. - * - * @param the type of the left element - * @param the type of the right element - * @param left the left element - * @param right the right element - * @return a new {@code Tuple} containing the specified elements - */ - public static Tuple of(L left, R right) { - return new Tuple<>(left, right); - } -} From 80bec17c7d82ed71119b0d0eb2b4c3f1fca75874 Mon Sep 17 00:00:00 2001 From: siujamo Date: Tue, 2 Jun 2026 13:42:43 +0800 Subject: [PATCH 4/6] refactor: split modules to separate repos --- README.md | 69 ++-- build.gradle.kts | 98 ++++- common-toolbox/README.md | 17 - common-toolbox/build.gradle.kts | 131 ------ .../common/adapter/ObjectMapAdapter.java | 85 ---- .../com/onixbyte/common/util/AesUtil.java | 206 ---------- .../com/onixbyte/common/util/Base64Util.java | 212 ---------- .../com/onixbyte/common/util/BoolUtil.java | 102 ----- .../com/onixbyte/common/util/BranchUtil.java | 213 ---------- .../onixbyte/common/util/CollectionUtil.java | 135 ------- .../com/onixbyte/common/util/MapUtil.java | 121 ------ .../com/onixbyte/common/util/RangeUtil.java | 207 ---------- common-toolbox/src/main/resources/logback.xml | 39 -- .../com/onixbyte/common/util/AesUtilTest.java | 79 ---- .../onixbyte/common/util/Base64UtilTest.java | 100 ----- .../onixbyte/common/util/BoolUtilTest.java | 137 ------- .../onixbyte/common/util/BranchUtilTest.java | 161 -------- .../common/util/CollectionUtilTest.java | 112 ----- .../onixbyte/common/util/RangeUtilTest.java | 131 ------ crypto-toolbox/README.md | 113 ------ crypto-toolbox/build.gradle.kts | 135 ------- .../com/onixbyte/crypto/PrivateKeyLoader.java | 44 -- .../com/onixbyte/crypto/PublicKeyLoader.java | 83 ---- .../algorithm/ecdsa/ECPrivateKeyLoader.java | 95 ----- .../algorithm/ecdsa/ECPublicKeyLoader.java | 159 -------- .../algorithm/rsa/RSAPrivateKeyLoader.java | 107 ----- .../algorithm/rsa/RSAPublicKeyLoader.java | 142 ------- .../crypto/exception/KeyLoadingException.java | 100 ----- .../com/onixbyte/crypto/util/CryptoUtil.java | 98 ----- .../onixbyte/crypto/util/EncodingUtil.java | 53 --- .../com/onixbyte/crypto/util/HashUtil.java | 270 ------------- crypto-toolbox/src/main/resources/logback.xml | 39 -- .../src/test/resources/ec_private_key.pem | 5 - .../src/test/resources/ec_public_key.pem | 4 - .../src/test/resources/rsa_private_key.pem | 28 -- .../src/test/resources/rsa_public_key.pem | 9 - identity-generator/README.md | 38 -- identity-generator/build.gradle.kts | 131 ------ .../identitygenerator/IdentityGenerator.java | 65 --- .../exceptions/TimingException.java | 74 ---- .../impl/SequentialUuidGenerator.java | 95 ----- .../impl/SnowflakeIdentityGenerator.java | 207 ---------- .../src/main/resources/logback.xml | 39 -- math-toolbox/README.md | 4 - math-toolbox/build.gradle.kts | 132 ------ .../java/com/onixbyte/math/Calculator.java | 381 ------------------ .../onixbyte/math/PercentileCalculator.java | 120 ------ .../onixbyte/math/model/QuartileBounds.java | 136 ------- math-toolbox/src/main/resources/logback.xml | 39 -- 49 files changed, 132 insertions(+), 5168 deletions(-) delete mode 100644 common-toolbox/README.md delete mode 100644 common-toolbox/build.gradle.kts delete mode 100644 common-toolbox/src/main/java/com/onixbyte/common/adapter/ObjectMapAdapter.java delete mode 100644 common-toolbox/src/main/java/com/onixbyte/common/util/AesUtil.java delete mode 100644 common-toolbox/src/main/java/com/onixbyte/common/util/Base64Util.java delete mode 100644 common-toolbox/src/main/java/com/onixbyte/common/util/BoolUtil.java delete mode 100644 common-toolbox/src/main/java/com/onixbyte/common/util/BranchUtil.java delete mode 100644 common-toolbox/src/main/java/com/onixbyte/common/util/CollectionUtil.java delete mode 100644 common-toolbox/src/main/java/com/onixbyte/common/util/MapUtil.java delete mode 100644 common-toolbox/src/main/java/com/onixbyte/common/util/RangeUtil.java delete mode 100644 common-toolbox/src/main/resources/logback.xml delete mode 100644 common-toolbox/src/test/java/com/onixbyte/common/util/AesUtilTest.java delete mode 100644 common-toolbox/src/test/java/com/onixbyte/common/util/Base64UtilTest.java delete mode 100644 common-toolbox/src/test/java/com/onixbyte/common/util/BoolUtilTest.java delete mode 100644 common-toolbox/src/test/java/com/onixbyte/common/util/BranchUtilTest.java delete mode 100644 common-toolbox/src/test/java/com/onixbyte/common/util/CollectionUtilTest.java delete mode 100644 common-toolbox/src/test/java/com/onixbyte/common/util/RangeUtilTest.java delete mode 100644 crypto-toolbox/README.md delete mode 100644 crypto-toolbox/build.gradle.kts delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/PrivateKeyLoader.java delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/PublicKeyLoader.java delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/ecdsa/ECPrivateKeyLoader.java delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/ecdsa/ECPublicKeyLoader.java delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/rsa/RSAPrivateKeyLoader.java delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/rsa/RSAPublicKeyLoader.java delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/exception/KeyLoadingException.java delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/util/CryptoUtil.java delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/util/EncodingUtil.java delete mode 100644 crypto-toolbox/src/main/java/com/onixbyte/crypto/util/HashUtil.java delete mode 100644 crypto-toolbox/src/main/resources/logback.xml delete mode 100644 crypto-toolbox/src/test/resources/ec_private_key.pem delete mode 100644 crypto-toolbox/src/test/resources/ec_public_key.pem delete mode 100644 crypto-toolbox/src/test/resources/rsa_private_key.pem delete mode 100644 crypto-toolbox/src/test/resources/rsa_public_key.pem delete mode 100644 identity-generator/README.md delete mode 100644 identity-generator/build.gradle.kts delete mode 100644 identity-generator/src/main/java/com/onixbyte/identitygenerator/IdentityGenerator.java delete mode 100644 identity-generator/src/main/java/com/onixbyte/identitygenerator/exceptions/TimingException.java delete mode 100644 identity-generator/src/main/java/com/onixbyte/identitygenerator/impl/SequentialUuidGenerator.java delete mode 100644 identity-generator/src/main/java/com/onixbyte/identitygenerator/impl/SnowflakeIdentityGenerator.java delete mode 100644 identity-generator/src/main/resources/logback.xml delete mode 100644 math-toolbox/README.md delete mode 100644 math-toolbox/build.gradle.kts delete mode 100644 math-toolbox/src/main/java/com/onixbyte/math/Calculator.java delete mode 100644 math-toolbox/src/main/java/com/onixbyte/math/PercentileCalculator.java delete mode 100644 math-toolbox/src/main/java/com/onixbyte/math/model/QuartileBounds.java delete mode 100644 math-toolbox/src/main/resources/logback.xml diff --git a/README.md b/README.md index 223f77b..c6e4105 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,49 @@ -# OnixByte Toolbox +# Version Catalogue -![Static Badge](https://img.shields.io/badge/dynamic/xml?url=https%3A%2F%2Frepo1.maven.org%2Fmaven2%2Fcom%2Fonixbyte%2Fversion-catalogue%2Fmaven-metadata.xml&query=%2F%2Fmetadata%2Fversioning%2Flatest&label=version) -![Static Badge](https://img.shields.io/badge/licence-MIT-green) -![Static Badge](https://img.shields.io/badge/java-%E2%89%A517-blue) +The **Version Catalogue** (Bill of Materials) is a Maven POM file provided by OnixByte to manage +dependency versions for the **OnixByte Toolbox**. By incorporating this BOM into your build +configuration, you can ensure consistent versioning across all included dependencies without +needing to specify versions explicitly in your project files. Published with Gradle metadata, +this BOM supports both Maven and Gradle projects, and this document outlines how to integrate +and use it effectively in both ecosystems. +## Using in Maven -OnixByte Toolbox is a Java Development Kit that offers a set of convenient tools for writing code efficiently. +Add the `version-catalogue` to your `pom.xml` under ``: -## Installation and Usage - -If you are using **Maven**, please paste the following codes to _pom.xml_ in your project. - -```xml - - com.onixbyte - ${artifactId} - ${version} - +```xml + + + + com.onixbyte + version-catalogue + 3.0.0 + pom + import + + + ``` -If you are using **Gradle**, please paste the following codes to _buile.gradle\[.kts\]_ in your project. +Then reference any dependency built by OnixByte without a version. + +## Using in Gradle + +In your `build.gradle[.kts]`, apply the BOM using the `platform` dependency: ```groovy -implementation 'com.onixbyte:$artifactId:$version' +dependencies { + implementation platform('com.onixbyte:version-catalogue:3.0.0') + implementation 'com.onixbyte:common-toolbox' +} ``` +If you are using Kotlin DSL: + ```kotlin -implementation("com.onixbyte:$artifactId:$version") +dependencies { + implementation(platform("com.onixbyte:version-catalogue:3.0.0")) + implementation("com.onixbyte:common-toolbox") +} ``` -If you want to check the available versions, please check out at our [official site](https://codecrafters.org.cn/devkit/changelog). - -## Contribution - -Contributions are welcome! If you encounter any issues or want to contribute to the project, please feel free to **[raise an issue](https://github.com/CodeCraftersCN/jdevkit/issues/new)** or **[submit a pull request](https://github.com/CodeCraftersCN/jdevkit/compare)**. - -## License - -This project is licensed under the [MIT](/LICENSE). - -## Contact - -If you have any suggestions, ideas, don't hesitate contacting us via [GitHub Issues](https://github.com/CodeCraftersCN/jdevkit/issues/new) or [Discord Community](https://discord.gg/NQK9tjcBB8). - -If you face any bugs while using our library and you are able to fix any bugs in our library, we would be happy to accept pull requests from you on [GitHub](https://github.com/CodeCraftersCN/jdevkit/compare). diff --git a/build.gradle.kts b/build.gradle.kts index 6449daa..9e90dde 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,6 +20,100 @@ * SOFTWARE. */ -subprojects { - group = "com.onixbyte" +import java.net.URI + +plugins { + id("java-platform") + id("maven-publish") + id("signing") +} + +val commonToolboxVersion: String by project +val identityGeneratorVersion: String by project +val cryptoToolboxVersion: String by project +val mathToolboxVersion: String by project +val tupleVersion: String by project +val versionCatalogueVersion: String by project + +version = versionCatalogueVersion +val projectUrl: String by project +val projectGithubUrl: String by project +val licenseName: String by project +val licenseUrl: String by project + +repositories { + mavenCentral() +} + +dependencies { + constraints { + api("com.onixbyte:common-toolbox:$commonToolboxVersion") + api("com.onixbyte:identity-generator:$identityGeneratorVersion") + api("com.onixbyte:crypto-toolbox:$cryptoToolboxVersion") + api("com.onixbyte:math-toolbox:$mathToolboxVersion") + api("com.onixbyte:tuple:$tupleVersion") + } +} + +publishing { + publications { + create("versionCatalogue") { + groupId = group.toString() + artifactId = "version-catalogue" + version = versionCatalogueVersion + + pom { + name = "OnixByte Version Catalogue" + description = "OnixByte DevKit BOM is designed to manage dependency versions centrally." + url = projectUrl + + licenses { + license { + name = licenseName + url = licenseUrl + } + } + + scm { + connection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" + developerConnection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" + url = projectGithubUrl + } + + developers { + developer { + id = "zihluwang" + name = "Zihlu Wang" + email = "really@zihlu.wang" + timezone = "Asia/Hong_Kong" + } + + developer { + id = "siujamo" + name = "Siu Jam'o" + email = "jamo.siu@outlook.com" + timezone = "Asia/Shanghai" + } + } + } + + from(components["javaPlatform"]) + + signing { + setRequired(project.hasProperty("signing.keyId")) + sign(publishing.publications["versionCatalogue"]) + } + } + + repositories { + maven { + name = "sonatypeNexus" + url = URI(providers.gradleProperty("repo.maven-central.host").get()) + credentials { + username = providers.gradleProperty("repo.maven-central.username").get() + password = providers.gradleProperty("repo.maven-central.password").get() + } + } + } + } } diff --git a/common-toolbox/README.md b/common-toolbox/README.md deleted file mode 100644 index 46be06b..0000000 --- a/common-toolbox/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Common Toolbox - -## Introduction - -Common Toolbox is a Java SE utility library, that provides a collection of utility to streamline -your Java coding experience. - -## Features - -- AES encryption and decryption; -- Base64 encode and decode; -- Boolean calculation; -- Reduce `if...else...` with **lambdas**; -- Hash calculation for strings; -- Convert Java beans to map and map to Java beans; -- Simplified range generator. - diff --git a/common-toolbox/build.gradle.kts b/common-toolbox/build.gradle.kts deleted file mode 100644 index 40f20e0..0000000 --- a/common-toolbox/build.gradle.kts +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import java.net.URI - -plugins { - java - id("java-library") - id("maven-publish") - id("signing") -} - -val commonToolboxVersion: String by project - -version = commonToolboxVersion -val projectUrl: String by project -val projectGithubUrl: String by project -val licenseName: String by project -val licenseUrl: String by project - -repositories { - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - withSourcesJar() - withJavadocJar() -} - -tasks.withType { - options.encoding = "UTF-8" -} - -tasks.withType { - exclude("logback.xml") -} - -dependencies { - compileOnly(libs.slf4j) - implementation(libs.logback) - testImplementation(platform(libs.junit.bom)) - testImplementation(libs.junit.jupiter) -} - -tasks.test { - useJUnitPlatform() -} - -publishing { - publications { - create("commonToolbox") { - groupId = group.toString() - artifactId = "common-toolbox" - version = commonToolboxVersion - - pom { - name = "OnixByte Common Toolbox" - description = "The utils module of OnixByte toolbox." - url = projectUrl - - licenses { - license { - name = licenseName - url = licenseUrl - } - } - - scm { - connection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - developerConnection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - url = projectGithubUrl - } - - developers { - developer { - id = "zihluwang" - name = "Zihlu Wang" - email = "really@zihlu.wang" - timezone = "Asia/Hong_Kong" - } - - developer { - id = "siujamo" - name = "Siu Jam'o" - email = "jamo.siu@outlook.com" - timezone = "Asia/Shanghai" - } - } - } - - from(components["java"]) - - signing { - setRequired(project.hasProperty("signing.keyId")) - sign(publishing.publications["commonToolbox"]) - } - } - - repositories { - maven { - name = "sonatypeNexus" - url = URI(providers.gradleProperty("repo.maven-central.host").get()) - credentials { - username = providers.gradleProperty("repo.maven-central.username").get() - password = providers.gradleProperty("repo.maven-central.password").get() - } - } - } - } -} diff --git a/common-toolbox/src/main/java/com/onixbyte/common/adapter/ObjectMapAdapter.java b/common-toolbox/src/main/java/com/onixbyte/common/adapter/ObjectMapAdapter.java deleted file mode 100644 index 561e8b6..0000000 --- a/common-toolbox/src/main/java/com/onixbyte/common/adapter/ObjectMapAdapter.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.common.adapter; - -import java.util.Map; - -/** - * The {@link ObjectMapAdapter} interface provides methods to convert between objects and maps. - * This interface is useful for scenarios where objects need to be represented as maps for - * serialization, deserialization, or other purposes. - * - *

Implementations of this interface should provide the logic to convert an object of type - * {@code T} to a {@link Map} and vice versa.

- * - *

Example usage:

- *
{@code
- * public class User {
- *     private String name;
- *     private int age;
- *     
- *     // getters and setters
- * }
- * 
- * public class UserMapAdapter implements ObjectMapAdapter {
- *     @Override
- *     public Map toMap(User user) {
- *         Map map = new HashMap<>();
- *         map.put("name", user.getName());
- *         map.put("age", user.getAge());
- *         return map;
- *     }
- * 
- *     @Override
- *     public User fromMap(Map map) {
- *         User user = new User();
- *         user.setName((String) map.get("name"));
- *         user.setAge((Integer) map.get("age"));
- *         return user;
- *     }
- * }
- * }
- * - * @param the type of the object to be converted - * @author zihluwang - * @version 3.0.0 - */ -public interface ObjectMapAdapter { - - /** - * Convert an object to a map. - * - * @param element the element that will be converted to Map - * @return a Map that is converted from the element - */ - Map toMap(T element); - - /** - * Convert a Map to an object. - * - * @param map the map that will be converted to an object - * @return the object that is converted from the Map - */ - T toObject(Map map); - -} diff --git a/common-toolbox/src/main/java/com/onixbyte/common/util/AesUtil.java b/common-toolbox/src/main/java/com/onixbyte/common/util/AesUtil.java deleted file mode 100644 index e62b86a..0000000 --- a/common-toolbox/src/main/java/com/onixbyte/common/util/AesUtil.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.common.util; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; -import java.util.Base64; -import java.util.UUID; - -/** - * The {@link AesUtil} class provides utility methods for encrypting and decrypting data using the - * AES algorithm. This class supports both byte array and string data, and uses a specified secret - * key for encryption and decryption. - *

- * The utility methods in this class are useful for scenarios where data needs to be securely - * encrypted and decrypted. - *

- * - *

Example usage:

- *
{@code
- * // Encrypting and decrypting byte array data
- * byte[] secretKey = "43f72073956d4c81".getBytes(StandardCharsets.UTF_8);
- * byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8);
- * byte[] encryptedData = AesUtil.encrypt(data, secretKey);
- * byte[] decryptedData = AesUtil.decrypt(encryptedData, secretKey);
- * System.out.println(new String(decryptedData, StandardCharsets.UTF_8)); // Output: Hello World
- *
- * // Encrypting and decrypting string data
- * String secret = "43f72073956d4c81";
- * String encryptedString = AesUtil.encrypt("Hello World", secret);
- * String decryptedString = AesUtil.decrypt(encryptedString, secret);
- * System.out.println(decryptedString); // Output: Hello World
- *
- * // Generating a random secret key
- * String randomSecret = AesUtil.generateRandomSecret();
- * System.out.println(randomSecret); // Output: A randomly generated 16-character long secret
- * }
- * - * @author hubin - * @version 3.0.0 - */ -public final class AesUtil { - - /** - * The algorithm AES. - */ - private static final String AES = "AES"; - - /** - * The algorithm AES/CBC/PKCS5Padding. - */ - private static final String AES_CBC_CIPHER = "AES/CBC/PKCS5Padding"; - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private AesUtil() { - } - - /** - * Encrypts the specified data using the AES algorithm with the provided secret key. - * - * @param data the data to be encrypted - * @param secret the secret key used for encryption - * @param ivParam the iv param - * @return the encrypted data as a byte array - * @throws GeneralSecurityException if any cryptographic error occurs during encryption - */ - public static byte[] encrypt(byte[] data, byte[] secret, byte[] ivParam) throws GeneralSecurityException { - var secretKeySpec = new SecretKeySpec(new SecretKeySpec(secret, AES).getEncoded(), AES); - var cipher = Cipher.getInstance(AES_CBC_CIPHER); - cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(ivParam)); - return cipher.doFinal(data); - } - - /** - * Encrypts the specified data using the AES algorithm with the provided secret key. - * - * @param data the data to be encrypted - * @param secret the secret key used for encryption - * @return the encrypted data as a byte array - * @throws GeneralSecurityException if any cryptographic error occurs during encryption - */ - public static byte[] encrypt(byte[] data, byte[] secret) throws GeneralSecurityException { - return encrypt(data, secret, secret); - } - - /** - * Decrypts the specified data using the AES algorithm with the provided secret key. - * - * @param data the data to be decrypted - * @param secret the secret key used for decryption - * @param ivParam the iv param - * @return the decrypted data as a byte array - * @throws GeneralSecurityException if any cryptographic error occurs during decryption - */ - public static byte[] decrypt(byte[] data, byte[] secret, byte[] ivParam) throws GeneralSecurityException { - var secretKeySpec = new SecretKeySpec(new SecretKeySpec(secret, AES).getEncoded(), AES); - var cipher = Cipher.getInstance(AES_CBC_CIPHER); - cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(ivParam)); - return cipher.doFinal(data); - } - - /** - * Decrypts the specified data using the AES algorithm with the provided secret key. - * - * @param data the data to be decrypted - * @param secret the secret key used for decryption - * @return the decrypted data as a byte array - * @throws GeneralSecurityException if any cryptographic error occurs during decryption - */ - public static byte[] decrypt(byte[] data, byte[] secret) throws GeneralSecurityException { - return decrypt(data, secret, secret); - } - - /** - * Encrypts the specified string data using the AES algorithm with the provided secret key. - * - * @param data the string data to be encrypted - * @param secret the secret key used for encryption - * @param ivParam the iv param - * @return the encrypted data encoded in Base64 - * @throws GeneralSecurityException if any cryptographic error occurs during encryption - */ - public static String encrypt(String data, String secret, String ivParam) throws GeneralSecurityException { - return Base64.getEncoder().encodeToString(encrypt( - data.getBytes(StandardCharsets.UTF_8), - secret.getBytes(StandardCharsets.UTF_8), - ivParam.getBytes(StandardCharsets.UTF_8) - )); - } - - /** - * Encrypts the specified string data using the AES algorithm with the provided secret key. - * - * @param data the string data to be encrypted - * @param secret the secret key used for encryption - * @return the encrypted data encoded in Base64 - * @throws GeneralSecurityException if any cryptographic error occurs during encryption - */ - public static String encrypt(String data, String secret) throws GeneralSecurityException { - return encrypt(data, secret, secret); - } - - /** - * Decrypts the specified Base64-encoded string data using the AES algorithm with the provided secret key. - * - * @param data the Base64-encoded string data to be decrypted - * @param secret the secret key used for decryption - * @param ivParam the initialization vector parameter used for AES decryption - * @return the decrypted string data - * @throws GeneralSecurityException if any cryptographic error occurs during decryption - */ - public static String decrypt(String data, String secret, String ivParam) throws GeneralSecurityException { - var decrypted = decrypt( - Base64.getDecoder().decode(data.getBytes(StandardCharsets.UTF_8)), - secret.getBytes(StandardCharsets.UTF_8), - ivParam.getBytes(StandardCharsets.UTF_8) - ); - return new String(decrypted, StandardCharsets.UTF_8); - } - - /** - * Decrypts the specified Base64-encoded string data using the AES algorithm with the provided secret key. - * - * @param data the Base64-encoded string data to be decrypted - * @param secret the secret key used for decryption - * @return the decrypted string data - * @throws GeneralSecurityException if any cryptographic error occurs during decryption - */ - public static String decrypt(String data, String secret) throws GeneralSecurityException { - return decrypt(data, secret, secret); - } - - /** - * Generates 16-character random secret. - * - * @return the generated secure secret - */ - public static String generateRandomSecret() { - return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 16); - } -} diff --git a/common-toolbox/src/main/java/com/onixbyte/common/util/Base64Util.java b/common-toolbox/src/main/java/com/onixbyte/common/util/Base64Util.java deleted file mode 100644 index 2aee71c..0000000 --- a/common-toolbox/src/main/java/com/onixbyte/common/util/Base64Util.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.common.util; - -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Objects; - -/** - * The {@link Base64Util} class provides static methods to encode and decode strings with Base64 - * encoding. It utilizes the {@link Base64} class from the Java standard library for performing the - * encoding and decoding operations. This utility class offers convenient methods to encode and - * decode strings with different character sets. - *

- * This class is designed as a final class with a private constructor to prevent instantiation. - * All methods in this class are static, allowing easy access to the Base64 encoding and - * decoding functionality. - *

- * Example usage: - *

- * String original = "Hello, World!";
- *
- * // Encode the string using UTF-8 charset
- * String encoded = Base64Util.encode(original);
- * System.out.println("Encoded string: " + encoded);
- *
- * // Decode the encoded string using UTF-8 charset
- * String decoded = Base64Util.decode(encoded);
- * System.out.println("Decoded string: " + decoded);
- * 
- *

- * Note: This utility class uses the default charset (UTF-8) if no specific charset is - * provided. It is recommended to specify the charset explicitly to ensure consistent - * encoding and decoding. - * - * @author zihluwang - * @version 3.0.0 - */ -public final class Base64Util { - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private Base64Util() { - } - - private static Base64.Encoder encoder; - private static Base64.Decoder decoder; - private static Base64.Encoder urlEncoder; - private static Base64.Decoder urlDecoder; - - /** - * Ensure that there is only one Base64 Encoder. - * - * @return the {@link Base64.Encoder} instance - */ - private static Base64.Encoder getEncoder() { - if (Objects.isNull(encoder)) { - encoder = Base64.getEncoder(); - } - return encoder; - } - - /** - * Ensure that there is only one Base64 Encoder. - * - * @return the {@link Base64.Encoder} instance - */ - private static Base64.Decoder getDecoder() { - if (Objects.isNull(decoder)) { - decoder = Base64.getDecoder(); - } - return decoder; - } - - /** - * Ensure that there is only one Base64 URL Encoder. - * - * @return the {@link Base64.Encoder} instance - */ - private static Base64.Encoder getUrlEncoder() { - if (Objects.isNull(urlEncoder)) { - urlEncoder = Base64.getUrlEncoder(); - } - return urlEncoder; - } - - /** - * Ensure that there is only one Base64 URL Decoder. - * - * @return the {@link Base64.Encoder} instance - */ - public static Base64.Decoder getUrlDecoder() { - if (Objects.isNull(urlDecoder)) { - urlDecoder = Base64.getUrlDecoder(); - } - return urlDecoder; - } - - /** - * Encodes the given string using the specified charset. - * - * @param value the string to be encoded - * @param charset the charset to be used for encoding - * @return the Base64 encoded string - */ - public static String encode(String value, Charset charset) { - var encoded = getEncoder().encode(value.getBytes(charset)); - - return new String(encoded); - } - - /** - * Encodes the given string using the default UTF-8 charset. - * - * @param value the string to be encoded - * @return the Base64 encoded string - */ - public static String encode(String value) { - return encode(value, StandardCharsets.UTF_8); - } - - /** - * Decodes the given Base64 encoded string using the specified charset. - * - * @param value the Base64 encoded string to be decoded - * @param charset the charset to be used for decoding - * @return the decoded string - */ - public static String decode(String value, Charset charset) { - var decoded = getDecoder().decode(value.getBytes(charset)); - - return new String(decoded); - } - - /** - * Decodes the given Base64 encoded string using the default UTF-8 charset. - * - * @param value the Base64 encoded string to be decoded - * @return the decoded string - */ - public static String decode(String value) { - return decode(value, StandardCharsets.UTF_8); - } - - /** - * Encodes the given string using the specified charset. - * - * @param value the string to be encoded - * @param charset the charset to be used for encoding - * @return the Base64 encoded string - */ - public static String encodeUrlComponents(String value, Charset charset) { - var encoded = getUrlEncoder().encode(value.getBytes(charset)); - - return new String(encoded); - } - - /** - * Encodes the given string using the default UTF-8 charset. - * - * @param value the string to be encoded - * @return the Base64 encoded string - */ - public static String encodeUrlComponents(String value) { - return encodeUrlComponents(value, StandardCharsets.UTF_8); - } - - /** - * Decodes the given Base64 encoded string using the specified charset. - * - * @param value the Base64 encoded string to be decoded - * @param charset the charset to be used for decoding - * @return the decoded string - */ - public static String decodeUrlComponents(String value, Charset charset) { - var decoded = getUrlDecoder().decode(value.getBytes(charset)); - - return new String(decoded); - } - - /** - * Decodes the given Base64 encoded string using the default UTF-8 charset. - * - * @param value the Base64 encoded string to be decoded - * @return the decoded string - */ - public static String decodeUrlComponents(String value) { - return decodeUrlComponents(value, StandardCharsets.UTF_8); - } -} diff --git a/common-toolbox/src/main/java/com/onixbyte/common/util/BoolUtil.java b/common-toolbox/src/main/java/com/onixbyte/common/util/BoolUtil.java deleted file mode 100644 index 4c6291c..0000000 --- a/common-toolbox/src/main/java/com/onixbyte/common/util/BoolUtil.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.common.util; - -import java.util.Arrays; -import java.util.Objects; -import java.util.function.BooleanSupplier; - -/** - * The {@link BoolUtil} class provides utility methods for boolean calculations. - * This class offers methods to perform logical operations such as AND, OR, and NOT on boolean values. - *

- * The utility methods in this class are useful for scenarios where multiple boolean values need to be - * evaluated together, and for simplifying complex boolean expressions. - *

- * - *

Example usage:

- *
{@code
- * boolean result1 = BoolUtil.and(true, true, false); // false
- * boolean result2 = BoolUtil.or(true, false, false); // true
- * boolean result3 = BoolUtil.not(false); // true
- * }
- * - * @author zihluwang - * @version 3.0.0 - */ -public final class BoolUtil { - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private BoolUtil() { - } - - /** - * Logical and calculation. - * - * @param values the values to be calculated - * @return {@code true} if all value in values is {@code true}, otherwise {@code false} - */ - public static boolean and(Boolean... values) { - return Arrays.stream(values) - .filter(Objects::nonNull) - .allMatch(Boolean::booleanValue); - } - - /** - * Logical and calculation. - * - * @param valueSuppliers the suppliers of value to be calculated - * @return {@code true} if all value in values is {@code true}, otherwise {@code false} - */ - public static boolean and(BooleanSupplier... valueSuppliers) { - return Arrays.stream(valueSuppliers) - .filter(Objects::nonNull) - .allMatch(BooleanSupplier::getAsBoolean); - } - - /** - * Logical or calculation. - * - * @param values the values to be calculated - * @return {@code true} if any value in values is {@code true}, otherwise {@code false} - */ - public static boolean or(Boolean... values) { - return Arrays.stream(values) - .filter(Objects::nonNull) - .anyMatch(Boolean::booleanValue); - } - - /** - * Logical or calculation. - * - * @param valueSuppliers the suppliers of value to be calculated - * @return {@code true} if any value in values is {@code true}, otherwise {@code false} - */ - public static boolean or(BooleanSupplier... valueSuppliers) { - return Arrays.stream(valueSuppliers) - .filter(Objects::nonNull) - .anyMatch(BooleanSupplier::getAsBoolean); - } -} diff --git a/common-toolbox/src/main/java/com/onixbyte/common/util/BranchUtil.java b/common-toolbox/src/main/java/com/onixbyte/common/util/BranchUtil.java deleted file mode 100644 index 2eaf345..0000000 --- a/common-toolbox/src/main/java/com/onixbyte/common/util/BranchUtil.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.common.util; - -import java.util.Objects; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -/** - * The {@link BranchUtil} class provides static methods to simplify conditional logic in Java - * development by leveraging lambda expressions. It offers convenient methods to replace verbose - * {@code if...else} statements with more concise and expressive functional constructs. - *

- * Developers can use methods in this utility class to streamline their code, enhance readability, - * and promote a more functional style of programming when dealing with branching logic and - * conditional statements. - *

- * Example: - *

- * // If you want to simplify an if (exp1 || exp2), you can use the following code:
- * String r1 = BranchUtil.or(1 == 1, 2 == 1)
- *     .handle(() -> "1 is equal to 1 or 2 is equal to 1.");
- *
- * // If you have an else branch, you can use the following code:
- * String r2 = BranchUtil.or(1 == 1, 2 == 1)
- *     .handle(() -> "1 is equal to 1 or 2 is equal to 1.",
- *             () -> "1 is not equal to 1 and 2 is not equal to 1.");
- *
- * // If you only need to execute code without a return value:
- * BranchUtil.or(1 == 1, 2 == 1)
- *     .handle(() -> {
- *         // do something
- *     }, () -> {
- *         // do something
- *     });
- * // If you only need an if branch, you can remove the second Supplier instance.
- *
- * // To check if all boolean expressions are true, use the 'and' method:
- * BranchUtil.and(1 == 1, 2 == 1)
- *     .handle(() -> {
- *         // do something
- *     }, () -> {
- *         // do something
- *     });
- * 
- *

- * Note: - * The {@link #and(Boolean...)} and {@link #or(Boolean...)} methods accept any number of boolean - * expressions. - * - * @author zihluwang - * @version 3.0.0 - * @see java.util.function.Supplier - * @see java.util.function.BooleanSupplier - * @see java.lang.Runnable - */ -public final class BranchUtil { - - /** - * The final result of the boolean expression. - */ - private final boolean result; - - /** - * Create a {@code BranchUtil} instance. - * - * @param result the result of the boolean expressions. - */ - private BranchUtil(boolean result) { - this.result = result; - } - - /** - * Creates a {@code BranchUtil} instance to evaluate a logical OR operation on the provided - * boolean expressions. - * - * @param values the boolean expressions to be evaluated - * @return a {@code BranchUtil} instance representing the result of the logical OR operation - */ - public static BranchUtil or(Boolean... values) { - return new BranchUtil(BoolUtil.or(values)); - } - - /** - * Creates a {@code BranchUtil} instance to evaluate a logical AND operation on the provided - * boolean expressions. - * - * @param values the boolean expressions to be evaluated - * @return a {@code BranchUtil} instance representing the result of the logical AND operation - */ - public static BranchUtil and(Boolean... values) { - return new BranchUtil(BoolUtil.and(values)); - } - - /** - * Creates a {@code BranchUtil} instance to evaluate a logical OR operation on the provided - * boolean suppliers. - * - * @param valueSuppliers the boolean suppliers to be evaluated - * @return a {@code BranchUtil} instance representing the result of the - * logical OR operation - */ - public static BranchUtil or(BooleanSupplier... valueSuppliers) { - return new BranchUtil(BoolUtil.or(valueSuppliers)); - } - - /** - * Creates a {@code BranchUtil} instance to evaluate a logical AND operation on the provided - * boolean suppliers. - * - * @param valueSuppliers the boolean suppliers to be evaluated - * @return a {@code BranchUtil} instance representing the result of the - * logical AND operation - */ - public static BranchUtil and(BooleanSupplier... valueSuppliers) { - return new BranchUtil(BoolUtil.and(valueSuppliers)); - } - - /** - * Handles the result of the boolean expressions by executing the appropriate handler based - * on the result. - *

- * If the result is {@code true}, the {@code trueSupplier} is executed. If the result is - * {@code false} and an {@code falseSupplier} is provided, it is executed. - *

- * Returns the result of the executed supplier. - * - * @param the type of the result to be handled by the methods - * @param trueSupplier the supplier to be executed if the result is {@code true} - * @param falseSupplier the supplier to be executed if the result is {@code false} (optional) - * @return the result of the executed supplier, or {@code null} if no {@code falseSupplier} is - * provided and the result of the evaluation is {@code false} - */ - public T thenSupply(Supplier trueSupplier, Supplier falseSupplier) { - if (this.result && Objects.nonNull(trueSupplier)) { - return trueSupplier.get(); - } - - if (Objects.isNull(falseSupplier)) { - return null; - } - - return falseSupplier.get(); - } - - /** - * Handles the result of the boolean expressions by executing the provided handler if the - * result is {@code true}. - *

- * Returns the result of the executed handler. - * - * @param the type of the result to be handled by the methods - * @param trueSupplier the supplier to be executed if the result is {@code true} - * @return the result of the executed handler, or {@code null} if result of evaluation - * is {@code false} - */ - public T thenSupply(Supplier trueSupplier) { - return thenSupply(trueSupplier, null); - } - - /** - * Handles the result of the boolean expressions by executing the appropriate handler based - * on the result. - *

- * If the result is {@code true}, the {@code ifHandler} is executed. If the result is - * {@code false} and an {@code elseHandler} is provided, it is executed. - * - * @param trueHandler the handler to be executed if the result is {@code true} - * @param falseHandler the handler to be executed if the result is {@code false} (optional) - */ - public void then(Runnable trueHandler, Runnable falseHandler) { - if (this.result && Objects.nonNull(trueHandler)) { - trueHandler.run(); - return; - } - - if (Objects.isNull(falseHandler)) { - return; - } - - falseHandler.run(); - } - - /** - * Handles the result of the boolean expressions by executing the provided handler if the - * result is {@code true}. - * - * @param trueHandler the handler to be executed if the result is {@code true} - */ - public void then(Runnable trueHandler) { - then(trueHandler, null); - } -} diff --git a/common-toolbox/src/main/java/com/onixbyte/common/util/CollectionUtil.java b/common-toolbox/src/main/java/com/onixbyte/common/util/CollectionUtil.java deleted file mode 100644 index 3ce2d95..0000000 --- a/common-toolbox/src/main/java/com/onixbyte/common/util/CollectionUtil.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.common.util; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.function.Supplier; - -/** - * A utility class providing static methods for manipulating collections. - * - * @author zihluwang - * @version 3.0.0 - */ -public final class CollectionUtil { - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private CollectionUtil() { - } - - /** - * Splits a collection into a list of sub-collections, each with a maximum size specified by - * the caller. - *

- * This method takes an original collection and divides it into smaller sub-collections, - * ensuring that each sub-collection contains no more than the specified maximum size. If the - * original collection's size is less than or equal to the maximum size, it is returned as a - * single sub-collection. The sub-collections are created using the provided collection factory. - * - * @param the type of elements in the collection - * @param the type of the collection, which must extend {@link Collection} - * @param originalCollection the collection to be split into sub-collections - * @param maxSize the maximum number of elements allowed in each sub-collection - * @param collectionFactory a supplier that creates new instances of the sub-collection type - * @return a list of sub-collections, each containing up to {@code maxSize} elements - * @throws IllegalArgumentException if {@code originalCollection} is {@code null}, - * {@code maxSize} is less than zero, or - * {@code collectionFactory} is {@code null} - */ - public static > List chunk( - C originalCollection, - int maxSize, - Supplier collectionFactory - ) { - // check inputs - if (Objects.isNull(originalCollection)) { - throw new IllegalArgumentException("Collection must not be null."); - } - - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize must greater than 0."); - } - - if (Objects.isNull(collectionFactory)) { - throw new IllegalArgumentException("Factory method cannot be null."); - } - - var result = new ArrayList(); - var size = originalCollection.size(); - - // if original collection is empty or the size less than maxSize, return it as a single - // sub collection - if (size <= maxSize) { - var singleCollection = collectionFactory.get(); - singleCollection.addAll(originalCollection); - result.add(singleCollection); - return result; - } - - // use iterator to split the given collection - var iter = originalCollection.iterator(); - var count = 0; - var currentSubCollection = collectionFactory.get(); - - while (iter.hasNext()) { - var element = iter.next(); - currentSubCollection.add(element); - count++; - - // add sub collection to result when current sub collection reached maxSize or - // collection traverse is completed - if (count % maxSize == 0 || !iter.hasNext()) { - result.add(currentSubCollection); - currentSubCollection = collectionFactory.get(); - } - } - - return result; - } - - /** - * Check if a collection is not null and not empty. - * - * @param collection the collection to check - * @return {@code true} if the collection is not null and not empty, {@code false} otherwise - */ - public static boolean notEmpty(Collection collection) { - return Objects.nonNull(collection) && !collection.isEmpty(); - } - - /** - * Check if a collection is null or empty. - * - * @param collection the collection to check - * @return {@code true} if the collection is null or empty, {@code false} otherwise - */ - public static boolean isEmpty(Collection collection) { - return Objects.isNull(collection) || collection.isEmpty(); - } - -} diff --git a/common-toolbox/src/main/java/com/onixbyte/common/util/MapUtil.java b/common-toolbox/src/main/java/com/onixbyte/common/util/MapUtil.java deleted file mode 100644 index 4f3400e..0000000 --- a/common-toolbox/src/main/java/com/onixbyte/common/util/MapUtil.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.common.util; - -import com.onixbyte.common.adapter.ObjectMapAdapter; - -import java.util.Map; - -/** - * The {@link MapUtil} class provides utility methods for converting between objects and maps. - * This class leverages the {@link ObjectMapAdapter} interface to perform the conversions. - *

- * The utility methods in this class are useful for scenarios where objects need to be represented - * as maps for serialization, deserialization, or other purposes. - *

- * - *

Example usage:

- *
{@code
- * // User.java
- * public class User {
- *     private String name;
- *     private int age;
- *     
- *     // getters and setters
- * }
- *
- * // UserMapAdapter.java
- * public class UserMapAdapter implements ObjectMapAdapter {
- *     @Override
- *     public Map toMap(User user) {
- *         Map map = new HashMap<>();
- *         map.put("name", user.getName());
- *         map.put("age", user.getAge());
- *         return map;
- *     }
- * 
- *     @Override
- *     public User fromMap(Map map) {
- *         User user = new User();
- *         user.setName((String) map.get("name"));
- *         user.setAge((Integer) map.get("age"));
- *         return user;
- *     }
- * }
- * 
- * public class Example {
- *     public static void main(String[] args) {
- *         User user = new User();
- *         user.setName("John");
- *         user.setAge(30);
- *         
- *         UserMapAdapter adapter = new UserMapAdapter();
- *         
- *         // Convert object to map
- *         Map userMap = MapUtil.objectToMap(user, adapter);
- *         System.out.println(userMap); // Output: {name=John, age=30}
- *         
- *         // Convert map to object
- *         User newUser = MapUtil.mapToObject(userMap, adapter);
- *         System.out.println(newUser.getName()); // Output: John
- *         System.out.println(newUser.getAge());  // Output: 30
- *     }
- * }
- * }
- * - * @author zihluwang - * @version 3.0.0 - */ -public final class MapUtil { - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private MapUtil() { - } - - /** - * Converts an object to a map by mapping the field names to their corresponding values. - * - * @param the type of the object - * @param entity the object to be converted to a map - * @param adapter adapts the entity for mapping to a map - * @return a map representing the fields and their values of the object - */ - public static Map objectToMap(T entity, ObjectMapAdapter adapter) { - return adapter.toMap(entity); - } - - /** - * Converts a map to an object of the specified type by setting the field values using the - * map entries. - * - * @param objectMap the map representing the fields and their values - * @param adapter the adapter to execute the setter for the entity - * @param the type of the object to be created - * @return an object of the specified type with the field values set from the map - */ - public static T mapToObject(Map objectMap, ObjectMapAdapter adapter) { - return adapter.toObject(objectMap); - } -} diff --git a/common-toolbox/src/main/java/com/onixbyte/common/util/RangeUtil.java b/common-toolbox/src/main/java/com/onixbyte/common/util/RangeUtil.java deleted file mode 100644 index ba96054..0000000 --- a/common-toolbox/src/main/java/com/onixbyte/common/util/RangeUtil.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.common.util; - -import java.util.stream.IntStream; - -/** - * {@code RangeUtil} is a utility class providing methods for generating streams of integers that - * emulate the behaviour of Python's {@code range} function. - *

- * This class offers static methods to create ranges with various configurations. These methods - * leverage the {@link IntStream} to provide efficient and versatile integer sequences. - * - * @author zihluwang - * @version 3.0.0 - * @see IntStream - */ -public final class RangeUtil { - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private RangeUtil() { - } - - /** - * Generates a stream of integers starting from {@code 0} up to the specified {@code end} value. - *

- * It creates a sequential, ordered {@code IntStream} that can be used for iteration or - * further processing. - *

- * Example Usage: - *

{@code
-     * RangeUtil.range(5).forEach(System.out::println);
-     *
-     * // Output:
-     * // 0
-     * // 1
-     * // 2
-     * // 3
-     * // 4
-     * }
- * - * @param end upper-bound of the range (exclusive) - * @return an {@code IntStream} of integers from {@code 0} (inclusive) to - * {@code end} (exclusive) - * @throws IllegalArgumentException if the given {@code end} value is less equal to 0 - * @see IntStream - */ - public static IntStream range(int end) { - if (end <= 0) { - throw new IllegalArgumentException("Parameter [end] should not be less than or equal to 0, provided: " + - end); - } - return IntStream.range(0, end); - } - - /** - * Generates a stream of integers starting from the specified {@code start} value up to the - * specified {@code end} value. - *

- * It creates a sequential, ordered {@code IntStream} that can be used for iteration or - * further processing. - *

- * If {@code start} is less than {@code end}, an ascending range (exclusive of {@code end}) - * is generated. If {@code start} is greater than {@code end}, a descending range (exclusive - * of {@code end}) is generated. If {@code start} equals {@code end}, an empty stream - * is returned. - *

- * Example Usage: - *

{@code
-     * RangeUtil.range(3, 8).forEach(System.out::println);
-     *
-     * // Output:
-     * // 3
-     * // 4
-     * // 5
-     * // 6
-     * // 7
-     *
-     * RangeUtil.range(8, 3).forEach(System.out::println);
-     *
-     * // Output:
-     * // 8
-     * // 7
-     * // 6
-     * // 5
-     * // 4
-     * }
- * - * @param start the starting value of the range (inclusive) - * @param end upper-bound of the range (exclusive) - * @return an {@code IntStream} of integers in ascending or descending order, exclusive - * of {@code end} - * @see IntStream - */ - public static IntStream range(int start, int end) { - if (start == end) { - return IntStream.empty(); - } - if (start < end) { - return IntStream.range(start, end); - } else { - // Descending range (exclusive of end) - return IntStream.iterate(start, (n) -> n > end, (n) -> n - 1); - } - } - - /** - * Generates a stream of integers starting from the specified {@code start} value up to the - * specified {@code end} value. - *

- * It creates a sequential, ordered {@code IntStream} that can be used for iteration or - * further processing. - *

- * The range includes both {@code start} and {@code end}. - *

- * Example Usage: - *

{@code
-     * RangeUtil.rangeClosed(3, 8).forEach(System.out::println);
-     *
-     * // Output:
-     * // 3
-     * // 4
-     * // 5
-     * // 6
-     * // 7
-     * // 8
-     * }
- * - * @param start the starting value of the range (inclusive) - * @param end upper-bound of the range (inclusive) - * @return an {@code IntStream} of integers from {@code start} to {@code end} inclusive - * @see IntStream - */ - public static IntStream rangeClosed(int start, int end) { - return IntStream.rangeClosed(start, end); - } - - /** - * Generates a stream of integers starting from the specified {@code start} value, incremented - * by the specified {@code step}, up to the specified {@code end} value. - *

- * It creates a sequential, ordered {@code IntStream} that can be used for iteration or - * further processing. - *

- * The stream excludes the {@code end} value. - *

- * Example Usage: - *

{@code
-     * RangeUtil.range(3, 10, 2).forEach(System.out::println);
-     *
-     * // Output:
-     * // 3
-     * // 5
-     * // 7
-     * // 9
-     *
-     * RangeUtil.range(10, 3, -2).forEach(System.out::println);
-     *
-     * // Output:
-     * // 10
-     * // 8
-     * // 6
-     * // 4
-     * }
- * - * @param start the starting value of the range (inclusive) - * @param end upper-bound of the range (exclusive) - * @param step the increment or decrement between each value (non-zero) - * @return an {@code IntStream} of integers from {@code start} to {@code end} exclusive stepping - * by {@code step} - * @throws IllegalArgumentException if {@code step} is zero or if {@code start} and {@code end} - * are inconsistent with the direction imposed by {@code step} - * @see IntStream - */ - public static IntStream range(int start, int end, int step) { - if (step == 0) { - throw new IllegalArgumentException("Step value must not be zero."); - } - if ((step > 0 && start >= end) || (step < 0 && start <= end)) { - throw new IllegalArgumentException("Range parameters are inconsistent with the step value."); - } - return IntStream.iterate(start, (n) -> step > 0 ? n < end : n > end, (n) -> n + step); - } - -} diff --git a/common-toolbox/src/main/resources/logback.xml b/common-toolbox/src/main/resources/logback.xml deleted file mode 100644 index 85b705f..0000000 --- a/common-toolbox/src/main/resources/logback.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - ${COLOURFUL_OUTPUT} - - - - - - diff --git a/common-toolbox/src/test/java/com/onixbyte/common/util/AesUtilTest.java b/common-toolbox/src/test/java/com/onixbyte/common/util/AesUtilTest.java deleted file mode 100644 index 2e69401..0000000 --- a/common-toolbox/src/test/java/com/onixbyte/common/util/AesUtilTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2024-2025 OnixByte. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.onixbyte.common.util; - -import org.junit.jupiter.api.Test; - -import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; - -import static org.junit.jupiter.api.Assertions.*; - -class AesUtilTest { - - @Test - void testEncryptAndDecryptByte() throws GeneralSecurityException { - byte[] secretKey = "43f72073956d4c81".getBytes(StandardCharsets.UTF_8); - byte[] originalData = "Hello World".getBytes(StandardCharsets.UTF_8); - - byte[] encryptedData = AesUtil.encrypt(originalData, secretKey); - assertNotNull(encryptedData); - - byte[] decryptedData = AesUtil.decrypt(encryptedData, secretKey); - assertNotNull(decryptedData); - - assertArrayEquals(originalData, decryptedData); - } - - @Test - void testEncryptAndDecryptString() throws GeneralSecurityException { - var secret = "43f72073956d4c81"; - var originalData = "Hello World"; - - var encryptedData = AesUtil.encrypt(originalData, secret); - assertNotNull(encryptedData); - assertNotEquals(originalData, encryptedData); - - var decryptedData = AesUtil.decrypt(encryptedData, secret); - assertNotNull(decryptedData); - assertEquals(originalData, decryptedData); - } - - @Test - void testEncryptWithWrongKeyFails() throws GeneralSecurityException { - var secret = "43f72073956d4c81"; - var wrongSecret = "0000000000000000"; - var originalData = "Hello World"; - - var encryptedData = AesUtil.encrypt(originalData.getBytes(StandardCharsets.UTF_8), - secret.getBytes(StandardCharsets.UTF_8)); - assertNotNull(encryptedData); - - // When decrypting with the wrong key, a BadPaddingException or IllegalBlockSizeException is expected to be thrown - assertThrows(GeneralSecurityException.class, () -> { - AesUtil.decrypt(encryptedData, wrongSecret.getBytes(StandardCharsets.UTF_8)); - }); - } - - @Test - void testGenerateRandomSecret() { - var randomSecret = AesUtil.generateRandomSecret(); - assertNotNull(randomSecret); - assertEquals(16, randomSecret.length()); - } -} diff --git a/common-toolbox/src/test/java/com/onixbyte/common/util/Base64UtilTest.java b/common-toolbox/src/test/java/com/onixbyte/common/util/Base64UtilTest.java deleted file mode 100644 index 732b4c1..0000000 --- a/common-toolbox/src/test/java/com/onixbyte/common/util/Base64UtilTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2024-2025 OnixByte. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.onixbyte.common.util; - -import org.junit.jupiter.api.Test; - -import java.nio.charset.StandardCharsets; - -import static org.junit.jupiter.api.Assertions.*; - -public class Base64UtilTest { - - @Test - void testEncodeAndDecodeWithUtf8() { - var original = "Hello, Base64!"; - var encoded = Base64Util.encode(original); - assertNotNull(encoded); - assertNotEquals(original, encoded); - - var decoded = Base64Util.decode(encoded); - assertNotNull(decoded); - assertEquals(original, decoded); - } - - @Test - void testEncodeAndDecodeWithCharset() { - var original = "编码测试"; // Some unicode characters (Chinese) - var charset = StandardCharsets.UTF_8; - - var encoded = Base64Util.encode(original, charset); - assertNotNull(encoded); - assertNotEquals(original, encoded); - - var decoded = Base64Util.decode(encoded, charset); - assertNotNull(decoded); - assertEquals(original, decoded); - } - - @Test - void testEncodeUrlComponentsAndDecodeWithUtf8() { - var original = "This is a test for URL-safe Base64 encoding+!"; - - var encodedUrl = Base64Util.encodeUrlComponents(original); - assertNotNull(encodedUrl); - assertNotEquals(original, encodedUrl); - // URL-safe encoding should not contain '+' or '/' characters - assertFalse(encodedUrl.contains("+")); - assertFalse(encodedUrl.contains("/")); - - var decodedUrl = Base64Util.decodeUrlComponents(encodedUrl); - assertNotNull(decodedUrl); - assertEquals(original, decodedUrl); - } - - @Test - void testEncodeUrlComponentsAndDecodeWithCharset() { - var original = "测试 URL 安全编码"; // Unicode string - var charset = StandardCharsets.UTF_8; - - var encodedUrl = Base64Util.encodeUrlComponents(original, charset); - assertNotNull(encodedUrl); - assertNotEquals(original, encodedUrl); - - var decodedUrl = Base64Util.decodeUrlComponents(encodedUrl, charset); - assertNotNull(decodedUrl); - assertEquals(original, decodedUrl); - } - - @Test - void testEncodeAndDecodeEmptyString() { - var original = ""; - - var encoded = Base64Util.encode(original); - assertNotNull(encoded); - assertEquals("", Base64Util.decode(encoded)); - } - - @Test - void testEncodeAndDecodeNullSafety() { - // Since Base64Util does not explicitly handle null, the test expects NPE if null is input - assertThrows(NullPointerException.class, () -> Base64Util.encode(null)); - assertThrows(NullPointerException.class, () -> Base64Util.decode(null)); - } - -} diff --git a/common-toolbox/src/test/java/com/onixbyte/common/util/BoolUtilTest.java b/common-toolbox/src/test/java/com/onixbyte/common/util/BoolUtilTest.java deleted file mode 100644 index f6302b5..0000000 --- a/common-toolbox/src/test/java/com/onixbyte/common/util/BoolUtilTest.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2024-2025 OnixByte. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.onixbyte.common.util; - -import org.junit.jupiter.api.Test; - -import java.util.function.BooleanSupplier; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class BoolUtilTest { - - // Tests for and(Boolean... values) - - @Test - void and_AllTrueValues_ReturnsTrue() { - assertTrue(BoolUtil.and(true, true, true)); - } - - @Test - void and_SomeFalseValues_ReturnsFalse() { - assertFalse(BoolUtil.and(true, false, true)); - } - - @Test - void and_AllFalseValues_ReturnsFalse() { - assertFalse(BoolUtil.and(false, false)); - } - - @Test - void and_WithNullValues_IgnoresNulls() { - assertTrue(BoolUtil.and(true, null, true)); - assertFalse(BoolUtil.and(true, null, false)); - } - - @Test - void and_AllNullValues_ReturnsTrue() { - // Stream after filtering null is empty, allMatch on empty returns true - assertTrue(BoolUtil.and((Boolean) null, null)); - } - - // Tests for and(BooleanSupplier... valueSuppliers) - - @Test - void and_AllSuppliersTrue_ReturnsTrue() { - BooleanSupplier trueSupplier = () -> true; - BooleanSupplier falseSupplier = () -> false; - - assertTrue(BoolUtil.and(trueSupplier, trueSupplier)); - assertFalse(BoolUtil.and(trueSupplier, falseSupplier)); - } - - @Test - void and_WithNullSuppliers_IgnoresNull() { - BooleanSupplier trueSupplier = () -> true; - - assertTrue(BoolUtil.and(trueSupplier, null, trueSupplier)); - assertFalse(BoolUtil.and(trueSupplier, null, () -> false)); - } - - @Test - void and_AllNullSuppliers_ReturnsTrue() { - assertTrue(BoolUtil.and((BooleanSupplier) null, null)); - } - - - // Tests for or(Boolean... values) - - @Test - void or_AllTrueValues_ReturnsTrue() { - assertTrue(BoolUtil.or(true, true, true)); - } - - @Test - void or_SomeTrueValues_ReturnsTrue() { - assertTrue(BoolUtil.or(false, true, false)); - } - - @Test - void or_AllFalseValues_ReturnsFalse() { - assertFalse(BoolUtil.or(false, false)); - } - - @Test - void or_WithNullValues_IgnoresNull() { - assertTrue(BoolUtil.or(false, null, true)); - assertFalse(BoolUtil.or(false, null, false)); - } - - @Test - void or_AllNullValues_ReturnsFalse() { - // Stream after filtering null is empty, anyMatch on empty returns false - assertFalse(BoolUtil.or((Boolean) null, null)); - } - - // Tests for or(BooleanSupplier... valueSuppliers) - - @Test - void or_AllSuppliersTrue_ReturnsTrue() { - BooleanSupplier trueSupplier = () -> true; - BooleanSupplier falseSupplier = () -> false; - - assertTrue(BoolUtil.or(trueSupplier, trueSupplier)); - assertTrue(BoolUtil.or(falseSupplier, trueSupplier)); - assertFalse(BoolUtil.or(falseSupplier, falseSupplier)); - } - - @Test - void or_WithNullSuppliers_IgnoresNull() { - BooleanSupplier trueSupplier = () -> true; - BooleanSupplier falseSupplier = () -> false; - - assertTrue(BoolUtil.or(falseSupplier, null, trueSupplier)); - assertFalse(BoolUtil.or(falseSupplier, null, falseSupplier)); - } - - @Test - void or_AllNullSuppliers_ReturnsFalse() { - assertFalse(BoolUtil.or((BooleanSupplier) null, null)); - } -} diff --git a/common-toolbox/src/test/java/com/onixbyte/common/util/BranchUtilTest.java b/common-toolbox/src/test/java/com/onixbyte/common/util/BranchUtilTest.java deleted file mode 100644 index f90f058..0000000 --- a/common-toolbox/src/test/java/com/onixbyte/common/util/BranchUtilTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2024-2025 OnixByte. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.onixbyte.common.util; - -import org.junit.jupiter.api.Test; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.BooleanSupplier; - -import static org.junit.jupiter.api.Assertions.*; - -class BranchUtilTest { - - // Test the static methods or(Boolean... values) and and(Boolean... values) - @Test - void testOrWithBooleanValues() { - BranchUtil trueResult = BranchUtil.or(true, false, false); - assertNotNull(trueResult); - - BranchUtil falseResult = BranchUtil.or(false, false, false); - assertNotNull(falseResult); - } - - @Test - void testAndWithBooleanValues() { - BranchUtil trueResult = BranchUtil.and(true, true, true); - assertNotNull(trueResult); - - BranchUtil falseResult = BranchUtil.and(true, false, true); - assertNotNull(falseResult); - } - - // Test the static methods or(BooleanSupplier... valueSuppliers) and and(BooleanSupplier... valueSuppliers) - @Test - void testOrWithBooleanSuppliers() { - BooleanSupplier trueSupplier = () -> true; - BooleanSupplier falseSupplier = () -> false; - - BranchUtil trueResult = BranchUtil.or(falseSupplier, trueSupplier); - - BranchUtil falseResult = BranchUtil.or(falseSupplier, falseSupplier); - } - - @Test - void testAndWithBooleanSuppliers() { - BooleanSupplier trueSupplier = () -> true; - BooleanSupplier falseSupplier = () -> false; - - BranchUtil trueResult = BranchUtil.and(trueSupplier, trueSupplier); - - BranchUtil falseResult = BranchUtil.and(trueSupplier, falseSupplier); - } - - // Test thenSupply(T, T) - @Test - void testThenSupplyBothSuppliers_ResultTrue() { - BranchUtil b = BranchUtil.and(true); - String trueVal = "yes"; - String falseVal = "no"; - - String result = b.thenSupply(() -> trueVal, () -> falseVal); - assertEquals(trueVal, result); - } - - @Test - void testThenSupplyBothSuppliers_ResultFalse_WithFalseSupplier() { - BranchUtil b = BranchUtil.and(false); - String trueVal = "yes"; - String falseVal = "no"; - - String result = b.thenSupply(() -> trueVal, () -> falseVal); - assertEquals(falseVal, result); - } - - @Test - void testThenSupplyBothSuppliers_ResultFalse_NoFalseSupplier() { - BranchUtil b = BranchUtil.and(false); - String trueVal = "yes"; - - String result = b.thenSupply(() -> trueVal, null); - assertNull(result); - } - - @Test - void testThenSupplySingleTrueSupplier_ResultTrue() { - BranchUtil b = BranchUtil.and(true); - String trueVal = "success"; - - String result = b.thenSupply(() -> trueVal); - assertEquals(trueVal, result); - } - - @Test - void testThenSupplySingleTrueSupplier_ResultFalse() { - BranchUtil b = BranchUtil.and(false); - String trueVal = "success"; - - String result = b.thenSupply(() -> trueVal); - assertNull(result); - } - - // Test then(Runnable, Runnable) - @Test - void testThenWithBothHandlers_ResultTrue() { - BranchUtil b = BranchUtil.and(true); - AtomicBoolean trueRun = new AtomicBoolean(false); - AtomicBoolean falseRun = new AtomicBoolean(false); - - b.then(() -> trueRun.set(true), () -> falseRun.set(true)); - - assertTrue(trueRun.get()); - assertFalse(falseRun.get()); - } - - @Test - void testThenWithBothHandlers_ResultFalse() { - BranchUtil b = BranchUtil.and(false); - AtomicBoolean trueRun = new AtomicBoolean(false); - AtomicBoolean falseRun = new AtomicBoolean(false); - - b.then(() -> trueRun.set(true), () -> falseRun.set(true)); - - assertFalse(trueRun.get()); - assertTrue(falseRun.get()); - } - - @Test - void testThenWithOnlyTrueHandler_ResultTrue() { - BranchUtil b = BranchUtil.and(true); - AtomicBoolean trueRun = new AtomicBoolean(false); - - b.then(() -> trueRun.set(true)); - - assertTrue(trueRun.get()); - } - - @Test - void testThenWithOnlyTrueHandler_ResultFalse() { - BranchUtil b = BranchUtil.and(false); - AtomicBoolean trueRun = new AtomicBoolean(false); - - b.then(() -> trueRun.set(true)); - - assertFalse(trueRun.get()); - } -} diff --git a/common-toolbox/src/test/java/com/onixbyte/common/util/CollectionUtilTest.java b/common-toolbox/src/test/java/com/onixbyte/common/util/CollectionUtilTest.java deleted file mode 100644 index 7807753..0000000 --- a/common-toolbox/src/test/java/com/onixbyte/common/util/CollectionUtilTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2024-2025 OnixByte. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.onixbyte.common.util; - -import org.junit.jupiter.api.Test; - -import java.util.*; -import java.util.function.Supplier; - -import static org.junit.jupiter.api.Assertions.*; - -class CollectionUtilTest { - - @Test - void chunk_NullOriginalCollection_ThrowsException() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, - () -> CollectionUtil.chunk(null, 3, ArrayList::new)); - assertEquals("Collection must not be null.", ex.getMessage()); - } - - @Test - void chunk_NegativeMaxSize_ThrowsException() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, - () -> CollectionUtil.chunk(List.of(1, 2), -1, ArrayList::new)); - assertEquals("maxSize must greater than 0.", ex.getMessage()); - } - - @Test - void chunk_NullCollectionFactory_ThrowsException() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, - () -> CollectionUtil.chunk(List.of(1, 2), 2, null)); - assertEquals("Factory method cannot be null.", ex.getMessage()); - } - - @Test - void chunk_EmptyCollection_ReturnsOneEmptySubCollection() { - List> chunks = CollectionUtil.chunk(Collections.emptyList(), 3, ArrayList::new); - assertEquals(1, chunks.size()); - assertTrue(chunks.get(0).isEmpty()); - } - - @Test - void chunk_CollectionSizeLessThanMaxSize_ReturnsOneSubCollectionWithAllElements() { - List list = List.of(1, 2); - List> chunks = CollectionUtil.chunk(list, 5, ArrayList::new); - assertEquals(1, chunks.size()); - assertEquals(list, chunks.get(0)); - } - - @Test - void chunk_CollectionSizeEqualMaxSize_ReturnsOneSubCollectionWithAllElements() { - List list = List.of(1, 2, 3); - List> chunks = CollectionUtil.chunk(list, 3, ArrayList::new); - assertEquals(1, chunks.size()); - assertEquals(list, chunks.get(0)); - } - - @Test - void chunk_CollectionSizeGreaterThanMaxSize_ReturnsMultipleSubCollections() { - List list = List.of(1, 2, 3, 4, 5, 6, 7); - int maxSize = 3; - List> chunks = CollectionUtil.chunk(list, maxSize, ArrayList::new); - - // Expect 3 subcollections: [1,2,3], [4,5,6], [7] - assertEquals(3, chunks.size()); - assertEquals(List.of(1, 2, 3), chunks.get(0)); - assertEquals(List.of(4, 5, 6), chunks.get(1)); - assertEquals(List.of(7), chunks.get(2)); - } - - @Test - void chunk_UsesDifferentCollectionTypeAsSubCollections() { - LinkedList list = new LinkedList<>(List.of(1, 2, 3, 4)); - Supplier> factory = LinkedList::new; - List> chunks = CollectionUtil.chunk(list, 2, factory); - assertEquals(2, chunks.size()); - assertInstanceOf(LinkedList.class, chunks.get(0)); - assertInstanceOf(LinkedList.class, chunks.get(1)); - assertEquals(List.of(1, 2), chunks.get(0)); - assertEquals(List.of(3, 4), chunks.get(1)); - } - - @Test - void chunk_CollectionWithOneElementAndMaxSizeOne_ReturnsOneSubCollection() { - List list = List.of("a"); - List> chunks = CollectionUtil.chunk(list, 1, ArrayList::new); - assertEquals(1, chunks.size()); - assertEquals(list, chunks.get(0)); - } - - @Test - void chunk_MaxSizeZero_ThrowsException() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, - () -> CollectionUtil.chunk(List.of(1), 0, ArrayList::new)); - assertEquals("maxSize must greater than 0.", ex.getMessage()); - } -} diff --git a/common-toolbox/src/test/java/com/onixbyte/common/util/RangeUtilTest.java b/common-toolbox/src/test/java/com/onixbyte/common/util/RangeUtilTest.java deleted file mode 100644 index a53ed6d..0000000 --- a/common-toolbox/src/test/java/com/onixbyte/common/util/RangeUtilTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2024-2025 OnixByte. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.onixbyte.common.util; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class RangeUtilTest { - - /** - * Tests generating ascending range from 0 up to end (exclusive). - */ - @Test - void testRangeEndValid() { - int[] expected = {0, 1, 2, 3, 4}; - assertArrayEquals(expected, RangeUtil.range(5).toArray()); - } - - /** - * Tests that range(end) throws IllegalArgumentException for end less than or equal to zero. - */ - @Test - void testRangeEndInvalidThrows() { - IllegalArgumentException ex1 = assertThrows(IllegalArgumentException.class, - () -> RangeUtil.range(0)); - assertTrue(ex1.getMessage().contains("should not be less than or equal to 0")); - - IllegalArgumentException ex2 = assertThrows(IllegalArgumentException.class, - () -> RangeUtil.range(-3)); - assertTrue(ex2.getMessage().contains("should not be less than or equal to 0")); - } - - /** - * Tests ascending range where start is less than end. - */ - @Test - void testRangeStartEndAscending() { - int[] expected = {3, 4, 5, 6, 7}; - assertArrayEquals(expected, RangeUtil.range(3, 8).toArray()); - } - - /** - * Tests descending range where start is greater than end. - */ - @Test - void testRangeStartEndDescending() { - int[] expected = {8, 7, 6, 5, 4}; - assertArrayEquals(expected, RangeUtil.range(8, 3).toArray()); - } - - /** - * Tests empty stream when start equals end. - */ - @Test - void testRangeStartEqualsEndReturnsEmpty() { - assertEquals(0, RangeUtil.range(5, 5).count()); - } - - /** - * Tests that rangeClosed generates inclusive range in ascending order. - */ - @Test - void testRangeClosedAscending() { - int[] expected = {3, 4, 5, 6, 7, 8}; - assertArrayEquals(expected, RangeUtil.rangeClosed(3, 8).toArray()); - } - - /** - * Tests range method with positive step generating ascending sequence. - */ - @Test - void testRangeWithPositiveStep() { - int[] expected = {2, 4, 6, 8}; - assertArrayEquals(expected, RangeUtil.range(2, 10, 2).toArray()); - } - - /** - * Tests range method with negative step generating descending sequence. - */ - @Test - void testRangeWithNegativeStep() { - int[] expected = {10, 7, 4, 1}; - assertArrayEquals(expected, RangeUtil.range(10, 0, -3).toArray()); - } - - /** - * Tests that passing zero step throws IllegalArgumentException. - */ - @Test - void testRangeStepZeroThrows() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, - () -> RangeUtil.range(0, 10, 0)); - assertEquals("Step value must not be zero.", ex.getMessage()); - } - - /** - * Tests that range with positive step but invalid start/end throws IllegalArgumentException. - */ - @Test - void testRangePositiveStepInvalidRangeThrows() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, - () -> RangeUtil.range(10, 5, 1)); - assertEquals("Range parameters are inconsistent with the step value.", ex.getMessage()); - } - - /** - * Tests that range with negative step but invalid start/end throws IllegalArgumentException. - */ - @Test - void testRangeNegativeStepInvalidRangeThrows() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, - () -> RangeUtil.range(5, 10, -1)); - assertEquals("Range parameters are inconsistent with the step value.", ex.getMessage()); - } -} diff --git a/crypto-toolbox/README.md b/crypto-toolbox/README.md deleted file mode 100644 index 8e287e8..0000000 --- a/crypto-toolbox/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# Crypto Toolbox - -Crypto Toolbox provides methods to simplify your codes on key pairs. - -## ECDSA-based algorithm - -### Generate key pair - -#### Generate private key - -Generate a private key by `genpkey` command provided by OpenSSL: - -```shell -openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ec_private_key.pem -``` - -The output of this command is a file called `ec_private_key.pem` and its content looks like the -following: - -```text ------BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs79JlARgXEf6EDV7 -+PHQCTHEMtqIoHOy1GZ1+ynQJ6yhRANCAARkA7GRY2i4gg8qx0XViAXUP9cPw9pn -Jg1wfrQ41FaMyqVBejNYxvaLtamErF/ySimnjafMJ+VZCh34lBj6Ez8R ------END PRIVATE KEY----- -``` - -#### Generate public key by private key - -Export public key from private key with `ec` command provided by OpenSSL: - -```shell -openssl ec -in ec_private_key.pem -pubout -out ec_public_key.pem -``` - -The output of this command is a file called `ec_public_key.pem` and its content looks like the -following: - -```text ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZAOxkWNouIIPKsdF1YgF1D/XD8Pa -ZyYNcH60ONRWjMqlQXozWMb2i7WphKxf8kopp42nzCflWQod+JQY+hM/EQ== ------END PUBLIC KEY----- -``` - -## RSA-based algorithm - -### Generate key pair - -#### Generate private key - -Generate a private key by `genpkey` command provided by OpenSSL: - -```shell -openssl genpkey -algorithm RSA -out rsa_private_key.pem -pkeyopt rsa_keygen_bits:2048 -``` - -The output of this command is a file called `rsa_private_key.pem` and its content looks like the -following: - -```text ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD4VIFYJFMAs15j -J3V3IicHd7sI2TIFqTZME40zlOlVAlPKLZmTQvZFLNgaUAAsvPi5i1DR2ywwK6Al -BfnwVnzvmDXC5mKHOz4oxOQVA6Nlp2yVaQMzidmfYNSkMtcv/4HRPsatc7K/M5l6 -pCP20DVRjkikBdIy8e9w+x6BrIFp5Q8PZc/X2BGNAUMMYACdeYH5R/A0CxqkND13 -esc4gkynMOrvZrZGHCz51usfSCqyDWWwsN+GG6LYWia4GkNlS0erQnP8gS93dfjl -e96BIfy3z7Iv+kUrf5ikNW2P8jMxLAv6LO+dcUAu9k477wIAF7Iq5KMuH/otsDOu -+h+2qXmBAgMBAAECggEAdRqcmC0g+y6arxV3fkObthjPGYAa57KBCWUa7B0n30+m -pavVRS2Jpttb2SSqwG4ouI6rARti/iBEd9EWqTCP4AieKZetFOpqCJ24lPRPRGus -d9S6jr5N4qut+vSCp37NABijZj4uJ540nTH0R7qtuhTnynl4Q0/1wwiYvTvVF1Lg -dn+I/8aRbshwDhdAOWOUe6GL7/eaCYgN8/UmlKIpp8tg0w2iWxbaFiR7gZiM41LA -M6SXXfcCas+ZVXsGbzQ3SNiVurCGuuRNcCScXS3/WoEDIb3cNtp49iOmQS+nmEoo -wh4uiEd+0+BrzxngS4o5+mKnHJnwgY0+veGVYLMR5QKBgQD9WKQmevMDU5c+NPq9 -8jaR457Fuxq1gwzeFNJdWfOc/K2LEWh+nFNFCb++EboEj6FdxWaWNMxbrmJps5gs -EoBUYy/Tl7UycDqDfiYLmDdTsf2pVjjh9jaIADiLcJ8S6wwJMZKub7Tp8UVkenAl -535MqShLUC11Y7VxLb3Tsll4XwKBgQD67mm6iCmshr/eszPfNE3ylZ+PiNa7nat7 -N7lQzBIiRJflT1kmVidC5gE+jASqH728ChkZZKxbHsjxpmWdAhLOITdXoTB4sDsd -wtV1lxkXxK9FnrpFvO3y1wZ/QsD3Z2KXxHYZqawkUETO9F3nqAXW0b2GDar5Qiyo -J3Tx/43aHwKBgDC0NMJtCoDONhowZy/S+6iqQKC0qprQec3L5PErVMkOTnKYwyTr -+pogGKt6ju9HiXcUdvdTaSIK8UJu00dNuzv94XjlBmGO78DNpJTAC4rcge5m9AKE -qdEVcclkukARzbuKuy8rrHT4/CUn4J141m/4aRWpcUPLCluato6XD9ozAoGBANvf -JhOFFgcPd3YazfvpZ9eE1XA+tfFlYYmxNRcgCU+vjO0oDvSxjutmgHae18N91pG6 -w21lskSRf/+GDwl5dKLbphOJsOA/gz07qDDGOf2CoRW+1Hcg6drcINxH0K+4DkLv -qZApBSY4k2JH6zR+HMeztn6M4WBRZLHfCPC3PUN/AoGAA3AoHbLTZvqMIKSDkP4Y -U/tTsSFDY4aYo7LG/jk8af3oPU3KyGh4ZFBd6aMmXbS8f8FjvmrM+/e+y9OOGAlq -iOl0hYrs5cJSMLW6i4KnJYuYbMkgmk3bN2t9apu64xKR94gbPrI6AGnPZp+iIzp0 -hXKe4HcuhQ3G0a2hjayiQ84= ------END PRIVATE KEY----- -``` - -#### Generate public key by private key - -Export public key from private key by OpenSSL: - -```shell -openssl pkey -in rsa_private_key.pem -pubout -out rsa_public_key.pem -``` - -The output of this command is a file called `rsa_public_key.pem` and its content looks like the -following: - -```text ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+FSBWCRTALNeYyd1dyIn -B3e7CNkyBak2TBONM5TpVQJTyi2Zk0L2RSzYGlAALLz4uYtQ0dssMCugJQX58FZ8 -75g1wuZihzs+KMTkFQOjZadslWkDM4nZn2DUpDLXL/+B0T7GrXOyvzOZeqQj9tA1 -UY5IpAXSMvHvcPsegayBaeUPD2XP19gRjQFDDGAAnXmB+UfwNAsapDQ9d3rHOIJM -pzDq72a2Rhws+dbrH0gqsg1lsLDfhhui2FomuBpDZUtHq0Jz/IEvd3X45XvegSH8 -t8+yL/pFK3+YpDVtj/IzMSwL+izvnXFALvZOO+8CABeyKuSjLh/6LbAzrvoftql5 -gQIDAQAB ------END PUBLIC KEY----- -``` diff --git a/crypto-toolbox/build.gradle.kts b/crypto-toolbox/build.gradle.kts deleted file mode 100644 index e7b7034..0000000 --- a/crypto-toolbox/build.gradle.kts +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import java.net.URI - -plugins { - java - id("java-library") - id("maven-publish") - id("signing") -} - -val cryptoToolboxVersion: String by project - -version = cryptoToolboxVersion -val projectUrl: String by project -val projectGithubUrl: String by project -val licenseName: String by project -val licenseUrl: String by project - -repositories { - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - withSourcesJar() - withJavadocJar() -} - -tasks.withType { - options.encoding = "UTF-8" -} - -tasks.withType { - exclude("logback.xml") -} - -dependencies { - compileOnly(libs.slf4j) - implementation(libs.logback) - testImplementation(platform(libs.junit.bom)) - testImplementation(libs.junit.jupiter) -} - -tasks.test { - useJUnitPlatform() - testLogging { - events("passed", "skipped", "failed") - } -} - -publishing { - publications { - create("cryptoToolbox") { - groupId = group.toString() - artifactId = "crypto-toolbox" - version = cryptoToolboxVersion - - pom { - name = "OnixByte Crypto Toolbox" - description = - "This module can easily load key pairs from a PEM content." - url = projectUrl - - licenses { - license { - name = licenseName - url = licenseUrl - } - } - - scm { - connection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - developerConnection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - url = projectGithubUrl - } - - developers { - developer { - id = "zihluwang" - name = "Zihlu Wang" - email = "really@zihlu.wang" - timezone = "Asia/Hong_Kong" - } - - developer { - id = "siujamo" - name = "Siu Jam'o" - email = "jamo.siu@outlook.com" - timezone = "Asia/Shanghai" - } - } - } - - from(components["java"]) - - signing { - setRequired(project.hasProperty("signing.keyId")) - sign(publishing.publications["cryptoToolbox"]) - } - } - - repositories { - maven { - name = "sonatypeNexus" - url = URI(providers.gradleProperty("repo.maven-central.host").get()) - credentials { - username = providers.gradleProperty("repo.maven-central.username").get() - password = providers.gradleProperty("repo.maven-central.password").get() - } - } - } - } -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/PrivateKeyLoader.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/PrivateKeyLoader.java deleted file mode 100644 index 4739a07..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/PrivateKeyLoader.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto; - -import java.security.PrivateKey; - -/** - * The {@code PrivateKeyLoader} provides utility methods for loading private keys from - * PEM-formatted key text. - * - * @author zihluwang - * @author siujamo - * @version 3.0.0 - */ -public interface PrivateKeyLoader { - - /** - * Load private key from pem-formatted key text. - * - * @param pemKeyText pem-formatted key text - * @return loaded private key - */ - PrivateKey loadPrivateKey(String pemKeyText); -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/PublicKeyLoader.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/PublicKeyLoader.java deleted file mode 100644 index 872b9fa..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/PublicKeyLoader.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto; - -import com.onixbyte.crypto.exception.KeyLoadingException; - -import java.security.PublicKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPublicKey; - -/** - * The {@code PublicKeyLoader} provides utility methods for loading public keys from PEM-formatted - * key text. - * - * @author zihluwang - * @author siujamo - * @version 3.0.0 - */ -public interface PublicKeyLoader { - - /** - * Load public key from PEM-formatted key text. - * - * @param pemKeyText PEM-formatted key text - * @return loaded private key - */ - PublicKey loadPublicKey(String pemKeyText); - - /** - * Loads an EC public key using the provided x and y coordinates together with the curve name. - *

- * This default implementation throws a {@link KeyLoadingException} to signify that this key - * loader does not support loading an EC public key. Implementing classes are expected to - * override this method to supply their own loading logic. - * - * @param xHex the hexadecimal string representing the x coordinate of the EC point - * @param yHex the hexadecimal string representing the y coordinate of the EC point - * @param curveName the name of the elliptic curve - * @return the loaded {@link ECPublicKey} instance - * @throws KeyLoadingException if loading is not supported or fails - */ - default ECPublicKey loadPublicKey(String xHex, String yHex, String curveName) { - throw new KeyLoadingException("This key loader does not support loading an EC public key."); - } - - /** - * Loads an RSA public key using the provided modulus and exponent. - *

- * This default implementation throws a {@link KeyLoadingException} to signify that this key - * loader does not support loading an RSA public key. Implementing classes are expected to - * override this method to supply their own loading logic. - * - * @param modulus the modulus value of the RSA public key, usually represented in hexadecimal - * or Base64 string format - * @param exponent the public exponent value of the RSA public key, usually represented in - * hexadecimal or Base64 string format - * @return the loaded {@link RSAPublicKey} instance - * @throws KeyLoadingException if loading is not supported or fails - */ - default RSAPublicKey loadPublicKey(String modulus, String exponent) { - throw new KeyLoadingException("This key loader does not support loading an RSA public key."); - } -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/ecdsa/ECPrivateKeyLoader.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/ecdsa/ECPrivateKeyLoader.java deleted file mode 100644 index 5e37364..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/ecdsa/ECPrivateKeyLoader.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto.algorithm.ecdsa; - -import com.onixbyte.crypto.PrivateKeyLoader; -import com.onixbyte.crypto.exception.KeyLoadingException; -import com.onixbyte.crypto.util.CryptoUtil; - -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.interfaces.ECPrivateKey; -import java.security.spec.*; -import java.util.Base64; - -/** - * A class responsible for loading private ECDSA keys from PEM formatted text. - *

- * This class implements the {@link PrivateKeyLoader} interface and provides methods to load private - * RSA keys. The keys are expected to be in the standard PEM format, which includes Base64-encoded - * key content surrounded by header and footer lines. The class handles the decoding of Base64 - * content and the generation of keys using the RSA key factory. - *

- * Any exceptions encountered during the loading process are encapsulated in a - * {@link KeyLoadingException}, allowing for flexible error handling. - * - * @author zihluwang - * @author siujamo - * @version 3.0.0 - * @see PrivateKeyLoader - * @see KeyLoadingException - */ -public class ECPrivateKeyLoader implements PrivateKeyLoader { - - private final KeyFactory keyFactory; - - private final Base64.Decoder decoder; - - /** - * Initialise a key loader for EC-based algorithms. - */ - public ECPrivateKeyLoader() { - try { - this.keyFactory = KeyFactory.getInstance("EC"); - this.decoder = Base64.getDecoder(); - } catch (NoSuchAlgorithmException e) { - throw new KeyLoadingException(e); - } - } - - /** - * Load ECDSA private key from pem-formatted key text. - * - * @param pemKeyText pem-formatted key text - * @return loaded private key - * @throws KeyLoadingException if the generated key is not a {@link ECPrivateKey} instance, - * or EC Key Factory is not loaded, or key spec is invalid - */ - @Override - public ECPrivateKey loadPrivateKey(String pemKeyText) { - try { - pemKeyText = CryptoUtil.getRawContent(pemKeyText); - var decodedKeyString = decoder.decode(pemKeyText); - var keySpec = new PKCS8EncodedKeySpec(decodedKeyString); - - var _key = keyFactory.generatePrivate(keySpec); - if (_key instanceof ECPrivateKey privateKey) { - return privateKey; - } else { - throw new KeyLoadingException("Unable to load private key from pem-formatted key text."); - } - } catch (InvalidKeySpecException e) { - throw new KeyLoadingException("Key spec is invalid.", e); - } - } -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/ecdsa/ECPublicKeyLoader.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/ecdsa/ECPublicKeyLoader.java deleted file mode 100644 index 7fd8bd3..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/ecdsa/ECPublicKeyLoader.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto.algorithm.ecdsa; - -import com.onixbyte.crypto.PrivateKeyLoader; -import com.onixbyte.crypto.PublicKeyLoader; -import com.onixbyte.crypto.exception.KeyLoadingException; -import com.onixbyte.crypto.util.CryptoUtil; - -import java.math.BigInteger; -import java.security.AlgorithmParameters; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.*; -import java.util.Base64; -import java.util.HashSet; -import java.util.Set; - -/** - * A class responsible for loading public ECDSA keys from PEM formatted text. - *

- * This class implements the {@link PublicKeyLoader} interface and provides methods to load private - * RSA keys. The keys are expected to be in the standard PEM format, which includes Base64-encoded - * key content surrounded by header and footer lines. The class handles the decoding of Base64 - * content and the generation of keys using the RSA key factory. - *

- * Any exceptions encountered during the loading process are encapsulated in a - * {@link KeyLoadingException}, allowing for flexible error handling. - * - * @author zihluwang - * @author siujamo - * @version 3.0.0 - * @see PrivateKeyLoader - * @see KeyLoadingException - */ -public class ECPublicKeyLoader implements PublicKeyLoader { - - /** - * Supported curves. - */ - public static final Set SUPPORTED_CURVES = new HashSet<>(Set.of( - "secp256r1", "secp384r1", "secp521r1", "secp224r1" - )); - - private final KeyFactory keyFactory; - - private final Base64.Decoder decoder; - - /** - * Initialise a key loader for EC-based algorithms. - */ - public ECPublicKeyLoader() { - try { - this.keyFactory = KeyFactory.getInstance("EC"); - this.decoder = Base64.getDecoder(); - } catch (NoSuchAlgorithmException e) { - throw new KeyLoadingException(e); - } - } - - /** - * Load public key from pem-formatted key text. - * - * @param pemKeyText pem-formatted key text - * @return loaded private key - * @throws KeyLoadingException if the generated key is not a {@link ECPrivateKey} instance, - * or EC Key Factory is not loaded, or key spec is invalid - */ - @Override - public ECPublicKey loadPublicKey(String pemKeyText) { - try { - pemKeyText = CryptoUtil.getRawContent(pemKeyText); - var keyBytes = decoder.decode(pemKeyText); - var spec = new X509EncodedKeySpec(keyBytes); - var key = keyFactory.generatePublic(spec); - if (key instanceof ECPublicKey publicKey) { - return publicKey; - } else { - throw new KeyLoadingException("Unable to load public key from pem-formatted key text."); - } - } catch (InvalidKeySpecException e) { - throw new KeyLoadingException("Key spec is invalid.", e); - } - } - - /** - * Loads an EC public key from the given hexadecimal x and y coordinates alongside the curve name. - *

- * This method converts the hexadecimal string representations of the EC point coordinates into {@link BigInteger} - * instances, then constructs an {@link ECPoint} and retrieves the corresponding {@link ECParameterSpec} for the - * named curve. Subsequently, it utilises the {@link KeyFactory} to generate an {@link ECPublicKey}. - *

- * Only curves listed in {@link #SUPPORTED_CURVES} are supported. Should the specified curve name be unsupported, - * or if key construction fails due to invalid parameters or unsupported algorithms, a {@link KeyLoadingException} - * will be thrown. - * - * @param xHex the hexadecimal string representing the x-coordinate of the EC point - * @param yHex the hexadecimal string representing the y-coordinate of the EC point - * @param curveName the name of the elliptic curve - * @return the {@link ECPublicKey} generated from the specified coordinates and curve - * @throws KeyLoadingException if the curve is unsupported or key generation fails - */ - @Override - public ECPublicKey loadPublicKey(String xHex, String yHex, String curveName) { - if (!SUPPORTED_CURVES.contains(curveName)) { - throw new KeyLoadingException("Given curve is not supported yet."); - } - - try { - // Convert hex string coordinates to BigInteger - var x = new BigInteger(xHex, 16); - var y = new BigInteger(yHex, 16); - - // Create ECPoint with (x, y) - var ecPoint = new ECPoint(x, y); - - // Get EC parameter spec for the named curve - var parameters = AlgorithmParameters.getInstance("EC"); - parameters.init(new ECGenParameterSpec(curveName)); - var ecParameterSpec = parameters.getParameterSpec(ECParameterSpec.class); - - // Create ECPublicKeySpec with point and curve params - var pubSpec = new ECPublicKeySpec(ecPoint, ecParameterSpec); - - // Generate public key using KeyFactory - var publicKey = keyFactory.generatePublic(pubSpec); - - if (publicKey instanceof ECPublicKey ecPublicKey) { - return ecPublicKey; - } else { - throw new KeyLoadingException("Cannot load EC public key with given x, y and curve name."); - } - } catch (NoSuchAlgorithmException | InvalidParameterSpecException | InvalidKeySpecException e) { - throw new KeyLoadingException("Cannot load EC public key with given x, y and curve name.", e); - } - } -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/rsa/RSAPrivateKeyLoader.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/rsa/RSAPrivateKeyLoader.java deleted file mode 100644 index ac3614c..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/rsa/RSAPrivateKeyLoader.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto.algorithm.rsa; - -import com.onixbyte.crypto.PrivateKeyLoader; -import com.onixbyte.crypto.exception.KeyLoadingException; -import com.onixbyte.crypto.util.CryptoUtil; - -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.*; -import java.util.Base64; - -/** - * A class responsible for loading private RSA keys from PEM formatted text. - *

- * This class implements the {@link PrivateKeyLoader} interface and provides methods to load private - * RSA keys. The keys are expected to be in the standard PEM format, which includes Base64-encoded - * key content surrounded by header and footer lines. The class handles the decoding of Base64 - * content and the generation of keys using the RSA key factory. - *

- * Any exceptions encountered during the loading process are encapsulated in a - * {@link KeyLoadingException}, allowing for flexible error handling. - * - * @author zihluwang - * @author siujamo - * @version 3.0.0 - * @see PrivateKeyLoader - * @see KeyLoadingException - */ -public class RSAPrivateKeyLoader implements PrivateKeyLoader { - - private final Base64.Decoder decoder; - - private final KeyFactory keyFactory; - - /** - * Constructs an instance of {@code RsaKeyLoader}. - *

- * This constructor initialises the Base64 decoder and the RSA {@link KeyFactory}. It may throw - * a {@link KeyLoadingException} if the RSA algorithm is not available. - */ - public RSAPrivateKeyLoader() { - try { - this.decoder = Base64.getDecoder(); - this.keyFactory = KeyFactory.getInstance("RSA"); - } catch (NoSuchAlgorithmException e) { - throw new KeyLoadingException(e); - } - } - - /** - * Loads an RSA private key from a given PEM formatted key text. - *

- * This method extracts the raw key content from the provided PEM text, decodes the - * Base64-encoded content, and generates an instance of {@link RSAPrivateKey}. If the key cannot - * be loaded due to invalid specifications or types, a {@link KeyLoadingException} is thrown. - * - * @param pemKeyText the PEM formatted private key text - * @return an instance of {@link RSAPrivateKey} - * @throws KeyLoadingException if the key loading process encounters an error - */ - @Override - public RSAPrivateKey loadPrivateKey(String pemKeyText) { - // Extract the raw key content - var rawKeyContent = CryptoUtil.getRawContent(pemKeyText); - - // Decode the Base64-encoded content - var keyBytes = decoder.decode(rawKeyContent); - - // Create a PKCS8EncodedKeySpec from the decoded bytes - var keySpec = new PKCS8EncodedKeySpec(keyBytes); - - try { - // Get an RSA KeyFactory and generate the private key - var _key = keyFactory.generatePrivate(keySpec); - if (_key instanceof RSAPrivateKey key) { - return key; - } else { - throw new KeyLoadingException("Unable to load private key from pem-formatted key text."); - } - } catch (InvalidKeySpecException e) { - throw new KeyLoadingException("Key spec is invalid.", e); - } - } -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/rsa/RSAPublicKeyLoader.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/rsa/RSAPublicKeyLoader.java deleted file mode 100644 index 5335ff6..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/algorithm/rsa/RSAPublicKeyLoader.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto.algorithm.rsa; - -import com.onixbyte.crypto.PrivateKeyLoader; -import com.onixbyte.crypto.PublicKeyLoader; -import com.onixbyte.crypto.exception.KeyLoadingException; -import com.onixbyte.crypto.util.CryptoUtil; - -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import java.security.spec.RSAPublicKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.Base64; - -/** - * A class responsible for loading public RSA keys from PEM formatted text. - *

- * This class implements the {@link PublicKeyLoader} interface and provides methods to load public - * RSA keys. The keys are expected to be in the standard PEM format, which includes Base64-encoded - * key content surrounded by header and footer lines. The class handles the decoding of Base64 - * content and the generation of keys using the RSA key factory. - *

- * Any exceptions encountered during the loading process are encapsulated in a - * {@link KeyLoadingException}, allowing for flexible error handling. - * - * @author zihluwang - * @author siujamo - * @version 3.0.0 - * @see PrivateKeyLoader - * @see KeyLoadingException - */ -public class RSAPublicKeyLoader implements PublicKeyLoader { - - private final Base64.Decoder decoder; - - private final Base64.Decoder urlDecoder; - - private final KeyFactory keyFactory; - - /** - * Constructs an instance of {@code RsaKeyLoader}. - *

- * This constructor initialises the Base64 decoder and the RSA {@link KeyFactory}. It may throw - * a {@link KeyLoadingException} if the RSA algorithm is not available. - */ - public RSAPublicKeyLoader() { - try { - this.decoder = Base64.getDecoder(); - this.urlDecoder = Base64.getUrlDecoder(); - this.keyFactory = KeyFactory.getInstance("RSA"); - } catch (NoSuchAlgorithmException e) { - throw new KeyLoadingException(e); - } - } - - /** - * Loads an RSA public key from a given PEM formatted key text. - *

- * This method extracts the raw key content from the provided PEM text, decodes the - * Base64-encoded content, and generates an instance of {@link RSAPublicKey}. If the key cannot - * be loaded due to invalid specifications or types, a {@link KeyLoadingException} is thrown. - * - * @param pemKeyText the PEM formatted public key text - * @return an instance of {@link RSAPublicKey} - * @throws KeyLoadingException if the key loading process encounters an error - */ - @Override - public RSAPublicKey loadPublicKey(String pemKeyText) { - // Extract the raw key content - var rawKeyContent = CryptoUtil.getRawContent(pemKeyText); - - // Decode the Base64-encoded content - var keyBytes = decoder.decode(rawKeyContent); - - // Create an X509EncodedKeySpec from the decoded bytes - var keySpec = new X509EncodedKeySpec(keyBytes); - - // Get an RSA KeyFactory and generate the public key - try { - var _key = keyFactory.generatePublic(keySpec); - if (_key instanceof RSAPublicKey key) { - return key; - } else { - throw new KeyLoadingException("Unable to load public key from pem-formatted key text."); - } - } catch (InvalidKeySpecException e) { - throw new KeyLoadingException("Key spec is invalid.", e); - } - } - - /** - * Get the public key with given modulus and public exponent. - * - * @param modulus the modulus - * @param exponent the public exponent - * @return generated public key object from the provided key specification - * @see KeyFactory#getInstance(String) - * @see KeyFactory#generatePublic(KeySpec) - */ - @Override - public RSAPublicKey loadPublicKey(String modulus, String exponent) { - try { - var _modulus = new BigInteger(1, urlDecoder.decode(modulus)); - var _exponent = new BigInteger(1, urlDecoder.decode(exponent)); - - var keySpec = new RSAPublicKeySpec(_modulus, _exponent); - var kf = KeyFactory.getInstance("RSA"); - if (kf.generatePublic(keySpec) instanceof RSAPublicKey rsaPublicKey) { - return rsaPublicKey; - } else { - throw new KeyLoadingException("Cannot generate RSA public key with given modulus and exponent."); - } - } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { - throw new KeyLoadingException("Cannot generate RSA public key with given modulus and exponent.", e); - } - } -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/exception/KeyLoadingException.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/exception/KeyLoadingException.java deleted file mode 100644 index 4f75e5f..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/exception/KeyLoadingException.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto.exception; - -/** - * The {@code KeyLoadingException} class represents an exception that is thrown when there is an - * error loading cryptographic keys. This exception can be used to indicate various issues such as - * invalid key specifications, unsupported key algorithms, or other key loading errors. - *

- * This class extends {@link RuntimeException}, allowing it to be thrown without being declared in - * a method's {@code throws} clause. - *

- * - *

Example usage:

- *
{@code
- * try {
- *     PrivateKeyLoader keyLoader = new ECPrivateKeyLoader();
- *     ECPrivateKey privateKey = keyLoader.loadPrivateKey(pemPrivateKey);
- * } catch (KeyLoadingException e) {
- *     // Handle the exception
- *     e.printStackTrace();
- * }
- * }
- * - * @author zihluwang - * @version 3.0.0 - */ -public class KeyLoadingException extends RuntimeException { - - /** - * Creates a new instance of {@code KeyLoadingException} without a specific message or cause. - */ - public KeyLoadingException() { - } - - /** - * Creates a new instance of {@code KeyLoadingException} with the specified detail message. - * - * @param message the detail message - */ - public KeyLoadingException(String message) { - super(message); - } - - /** - * Creates a new instance of {@code KeyLoadingException} with the specified detail message - * and cause. - * - * @param message the detail message - * @param cause the cause of this exception - */ - public KeyLoadingException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance of {@code KeyLoadingException} with the specified cause. - * - * @param cause the cause of this exception - */ - public KeyLoadingException(Throwable cause) { - super(cause); - } - - /** - * Constructs a new exception with the specified detail message, cause, suppression enabled - * or disabled, and writable stack trace enabled or disabled. - * - * @param message the detail message - * @param cause the cause of this exception - * @param enableSuppression whether suppression is enabled or disabled - * @param writableStackTrace whether the stack trace should be writable - */ - public KeyLoadingException(String message, - Throwable cause, - boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/util/CryptoUtil.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/util/CryptoUtil.java deleted file mode 100644 index cf42471..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/util/CryptoUtil.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto.util; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import java.nio.charset.StandardCharsets; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; - -/** - * Utility class for cryptographic operations. - * - * @author zihluwang - * @author siujamo - * @version 3.0.0 - */ -public final class CryptoUtil { - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private CryptoUtil() { - } - - /** - * Extracts the raw content from a PEM-formatted key by removing any headers, footers, - * and newline characters. - * - *

- * This method processes the given PEM key text and returns a cleaned string containing only - * the key material. It removes the lines matching the - * {@code "-----BEGIN (EC )?(RSA )?(PRIVATE|PUBLIC) KEY-----"} and - * {@code "-----END (EC )?(RSA )?(PRIVATE|PUBLIC) KEY-----"} patterns, - * as well as any newline characters, - * resulting in a continuous string that can be used directly for cryptographic operations. - * - * @param pemKeyText the PEM-formatted key as a string, which may include headers, footers, - * and line breaks - * @return a string containing the raw key content without any unnecessary formatting or whitespace - */ - public static String getRawContent(String pemKeyText) { - return pemKeyText - .replaceAll("-----BEGIN ((EC )|(RSA ))?(PRIVATE|PUBLIC) KEY-----", "") - .replaceAll("-----END ((EC )|(RSA ))?(PRIVATE|PUBLIC) KEY-----", "") - .replace("\n", ""); - } - - /** - * Computes a Hash-based Message Authentication Code (HMAC) using the SHA-256 algorithm. - *

- * The input payload and secret key are both processed using the {@code UTF-8} charset - * to guarantee consistent results across different operating system environments. - * The final byte array output is converted into a lower-case hexadecimal string. - * - * @param payload the raw string data or message content to be authenticated - * @param secret the secret key used to sign the payload - * @return a lower-case hexadecimal string representing the computed HMAC-SHA256 signature - * @throws NoSuchAlgorithmException if the HmacSHA256 algorithm is not available in the environment - * @throws InvalidKeyException if the provided secret key is inappropriate for - * initialising the MAC - */ - public static String hmacSha256( - String payload, - String secret - ) throws NoSuchAlgorithmException, InvalidKeyException { - var secretKeySpec = new SecretKeySpec( - secret.getBytes(StandardCharsets.UTF_8), - "HmacSHA256" - ); - - var mac = Mac.getInstance("HmacSHA256"); - mac.init(secretKeySpec); - - var rawHmac = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8)); - return EncodingUtil.bytesToHex(rawHmac); - } -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/util/EncodingUtil.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/util/EncodingUtil.java deleted file mode 100644 index b105409..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/util/EncodingUtil.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto.util; - -import java.util.HexFormat; - -/** - * Utility class for handling various data encoding and formatting operations. - *

- * This class provides helper methods to convert raw binary data into standardised - * string representations (such as hexadecimal format) commonly required for - * cryptographic verification, logging, and data transmission. - *

- * This utility class is stateless and thread-safe. - * - * @author siujamo - */ -public class EncodingUtil { - - /** - * Converts an array of bytes into its corresponding hexadecimal string representation. - *

- * Each byte is converted to a two-digit hex string. If the resulting hex value - * is a single digit (i.e., less than 16), a leading '0' is automatically prepended - * to ensure a consistent and uniform format throughout the output string. - * - * @param bytes the byte array to be converted, typically the raw output of a cryptographic hash - * @return a lower-case hexadecimal string representing the input bytes - */ - public static String bytesToHex(byte[] bytes) { - return HexFormat.of().formatHex(bytes); - } -} diff --git a/crypto-toolbox/src/main/java/com/onixbyte/crypto/util/HashUtil.java b/crypto-toolbox/src/main/java/com/onixbyte/crypto/util/HashUtil.java deleted file mode 100644 index e1edfc0..0000000 --- a/crypto-toolbox/src/main/java/com/onixbyte/crypto/util/HashUtil.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.crypto.util; - -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Optional; - -/** - * The {@code HashUtil} class provides convenient methods for calculating various hash functions on - * strings, including MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512. It allows developers - * to easily obtain the hash value of a given string using different algorithms. - *

- * Example usage: - *

- * // Perform MD2 hash operation
- * String md2Hash = HashUtil.md2("someString");
- *
- * // Perform MD5 hash operation
- * String md5Hash = HashUtil.md5("someString");
- *
- * // Perform SHA-1 hash operation
- * String sha1Hash = HashUtil.sha1("someString");
- *
- * // Perform SHA-224 hash operation
- * String sha224Hash = HashUtil.sha224("someString");
- *
- * // Perform SHA-256 hash operation
- * String sha256Hash = HashUtil.sha256("someString");
- *
- * // Perform SHA-384 hash operation
- * String sha384Hash = HashUtil.sha384("someString");
- *
- * // Perform SHA-512 hash operation
- * String sha512Hash = HashUtil.sha512("someString");
- * 
- * The above examples demonstrate how to use the {@code HashUtil} class to calculate hash values - * for a given string using different algorithms. - *

- * The hash functions provided by the {@link HashUtil} are one-way hash functions, meaning the - * original data cannot be retrieved from the hash value. These hash functions are commonly used - * for data integrity checks and password storage, but they should not be used for - * encryption purposes. - * - * @author zihluwang - * @version 3.0.0 - * @see MessageDigest - */ -public final class HashUtil { - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private HashUtil() { - } - - /** - * Calculates the MD2 hash value of the specified string using the given charset. - * - * @param value the string to calculate with the MD2 algorithm - * @param charset the charset to use for encoding the string (default is UTF-8 if null) - * @return the MD2 hash value as a hexadecimal string - */ - public static String md2(String value, Charset charset) { - charset = Optional.ofNullable(charset).orElse(StandardCharsets.UTF_8); - return hash("MD2", value, charset); - } - - /** - * Calculates the MD2 hash value of the specified string using the UTF-8 charset. - * - * @param value the string to calculate with the MD2 algorithm - * @return the MD2 hash value as a hexadecimal string - */ - public static String md2(String value) { - return hash("MD2", value, StandardCharsets.UTF_8); - } - - /** - * Calculates the MD5 hash value of the specified string using the given charset. - * - * @param value the string to calculate with the MD5 algorithm - * @param charset the charset to use for encoding the string (default is UTF-8 if null) - * @return the MD5 hash value as a hexadecimal string - */ - public static String md5(String value, Charset charset) { - charset = Optional.ofNullable(charset).orElse(StandardCharsets.UTF_8); - return hash("MD5", value, charset); - } - - /** - * Calculates the MD5 hash value of the specified string using the UTF-8 charset. - * - * @param value the string to calculate with the MD5 algorithm - * @return the MD5 hash value as a hexadecimal string - */ - public static String md5(String value) { - return hash("MD5", value, StandardCharsets.UTF_8); - } - - /** - * Calculates the SHA-1 hash value of the specified string using the given charset. - * - * @param value the string to calculate with the SHA-1 algorithm - * @param charset the charset to use for encoding the string (default is UTF-8 if null) - * @return the SHA-1 hash value as a hexadecimal string - */ - public static String sha1(String value, Charset charset) { - charset = Optional.ofNullable(charset).orElse(StandardCharsets.UTF_8); - return hash("SHA-1", value, charset); - } - - /** - * Calculates the SHA-1 hash value of the specified string using the UTF-8 charset. - * - * @param value the string to calculate with the SHA-1 algorithm - * @return the SHA-1 hash value as a hexadecimal string - */ - public static String sha1(String value) { - return hash("SHA-1", value, StandardCharsets.UTF_8); - } - - /** - * Calculates the SHA-224 hash value of the specified string using the given charset. - * - * @param value the string to calculate with the SHA-225 algorithm - * @param charset the charset to use for encoding the string (default is UTF-8 if null) - * @return the SHA-224 hash value as a hexadecimal string - */ - public static String sha224(String value, Charset charset) { - charset = Optional.ofNullable(charset).orElse(StandardCharsets.UTF_8); - return hash("SHA-224", value, charset); - } - - /** - * Calculates the SHA-224 hash value of the specified string using the - * UTF-8 charset. - * - * @param value the string to calculate with the SHA-224 algorithm - * @return the SHA-224 hash value as a hexadecimal string - */ - public static String sha224(String value) { - return hash("SHA-224", value, StandardCharsets.UTF_8); - } - - /** - * Calculates the SHA-256 hash value of the specified string using the - * given charset. - * - * @param value the string to calculate with the SHA-256 algorithm - * @param charset the charset to use for encoding the string (default is UTF-8 if null) - * @return the SHA-256 hash value as a hexadecimal string - */ - public static String sha256(String value, Charset charset) { - charset = Optional.ofNullable(charset).orElse(StandardCharsets.UTF_8); - return hash("SHA-256", value, charset); - } - - /** - * Calculates the SHA-256 hash value of the specified string using the UTF-8 charset. - * - * @param value the string to calculate with the SHA-256 algorithm - * @return the SHA-256 hash value as a hexadecimal string - */ - public static String sha256(String value) { - return hash("SHA-256", value, StandardCharsets.UTF_8); - } - - /** - * Calculates the SHA-384 hash value of the specified string using the given charset. - * - * @param value the string to calculate with the SHA-384 algorithm - * @param charset the charset to use for encoding the string (default is UTF-8 if null) - * @return the SHA-384 hash value as a hexadecimal string - */ - public static String sha384(String value, Charset charset) { - charset = Optional.ofNullable(charset).orElse(StandardCharsets.UTF_8); - return hash("SHA-384", value, charset); - } - - /** - * Calculates the SHA-384 hash value of the specified string using the UTF-8 charset. - * - * @param value the string to calculate with the SHA-384 algorithm - * @return the SHA-384 hash value as a hexadecimal string - */ - public static String sha384(String value) { - return hash("SHA-384", value, StandardCharsets.UTF_8); - } - - /** - * Calculates the SHA-512 hash value of the specified string using the given charset. - * - * @param value the string to calculate with the SHA-512 algorithm - * @param charset the charset to use for encoding the string (default is UTF-8 if null) - * @return the SHA-512 hash value as a hexadecimal string - */ - public static String sha512(String value, Charset charset) { - charset = Optional.ofNullable(charset).orElse(StandardCharsets.UTF_8); - return hash("SHA-512", value, charset); - } - - /** - * Calculates the SHA-512 hash value of the specified string using the UTF-8 charset. - * - * @param value the string to calculate with the SHA-512 algorithm - * @return the SHA-512 hash value as a hexadecimal string - */ - public static String sha512(String value) { - return hash("SHA-512", value, StandardCharsets.UTF_8); - } - - /** - * Calculates the hash value of the specified string using the specified - * algorithm and charset. - * - * @param method the hash algorithm to use - * @param value the string to calculate the hash value for - * @param charset the charset to use for encoding the string (default is UTF-8 if null) - * @return the hash value as a hexadecimal string, or an empty string if the algorithm is - * not available - * @throws RuntimeException if an unknown algorithm name is provided (should not occur under - * controlled usage) - */ - private static String hash(String method, String value, Charset charset) { - try { - var messageDigest = MessageDigest.getInstance(method); - messageDigest.update(value.getBytes(charset)); - var bytes = messageDigest.digest(); - var builder = new StringBuilder(); - - for (var b : bytes) { - var str = Integer.toHexString(b & 0xff); - if (str.length() == 1) { - builder.append(0); - } - builder.append(str); - } - - return builder.toString(); - } catch (NoSuchAlgorithmException ignored) { - // This should not occur under controlled usage - // Only trusted algorithms are allowed - return ""; - } - } - -} diff --git a/crypto-toolbox/src/main/resources/logback.xml b/crypto-toolbox/src/main/resources/logback.xml deleted file mode 100644 index 85b705f..0000000 --- a/crypto-toolbox/src/main/resources/logback.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - ${COLOURFUL_OUTPUT} - - - - - - diff --git a/crypto-toolbox/src/test/resources/ec_private_key.pem b/crypto-toolbox/src/test/resources/ec_private_key.pem deleted file mode 100644 index 02dfcc8..0000000 --- a/crypto-toolbox/src/test/resources/ec_private_key.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs79JlARgXEf6EDV7 -+PHQCTHEMtqIoHOy1GZ1+ynQJ6yhRANCAARkA7GRY2i4gg8qx0XViAXUP9cPw9pn -Jg1wfrQ41FaMyqVBejNYxvaLtamErF/ySimnjafMJ+VZCh34lBj6Ez8R ------END PRIVATE KEY----- diff --git a/crypto-toolbox/src/test/resources/ec_public_key.pem b/crypto-toolbox/src/test/resources/ec_public_key.pem deleted file mode 100644 index ff0054e..0000000 --- a/crypto-toolbox/src/test/resources/ec_public_key.pem +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZAOxkWNouIIPKsdF1YgF1D/XD8Pa -ZyYNcH60ONRWjMqlQXozWMb2i7WphKxf8kopp42nzCflWQod+JQY+hM/EQ== ------END PUBLIC KEY----- diff --git a/crypto-toolbox/src/test/resources/rsa_private_key.pem b/crypto-toolbox/src/test/resources/rsa_private_key.pem deleted file mode 100644 index f8b0fc4..0000000 --- a/crypto-toolbox/src/test/resources/rsa_private_key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD4VIFYJFMAs15j -J3V3IicHd7sI2TIFqTZME40zlOlVAlPKLZmTQvZFLNgaUAAsvPi5i1DR2ywwK6Al -BfnwVnzvmDXC5mKHOz4oxOQVA6Nlp2yVaQMzidmfYNSkMtcv/4HRPsatc7K/M5l6 -pCP20DVRjkikBdIy8e9w+x6BrIFp5Q8PZc/X2BGNAUMMYACdeYH5R/A0CxqkND13 -esc4gkynMOrvZrZGHCz51usfSCqyDWWwsN+GG6LYWia4GkNlS0erQnP8gS93dfjl -e96BIfy3z7Iv+kUrf5ikNW2P8jMxLAv6LO+dcUAu9k477wIAF7Iq5KMuH/otsDOu -+h+2qXmBAgMBAAECggEAdRqcmC0g+y6arxV3fkObthjPGYAa57KBCWUa7B0n30+m -pavVRS2Jpttb2SSqwG4ouI6rARti/iBEd9EWqTCP4AieKZetFOpqCJ24lPRPRGus -d9S6jr5N4qut+vSCp37NABijZj4uJ540nTH0R7qtuhTnynl4Q0/1wwiYvTvVF1Lg -dn+I/8aRbshwDhdAOWOUe6GL7/eaCYgN8/UmlKIpp8tg0w2iWxbaFiR7gZiM41LA -M6SXXfcCas+ZVXsGbzQ3SNiVurCGuuRNcCScXS3/WoEDIb3cNtp49iOmQS+nmEoo -wh4uiEd+0+BrzxngS4o5+mKnHJnwgY0+veGVYLMR5QKBgQD9WKQmevMDU5c+NPq9 -8jaR457Fuxq1gwzeFNJdWfOc/K2LEWh+nFNFCb++EboEj6FdxWaWNMxbrmJps5gs -EoBUYy/Tl7UycDqDfiYLmDdTsf2pVjjh9jaIADiLcJ8S6wwJMZKub7Tp8UVkenAl -535MqShLUC11Y7VxLb3Tsll4XwKBgQD67mm6iCmshr/eszPfNE3ylZ+PiNa7nat7 -N7lQzBIiRJflT1kmVidC5gE+jASqH728ChkZZKxbHsjxpmWdAhLOITdXoTB4sDsd -wtV1lxkXxK9FnrpFvO3y1wZ/QsD3Z2KXxHYZqawkUETO9F3nqAXW0b2GDar5Qiyo -J3Tx/43aHwKBgDC0NMJtCoDONhowZy/S+6iqQKC0qprQec3L5PErVMkOTnKYwyTr -+pogGKt6ju9HiXcUdvdTaSIK8UJu00dNuzv94XjlBmGO78DNpJTAC4rcge5m9AKE -qdEVcclkukARzbuKuy8rrHT4/CUn4J141m/4aRWpcUPLCluato6XD9ozAoGBANvf -JhOFFgcPd3YazfvpZ9eE1XA+tfFlYYmxNRcgCU+vjO0oDvSxjutmgHae18N91pG6 -w21lskSRf/+GDwl5dKLbphOJsOA/gz07qDDGOf2CoRW+1Hcg6drcINxH0K+4DkLv -qZApBSY4k2JH6zR+HMeztn6M4WBRZLHfCPC3PUN/AoGAA3AoHbLTZvqMIKSDkP4Y -U/tTsSFDY4aYo7LG/jk8af3oPU3KyGh4ZFBd6aMmXbS8f8FjvmrM+/e+y9OOGAlq -iOl0hYrs5cJSMLW6i4KnJYuYbMkgmk3bN2t9apu64xKR94gbPrI6AGnPZp+iIzp0 -hXKe4HcuhQ3G0a2hjayiQ84= ------END PRIVATE KEY----- diff --git a/crypto-toolbox/src/test/resources/rsa_public_key.pem b/crypto-toolbox/src/test/resources/rsa_public_key.pem deleted file mode 100644 index edde855..0000000 --- a/crypto-toolbox/src/test/resources/rsa_public_key.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+FSBWCRTALNeYyd1dyIn -B3e7CNkyBak2TBONM5TpVQJTyi2Zk0L2RSzYGlAALLz4uYtQ0dssMCugJQX58FZ8 -75g1wuZihzs+KMTkFQOjZadslWkDM4nZn2DUpDLXL/+B0T7GrXOyvzOZeqQj9tA1 -UY5IpAXSMvHvcPsegayBaeUPD2XP19gRjQFDDGAAnXmB+UfwNAsapDQ9d3rHOIJM -pzDq72a2Rhws+dbrH0gqsg1lsLDfhhui2FomuBpDZUtHq0Jz/IEvd3X45XvegSH8 -t8+yL/pFK3+YpDVtj/IzMSwL+izvnXFALvZOO+8CABeyKuSjLh/6LbAzrvoftql5 -gQIDAQAB ------END PUBLIC KEY----- diff --git a/identity-generator/README.md b/identity-generator/README.md deleted file mode 100644 index d77c49d..0000000 --- a/identity-generator/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Module `guid` - -## Introduction - -Module `guid` serves as a guid creator for other `JDevKit` modules. You can also use this module as a guid creator standards. - -We have already implemented `SnowflakeGuidCreator`, you can also implement a custom guid creations by implementing `com.onixbyte.identitygenerator.IdentityGenerator`. - -## Example usage - -### A UUID creator - -```java -GuidCreator uuidCreator = (GuidCreator) UUID::randomUUID; -``` - -### A custom guid creator - -Assume that you need serial guid creator. - -```java -@Component -public class CustomGuidCreator implementes GuidCreator { - - public final RedisTemplate serialRedisTemplate; - - @Autowired - public CustomGuidCreator(RedisTemplate serialRedisTemplate) { - this.serialRedisTemplate = serialRedisTemplate; - } - - @Override public String nextId() { - return "SOME_PREFIX" + serialRedisTemplate.opsForValue().get("some_serial_key"); - } - -} -``` - diff --git a/identity-generator/build.gradle.kts b/identity-generator/build.gradle.kts deleted file mode 100644 index 1889597..0000000 --- a/identity-generator/build.gradle.kts +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import java.net.URI - -plugins { - java - id("java-library") - id("maven-publish") - id("signing") -} - -val identityGeneratorVersion: String by project - -version = identityGeneratorVersion -val projectUrl: String by project -val projectGithubUrl: String by project -val licenseName: String by project -val licenseUrl: String by project - -repositories { - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - withSourcesJar() - withJavadocJar() -} - -tasks.withType { - options.encoding = "UTF-8" -} - -tasks.withType { - exclude("logback.xml") -} - -dependencies { - compileOnly(libs.slf4j) - implementation(libs.logback) - testImplementation(platform(libs.junit.bom)) - testImplementation(libs.junit.jupiter) -} - -tasks.test { - useJUnitPlatform() -} - -publishing { - publications { - create("identityGenerator") { - groupId = group.toString() - artifactId = "identity-generator" - version = identityGeneratorVersion - - pom { - name = "OnixByte Identity Generator" - description = "The module for generating GUIDs of JDevKit." - url = projectUrl - - licenses { - license { - name = licenseName - url = licenseUrl - } - } - - scm { - connection = "scm:git:git://github.com:OnixByte/JDevKit.git" - developerConnection = "scm:git:git://github.com:OnixByte/JDevKit.git" - url = projectGithubUrl - } - - developers { - developer { - id = "zihluwang" - name = "Zihlu Wang" - email = "really@zihlu.wang" - timezone = "Asia/Hong_Kong" - } - - developer { - id = "siujamo" - name = "Siu Jam'o" - email = "jamo.siu@outlook.com" - timezone = "Asia/Shanghai" - } - } - } - - from(components["java"]) - - signing { - setRequired(project.hasProperty("signing.keyId")) - sign(publishing.publications["identityGenerator"]) - } - } - - repositories { - maven { - name = "sonatypeNexus" - url = URI(providers.gradleProperty("repo.maven-central.host").get()) - credentials { - username = providers.gradleProperty("repo.maven-central.username").get() - password = providers.gradleProperty("repo.maven-central.password").get() - } - } - } - } -} diff --git a/identity-generator/src/main/java/com/onixbyte/identitygenerator/IdentityGenerator.java b/identity-generator/src/main/java/com/onixbyte/identitygenerator/IdentityGenerator.java deleted file mode 100644 index d9317ea..0000000 --- a/identity-generator/src/main/java/com/onixbyte/identitygenerator/IdentityGenerator.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.identitygenerator; - -/** - * The {@code IdentityGenerator} is a generic interface for generating globally unique identifiers - * (GUIDs) of a specific type. - *

- * The type of ID is determined by the class implementing this interface. - *

- * - *

Example usage:

- *
{@code
- * public class StringGuidCreator implements IdentityGenerator {
- *     private final AtomicLong counter = new AtomicLong();
- *
- *     @Override
- *     public String nextId() {
- *         return UUID.randomUUID().toString() + "-" + counter.incrementAndGet();
- *     }
- * }
- *
- * public class Example {
- *     public static void main(String[] args) {
- *         IdentityGenerator guidCreator = new StringGuidCreator();
- *         String guid = guidCreator.nextId();
- *         System.out.println("Generated GUID: " + guid);
- *     }
- * }
- * }
- * - * @param this represents the type of the Global Unique Identifier - * @author zihluwang - * @version 3.0.0 - */ -public interface IdentityGenerator { - - /** - * Generates and returns the next globally unique ID. - * - * @return the next globally unique ID - */ - IdType nextId(); - -} diff --git a/identity-generator/src/main/java/com/onixbyte/identitygenerator/exceptions/TimingException.java b/identity-generator/src/main/java/com/onixbyte/identitygenerator/exceptions/TimingException.java deleted file mode 100644 index 0468f3c..0000000 --- a/identity-generator/src/main/java/com/onixbyte/identitygenerator/exceptions/TimingException.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.identitygenerator.exceptions; - -/** - * The {@code TimingException} class represents an exception that is thrown when there is an error - * related to time sequence. - *

- * Instances of TimingException can be created with or without a message and a cause. The message - * provides a description of the exception, while the cause represents the underlying cause of the - * exception and provides additional information about the error. - * - * @author zihluwang - * @since 3.0.0 - */ -public class TimingException extends RuntimeException { - - /** - * A custom exception that is thrown when there is an issue with timing or scheduling. - */ - public TimingException() { - } - - /** - * A custom exception that is thrown when there is an issue with timing or scheduling with - * customised error message. - * - * @param message customised message - */ - public TimingException(String message) { - super(message); - } - - /** - * A custom exception that is thrown when there is an issue with timing or scheduling with - * customised error message. - * - * @param message customised message - * @param cause the cause of this exception - */ - public TimingException(String message, Throwable cause) { - super(message, cause); - } - - /** - * A custom exception that is thrown when there is an issue with timing or scheduling with - * customised error message. - * - * @param cause the cause of this exception - */ - public TimingException(Throwable cause) { - super(cause); - } -} diff --git a/identity-generator/src/main/java/com/onixbyte/identitygenerator/impl/SequentialUuidGenerator.java b/identity-generator/src/main/java/com/onixbyte/identitygenerator/impl/SequentialUuidGenerator.java deleted file mode 100644 index e9cad69..0000000 --- a/identity-generator/src/main/java/com/onixbyte/identitygenerator/impl/SequentialUuidGenerator.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.identitygenerator.impl; - -import com.onixbyte.identitygenerator.IdentityGenerator; - -import java.nio.ByteBuffer; -import java.security.SecureRandom; -import java.util.UUID; - -/** - * A {@code SequentialUuidGenerator} is responsible for generating UUIDs following the - * UUID version 7 specification, which combines a timestamp with random bytes to create time-ordered - * unique identifiers. - *

- * This implementation utilises a cryptographically strong {@link SecureRandom} instance to produce - * the random component of the UUID. The first 6 bytes of the UUID encode the current timestamp in - * milliseconds, ensuring that generated UUIDs are roughly ordered by creation time. - *

- * The generated UUID adheres strictly to the layout and variant bits of UUID version 7 as defined - * in the specification. - * - * @author zihluwang - * @author siujamo - * @version 3.0.0 - */ -public class SequentialUuidGenerator implements IdentityGenerator { - - private final SecureRandom random; - - /** - * Constructs a new {@code SequentialUuidGenerator} with its own {@link SecureRandom} instance. - */ - public SequentialUuidGenerator() { - this.random = new SecureRandom(); - } - - /** - * Generates and returns the next UUID version 7 identifier. - * - * @return a {@link UUID} instance representing a unique, time-ordered identifier - */ - @Override - public UUID nextId() { - var value = randomBytes(); - var buf = ByteBuffer.wrap(value); - var high = buf.getLong(); - var low = buf.getLong(); - return new UUID(high, low); - } - - /** - * Produces a byte array representation of a UUID version 7, - * combining the current timestamp with random bytes. - * - * @return a 16-byte array conforming to UUIDv7 layout and variant bits - */ - private byte[] randomBytes() { - var value = new byte[16]; - random.nextBytes(value); - - var timestamp = ByteBuffer.allocate(Long.BYTES); - timestamp.putLong(System.currentTimeMillis()); - - System.arraycopy(timestamp.array(), 2, value, 0, 6); - - // Set version to 7 (UUIDv7) - value[6] = (byte) ((value[6] & 0x0F) | 0x70); - - // Set variant bits as per RFC 4122 - value[8] = (byte) ((value[8] & 0x3F) | 0x80); - - return value; - } -} diff --git a/identity-generator/src/main/java/com/onixbyte/identitygenerator/impl/SnowflakeIdentityGenerator.java b/identity-generator/src/main/java/com/onixbyte/identitygenerator/impl/SnowflakeIdentityGenerator.java deleted file mode 100644 index 041cef4..0000000 --- a/identity-generator/src/main/java/com/onixbyte/identitygenerator/impl/SnowflakeIdentityGenerator.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.identitygenerator.impl; - -import com.onixbyte.identitygenerator.IdentityGenerator; -import com.onixbyte.identitygenerator.exceptions.TimingException; - -import java.time.LocalDateTime; -import java.time.ZoneId; - -/** - * The {@code SnowflakeIdentityGenerator} generates unique identifiers using the - * Snowflake algorithm, which combines a timestamp, worker ID, and data centre ID to create 64-bit - * long integers. The bit distribution for the generated IDs is as follows: - *

    - *
  • 1 bit for sign
  • - *
  • 41 bits for timestamp (in milliseconds)
  • - *
  • 5 bits for data centre ID
  • - *
  • 5 bits for worker ID
  • - *
  • 12 bits for sequence number (per millisecond)
  • - *
- *

- * When initialising a {@link SnowflakeIdentityGenerator}, you must provide the worker ID and data - * centre ID, ensuring they are within the valid range defined by the bit size. The generator - * maintains an internal sequence number that increments for IDs generated within the - * same millisecond. If the system clock moves backward, an exception is thrown to prevent - * generating IDs with repeated timestamps. - * - * @author zihluwang - * @version 3.0.0 - */ -public final class SnowflakeIdentityGenerator implements IdentityGenerator { - - /** - * Default custom epoch. - * - * @value 2015-01-01T00:00:00Z - */ - private static final long DEFAULT_CUSTOM_EPOCH = 1_420_070_400_000L; - - /** - * The start epoch timestamp to generate IDs from. - */ - private final long startEpoch; - - /** - * The number of bits reserved for the data centre ID. - */ - private static final long DATA_CENTRE_ID_BITS = 5L; - - /** - * The number of bits reserved for the worker ID. - */ - private static final long WORKER_ID_BITS = 5L; - - /** - * The worker ID assigned to this generator. - */ - private final long workerId; - - /** - * The data centre ID assigned to this generator. - */ - private final long dataCentreId; - - /** - * The current sequence number. - */ - private long sequence = 0L; - - /** - * The timestamp of the last generated ID. - */ - private long lastTimestamp = -1L; - - /** - * Constructs a SnowflakeGuidGenerator with the default start epoch and custom worker ID, data - * centre ID. - * - * @param dataCentreId the data centre ID (between 0 and 31) - * @param workerId the worker ID (between 0 and 31) - */ - public SnowflakeIdentityGenerator(long dataCentreId, long workerId) { - this(dataCentreId, workerId, DEFAULT_CUSTOM_EPOCH); - } - - /** - * Constructs a SnowflakeGuidGenerator with a custom epoch, worker ID, and data centre ID. - * - * @param dataCentreId the data centre ID (between 0 and 31) - * @param workerId the worker ID (between 0 and 31) - * @param startEpoch the custom epoch timestamp (in milliseconds) to start generating IDs from - * @throws IllegalArgumentException if the start epoch is greater than the current timestamp, - * or if the worker ID or data centre ID is out of range - */ - public SnowflakeIdentityGenerator(long dataCentreId, long workerId, long startEpoch) { - if (startEpoch > currentTimestamp()) { - throw new IllegalArgumentException("Start Epoch can not be greater than current timestamp!"); - } - - var maxWorkerId = ~(-1L << WORKER_ID_BITS); - if (workerId > maxWorkerId || workerId < 0) { - throw new IllegalArgumentException(String.format("Worker Id can't be greater than %d or less than 0", - maxWorkerId)); - } - - var maxDataCentreId = ~(-1L << DATA_CENTRE_ID_BITS); - if (dataCentreId > maxDataCentreId || dataCentreId < 0) { - throw new IllegalArgumentException(String.format("Data Centre Id can't be greater than %d or less than 0", - maxDataCentreId)); - } - - this.startEpoch = startEpoch; - this.workerId = workerId; - this.dataCentreId = dataCentreId; - } - - /** - * Generates the next unique ID. - * - * @return the generated unique ID - * @throws TimingException if the system clock moves backwards, indicating an invalid sequence - * of timestamps. - */ - @Override - public synchronized Long nextId() { - var timestamp = currentTimestamp(); - - // if the current time is less than the timestamp of the last ID generation, it means that - // the system clock has been set back and an exception should be thrown - if (timestamp < lastTimestamp) { - throw new TimingException("Clock moved backwards. Refusing to generate id for %d milliseconds" - .formatted(lastTimestamp - timestamp)); - } - - // if generated at the same time, perform intra-millisecond sequences - var sequenceBits = 12L; - if (lastTimestamp == timestamp) { - var sequenceMask = ~(-1L << sequenceBits); - sequence = (sequence + 1) & sequenceMask; - // sequence overflow in milliseconds - if (sequence == 0) { - // block to the next millisecond, get a new timestamp - timestamp = awaitToNextMillis(lastTimestamp); - } - } else { - // timestamp change, sequence reset in milliseconds - sequence = 0L; - } - - // timestamp of last ID generation - lastTimestamp = timestamp; - - // shifted and put together by or operations to form a 64-bit ID - var timestampLeftShift = sequenceBits + WORKER_ID_BITS + DATA_CENTRE_ID_BITS; - var dataCentreIdShift = sequenceBits + WORKER_ID_BITS; - return ((timestamp - startEpoch) << timestampLeftShift) - | (dataCentreId << dataCentreIdShift) - | (workerId << sequenceBits) - | sequence; - } - - /** - * Blocks until the next millisecond to obtain a new timestamp. - * - * @param lastTimestamp the timestamp when the last ID was generated - * @return the current timestamp - */ - private long awaitToNextMillis(long lastTimestamp) { - var timestamp = currentTimestamp(); - while (timestamp <= lastTimestamp) { - timestamp = currentTimestamp(); - } - return timestamp; - } - - /** - * Returns the current timestamp in milliseconds. - * - * @return the current timestamp - */ - private long currentTimestamp() { - return LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); - } - -} - diff --git a/identity-generator/src/main/resources/logback.xml b/identity-generator/src/main/resources/logback.xml deleted file mode 100644 index 85b705f..0000000 --- a/identity-generator/src/main/resources/logback.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - ${COLOURFUL_OUTPUT} - - - - - - diff --git a/math-toolbox/README.md b/math-toolbox/README.md deleted file mode 100644 index 72b11d8..0000000 --- a/math-toolbox/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Math Toolkit - -**Math Toolkit** provides some mathematical algorithms and utilities such as chained high-precision -mathematical calculator and percentile statistic algorithm. diff --git a/math-toolbox/build.gradle.kts b/math-toolbox/build.gradle.kts deleted file mode 100644 index 910e86b..0000000 --- a/math-toolbox/build.gradle.kts +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import java.net.URI - -plugins { - java - id("java-library") - id("maven-publish") - id("signing") -} - -val mathToolboxVersion: String by project - -version = mathToolboxVersion -val projectUrl: String by project -val projectGithubUrl: String by project -val licenseName: String by project -val licenseUrl: String by project - -repositories { - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - withSourcesJar() - withJavadocJar() -} - -tasks.withType { - options.encoding = "UTF-8" -} - -tasks.withType { - exclude("logback.xml") -} - -dependencies { - compileOnly(libs.slf4j) - implementation(libs.logback) - testImplementation(platform(libs.junit.bom)) - testImplementation(libs.junit.jupiter) -} - -tasks.test { - useJUnitPlatform() -} - -publishing { - publications { - create("mathToolbox") { - groupId = group.toString() - artifactId = "math-toolbox" - version = mathToolboxVersion - - pom { - name = "OnixByte Math Toolbox" - description = - "This module is an easy-to-use util for mathematical calculations in Java." - url = projectUrl - - licenses { - license { - name = licenseName - url = licenseUrl - } - } - - scm { - connection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - developerConnection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - url = projectGithubUrl - } - - developers { - developer { - id = "zihluwang" - name = "Zihlu Wang" - email = "really@zihlu.wang" - timezone = "Asia/Hong_Kong" - } - - developer { - id = "siujamo" - name = "Siu Jam'o" - email = "jamo.siu@outlook.com" - timezone = "Asia/Shanghai" - } - } - } - - from(components["java"]) - - signing { - setRequired(project.hasProperty("signing.keyId")) - sign(publishing.publications["mathToolbox"]) - } - } - - repositories { - maven { - name = "sonatypeNexus" - url = URI(providers.gradleProperty("repo.maven-central.host").get()) - credentials { - username = providers.gradleProperty("repo.maven-central.username").get() - password = providers.gradleProperty("repo.maven-central.password").get() - } - } - } - } -} diff --git a/math-toolbox/src/main/java/com/onixbyte/math/Calculator.java b/math-toolbox/src/main/java/com/onixbyte/math/Calculator.java deleted file mode 100644 index 00fbd1f..0000000 --- a/math-toolbox/src/main/java/com/onixbyte/math/Calculator.java +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.math; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.Objects; -import java.util.function.BiFunction; -import java.util.function.Function; - -/** - * The {@code ChainedCalcUtil} class provides a convenient way to perform chained high-precision - * calculations using {@link BigDecimal}. It allows users to perform mathematical operations such - * as addition, subtraction, multiplication, and division with customisable precision and scale. - * By using this utility class, developers can achieve accurate results and avoid precision loss - * in their calculations. - *

- * Usage: - *

- *  // Perform addition: 3 + 4
- *  BigDecimal result1 = Calculator.startWith(3)
- *                                      .add(4)
- *                                      .getValue();
- *
- *  // Perform subtraction: 4 - 2
- *  BigDecimal result2 = Calculator.startWith(4)
- *                                      .subtract(2)
- *                                      .getValue();
- *
- *  // Perform multiplication: 3 * 6
- *  BigDecimal result3 = Calculator.startWith(3)
- *                                      .multiply(6)
- *                                      .getValue();
- *
- *  // Perform division: 6 ÷ 2
- *  BigDecimal result4 = Calculator.startWith(6)
- *                                      .divide(2)
- *                                      .getValue();
- *
- *  // Perform division with specified scale: 13 ÷ 7 with a scale of 2
- *  BigDecimal result5 = Calculator.startWith(13)
- *                                      .divideWithScale(7, 2)
- *                                      .getValue();
- *
- *  // Get int, long, or double results
- *  int intResult = Calculator.startWith(3)
- *                                .add(4)
- *                                .getInteger();
- *
- *  long longResult = Calculator.startWith(4)
- *                                  .subtract(2)
- *                                  .getLong();
- *
- *  double doubleResult = Calculator.startWith(6)
- *                                      .divide(2)
- *                                      .getDouble();
- *
- *  // Get BigDecimal result with specified scale
- *  BigDecimal result6 = Calculator.startWith(13)
- *                                      .divide(7)
- *                                      .getValue(2);
- *  
- * The above expressions perform various mathematical calculations using the - * {@code ChainedCalcUtil} class. - *

- * Note: - * The {@code ChainedCalcUtil} class internally uses {@link BigDecimal} to handle high-precision - * calculations. It is important to note that {@link BigDecimal} operations can be memory-intensive - * and may have performance implications for extremely large numbers or complex calculations. - * - * @author sunzsh - * @version 3.3.0 - * @see BigDecimal - * @since 1.0.0 - */ -public final class Calculator { - - /** - * Creates a {@code ChainedCalcUtil} instance with the specified initial value. - * - * @param value the initial value for the calculation - */ - private Calculator(Number value) { - this.value = convertBigDecimal(value, null); - } - - /** - * Starts a chained calculation with the specified initial value. - * - * @param value the initial value for the calculation - * @return a {@code ChainedCalcUtil} instance for performing chained calculations - */ - public static Calculator startWith(Number value) { - return new Calculator(value); - } - - /** - * Adds the specified value to the current value. - * - * @param other the value to be added - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator add(Number other) { - return operator(BigDecimal::add, other); - } - - /** - * Adds the specified value to the current value with a specified scale before the operation. - * - * @param other the value to be added - * @param beforeOperateScale the scale to be applied before the operation - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator add(Number other, Integer beforeOperateScale) { - return operator(BigDecimal::add, other, beforeOperateScale); - } - - /** - * Subtracts the specified value from the current value. - * - * @param other the value to be subtracted - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator subtract(Number other) { - return operator(BigDecimal::subtract, other); - } - - /** - * Subtracts the specified value from the current value with a specified scale before - * the operation. - * - * @param other the value to be subtracted - * @param beforeOperateScale the scale to be applied before the operation - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator subtract(Number other, Integer beforeOperateScale) { - return operator(BigDecimal::subtract, other, beforeOperateScale); - } - - /** - * Multiplies the current value by the specified value. - * - * @param other the value to be multiplied by - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator multiply(Number other) { - return operator(BigDecimal::multiply, other); - } - - /** - * Multiplies the current value by the specified value with a specified scale before - * the operation. - * - * @param other the value to be multiplied by - * @param beforeOperateScale the scale to be applied before the operation - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator multiply(Number other, Integer beforeOperateScale) { - return operator(BigDecimal::multiply, other, beforeOperateScale); - } - - /** - * Divides the current value by the specified value. - * - * @param other the value to divide by - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator divide(Number other) { - return operator(BigDecimal::divide, other); - } - - /** - * Divides the current value by the specified value with a specified scale before the operation. - * - * @param other the value to divide by - * @param beforeOperateScale the scale to be applied before the operation - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator divide(Number other, Integer beforeOperateScale) { - return operator(BigDecimal::divide, other, beforeOperateScale); - } - - /** - * Divides the current value by the specified value with a specified scale. - * - * @param other the value to divide by - * @param scale the scale for the result - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator divideWithScale(Number other, Integer scale) { - return baseOperator(otherValue -> - this.value.divide(otherValue, scale, RoundingMode.HALF_UP), other, null); - } - - /** - * Divides the current value by the specified value with a specified scale and a scale applied - * before the operation. - * - * @param other the value to divide by - * @param scale the scale for the result - * @param beforeOperateScale the scale to be applied before the operation - * @return a {@code ChainedCalcUtil} instance with the updated value - */ - public Calculator divideWithScale(Number other, Integer scale, Integer beforeOperateScale) { - return baseOperator((otherValue) -> - this.value.divide(otherValue, scale, RoundingMode.HALF_UP), - other, beforeOperateScale); - } - - /** - * Returns the current value as a {@link BigDecimal} with the specified scale. - * - * @param scale the scale for the result - * @return the current value as a {@link BigDecimal} with the specified scale - */ - public BigDecimal getValue(int scale) { - return value.setScale(scale, RoundingMode.HALF_UP); - } - - /** - * Returns the current value as a {@link BigDecimal}. - * - * @return the current value as a {@link BigDecimal} - */ - public BigDecimal getValue() { - return value; - } - - /** - * Returns the current value as a {@link Double}. - * - * @return the current value as a {@link Double} - */ - public double getDouble() { - return getValue().doubleValue(); - } - - /** - * Returns the current value as a {@link Double} with the specified scale. - * - * @param scale the scale for the result - * @return the current value as a {@link Double} with the specified scale - */ - public double getDouble(int scale) { - return getValue(scale).doubleValue(); - } - - /** - * Returns the current value as a {@link Long}. - * - * @return the current value as a {@link Long} - */ - public long getLong() { - return getValue().longValue(); - } - - /** - * Returns the current value as an {@link Integer}. - * - * @return the current value as an {@link Integer} - */ - public int getInteger() { - return getValue().intValue(); - } - - /** - * Applies the specified operator function to the current value and another value. - * - * @param operator the operator function to apply - * @param otherValue the value to apply the operator with - * @return a ChainedCalcUtil instance with the updated value - */ - private Calculator operator( - BiFunction operator, - Object otherValue - ) { - return operator(operator, otherValue, 9); - } - - /** - * Applies the specified operator function to the current value and another value with a - * specified scale before the operation. - * - * @param operator the operator function to apply - * @param other the value to apply the operator with - * @param beforeOperateScale the scale to be applied before the operation, - * or null if not applicable - * @return a ChainedCalcUtil instance with the updated value - */ - private Calculator operator( - BiFunction operator, - Object other, - Integer beforeOperateScale - ) { - return baseOperator( - (otherValue) -> operator.apply(this.value, otherValue), - other, - beforeOperateScale - ); - } - - /** - * Applies the specified operator function to the current value and another - * value. - * - * @param operatorFunction the operator function to apply - * @param anotherValue the value to apply the operator with - * @param beforeOperateScale the scale to be applied before the operation, - * or null if not applicable - * @return a ChainedCalcUtil instance with the updated value - */ - private synchronized Calculator baseOperator( - Function operatorFunction, - Object anotherValue, - Integer beforeOperateScale - ) { - if (Objects.isNull(anotherValue)) { - return this; - } - if (anotherValue instanceof Calculator) { - this.value = operatorFunction.apply(((Calculator) anotherValue).getValue()); - return this; - } - this.value = operatorFunction.apply(convertBigDecimal(anotherValue, beforeOperateScale)); - return this; - } - - /** - * Converts the specified value to a {@link BigDecimal}. - * - * @param value the value to convert - * @param scale the scale to apply to the resulting BigDecimal, or null if not applicable - * @return the converted BigDecimal value - */ - private BigDecimal convertBigDecimal(Object value, Integer scale) { - if (Objects.isNull(value)) { - return BigDecimal.ZERO; - } - BigDecimal res; - if (value instanceof Number num) { - res = BigDecimal.valueOf(num.doubleValue()); - } else { - try { - res = new BigDecimal(value.toString()); - } catch (NumberFormatException ignored) { - return BigDecimal.ZERO; - } - } - - if (Objects.nonNull(scale)) { - return res.setScale(scale, RoundingMode.HALF_UP); - } - return res; - } - - /** - * Final result. - */ - private BigDecimal value; - -} diff --git a/math-toolbox/src/main/java/com/onixbyte/math/PercentileCalculator.java b/math-toolbox/src/main/java/com/onixbyte/math/PercentileCalculator.java deleted file mode 100644 index f5208f7..0000000 --- a/math-toolbox/src/main/java/com/onixbyte/math/PercentileCalculator.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.math; - -import com.onixbyte.math.model.QuartileBounds; - -import java.util.List; - -/** - * A utility class that provides methods for calculating percentiles and interquartile range (IQR) - * bounds for a dataset. - *

- * This class contains static methods to: - *

    - *
  • - * Calculate a specified percentile from a list of double values using linear interpolation. - *
  • - *
  • - * Calculate interquartile bounds (Q1, Q3) and the corresponding lower and upper bounds, - * which can be used to identify outliers in the dataset. - *
  • - *
- *

- * This class is final, meaning it cannot be subclassed, and it only contains static methods, - * so instances of the class cannot be created. - *

Example usage:

- *
{@code
- * List data = Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0);
- * Double percentileValue = PercentileCalculator.calculatePercentile(data, 50.0);  // Calculates median
- * QuartileBounds bounds = PercentileCalculator.calculatePercentileBounds(data);   // Calculates IQR bounds
- * }
- * - * @author zihluwang - * @version 3.0.0 - * @since 1.6.5 - */ -public final class PercentileCalculator { - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private PercentileCalculator() { - } - - /** - * Calculates the specified percentile from a list of values. - *

- * This method takes a list of double values and calculates the given percentile using linear - * interpolation between the two closest ranks. The list is first sorted in ascending order, - * and the specified percentile is then calculated. - * - * @param values a list of {@code Double} values from which the percentile is calculated. - * @param percentile a {@code Double} representing the percentile to be calculated (e.g., 50.0 - * for the median) - * @return a {@code Double} value representing the calculated percentile - */ - public static Double calculatePercentile(List values, Double percentile) { - if (values.isEmpty()) { - throw new IllegalArgumentException("Unable to sort an empty list."); - } - var sorted = values.stream().sorted().toList(); - - var rank = percentile / 100. * (sorted.size() - 1); - var lowerIndex = (int) Math.floor(rank); - var upperIndex = (int) Math.ceil(rank); - var weight = rank - lowerIndex; - - return sorted.get(lowerIndex) * (1 - weight) + sorted.get(upperIndex) * weight; - } - - /** - * Calculates the interquartile range (IQR) and the corresponding lower and upper bounds - * based on the first (Q1) and third (Q3) quartiles of a dataset. - *

- * This method takes a list of double values, calculates the first quartile (Q1), - * the third quartile (Q3), and the interquartile range (IQR). Using the IQR, it computes - * the lower and upper bounds, which can be used to detect outliers in the dataset. - * The lower bound is defined as {@code Q1 - 1.5 * IQR}, and the upper bound is defined as - * {@code Q3 + 1.5 * IQR}. - * - * @param data a list of {@code Double} values for which the quartile bounds will be calculated - * @return a {@code QuartileBounds} object containing the calculated lower and upper bounds - */ - public static QuartileBounds calculatePercentileBounds(List data) { - var sorted = data.stream().sorted().toList(); - var q1 = calculatePercentile(sorted, 25.); - var q3 = calculatePercentile(sorted, 75.); - - var iqr = q3 - q1; - - var lowerBound = q1 - 1.5 * iqr; - var upperBound = q3 + 1.5 * iqr; - - return QuartileBounds.builder() - .upperBound(upperBound) - .lowerBound(lowerBound) - .build(); - } - -} diff --git a/math-toolbox/src/main/java/com/onixbyte/math/model/QuartileBounds.java b/math-toolbox/src/main/java/com/onixbyte/math/model/QuartileBounds.java deleted file mode 100644 index 84f359e..0000000 --- a/math-toolbox/src/main/java/com/onixbyte/math/model/QuartileBounds.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.onixbyte.math.model; - -/** - * A record representing the quartile bounds of a dataset. - *

- * This class encapsulates the lower and upper bounds of a dataset, which are typically used for - * detecting outliers in the data. The bounds are calculated based on the interquartile range (IQR) - * of the dataset. Values below the lower bound or above the upper bound may be considered outliers. - *

- * Quartile bounds consist of: - *

    - *
  • - * {@code lowerBound} - The lower bound of the dataset, typically {@code Q1 - 1.5 * IQR}. - *
  • - *
  • - * {@code upperBound} - The upper bound of the dataset, typically {@code Q3 + 1.5 * IQR}. - *
  • - *
- *

- * Example usage: - *

{@code
- * QuartileBounds bounds = QuartileBounds.builder()
- *      .lowerBound(1.5)
- *      .upperBound(7.5)
- *      .build();
- * }
- * - * @param upperBound the upper bound of the dataset - * @param lowerBound the lower bound of the dataset - * @author zihluwang - * @version 3.0.0 - * @since 1.6.5 - */ -public record QuartileBounds( - Double upperBound, - Double lowerBound -) { - - /** - * Creates a new {@link Builder} instance for building a {@code QuartileBounds} object. - *

- * The {@link Builder} pattern is used to construct the {@code QuartileBounds} object with - * optional values for the upper and lower bounds. - *

- * - * @return a new instance of the {@link Builder} class - */ - public static Builder builder() { - return new Builder(); - } - - /** - * A builder class for constructing instances of the {@code QuartileBounds} record. - *

- * The {@link Builder} pattern allows for the step-by-step construction of a - * {@code QuartileBounds} object, providing a flexible way to set values for the lower and - * upper bounds. Once the builder has the required values, the {@link #build()} method creates - * and returns a new {@code QuartileBounds} object. - *

- *

- * Example usage: - *

-     * {@code
-     * QuartileBounds bounds = QuartileBounds.builder()
-     *     .lowerBound(1.5)
-     *     .upperBound(7.5)
-     *     .build();
-     * }
-     * 
- */ - public static class Builder { - private Double upperBound; - private Double lowerBound; - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private Builder() { - } - - /** - * Sets the upper bound for the {@code QuartileBounds}. - * - * @param upperBound the upper bound of the dataset - * @return the current {@code Builder} instance, for method chaining - */ - public Builder upperBound(Double upperBound) { - this.upperBound = upperBound; - return this; - } - - /** - * Sets the lower bound for the {@code QuartileBounds}. - * - * @param lowerBound the lower bound of the dataset - * @return the current {@code Builder} instance, for method chaining - */ - public Builder lowerBound(Double lowerBound) { - this.lowerBound = lowerBound; - return this; - } - - /** - * Builds and returns a new {@code QuartileBounds} instance with the specified upper and - * lower bounds. - * - * @return a new {@code QuartileBounds} object containing the specified bounds - */ - public QuartileBounds build() { - return new QuartileBounds(upperBound, lowerBound); - } - } - -} diff --git a/math-toolbox/src/main/resources/logback.xml b/math-toolbox/src/main/resources/logback.xml deleted file mode 100644 index 85b705f..0000000 --- a/math-toolbox/src/main/resources/logback.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - ${COLOURFUL_OUTPUT} - - - - - - From 7bb9383c2b3424692ab496036153ac95e1c5282e Mon Sep 17 00:00:00 2001 From: siujamo Date: Tue, 2 Jun 2026 13:42:57 +0800 Subject: [PATCH 5/6] refactor: split modules to separate repos --- version-catalogue/README.md | 49 ------------ version-catalogue/build.gradle.kts | 119 ----------------------------- 2 files changed, 168 deletions(-) delete mode 100644 version-catalogue/README.md delete mode 100644 version-catalogue/build.gradle.kts diff --git a/version-catalogue/README.md b/version-catalogue/README.md deleted file mode 100644 index c6e4105..0000000 --- a/version-catalogue/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# Version Catalogue - -The **Version Catalogue** (Bill of Materials) is a Maven POM file provided by OnixByte to manage -dependency versions for the **OnixByte Toolbox**. By incorporating this BOM into your build -configuration, you can ensure consistent versioning across all included dependencies without -needing to specify versions explicitly in your project files. Published with Gradle metadata, -this BOM supports both Maven and Gradle projects, and this document outlines how to integrate -and use it effectively in both ecosystems. - -## Using in Maven - -Add the `version-catalogue` to your `pom.xml` under ``: - -```xml - - - - com.onixbyte - version-catalogue - 3.0.0 - pom - import - - - -``` - -Then reference any dependency built by OnixByte without a version. - -## Using in Gradle - -In your `build.gradle[.kts]`, apply the BOM using the `platform` dependency: - -```groovy -dependencies { - implementation platform('com.onixbyte:version-catalogue:3.0.0') - implementation 'com.onixbyte:common-toolbox' -} -``` - -If you are using Kotlin DSL: - -```kotlin -dependencies { - implementation(platform("com.onixbyte:version-catalogue:3.0.0")) - implementation("com.onixbyte:common-toolbox") -} -``` - diff --git a/version-catalogue/build.gradle.kts b/version-catalogue/build.gradle.kts deleted file mode 100644 index 9e90dde..0000000 --- a/version-catalogue/build.gradle.kts +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2024-2026 OnixByte - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import java.net.URI - -plugins { - id("java-platform") - id("maven-publish") - id("signing") -} - -val commonToolboxVersion: String by project -val identityGeneratorVersion: String by project -val cryptoToolboxVersion: String by project -val mathToolboxVersion: String by project -val tupleVersion: String by project -val versionCatalogueVersion: String by project - -version = versionCatalogueVersion -val projectUrl: String by project -val projectGithubUrl: String by project -val licenseName: String by project -val licenseUrl: String by project - -repositories { - mavenCentral() -} - -dependencies { - constraints { - api("com.onixbyte:common-toolbox:$commonToolboxVersion") - api("com.onixbyte:identity-generator:$identityGeneratorVersion") - api("com.onixbyte:crypto-toolbox:$cryptoToolboxVersion") - api("com.onixbyte:math-toolbox:$mathToolboxVersion") - api("com.onixbyte:tuple:$tupleVersion") - } -} - -publishing { - publications { - create("versionCatalogue") { - groupId = group.toString() - artifactId = "version-catalogue" - version = versionCatalogueVersion - - pom { - name = "OnixByte Version Catalogue" - description = "OnixByte DevKit BOM is designed to manage dependency versions centrally." - url = projectUrl - - licenses { - license { - name = licenseName - url = licenseUrl - } - } - - scm { - connection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - developerConnection = "scm:git:git://github.com:onixbyte/onixbyte-toolbox.git" - url = projectGithubUrl - } - - developers { - developer { - id = "zihluwang" - name = "Zihlu Wang" - email = "really@zihlu.wang" - timezone = "Asia/Hong_Kong" - } - - developer { - id = "siujamo" - name = "Siu Jam'o" - email = "jamo.siu@outlook.com" - timezone = "Asia/Shanghai" - } - } - } - - from(components["javaPlatform"]) - - signing { - setRequired(project.hasProperty("signing.keyId")) - sign(publishing.publications["versionCatalogue"]) - } - } - - repositories { - maven { - name = "sonatypeNexus" - url = URI(providers.gradleProperty("repo.maven-central.host").get()) - credentials { - username = providers.gradleProperty("repo.maven-central.username").get() - password = providers.gradleProperty("repo.maven-central.password").get() - } - } - } - } -} From e4e1eb824b0067cdc299f9d288276ada79740c0a Mon Sep 17 00:00:00 2001 From: siujamo Date: Tue, 2 Jun 2026 14:05:27 +0800 Subject: [PATCH 6/6] refactor: split modules to separate repos --- .github/workflows/github-packages-publish.yml | 114 +++--------------- gradle.properties | 2 +- 2 files changed, 16 insertions(+), 100 deletions(-) diff --git a/.github/workflows/github-packages-publish.yml b/.github/workflows/github-packages-publish.yml index 9894b8a..8e1abce 100644 --- a/.github/workflows/github-packages-publish.yml +++ b/.github/workflows/github-packages-publish.yml @@ -1,25 +1,18 @@ -# This workflow publishes one or more modules to Maven Central when a version tag is pushed -# to the main branch. +# Publishes onixbyte-tuple to Maven Central when a version tag is pushed to main. # -# Supported tag formats: -# /v — publish a single module (e.g. tuple/v3.3.1) -# +/v — publish multiple modules (e.g. tuple+crypto-toolbox/v3.3.1) -# v — publish all modules (e.g. v3.4.0) -# -# Valid module names: common-toolbox, tuple, identity-generator, crypto-toolbox, math-toolbox, version-catalogue +# Supported tag format: ..[-suffix] (e.g. 3.3.1, 3.3.1-alpha) -name: Publish Packages to Maven Central +name: Publish Package to Maven Central on: push: tags: - - 'v[0-9]*.[0-9]*.[0-9]*' - - '*/v[0-9]*.[0-9]*.[0-9]*' + - '[0-9]*.[0-9]*.[0-9]*' jobs: publish: name: Build and Publish - runs-on: self-hosted + runs-on: ubuntu-latest permissions: contents: read @@ -38,63 +31,12 @@ jobs: fi echo "✓ Tag ${{ github.ref_name }} is on main" - - name: Parse Tag - id: parse-tag + - name: Extract Version + id: version run: | - declare -A MODULE_PROPS=( - ["common-toolbox"]="commonToolboxVersion" - ["tuple"]="tupleVersion" - ["identity-generator"]="identityGeneratorVersion" - ["crypto-toolbox"]="cryptoToolboxVersion" - ["math-toolbox"]="mathToolboxVersion" - ["version-catalogue"]="versionCatalogueVersion" - ) - - TAG="${{ github.ref_name }}" - echo "Tag: ${TAG}" - - # [+...]/v — one or more specific modules - if [[ "${TAG}" =~ ^([a-z][a-z0-9-]+(\+[a-z][a-z0-9-]+)*)/v?([0-9]+\.[0-9]+\.[0-9]+.*)$ ]]; then - IFS='+' read -ra MODULES <<< "${BASH_REMATCH[1]}" - VERSION="${BASH_REMATCH[3]}" - - # v — all modules - else - MODULES=("common-toolbox" "tuple" "identity-generator" "crypto-toolbox" "math-toolbox" "version-catalogue") - VERSION="${TAG#v}" - fi - - # Validate all modules - for m in "${MODULES[@]}"; do - if [ -z "${MODULE_PROPS[$m]}" ]; then - echo "::error::Unknown module: ${m}" - echo "Valid modules: ${!MODULE_PROPS[*]}" - exit 1 - fi - done - - echo "version=${VERSION}" >> $GITHUB_OUTPUT - echo "count=${#MODULES[@]}" >> $GITHUB_OUTPUT - - for m in "${MODULES[@]}"; do - echo "→ ${m} @ ${VERSION}" - done - - # Store module list as a multi-line output - { - echo "modules<> $GITHUB_OUTPUT - - # Store property mappings - { - echo "props<> $GITHUB_OUTPUT + VERSION="${{ github.ref_name }}" + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "Version: ${VERSION}" - name: Setup GPG TTY run: export GPG_TTY=$(tty) @@ -134,42 +76,16 @@ jobs: - name: Build with Gradle env: - MODULES: ${{ steps.parse-tag.outputs.modules }} - PROPS: ${{ steps.parse-tag.outputs.props }} - VERSION: ${{ steps.parse-tag.outputs.version }} - run: | - declare -A MODULE_PROPS - while IFS='=' read -r key value; do - MODULE_PROPS[$key]="$value" - done <<< "$PROPS" - - while IFS= read -r MODULE; do - echo "::group::Building ${MODULE}" - PROP="${MODULE_PROPS[$MODULE]}" - ./gradlew ":${MODULE}:build" "-P${PROP}=${VERSION}" - echo "::endgroup::" - done <<< "$MODULES" + VERSION: ${{ steps.version.outputs.version }} + run: ./gradlew build "-PartefactVersion=${VERSION}" - name: List Output Items - run: ls -l ./**/build/libs + run: ls -l ./build/libs - name: Publish to Maven Central env: - MODULES: ${{ steps.parse-tag.outputs.modules }} - PROPS: ${{ steps.parse-tag.outputs.props }} - VERSION: ${{ steps.parse-tag.outputs.version }} - run: | - declare -A MODULE_PROPS - while IFS='=' read -r key value; do - MODULE_PROPS[$key]="$value" - done <<< "$PROPS" - - while IFS= read -r MODULE; do - echo "::group::Publishing ${MODULE}" - PROP="${MODULE_PROPS[$MODULE]}" - ./gradlew ":${MODULE}:publish" "-P${PROP}=${VERSION}" - echo "::endgroup::" - done <<< "$MODULES" + VERSION: ${{ steps.version.outputs.version }} + run: ./gradlew publish "-PartefactVersion=${VERSION}" - name: Create Deployment on Central Publisher Portal run: | diff --git a/gradle.properties b/gradle.properties index 310f921..119b922 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,7 +20,7 @@ # SOFTWARE. # -artefactVersion=3.3.0 +artefactVersion=3.4.0 commonToolboxVersion=3.4.0 tupleVersion=3.3.0 identityGeneratorVersion=3.3.0