docs: added docs
This commit is contained in:
+10
-8
@@ -18,12 +18,13 @@
|
||||
package com.onixbyte.devkit.core.exceptions;
|
||||
|
||||
/**
|
||||
* The {@code NotImplementedException} class is a custom runtime exception that represents a situation where a
|
||||
* particular method or functionality is not implemented or is currently unavailable in the codebase.
|
||||
* The {@code NotImplementedException} class is a custom runtime exception that represents a
|
||||
* situation where a particular method or functionality is not implemented or is currently
|
||||
* unavailable in the codebase.
|
||||
* <p>
|
||||
* This exception is typically thrown when developers need to indicate that a specific part of the code is incomplete
|
||||
* or requires further implementation. It serves as a placeholder to highlight unfinished sections of the application
|
||||
* during development and testing phases.
|
||||
* This exception is typically thrown when developers need to indicate that a specific part of the
|
||||
* code is incomplete or requires further implementation. It serves as a placeholder to highlight
|
||||
* unfinished sections of the application during development and testing phases.
|
||||
* <p>
|
||||
* Usage Example:
|
||||
* <pre>
|
||||
@@ -57,7 +58,8 @@ public class NotImplementedException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code NotImplementedException} with the specified error message and a cause for this exception.
|
||||
* Creates a new {@code NotImplementedException} with the specified error message and a cause
|
||||
* for this exception.
|
||||
*
|
||||
* @param message the error message associated with this exception
|
||||
* @param cause the cause of this exception
|
||||
@@ -76,8 +78,8 @@ public class NotImplementedException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code NotImplementedException} with the specified error message, cause, suppression flag, and
|
||||
* stack trace writable flag.
|
||||
* Creates a new {@code NotImplementedException} with the specified error message, cause,
|
||||
* suppression flag, and stack trace writable flag.
|
||||
*
|
||||
* @param message the error message associated with this
|
||||
* exception
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
-->
|
||||
|
||||
<configuration>
|
||||
<property name="COLOURFUL_OUTPUT" value="%black(%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK}) %highlight(%-5level) %black(---) %black([%10.10t]) %cyan(%-20.20logger{20}) %black(:) %msg%n"/>
|
||||
<property name="STANDARD_OUTPUT" value="%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK} %-5level %black(---) [%10.10t] %-20.20logger{20} : %msg%n"/>
|
||||
<property name="COLOURFUL_OUTPUT"
|
||||
value="%black(%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK}) %highlight(%-5level) %black(---) %black([%10.10t]) %cyan(%-20.20logger{20}) %black(:) %msg%n"/>
|
||||
<property name="STANDARD_OUTPUT"
|
||||
value="%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK} %-5level %black(---) [%10.10t] %-20.20logger{20} : %msg%n"/>
|
||||
|
||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
||||
@@ -34,7 +34,35 @@ import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* {@link AesUtil} can help you encrypt and decrypt data with specified secret by AES algorithm.
|
||||
* 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.
|
||||
* <p>
|
||||
* The utility methods in this class are useful for scenarios where data needs to be securely
|
||||
* encrypted and decrypted.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>Example usage:</b></p>
|
||||
* <pre>
|
||||
* {@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 ramdomly generated 16-character long secret
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author hubin@baomidou
|
||||
* @version 1.1.0
|
||||
@@ -54,7 +82,7 @@ public final class AesUtil {
|
||||
try {
|
||||
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(secret));
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(secret)); // set IV to secret
|
||||
return cipher.doFinal(data);
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException | UnsupportedOperationException |
|
||||
InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException |
|
||||
@@ -78,7 +106,7 @@ public final class AesUtil {
|
||||
try {
|
||||
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(secret));
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(secret)); // set IV to secret
|
||||
return cipher.doFinal(data);
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException |
|
||||
UnsupportedOperationException | InvalidKeyException |
|
||||
|
||||
@@ -22,10 +22,25 @@ import java.util.Objects;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
/**
|
||||
* A util for boolean calculations.
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* @author shaoxinke
|
||||
* <p><b>Example usage:</b></p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* boolean result1 = BoolUtil.and(true, true, false); // false
|
||||
* boolean result2 = BoolUtil.or(true, false, false); // true
|
||||
* boolean result3 = BoolUtil.not(false); // true
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author zihluwang
|
||||
* @version 1.6.2
|
||||
* @since 1.6.2
|
||||
*/
|
||||
public final class BoolUtil {
|
||||
|
||||
|
||||
@@ -32,8 +32,7 @@ import java.util.function.Supplier;
|
||||
* <p>
|
||||
* <b>Example:</b>
|
||||
* <pre>
|
||||
* // If you want to simplify an if (exp1 || exp2), you can use the
|
||||
* // following code:
|
||||
* // 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.");
|
||||
*
|
||||
@@ -49,8 +48,7 @@ import java.util.function.Supplier;
|
||||
* }, () -> {
|
||||
* // do something
|
||||
* });
|
||||
* // If you only need an if branch, you can remove the second Supplier
|
||||
* // instance.
|
||||
* // 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)
|
||||
|
||||
@@ -55,8 +55,7 @@ import java.util.Optional;
|
||||
* The above examples demonstrate how to use the {@code HashUtil} class to calculate hash values
|
||||
* for a given string using different algorithms.
|
||||
* <p>
|
||||
* <b>Note:</b>
|
||||
* The hash functions provided by the HashUtil class are one-way hash functions, meaning the
|
||||
* 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.
|
||||
|
||||
@@ -24,11 +24,61 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* {@code MapUtil} is a utility class that provides methods for converting objects to maps and maps
|
||||
* to objects.
|
||||
* The {@link MapUtil} class provides utility methods for converting between objects and maps.
|
||||
* This class leverages the {@link ObjectMapAdapter} interface to perform the conversions.
|
||||
* <p>
|
||||
* Note: Since version 1.4.2, this util class removed reflection API and transferred to a safer API.
|
||||
* Please see documentation for more information.
|
||||
* The utility methods in this class are useful for scenarios where objects need to be represented as maps for
|
||||
* serialization, deserialization, or other purposes.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>Example usage:</b></p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* public class User {
|
||||
* private String name;
|
||||
* private int age;
|
||||
*
|
||||
* // getters and setters
|
||||
* }
|
||||
*
|
||||
* public class UserMapAdapter implements ObjectMapAdapter<User> {
|
||||
* @Override
|
||||
* public Map<String, Object> toMap(User user) {
|
||||
* Map<String, Object> map = new HashMap<>();
|
||||
* map.put("name", user.getName());
|
||||
* map.put("age", user.getAge());
|
||||
* return map;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public User fromMap(Map<String, Object> 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<String, Object> 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
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author zihluwang
|
||||
* @version 1.7.0
|
||||
|
||||
@@ -20,9 +20,44 @@ package com.onixbyte.devkit.utils;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Adapts an Object to a Map, making conversion between Map and Object much more safe.
|
||||
* 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.
|
||||
*
|
||||
* @param <T> field type
|
||||
* <p>Implementations of this interface should provide the logic to convert an object of type {@code T}
|
||||
* to a {@link Map} and vice versa.</p>
|
||||
*
|
||||
* <p><b>Example usage:</b></p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* public class User {
|
||||
* private String name;
|
||||
* private int age;
|
||||
*
|
||||
* // getters and setters
|
||||
* }
|
||||
*
|
||||
* public class UserMapAdapter implements ObjectMapAdapter<User> {
|
||||
* @Override
|
||||
* public Map<String, Object> toMap(User user) {
|
||||
* Map<String, Object> map = new HashMap<>();
|
||||
* map.put("name", user.getName());
|
||||
* map.put("age", user.getAge());
|
||||
* return map;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public User fromMap(Map<String, Object> map) {
|
||||
* User user = new User();
|
||||
* user.setName((String) map.get("name"));
|
||||
* user.setAge((Integer) map.get("age"));
|
||||
* return user;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> the type of the object to be converted
|
||||
* @author zihluwang
|
||||
* @version 1.7.0
|
||||
* @since 1.4.2
|
||||
@@ -40,7 +75,7 @@ public interface ObjectMapAdapter<T> {
|
||||
/**
|
||||
* Convert a Map to an object.
|
||||
*
|
||||
* @param map the map that will be converted to Object
|
||||
* @param map the map that will be converted to an object
|
||||
* @return the object that is converted from the Map
|
||||
*/
|
||||
T toObject(Map<String, Object> map);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
* dev-utils, which contains a collection of common utility classes commonly
|
||||
* used in all Java Application development.
|
||||
*
|
||||
* @author Zihlu Wang
|
||||
* @since 1.0.0
|
||||
*/
|
||||
package com.onixbyte.devkit.utils;
|
||||
@@ -17,8 +17,10 @@
|
||||
-->
|
||||
|
||||
<configuration>
|
||||
<property name="COLOURFUL_OUTPUT" value="%black(%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK}) %highlight(%-5level) %black(---) %black([%10.10t]) %cyan(%-20.20logger{20}) %black(:) %msg%n"/>
|
||||
<property name="STANDARD_OUTPUT" value="%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK} %-5level %black(---) [%10.10t] %-20.20logger{20} : %msg%n"/>
|
||||
<property name="COLOURFUL_OUTPUT"
|
||||
value="%black(%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK}) %highlight(%-5level) %black(---) %black([%10.10t]) %cyan(%-20.20logger{20}) %black(:) %msg%n"/>
|
||||
<property name="STANDARD_OUTPUT"
|
||||
value="%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK} %-5level %black(---) [%10.10t] %-20.20logger{20} : %msg%n"/>
|
||||
|
||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
||||
@@ -18,10 +18,33 @@
|
||||
package com.onixbyte.guid;
|
||||
|
||||
/**
|
||||
* The {@code GuidCreator} is a generic interface for generating globally unique
|
||||
* identifiers (GUIDs) of a specific type.
|
||||
* The {@code GuidCreator} is a generic interface for generating globally unique identifiers (GUIDs)
|
||||
* of a specific type.
|
||||
* <p>
|
||||
* The type of ID is determined by the class implementing this interface.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>Example usage:</b></p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* public class StringGuidCreator implements GuidCreator<String> {
|
||||
* 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) {
|
||||
* GuidCreator<String> guidCreator = new StringGuidCreator();
|
||||
* String guid = guidCreator.nextId();
|
||||
* System.out.println("Generated GUID: " + guid);
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param <IdType> this represents the type of the Global Unique Identifier
|
||||
* @author Zihlu Wang
|
||||
@@ -32,9 +55,6 @@ public interface GuidCreator<IdType> {
|
||||
|
||||
/**
|
||||
* Generates and returns the next globally unique ID.
|
||||
* <p>
|
||||
* The exact implementation of how the globally unique ID is generated and
|
||||
* returned will depend on the class implementing this method.
|
||||
*
|
||||
* @return the next globally unique ID
|
||||
*/
|
||||
|
||||
@@ -18,13 +18,12 @@
|
||||
package com.onixbyte.guid.exceptions;
|
||||
|
||||
/**
|
||||
* The {@code TimingException} class represents an exception that is thrown
|
||||
* when there is an error related to time sequence.
|
||||
* The {@code TimingException} class represents an exception that is thrown when there is an error
|
||||
* related to time sequence.
|
||||
* <p>
|
||||
* 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.
|
||||
* 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 Zihlu Wang
|
||||
* @since 1.0.0
|
||||
@@ -32,15 +31,14 @@ package com.onixbyte.guid.exceptions;
|
||||
public class TimingException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* A custom exception that is thrown when there is an issue with timing or
|
||||
* scheduling.
|
||||
* 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.
|
||||
* A custom exception that is thrown when there is an issue with timing or scheduling with
|
||||
* customised error message.
|
||||
*
|
||||
* @param message customised message
|
||||
*/
|
||||
@@ -49,8 +47,8 @@ public class TimingException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom exception that is thrown when there is an issue with timing or
|
||||
* scheduling with customised error 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
|
||||
@@ -60,8 +58,8 @@ public class TimingException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom exception that is thrown when there is an issue with timing or
|
||||
* scheduling with customised error message.
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -16,25 +16,23 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains the custom exception classes related to GUID
|
||||
* generation. These exceptions are thrown when there are issues or errors
|
||||
* during the generation or processing of global unique identifiers (GUIDs).
|
||||
* This package contains the custom exception classes related to GUID generation. These exceptions
|
||||
* are thrown when there are issues or errors during the generation or processing of global unique
|
||||
* identifiers (GUIDs).
|
||||
* <p>
|
||||
* The main exception class in this package is {@link
|
||||
* com.onixbyte.guid.exceptions.TimingException}, which is a runtime
|
||||
* exception and serves as the base exception for all other custom exceptions
|
||||
* The main exception class in this package is {@link com.onixbyte.guid.exceptions.TimingException},
|
||||
* which is a runtime exception and serves as the base exception for all other custom exceptions
|
||||
* related to GUID generation.
|
||||
* <p>
|
||||
* Custom exceptions in this package provide specific information about the
|
||||
* type of error that occurred during GUID generation, making it easier for
|
||||
* developers to handle and respond to different scenarios when dealing with
|
||||
* GUIDs. They are designed to enhance the robustness and reliability of the
|
||||
* GUID generation process by providing clear and meaningful error messages to
|
||||
* Custom exceptions in this package provide specific information about the type of error that
|
||||
* occurred during GUID generation, making it easier for developers to handle and respond to
|
||||
* different scenarios when dealing with GUIDs. They are designed to enhance the robustness and
|
||||
* reliability of the GUID generation process by providing clear and meaningful error messages to
|
||||
* the developers.
|
||||
* <p>
|
||||
* Developers using the GUID generation module should be aware of the possible
|
||||
* exceptions that can be thrown and handle them appropriately to ensure smooth
|
||||
* operation and error handling in their applications.
|
||||
* Developers using the GUID generation module should be aware of the possible exceptions that can
|
||||
* be thrown and handle them appropriately to ensure smooth operation and error handling in
|
||||
* their applications.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
@@ -24,10 +24,9 @@ import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
/**
|
||||
* The {@code SnowflakeGuidCreator} 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:
|
||||
* The {@code SnowflakeGuidCreator} 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:
|
||||
* <ul>
|
||||
* <li>1 bit for sign</li>
|
||||
* <li>41 bits for timestamp (in milliseconds)</li>
|
||||
@@ -36,11 +35,10 @@ import java.time.ZoneId;
|
||||
* <li>12 bits for sequence number (per millisecond)</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* When initializing a {@link SnowflakeGuidCreator}, 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
|
||||
* When initializing a {@link SnowflakeGuidCreator}, 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 Zihlu Wang
|
||||
@@ -50,8 +48,8 @@ import java.time.ZoneId;
|
||||
public final class SnowflakeGuidCreator implements GuidCreator<Long> {
|
||||
|
||||
/**
|
||||
* Constructs a SnowflakeGuidGenerator with the default start epoch and
|
||||
* custom worker ID, data centre ID.
|
||||
* 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)
|
||||
@@ -61,16 +59,13 @@ public final class SnowflakeGuidCreator implements GuidCreator<Long> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a SnowflakeGuidGenerator with a custom epoch, worker ID, and
|
||||
* data centre ID.
|
||||
* 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
|
||||
* @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 SnowflakeGuidCreator(long dataCentreId, long workerId, long startEpoch) {
|
||||
if (startEpoch > currentTimestamp()) {
|
||||
@@ -98,37 +93,37 @@ public final class SnowflakeGuidCreator implements GuidCreator<Long> {
|
||||
* Generates the next unique ID.
|
||||
*
|
||||
* @return the generated unique ID
|
||||
* @throws TimingException if the system clock moves backwards,
|
||||
* indicating an invalid sequence of timestamps.
|
||||
* @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 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
|
||||
// if generated at the same time, perform intra-millisecond sequences
|
||||
long sequenceBits = 12L;
|
||||
if (lastTimestamp == timestamp) {
|
||||
long sequenceMask = ~(-1L << sequenceBits);
|
||||
sequence = (sequence + 1) & sequenceMask;
|
||||
// Sequence overflow in milliseconds
|
||||
// sequence overflow in milliseconds
|
||||
if (sequence == 0) {
|
||||
// Block to the next millisecond, get a new timestamp
|
||||
// block to the next millisecond, get a new timestamp
|
||||
timestamp = awaitToNextMillis(lastTimestamp);
|
||||
}
|
||||
}
|
||||
// Timestamp change, sequence reset in milliseconds
|
||||
// timestamp change, sequence reset in milliseconds
|
||||
else {
|
||||
sequence = 0L;
|
||||
}
|
||||
|
||||
// Timestamp of last ID generation
|
||||
// timestamp of last ID generation
|
||||
lastTimestamp = timestamp;
|
||||
|
||||
// shifted and put together by or operations to form a 64-bit ID
|
||||
|
||||
@@ -16,12 +16,10 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* The package provides a set of tools for generating globally unique
|
||||
* identifiers (GUIDs).
|
||||
* The package provides a set of tools for generating globally unique identifiers (GUIDs).
|
||||
* <p>
|
||||
* The goal of this library is to provide an efficient, reliable way to
|
||||
* generate globally unique identifiers without requiring any specific
|
||||
* environment or configuration.
|
||||
* The goal of this library is to provide an efficient, reliable way to generate globally unique
|
||||
* identifiers without requiring any specific environment or configuration.
|
||||
* <p>
|
||||
* Key features include:
|
||||
* <ul>
|
||||
|
||||
@@ -30,7 +30,29 @@ import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* KeyLoader can load key pairs from PEM formated content.
|
||||
* The {@code KeyLoader} class provides utility methods for loading ECDSA keys from PEM-formatted
|
||||
* key text. This class supports loading both private and public keys.
|
||||
* <p>
|
||||
* The utility methods in this class are useful for scenarios where ECDSA keys need to be loaded
|
||||
* from PEM-formatted strings for cryptographic operations.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>Example usage:</b></p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* String pemPrivateKey = """
|
||||
* -----BEGIN PRIVATE KEY-----
|
||||
* ...
|
||||
* -----END PRIVATE KEY-----""";
|
||||
* ECPrivateKey privateKey = KeyLoader.loadEcdsaPrivateKey(pemPrivateKey);
|
||||
*
|
||||
* String pemPublicKey = """
|
||||
* -----BEGIN PUBLIC KEY-----
|
||||
* ...
|
||||
* -----END PUBLIC KEY-----""";
|
||||
* ECPublicKey publicKey = KeyLoader.loadEcdsaPublicKey(pemPublicKey);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author zihluwang
|
||||
* @version 1.6.0
|
||||
|
||||
+19
-1
@@ -18,7 +18,25 @@
|
||||
package com.onixbyte.security.exception;
|
||||
|
||||
/**
|
||||
* {@code KeyLoadingException} is an exception indicating an error occurred while loading a key.
|
||||
* 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.
|
||||
* <p>
|
||||
* This class extends {@link RuntimeException}, allowing it to be thrown without being declared in a method's
|
||||
* {@code throws} clause.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>Example usage:</b></p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* try {
|
||||
* ECPrivateKey privateKey = KeyLoader.loadEcdsaPrivateKey(pemPrivateKey);
|
||||
* } catch (KeyLoadingException e) {
|
||||
* // Handle the exception
|
||||
* e.printStackTrace();
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author zihluwang
|
||||
* @version 1.6.0
|
||||
|
||||
@@ -24,10 +24,43 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@code MapUtil} is a utility class that provides methods for converting objects to maps and
|
||||
* maps to objects.
|
||||
* The {@link ReflectMapUtil} class provides utility methods for converting between objects and maps
|
||||
* using reflection. This class allows for dynamic mapping of object fields to map entries and
|
||||
* vice versa.
|
||||
* <p>
|
||||
* It also provides methods for getting and setting field values using reflection.
|
||||
* The utility methods in this class are useful for scenarios where objects need to be represented
|
||||
* as maps for serialization, deserialization, or other purposes, and where the structure of the
|
||||
* objects is not known at compile time.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>Example usage:</b></p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* public class User {
|
||||
* private String name;
|
||||
* private int age;
|
||||
*
|
||||
* // getters and setters
|
||||
* }
|
||||
*
|
||||
* public class Example {
|
||||
* public static void main(String[] args) throws IllegalAccessException {
|
||||
* User user = new User();
|
||||
* user.setName("John");
|
||||
* user.setAge(30);
|
||||
*
|
||||
* // Convert object to map
|
||||
* Map<String, Object> userMap = ReflectMapUtil.objectToMap(user);
|
||||
* System.out.println(userMap); // Output: {name=John, age=30}
|
||||
*
|
||||
* // Convert map to object
|
||||
* User newUser = ReflectMapUtil.mapToObject(userMap, User.class);
|
||||
* System.out.println(newUser.getName()); // Output: John
|
||||
* System.out.println(newUser.getAge()); // Output: 30
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author zihluwang
|
||||
* @version 1.4.2
|
||||
@@ -131,10 +164,8 @@ public final class ReflectMapUtil {
|
||||
* @param <T> the type of the field value
|
||||
* @return the value of the field in the object, or null if the field does
|
||||
* not exist or cannot be accessed
|
||||
* @throws IllegalAccessException if an error occurs while accessing the
|
||||
* field
|
||||
* @throws InvocationTargetException if an error occurs while invoking the
|
||||
* field getter method
|
||||
* @throws IllegalAccessException if an error occurs while accessing the field
|
||||
* @throws InvocationTargetException if an error occurs while invoking the field getter method
|
||||
* @throws NoSuchMethodException if the specified getter is not present
|
||||
*/
|
||||
public static <T> T getFieldValue(Object obj, String fieldName, Class<T> fieldType)
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
-->
|
||||
|
||||
<configuration>
|
||||
<property name="COLOURFUL_OUTPUT" value="%black(%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK}) %highlight(%-5level) %black(---) %black([%10.10t]) %cyan(%-20.20logger{20}) %black(:) %msg%n"/>
|
||||
<property name="STANDARD_OUTPUT" value="%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK} %-5level %black(---) [%10.10t] %-20.20logger{20} : %msg%n"/>
|
||||
<property name="COLOURFUL_OUTPUT"
|
||||
value="%black(%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK}) %highlight(%-5level) %black(---) %black([%10.10t]) %cyan(%-20.20logger{20}) %black(:) %msg%n"/>
|
||||
<property name="STANDARD_OUTPUT"
|
||||
value="%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK} %-5level %black(---) [%10.10t] %-20.20logger{20} : %msg%n"/>
|
||||
|
||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
||||
@@ -21,8 +21,8 @@ import com.onixbyte.nums.model.QuartileBounds;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A utility class that provides methods for calculating percentiles and interquartile range (IQR) bounds
|
||||
* for a dataset.
|
||||
* A utility class that provides methods for calculating percentiles and interquartile range (IQR)
|
||||
* bounds for a dataset.
|
||||
* <p>
|
||||
* This class contains static methods to:
|
||||
* <ul>
|
||||
@@ -57,12 +57,13 @@ public final class PercentileCalculator {
|
||||
/**
|
||||
* Calculates the specified percentile from a list of values.
|
||||
* <p>
|
||||
* 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.
|
||||
* 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)
|
||||
* @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<Double> values, Double percentile) {
|
||||
|
||||
@@ -20,9 +20,9 @@ package com.onixbyte.nums.model;
|
||||
/**
|
||||
* A record representing the quartile bounds of a dataset.
|
||||
* <p>
|
||||
* 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.
|
||||
* 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.
|
||||
* <p>
|
||||
* Quartile bounds consist of:
|
||||
* <ul>
|
||||
@@ -52,8 +52,8 @@ public record QuartileBounds(
|
||||
/**
|
||||
* Creates a new {@link Builder} instance for building a {@code QuartileBounds} object.
|
||||
* <p>
|
||||
* The {@link Builder} pattern is used to construct the {@code QuartileBounds} object with optional values for the
|
||||
* upper and lower bounds.
|
||||
* The {@link Builder} pattern is used to construct the {@code QuartileBounds} object with
|
||||
* optional values for the upper and lower bounds.
|
||||
* </p>
|
||||
*
|
||||
* @return a new instance of the {@link Builder} class
|
||||
@@ -65,9 +65,10 @@ public record QuartileBounds(
|
||||
/**
|
||||
* A builder class for constructing instances of the {@code QuartileBounds} record.
|
||||
* <p>
|
||||
* 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.
|
||||
* 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.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example usage:
|
||||
@@ -114,7 +115,8 @@ public record QuartileBounds(
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns a new {@code QuartileBounds} instance with the specified upper and lower bounds.
|
||||
* 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
|
||||
*/
|
||||
|
||||
+20
-25
@@ -29,39 +29,34 @@ import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* {@code PropertyGuard} is a utility class designed for encrypting
|
||||
* configuration properties in Spring Boot applications.
|
||||
* {@code PropertyGuard} is a utility class designed for encrypting configuration properties in
|
||||
* Spring Boot applications.
|
||||
* <p>
|
||||
* Spring Boot applications often need to store sensitive configuration details
|
||||
* such as database passwords, API keys, etc. To ensure that these sensitive
|
||||
* pieces of information are not exposed to the public, developers can utilize
|
||||
* the {@code PropertyGuard} class to encrypt and store them within
|
||||
* configuration files.
|
||||
* Spring Boot applications often need to store sensitive configuration details such as database
|
||||
* passwords, API keys, etc. To ensure that these sensitive pieces of information are not exposed
|
||||
* to the public, developers can utilize the {@code PropertyGuard} class to encrypt and store them
|
||||
* within configuration files.
|
||||
* <p>
|
||||
* <b>Usage</b>
|
||||
* You need a 16-char long secret for encrypting a configuration property. You
|
||||
* can get this secret on your own, or use the helper utility class by the
|
||||
* following code:
|
||||
* You need a 16-char long secret for encrypting a configuration property. You can get this secret
|
||||
* on your own, or use the helper utility class by the following code:
|
||||
* <pre>{@code
|
||||
* var secret = AesUtil.generateRandomSecret(); // Let's presume the result is
|
||||
* // "3856faef0d2d4f33"
|
||||
* var secret = AesUtil.generateRandomSecret(); // Let's presume the result is "3856faef0d2d4f33"
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Then, in {@code application.yml} or {@code application.properties}, change
|
||||
* the original value from plain text to encrypted value with the prefix
|
||||
* "<code>pg:</code>".
|
||||
* <pre>
|
||||
* # original
|
||||
* app.example-properties=Sample Value
|
||||
* Then, in {@code application.yml} or {@code application.properties}, change the original value
|
||||
* from plain text to encrypted value with the prefix "<code>pg:</code>".
|
||||
* <pre>{@code
|
||||
* # original
|
||||
* app.example-properties=Sample Value
|
||||
*
|
||||
* # encrypted with key 3856faef0d2d4f33
|
||||
* app.example-properties=pg:t4YBfv8M9ZmTzWgTi2gJqg==
|
||||
* </pre>
|
||||
* After that, before running, you need to add the command line arguments
|
||||
* "pg.key" as the following codes: {@code --pg.key=<the secret>}.
|
||||
* # encrypted with key 3856faef0d2d4f33
|
||||
* app.example-properties=pg:t4YBfv8M9ZmTzWgTi2gJqg==
|
||||
* }</pre>
|
||||
* After that, before running, you need to add the command line arguments "pg.key" as the following
|
||||
* codes: {@code --pg.key=<the secret>}.
|
||||
* <p>
|
||||
* This class is extracted from <a href="https://baomidou.com/pages/e0a5ce/"
|
||||
* >MyBatis-Plus</a>.
|
||||
* This class is extracted from <a href="https://baomidou.com/pages/e0a5ce/">MyBatis-Plus</a>.
|
||||
*
|
||||
* @author hubin@baomidou
|
||||
* @version 1.1.0
|
||||
|
||||
Reference in New Issue
Block a user