@@ -17,21 +17,12 @@
|
|||||||
|
|
||||||
package com.onixbyte.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.InvalidKeyException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,8 +35,7 @@ import java.util.UUID;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <p><b>Example usage:</b></p>
|
* <p><b>Example usage:</b></p>
|
||||||
* <pre>
|
* <pre>{@code
|
||||||
* {@code
|
|
||||||
* // Encrypting and decrypting byte array data
|
* // Encrypting and decrypting byte array data
|
||||||
* byte[] secretKey = "43f72073956d4c81".getBytes(StandardCharsets.UTF_8);
|
* byte[] secretKey = "43f72073956d4c81".getBytes(StandardCharsets.UTF_8);
|
||||||
* byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8);
|
* byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8);
|
||||||
@@ -61,9 +51,8 @@ import java.util.UUID;
|
|||||||
*
|
*
|
||||||
* // Generating a random secret key
|
* // Generating a random secret key
|
||||||
* String randomSecret = AesUtil.generateRandomSecret();
|
* String randomSecret = AesUtil.generateRandomSecret();
|
||||||
* System.out.println(randomSecret); // Output: A ramdomly generated 16-character long secret
|
* System.out.println(randomSecret); // Output: A randomly generated 16-character long secret
|
||||||
* }
|
* }</pre>
|
||||||
* </pre>
|
|
||||||
*
|
*
|
||||||
* @author hubin@baomidou
|
* @author hubin@baomidou
|
||||||
* @version 1.1.0
|
* @version 1.1.0
|
||||||
@@ -71,81 +60,61 @@ import java.util.UUID;
|
|||||||
*/
|
*/
|
||||||
public final class AesUtil {
|
public final class AesUtil {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(AesUtil.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts the data using the AES algorithm with the given secret.
|
* Encrypts the specified data using the AES algorithm with the provided secret key.
|
||||||
*
|
*
|
||||||
* @param data the data to be encrypted
|
* @param data the data to be encrypted
|
||||||
* @param secret the secret to encrypt the data
|
* @param secret the secret key used for encryption
|
||||||
* @return the encryption result or {@code null} if encryption failed
|
* @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) {
|
public static byte[] encrypt(byte[] data, byte[] secret) throws GeneralSecurityException {
|
||||||
try {
|
|
||||||
var secretKeySpec = new SecretKeySpec(new SecretKeySpec(secret, AES).getEncoded(), AES);
|
var secretKeySpec = new SecretKeySpec(new SecretKeySpec(secret, AES).getEncoded(), AES);
|
||||||
var cipher = Cipher.getInstance(AES_CBC_CIPHER);
|
var cipher = Cipher.getInstance(AES_CBC_CIPHER);
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(secret)); // set IV to secret
|
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(secret));
|
||||||
return cipher.doFinal(data);
|
return cipher.doFinal(data);
|
||||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException | UnsupportedOperationException |
|
|
||||||
InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException |
|
|
||||||
BadPaddingException exception) {
|
|
||||||
log.error(exception.getMessage());
|
|
||||||
for (var stackTraceElement : exception.getStackTrace()) {
|
|
||||||
log.error("{}", stackTraceElement.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts the data using the AES algorithm with the given secret.
|
* Decrypts the specified data using the AES algorithm with the provided secret key.
|
||||||
*
|
*
|
||||||
* @param data the data to be decrypted
|
* @param data the data to be decrypted
|
||||||
* @param secret the secret to encrypt the data
|
* @param secret the secret key used for decryption
|
||||||
* @return the decryption result or {@code null} if decryption failed
|
* @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) {
|
public static byte[] decrypt(byte[] data, byte[] secret) throws GeneralSecurityException {
|
||||||
try {
|
|
||||||
var secretKeySpec = new SecretKeySpec(new SecretKeySpec(secret, AES).getEncoded(), AES);
|
var secretKeySpec = new SecretKeySpec(new SecretKeySpec(secret, AES).getEncoded(), AES);
|
||||||
var cipher = Cipher.getInstance(AES_CBC_CIPHER);
|
var cipher = Cipher.getInstance(AES_CBC_CIPHER);
|
||||||
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(secret)); // set IV to secret
|
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(secret));
|
||||||
return cipher.doFinal(data);
|
return cipher.doFinal(data);
|
||||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException |
|
|
||||||
UnsupportedOperationException | InvalidKeyException |
|
|
||||||
InvalidAlgorithmParameterException | IllegalBlockSizeException |
|
|
||||||
BadPaddingException exception) {
|
|
||||||
log.error(exception.getMessage());
|
|
||||||
for (var stackTraceElement : exception.getStackTrace()) {
|
|
||||||
log.error("{}", stackTraceElement.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts the data using the AES algorithm with the given secret.
|
* Encrypts the specified string data using the AES algorithm with the provided secret key.
|
||||||
*
|
*
|
||||||
* @param data the data to be encrypted
|
* @param data the string data to be encrypted
|
||||||
* @param secret the secret to encrypt the data
|
* @param secret the secret key used for encryption
|
||||||
* @return the encryption result or {@code null} if encryption failed
|
* @return the encrypted data encoded in Base64
|
||||||
|
* @throws GeneralSecurityException if any cryptographic error occurs during encryption
|
||||||
*/
|
*/
|
||||||
public static String encrypt(String data, String secret) {
|
public static String encrypt(String data, String secret) throws GeneralSecurityException {
|
||||||
return Base64.getEncoder().encodeToString(encrypt(data.getBytes(StandardCharsets.UTF_8),
|
return Base64.getEncoder().encodeToString(encrypt(data.getBytes(StandardCharsets.UTF_8),
|
||||||
secret.getBytes(StandardCharsets.UTF_8)));
|
secret.getBytes(StandardCharsets.UTF_8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts the data using the AES algorithm with the given secret.
|
* Decrypts the specified Base64-encoded string data using the AES algorithm with the provided secret key.
|
||||||
*
|
*
|
||||||
* @param data the data to be decrypted
|
* @param data the Base64-encoded string data to be decrypted
|
||||||
* @param secret the secret to encrypt the data
|
* @param secret the secret key used for decryption
|
||||||
* @return the decryption result or {@code null} if decryption failed
|
* @return the decrypted string data
|
||||||
|
* @throws GeneralSecurityException if any cryptographic error occurs during decryption
|
||||||
*/
|
*/
|
||||||
public static String decrypt(String data, String secret) {
|
public static String decrypt(String data, String secret) throws GeneralSecurityException {
|
||||||
return new String(Objects.requireNonNull(
|
var decrypted = decrypt(Base64.getDecoder().decode(data.getBytes(StandardCharsets.UTF_8)),
|
||||||
decrypt(Base64.getDecoder().decode(data.getBytes()),
|
secret.getBytes(StandardCharsets.UTF_8));
|
||||||
secret.getBytes(StandardCharsets.UTF_8)))
|
return new String(decrypted, StandardCharsets.UTF_8);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package com.onixbyte.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
@@ -58,8 +55,6 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public final class Base64Util {
|
public final class Base64Util {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(Base64Util.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that there is only one Base64 Encoder.
|
* Ensure that there is only one Base64 Encoder.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package com.onixbyte.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
@@ -47,8 +44,6 @@ import java.util.function.BooleanSupplier;
|
|||||||
*/
|
*/
|
||||||
public final class BoolUtil {
|
public final class BoolUtil {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(BoolUtil.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logical and calculation.
|
* Logical and calculation.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -206,18 +206,4 @@ public final class BranchUtil {
|
|||||||
then(trueHandler, null);
|
then(trueHandler, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the boolean result.
|
|
||||||
* <p>
|
|
||||||
* <b>Note:</b> {@link BranchUtil} is not responsible for getting a raw boolean result, consider use
|
|
||||||
* {@link BoolUtil} to replace.
|
|
||||||
*
|
|
||||||
* @return the result
|
|
||||||
* @see BoolUtil
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
public boolean getResult() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package com.onixbyte.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -33,8 +30,6 @@ import java.util.function.Supplier;
|
|||||||
*/
|
*/
|
||||||
public final class CollectionUtil {
|
public final class CollectionUtil {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(CollectionUtil.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor to prevent instantiation of this utility class.
|
* Private constructor to prevent instantiation of this utility class.
|
||||||
*/
|
*/
|
||||||
@@ -68,7 +63,7 @@ public final class CollectionUtil {
|
|||||||
throw new IllegalArgumentException("Collection must not be null.");
|
throw new IllegalArgumentException("Collection must not be null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxSize < 0) {
|
if (maxSize <= 0) {
|
||||||
throw new IllegalArgumentException("maxSize must greater than 0.");
|
throw new IllegalArgumentException("maxSize must greater than 0.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,14 +17,10 @@
|
|||||||
|
|
||||||
package com.onixbyte.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,8 +66,6 @@ import java.util.Optional;
|
|||||||
*/
|
*/
|
||||||
public final class HashUtil {
|
public final class HashUtil {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(HashUtil.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the MD2 hash value of the specified string using the given charset.
|
* Calculates the MD2 hash value of the specified string using the given charset.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,114 +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.devkit.utils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A utility class providing static methods for manipulating lists.
|
|
||||||
*
|
|
||||||
* @author siujamo
|
|
||||||
* @author zihluwang
|
|
||||||
*/
|
|
||||||
public final class ListUtil {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor to prevent instantiation of this utility class.
|
|
||||||
*/
|
|
||||||
private ListUtil() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits a given List into a List of sub lists, where each sublist contains at most
|
|
||||||
* {@code maxSize} elements. The original list is not modified, and new sub lists are created
|
|
||||||
* to hold the partitioned data.
|
|
||||||
* <p>
|
|
||||||
* If the original list's size is less than or equal to {@code maxSize}, a single sublist
|
|
||||||
* containing all elements is returned. If the list is empty, an empty list of sub lists
|
|
||||||
* is returned.
|
|
||||||
*
|
|
||||||
* @param <T> the type of elements in the list
|
|
||||||
* @param originalList the list to be split, must not be null
|
|
||||||
* @param maxSize the maximum number of elements in each sublist, must be positive
|
|
||||||
* @param listFactory list factory
|
|
||||||
* @return a List of sub lists, where each sublist has at most {@code maxSize} elements
|
|
||||||
* @throws IllegalArgumentException if {@code originalList} is null or {@code maxSize} is less
|
|
||||||
* than or equal to 0
|
|
||||||
*/
|
|
||||||
public static <T> List<List<T>> chunk(List<T> originalList, int maxSize, Supplier<List<T>> listFactory) {
|
|
||||||
// check input
|
|
||||||
if (Objects.isNull(originalList)) {
|
|
||||||
throw new IllegalArgumentException("List cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxSize <= 0) {
|
|
||||||
throw new IllegalArgumentException("Max size should be greater than 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Objects.isNull(listFactory)) {
|
|
||||||
throw new IllegalArgumentException("List factory cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = new ArrayList<List<T>>();
|
|
||||||
var size = originalList.size();
|
|
||||||
|
|
||||||
// if the original list is empty or smaller than maxSize, return it as a single sublist
|
|
||||||
if (size <= maxSize) {
|
|
||||||
var singleSubList = listFactory.get();
|
|
||||||
singleSubList.addAll(originalList);
|
|
||||||
result.add(singleSubList);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// split the list
|
|
||||||
for (var i = 0; i < size; i += maxSize) {
|
|
||||||
var end = Math.min(i + maxSize, size); // ensure not to exceed list length
|
|
||||||
var subList = originalList.subList(i, end);
|
|
||||||
var subListWrapper = listFactory.get();
|
|
||||||
subListWrapper.addAll(subList);
|
|
||||||
result.add(subListWrapper); // create a new list to avoid reference issues
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits a given List into a List of sub lists, where each sublist contains at most
|
|
||||||
* {@code maxSize} elements. The original list is not modified, and new sub lists are created
|
|
||||||
* to hold the partitioned data.
|
|
||||||
* <p>
|
|
||||||
* If the original list's size is less than or equal to {@code maxSize}, a single sublist
|
|
||||||
* containing all elements is returned. If the list is empty, an empty list of sub lists
|
|
||||||
* is returned.
|
|
||||||
*
|
|
||||||
* @param <T> the type of elements in the list
|
|
||||||
* @param originalList the list to be split, must not be null
|
|
||||||
* @param maxSize the maximum number of elements in each sublist, must be positive
|
|
||||||
* @return a List of sub lists, where each sublist has at most {@code maxSize} elements
|
|
||||||
* @throws IllegalArgumentException if {@code originalList} is null or {@code maxSize} is less
|
|
||||||
* than or equal to 0
|
|
||||||
* @see #chunk(List, int, Supplier)
|
|
||||||
*/
|
|
||||||
public static <T> List<List<T>> chunk(List<T> originalList, int maxSize) {
|
|
||||||
return chunk(originalList, maxSize, ArrayList::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package com.onixbyte.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,8 +82,6 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public final class MapUtil {
|
public final class MapUtil {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(MapUtil.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an object to a map by mapping the field names to their corresponding values.
|
* Converts an object to a map by mapping the field names to their corresponding values.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package com.onixbyte.devkit.utils;
|
package com.onixbyte.devkit.utils;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,8 +31,6 @@ import java.util.stream.IntStream;
|
|||||||
*/
|
*/
|
||||||
public final class RangeUtil {
|
public final class RangeUtil {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(RangeUtil.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor to prevent instantiation of this utility class.
|
* Private constructor to prevent instantiation of this utility class.
|
||||||
*/
|
*/
|
||||||
@@ -68,7 +63,7 @@ public final class RangeUtil {
|
|||||||
*/
|
*/
|
||||||
public static IntStream range(int end) {
|
public static IntStream range(int end) {
|
||||||
if (end <= 0) {
|
if (end <= 0) {
|
||||||
throw new IllegalArgumentException("Parameter [end] should not less than 0, provided is " +
|
throw new IllegalArgumentException("Parameter [end] should not be less than or equal to 0, provided: " +
|
||||||
end);
|
end);
|
||||||
}
|
}
|
||||||
return IntStream.range(0, end);
|
return IntStream.range(0, end);
|
||||||
@@ -81,6 +76,10 @@ public final class RangeUtil {
|
|||||||
* It creates a sequential, ordered {@code IntStream} that can be used for iteration or
|
* It creates a sequential, ordered {@code IntStream} that can be used for iteration or
|
||||||
* further processing.
|
* further processing.
|
||||||
* <p>
|
* <p>
|
||||||
|
* 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.
|
||||||
|
* <p>
|
||||||
* <b>Example Usage:</b>
|
* <b>Example Usage:</b>
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* RangeUtil.range(3, 8).forEach(System.out::println);
|
* RangeUtil.range(3, 8).forEach(System.out::println);
|
||||||
@@ -91,20 +90,32 @@ public final class RangeUtil {
|
|||||||
* // 5
|
* // 5
|
||||||
* // 6
|
* // 6
|
||||||
* // 7
|
* // 7
|
||||||
|
*
|
||||||
|
* RangeUtil.range(8, 3).forEach(System.out::println);
|
||||||
|
*
|
||||||
|
* // Output:
|
||||||
|
* // 8
|
||||||
|
* // 7
|
||||||
|
* // 6
|
||||||
|
* // 5
|
||||||
|
* // 4
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @param start the starting value of the range (inclusive)
|
* @param start the starting value of the range (inclusive)
|
||||||
* @param end upper-bound of the range (exclusive)
|
* @param end upper-bound of the range (exclusive)
|
||||||
* @return an {@code IntStream} of integers from {@code 0} (inclusive) to
|
* @return an {@code IntStream} of integers in ascending or descending order, exclusive of {@code end}
|
||||||
* {@code end} (exclusive)
|
|
||||||
* @throws IllegalArgumentException if the given {@code end} value is less equal to 0
|
|
||||||
* @see IntStream
|
* @see IntStream
|
||||||
*/
|
*/
|
||||||
public static IntStream range(int start, int end) {
|
public static IntStream range(int start, int end) {
|
||||||
if (end >= start) {
|
if (start == end) {
|
||||||
throw new IllegalStateException("Parameter [start] should less than parameter [end].");
|
return IntStream.empty();
|
||||||
}
|
}
|
||||||
|
if (start < end) {
|
||||||
return IntStream.range(start, end);
|
return IntStream.range(start, end);
|
||||||
|
} else {
|
||||||
|
// Descending range (exclusive of end)
|
||||||
|
return IntStream.iterate(start, n -> n > end, n -> n - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,6 +125,8 @@ public final class RangeUtil {
|
|||||||
* It creates a sequential, ordered {@code IntStream} that can be used for iteration or
|
* It creates a sequential, ordered {@code IntStream} that can be used for iteration or
|
||||||
* further processing.
|
* further processing.
|
||||||
* <p>
|
* <p>
|
||||||
|
* The range includes both {@code start} and {@code end}.
|
||||||
|
* <p>
|
||||||
* <b>Example Usage:</b>
|
* <b>Example Usage:</b>
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* RangeUtil.rangeClosed(3, 8).forEach(System.out::println);
|
* RangeUtil.rangeClosed(3, 8).forEach(System.out::println);
|
||||||
@@ -129,9 +142,7 @@ public final class RangeUtil {
|
|||||||
*
|
*
|
||||||
* @param start the starting value of the range (inclusive)
|
* @param start the starting value of the range (inclusive)
|
||||||
* @param end upper-bound of the range (inclusive)
|
* @param end upper-bound of the range (inclusive)
|
||||||
* @return an {@code IntStream} of integers from {@code 0} (inclusive) to
|
* @return an {@code IntStream} of integers from {@code start} to {@code end} inclusive
|
||||||
* {@code end} (inclusive)
|
|
||||||
* @throws IllegalArgumentException if the given {@code end} value is less equal to 0
|
|
||||||
* @see IntStream
|
* @see IntStream
|
||||||
*/
|
*/
|
||||||
public static IntStream rangeClosed(int start, int end) {
|
public static IntStream rangeClosed(int start, int end) {
|
||||||
@@ -139,28 +150,39 @@ public final class RangeUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a stream of integers starting from the specified {@code start} value, increment by
|
* 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.
|
* the specified {@code step}, up to the specified {@code end} value.
|
||||||
* <p>
|
* <p>
|
||||||
* It creates a sequential, ordered {@code IntStream} that can be used for iteration or
|
* It creates a sequential, ordered {@code IntStream} that can be used for iteration or
|
||||||
* further processing.
|
* further processing.
|
||||||
* <p>
|
* <p>
|
||||||
|
* The stream excludes the {@code end} value.
|
||||||
|
* <p>
|
||||||
* <b>Example Usage:</b>
|
* <b>Example Usage:</b>
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* RangeUtil.range(3, 8, 2).forEach(System.out::println);
|
* RangeUtil.range(3, 10, 2).forEach(System.out::println);
|
||||||
*
|
*
|
||||||
* // Output:
|
* // Output:
|
||||||
* // 3
|
* // 3
|
||||||
* // 5
|
* // 5
|
||||||
* // 7
|
* // 7
|
||||||
|
* // 9
|
||||||
|
*
|
||||||
|
* RangeUtil.range(10, 3, -2).forEach(System.out::println);
|
||||||
|
*
|
||||||
|
* // Output:
|
||||||
|
* // 10
|
||||||
|
* // 8
|
||||||
|
* // 6
|
||||||
|
* // 4
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @param start the starting value of the range (inclusive)
|
* @param start the starting value of the range (inclusive)
|
||||||
* @param end upper-bound of the range (exclusive)
|
* @param end upper-bound of the range (exclusive)
|
||||||
* @param step the increment (or decrement) between each value
|
* @param step the increment or decrement between each value (non-zero)
|
||||||
* @return an {@code IntStream} of integers from {@code 0} (inclusive) to
|
* @return an {@code IntStream} of integers from {@code start} to {@code end} exclusive stepping by {@code step}
|
||||||
* {@code end} (exclusive)
|
* @throws IllegalArgumentException if {@code step} is zero or if {@code start} and {@code end} are inconsistent
|
||||||
* @throws IllegalArgumentException if the given {@code end} value is less equal to 0
|
* with the direction imposed by {@code step}
|
||||||
* @see IntStream
|
* @see IntStream
|
||||||
*/
|
*/
|
||||||
public static IntStream range(int start, int end, int step) {
|
public static IntStream range(int start, int end, int step) {
|
||||||
@@ -170,7 +192,7 @@ public final class RangeUtil {
|
|||||||
if ((step > 0 && start >= end) || (step < 0 && start <= end)) {
|
if ((step > 0 && start >= end) || (step < 0 && start <= end)) {
|
||||||
throw new IllegalArgumentException("Range parameters are inconsistent with the step value.");
|
throw new IllegalArgumentException("Range parameters are inconsistent with the step value.");
|
||||||
}
|
}
|
||||||
return IntStream.iterate(start, (n) -> n < end, (n) -> n + step);
|
return IntStream.iterate(start, (n) -> step > 0 ? n < end : n > end, (n) -> n + step);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* 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.devkit.utils;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* 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.devkit.utils;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* 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.devkit.utils;
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* 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.devkit.utils;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* 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.devkit.utils;
|
||||||
|
|
||||||
|
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<List<Integer>> chunks = CollectionUtil.chunk(Collections.emptyList(), 3, ArrayList::new);
|
||||||
|
assertEquals(1, chunks.size());
|
||||||
|
assertTrue(chunks.get(0).isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void chunk_CollectionSizeLessThanMaxSize_ReturnsOneSubCollectionWithAllElements() {
|
||||||
|
List<Integer> list = List.of(1, 2);
|
||||||
|
List<List<Integer>> chunks = CollectionUtil.chunk(list, 5, ArrayList::new);
|
||||||
|
assertEquals(1, chunks.size());
|
||||||
|
assertEquals(list, chunks.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void chunk_CollectionSizeEqualMaxSize_ReturnsOneSubCollectionWithAllElements() {
|
||||||
|
List<Integer> list = List.of(1, 2, 3);
|
||||||
|
List<List<Integer>> chunks = CollectionUtil.chunk(list, 3, ArrayList::new);
|
||||||
|
assertEquals(1, chunks.size());
|
||||||
|
assertEquals(list, chunks.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void chunk_CollectionSizeGreaterThanMaxSize_ReturnsMultipleSubCollections() {
|
||||||
|
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7);
|
||||||
|
int maxSize = 3;
|
||||||
|
List<List<Integer>> 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<Integer> list = new LinkedList<>(List.of(1, 2, 3, 4));
|
||||||
|
Supplier<LinkedList<Integer>> factory = LinkedList::new;
|
||||||
|
List<LinkedList<Integer>> 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<String> list = List.of("a");
|
||||||
|
List<List<String>> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* 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.devkit.utils;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class HashUtilTest {
|
||||||
|
|
||||||
|
// Test MD2 hashing with explicit charset and default charset
|
||||||
|
@Test
|
||||||
|
void testMd2() {
|
||||||
|
String input = "test";
|
||||||
|
// Known MD2 hash of "test" with UTF-8
|
||||||
|
String expectedHash = "dd34716876364a02d0195e2fb9ae2d1b";
|
||||||
|
assertEquals(expectedHash, HashUtil.md2(input, StandardCharsets.UTF_8));
|
||||||
|
assertEquals(expectedHash, HashUtil.md2(input));
|
||||||
|
// Test null charset fallback to UTF-8
|
||||||
|
assertEquals(expectedHash, HashUtil.md2(input, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test MD5 hashing with explicit charset and default charset
|
||||||
|
@Test
|
||||||
|
void testMd5() {
|
||||||
|
String input = "test";
|
||||||
|
// Known MD5 hash of "test"
|
||||||
|
String expectedHash = "098f6bcd4621d373cade4e832627b4f6";
|
||||||
|
assertEquals(expectedHash, HashUtil.md5(input, StandardCharsets.UTF_8));
|
||||||
|
assertEquals(expectedHash, HashUtil.md5(input));
|
||||||
|
assertEquals(expectedHash, HashUtil.md5(input, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test SHA-1 hashing with explicit charset and default charset
|
||||||
|
@Test
|
||||||
|
void testSha1() {
|
||||||
|
String input = "test";
|
||||||
|
// Known SHA-1 hash of "test"
|
||||||
|
String expectedHash = "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3";
|
||||||
|
assertEquals(expectedHash, HashUtil.sha1(input, StandardCharsets.UTF_8));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha1(input));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha1(input, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test SHA-224 hashing with explicit charset and default charset
|
||||||
|
@Test
|
||||||
|
void testSha224() {
|
||||||
|
String input = "test";
|
||||||
|
// Known SHA-224 hash of "test"
|
||||||
|
String expectedHash = "90a3ed9e32b2aaf4c61c410eb925426119e1a9dc53d4286ade99a809";
|
||||||
|
assertEquals(expectedHash, HashUtil.sha224(input, StandardCharsets.UTF_8));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha224(input));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha224(input, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test SHA-256 hashing with explicit charset and default charset
|
||||||
|
@Test
|
||||||
|
void testSha256() {
|
||||||
|
String input = "test";
|
||||||
|
// Known SHA-256 hash of "test"
|
||||||
|
String expectedHash = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08";
|
||||||
|
assertEquals(expectedHash, HashUtil.sha256(input, StandardCharsets.UTF_8));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha256(input));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha256(input, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test SHA-384 hashing with explicit charset and default charset
|
||||||
|
@Test
|
||||||
|
void testSha384() {
|
||||||
|
String input = "test";
|
||||||
|
// Known SHA-384 hash of "test"
|
||||||
|
String expectedHash = "768412320f7b0aa5812fce428dc4706b3cae50e02a64caa16a782249bfe8efc4b7ef1ccb126255d196047dfedf17a0a9";
|
||||||
|
assertEquals(expectedHash, HashUtil.sha384(input, StandardCharsets.UTF_8));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha384(input));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha384(input, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test SHA-512 hashing with explicit charset and default charset
|
||||||
|
@Test
|
||||||
|
void testSha512() {
|
||||||
|
String input = "test";
|
||||||
|
// Known SHA-512 hash of "test"
|
||||||
|
String expectedHash = "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff";
|
||||||
|
// remove all whitespace in expected to match format generated
|
||||||
|
expectedHash = expectedHash.replaceAll("\\s+", "");
|
||||||
|
assertEquals(expectedHash, HashUtil.sha512(input, StandardCharsets.UTF_8));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha512(input));
|
||||||
|
assertEquals(expectedHash, HashUtil.sha512(input, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test empty string input
|
||||||
|
@Test
|
||||||
|
void testEmptyString() {
|
||||||
|
String input = "";
|
||||||
|
// MD5 hash of empty string
|
||||||
|
String expectedMd5 = "d41d8cd98f00b204e9800998ecf8427e";
|
||||||
|
assertEquals(expectedMd5, HashUtil.md5(input));
|
||||||
|
// SHA-256 hash of empty string
|
||||||
|
String expectedSha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
||||||
|
assertEquals(expectedSha256, HashUtil.sha256(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test null charset fallback for one algorithm as a sample
|
||||||
|
@Test
|
||||||
|
void testNullCharsetFallsBackToUtf8() {
|
||||||
|
String input = "abc";
|
||||||
|
String hashWithNull = HashUtil.md5(input, null);
|
||||||
|
String hashWithUtf8 = HashUtil.md5(input, StandardCharsets.UTF_8);
|
||||||
|
assertEquals(hashWithUtf8, hashWithNull);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* 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.devkit.utils;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,56 +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.devkit.utils;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class TestAesUtil {
|
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(TestAesUtil.class);
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGenerateRandomSecret() {
|
|
||||||
log.info("Secret is {}", AesUtil.generateRandomSecret());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEncrypt() {
|
|
||||||
var secret = "43f72073956d4c81";
|
|
||||||
|
|
||||||
Assertions.assertEquals("IbbYZu8GtMruBURfMBVy/w==", AesUtil.encrypt("Hello World", secret));
|
|
||||||
Assertions.assertEquals("1eVA7oQpTIhI7jc+6cdkmg==", AesUtil.encrypt("OnixByte", secret));
|
|
||||||
Assertions.assertEquals("fk6oNRJK8a+Pz7zVwtlD0UQocq5c3GkRuem0Z6jdAN8=", AesUtil.encrypt("Welcome to use JDevKit!", secret));
|
|
||||||
Assertions.assertEquals("dqzGjawNcQdBpXJWk/08UQ==", AesUtil.encrypt("127.0.0.1", secret));
|
|
||||||
Assertions.assertEquals("uwQQI60yAGL91q9jCDgoeA==", AesUtil.encrypt("root", secret));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDecrypt() {
|
|
||||||
var secret = "43f72073956d4c81";
|
|
||||||
|
|
||||||
Assertions.assertEquals("Hello World", AesUtil.decrypt("IbbYZu8GtMruBURfMBVy/w==", secret));
|
|
||||||
Assertions.assertEquals("OnixByte", AesUtil.decrypt("1eVA7oQpTIhI7jc+6cdkmg==", secret));
|
|
||||||
Assertions.assertEquals("Welcome to use JDevKit!", AesUtil.decrypt("fk6oNRJK8a+Pz7zVwtlD0UQocq5c3GkRuem0Z6jdAN8=", secret));
|
|
||||||
Assertions.assertEquals("127.0.0.1", AesUtil.decrypt("dqzGjawNcQdBpXJWk/08UQ==", secret));
|
|
||||||
Assertions.assertEquals("root", AesUtil.decrypt("uwQQI60yAGL91q9jCDgoeA==", secret));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,55 +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.devkit.utils;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class TestBase64Util {
|
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(TestBase64Util.class);
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEncode() {
|
|
||||||
Assertions.assertEquals("SGVsbG8gV29ybGQ=", Base64Util.encode("Hello World"));
|
|
||||||
Assertions.assertEquals("MTI3LjAuMC4x", Base64Util.encode("127.0.0.1"));
|
|
||||||
Assertions.assertEquals("cm9vdA==", Base64Util.encode("root"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDecode() {
|
|
||||||
Assertions.assertEquals("Hello World", Base64Util.decode("SGVsbG8gV29ybGQ="));
|
|
||||||
Assertions.assertEquals("127.0.0.1", Base64Util.decode("MTI3LjAuMC4x"));
|
|
||||||
Assertions.assertEquals("root", Base64Util.decode("cm9vdA=="));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEncodeUriComponent() {
|
|
||||||
Assertions.assertEquals("aHR0cHM6Ly9nb29nbGUuY29t", Base64Util.encodeUrlComponents("https://google.com"));
|
|
||||||
Assertions.assertEquals("aHR0cDovLzEyNy4wLjAuMTo4MDgwL2FwaS91c2VyLzEyMzQ1", Base64Util.encodeUrlComponents("http://127.0.0.1:8080/api/user/12345"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDecodeUriComponent() {
|
|
||||||
Assertions.assertEquals("https://google.com", Base64Util.decodeUrlComponents("aHR0cHM6Ly9nb29nbGUuY29t"));
|
|
||||||
Assertions.assertEquals("http://127.0.0.1:8080/api/user/12345", Base64Util.decodeUrlComponents("aHR0cDovLzEyNy4wLjAuMTo4MDgwL2FwaS91c2VyLzEyMzQ1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* 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.guid.impl;
|
||||||
|
|
||||||
|
import com.onixbyte.guid.GuidCreator;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code SequentialUuidCreator} is responsible for generating UUIDs following the UUID version 7 specification, which
|
||||||
|
* combines a timestamp with random bytes to create time-ordered unique identifiers.
|
||||||
|
* <p>
|
||||||
|
* 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.
|
||||||
|
* <p>
|
||||||
|
* The generated UUID adheres strictly to the layout and variant bits of UUID version 7 as defined in the specification.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @implNote This class implements the {@link GuidCreator} interface, providing UUID instances as unique identifiers.
|
||||||
|
*/
|
||||||
|
public class SequentialUuidCreator implements GuidCreator<UUID> {
|
||||||
|
|
||||||
|
private final SecureRandom random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@code SequentialUuidCreator} with its own {@link SecureRandom} instance.
|
||||||
|
*/
|
||||||
|
public SequentialUuidCreator() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,8 +19,6 @@ package com.onixbyte.guid.impl;
|
|||||||
|
|
||||||
import com.onixbyte.guid.GuidCreator;
|
import com.onixbyte.guid.GuidCreator;
|
||||||
import com.onixbyte.guid.exceptions.TimingException;
|
import com.onixbyte.guid.exceptions.TimingException;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
@@ -49,8 +47,6 @@ import java.time.ZoneId;
|
|||||||
*/
|
*/
|
||||||
public final class SnowflakeGuidCreator implements GuidCreator<Long> {
|
public final class SnowflakeGuidCreator implements GuidCreator<Long> {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(SnowflakeGuidCreator.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a SnowflakeGuidGenerator with the default start epoch and custom worker ID, data
|
* Constructs a SnowflakeGuidGenerator with the default start epoch and custom worker ID, data
|
||||||
* centre ID.
|
* centre ID.
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ public final class PercentileCalculator {
|
|||||||
* @return a {@code Double} value representing the calculated percentile
|
* @return a {@code Double} value representing the calculated percentile
|
||||||
*/
|
*/
|
||||||
public static Double calculatePercentile(List<Double> values, Double percentile) {
|
public static Double calculatePercentile(List<Double> values, Double percentile) {
|
||||||
var sorted = values.stream().sorted().toList();
|
if (values.isEmpty()) {
|
||||||
if (sorted.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("Unable to sort an empty list.");
|
throw new IllegalArgumentException("Unable to sort an empty list.");
|
||||||
}
|
}
|
||||||
|
var sorted = values.stream().sorted().toList();
|
||||||
|
|
||||||
var rank = percentile / 100. * (sorted.size() - 1);
|
var rank = percentile / 100. * (sorted.size() - 1);
|
||||||
var lowerIndex = (int) Math.floor(rank);
|
var lowerIndex = (int) Math.floor(rank);
|
||||||
|
|||||||
Reference in New Issue
Block a user