[공통] util → framework 유틸 #2
7 changed files with 1846 additions and 0 deletions
3
.forge/ACM-CM-002-attempt-1-run-bd1b68b4d412.md
Normal file
3
.forge/ACM-CM-002-attempt-1-run-bd1b68b4d412.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# ACM-CM-002-attempt-1-run-bd1b68b4d412
|
||||
|
||||
Forge 이슈 작업 브랜치 `forge/ACM-CM-002-attempt-1-run-bd1b68b4d412`.
|
||||
|
|
@ -0,0 +1,438 @@
|
|||
package com.klaro.acquirecore.framework.util;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Static utility class for amount/money operations migrated from legacy/util_amount.c
|
||||
* Uses java.math.BigDecimal for precise monetary calculations.
|
||||
*/
|
||||
public final class AmountUtil {
|
||||
|
||||
public static final int DEFAULT_SCALE = 2;
|
||||
public static final RoundingMode DEFAULT_ROUNDING_MODE = RoundingMode.HALF_UP;
|
||||
public static final String KOREAN_WON_SYMBOL = "₩";
|
||||
public static final String USDollar_SYMBOL = "$";
|
||||
public static final String EURO_SYMBOL = "€";
|
||||
|
||||
private static final DecimalFormat KOREAN_WON_FORMAT = new DecimalFormat("#,###");
|
||||
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,###.##");
|
||||
private static final DecimalFormat CURRENCY_FORMAT = new DecimalFormat("#,###.00");
|
||||
|
||||
private AmountUtil() {
|
||||
throw new UnsupportedOperationException("Utility class cannot be instantiated");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigDecimal from a string value.
|
||||
*
|
||||
* @param value the string value to convert
|
||||
* @return the BigDecimal value
|
||||
* @throws NumberFormatException if the string is not a valid number
|
||||
*/
|
||||
public static BigDecimal of(String value) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
return new BigDecimal(value.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigDecimal from a long value.
|
||||
*
|
||||
* @param value the long value to convert
|
||||
* @return the BigDecimal value
|
||||
*/
|
||||
public static BigDecimal of(long value) {
|
||||
return BigDecimal.valueOf(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigDecimal from a double value.
|
||||
*
|
||||
* @param value the double value to convert
|
||||
* @return the BigDecimal value
|
||||
*/
|
||||
public static BigDecimal of(double value) {
|
||||
return BigDecimal.valueOf(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two BigDecimal values.
|
||||
*
|
||||
* @param a the first operand
|
||||
* @param b the second operand
|
||||
* @return the sum
|
||||
*/
|
||||
public static BigDecimal add(BigDecimal a, BigDecimal b) {
|
||||
Objects.requireNonNull(a, "a must not be null");
|
||||
Objects.requireNonNull(b, "b must not be null");
|
||||
return a.add(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts the second BigDecimal from the first.
|
||||
*
|
||||
* @param a the minuend
|
||||
* @param b the subtrahend
|
||||
* @return the difference
|
||||
*/
|
||||
public static BigDecimal subtract(BigDecimal a, BigDecimal b) {
|
||||
Objects.requireNonNull(a, "a must not be null");
|
||||
Objects.requireNonNull(b, "b must not be null");
|
||||
return a.subtract(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two BigDecimal values.
|
||||
*
|
||||
* @param a the first operand
|
||||
* @param b the second operand
|
||||
* @return the product
|
||||
*/
|
||||
public static BigDecimal multiply(BigDecimal a, BigDecimal b) {
|
||||
Objects.requireNonNull(a, "a must not be null");
|
||||
Objects.requireNonNull(b, "b must not be null");
|
||||
return a.multiply(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides the first BigDecimal by the second.
|
||||
*
|
||||
* @param dividend the dividend
|
||||
* @param divisor the divisor
|
||||
* @return the quotient
|
||||
* @throws ArithmeticException if divisor is zero
|
||||
*/
|
||||
public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor) {
|
||||
Objects.requireNonNull(dividend, "dividend must not be null");
|
||||
Objects.requireNonNull(divisor, "divisor must not be null");
|
||||
if (BigDecimal.ZERO.compareTo(divisor) == 0) {
|
||||
throw new ArithmeticException("Division by zero");
|
||||
}
|
||||
return dividend.divide(divisor, DEFAULT_SCALE, DEFAULT_ROUNDING_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides the first BigDecimal by the second with specified scale and rounding mode.
|
||||
*
|
||||
* @param dividend the dividend
|
||||
* @param divisor the divisor
|
||||
* @param scale the scale
|
||||
* @param roundingMode the rounding mode
|
||||
* @return the quotient
|
||||
* @throws ArithmeticException if divisor is zero
|
||||
*/
|
||||
public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor, int scale, RoundingMode roundingMode) {
|
||||
Objects.requireNonNull(dividend, "dividend must not be null");
|
||||
Objects.requireNonNull(divisor, "divisor must not be null");
|
||||
Objects.requireNonNull(roundingMode, "roundingMode must not be null");
|
||||
if (BigDecimal.ZERO.compareTo(divisor) == 0) {
|
||||
throw new ArithmeticException("Division by zero");
|
||||
}
|
||||
return dividend.divide(divisor, scale, roundingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds a BigDecimal to the default scale (2) using default rounding mode (HALF_UP).
|
||||
*
|
||||
* @param value the value to round
|
||||
* @return the rounded value
|
||||
*/
|
||||
public static BigDecimal round(BigDecimal value) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
return value.setScale(DEFAULT_SCALE, DEFAULT_ROUNDING_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds a BigDecimal to the specified scale using the specified rounding mode.
|
||||
*
|
||||
* @param value the value to round
|
||||
* @param scale the scale
|
||||
* @param roundingMode the rounding mode
|
||||
* @return the rounded value
|
||||
*/
|
||||
public static BigDecimal round(BigDecimal value, int scale, RoundingMode roundingMode) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
Objects.requireNonNull(roundingMode, "roundingMode must not be null");
|
||||
return value.setScale(scale, roundingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates percentage of a value.
|
||||
*
|
||||
* @param value the base value
|
||||
* @param percentage the percentage (e.g., 10 for 10%)
|
||||
* @return the percentage amount
|
||||
*/
|
||||
public static BigDecimal percentage(BigDecimal value, BigDecimal percentage) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
Objects.requireNonNull(percentage, "percentage must not be null");
|
||||
return value.multiply(percentage).divide(BigDecimal.valueOf(100), DEFAULT_SCALE, DEFAULT_ROUNDING_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates percentage of a value and adds it.
|
||||
*
|
||||
* @param value the base value
|
||||
* @param percentage the percentage to add
|
||||
* @return the value plus percentage amount
|
||||
*/
|
||||
public static BigDecimal addPercentage(BigDecimal value, BigDecimal percentage) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
Objects.requireNonNull(percentage, "percentage must not be null");
|
||||
return value.add(percentage(value, percentage));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates percentage of a value and subtracts it.
|
||||
*
|
||||
* @param value the base value
|
||||
* @param percentage the percentage to subtract
|
||||
* @return the value minus percentage amount
|
||||
*/
|
||||
public static BigDecimal subtractPercentage(BigDecimal value, BigDecimal percentage) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
Objects.requireNonNull(percentage, "percentage must not be null");
|
||||
return value.subtract(percentage(value, percentage));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a BigDecimal as a Korean Won amount (e.g., "₩1,000").
|
||||
*
|
||||
* @param amount the amount to format
|
||||
* @return the formatted string
|
||||
*/
|
||||
public static String formatKoreanWon(BigDecimal amount) {
|
||||
Objects.requireNonNull(amount, "amount must not be null");
|
||||
return KOREAN_WON_SYMBOL + KOREAN_WON_FORMAT.format(amount.setScale(0, RoundingMode.DOWN));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a BigDecimal as a currency amount with 2 decimal places.
|
||||
*
|
||||
* @param amount the amount to format
|
||||
* @return the formatted string
|
||||
*/
|
||||
public static String formatCurrency(BigDecimal amount) {
|
||||
Objects.requireNonNull(amount, "amount must not be null");
|
||||
return CURRENCY_FORMAT.format(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a BigDecimal as a decimal number.
|
||||
*
|
||||
* @param amount the amount to format
|
||||
* @return the formatted string
|
||||
*/
|
||||
public static String formatDecimal(BigDecimal amount) {
|
||||
Objects.requireNonNull(amount, "amount must not be null");
|
||||
return DECIMAL_FORMAT.format(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a BigDecimal with a custom pattern.
|
||||
*
|
||||
* @param amount the amount to format
|
||||
* @param pattern the DecimalFormat pattern
|
||||
* @return the formatted string
|
||||
*/
|
||||
public static String format(BigDecimal amount, String pattern) {
|
||||
Objects.requireNonNull(amount, "amount must not be null");
|
||||
Objects.requireNonNull(pattern, "pattern must not be null");
|
||||
DecimalFormat formatter = new DecimalFormat(pattern);
|
||||
return formatter.format(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two BigDecimal values.
|
||||
*
|
||||
* @param a the first value
|
||||
* @param b the second value
|
||||
* @return -1 if a < b, 0 if a == b, 1 if a > b
|
||||
*/
|
||||
public static int compare(BigDecimal a, BigDecimal b) {
|
||||
Objects.requireNonNull(a, "a must not be null");
|
||||
Objects.requireNonNull(b, "b must not be null");
|
||||
return a.compareTo(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the first value is greater than the second.
|
||||
*
|
||||
* @param a the first value
|
||||
* @param b the second value
|
||||
* @return true if a > b
|
||||
*/
|
||||
public static boolean isGreaterThan(BigDecimal a, BigDecimal b) {
|
||||
return compare(a, b) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the first value is less than the second.
|
||||
*
|
||||
* @param a the first value
|
||||
* @param b the second value
|
||||
* @return true if a < b
|
||||
*/
|
||||
public static boolean isLessThan(BigDecimal a, BigDecimal b) {
|
||||
return compare(a, b) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the first value is greater than or equal to the second.
|
||||
*
|
||||
* @param a the first value
|
||||
* @param b the second value
|
||||
* @return true if a >= b
|
||||
*/
|
||||
public static boolean isGreaterThanOrEqual(BigDecimal a, BigDecimal b) {
|
||||
return compare(a, b) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the first value is less than or equal to the second.
|
||||
*
|
||||
* @param a the first value
|
||||
* @param b the second value
|
||||
* @return true if a <= b
|
||||
*/
|
||||
public static boolean isLessThanOrEqual(BigDecimal a, BigDecimal b) {
|
||||
return compare(a, b) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is zero.
|
||||
*
|
||||
* @param value the value to check
|
||||
* @return true if value is zero
|
||||
*/
|
||||
public static boolean isZero(BigDecimal value) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
return BigDecimal.ZERO.compareTo(value) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is positive (greater than zero).
|
||||
*
|
||||
* @param value the value to check
|
||||
* @return true if value > 0
|
||||
*/
|
||||
public static boolean isPositive(BigDecimal value) {
|
||||
return compare(value, BigDecimal.ZERO) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is negative (less than zero).
|
||||
*
|
||||
* @param value the value to check
|
||||
* @return true if value < 0
|
||||
*/
|
||||
public static boolean isNegative(BigDecimal value) {
|
||||
return compare(value, BigDecimal.ZERO) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value.
|
||||
*
|
||||
* @param value the value
|
||||
* @return the absolute value
|
||||
*/
|
||||
public static BigDecimal abs(BigDecimal value) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
return value.abs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates the value.
|
||||
*
|
||||
* @param value the value
|
||||
* @return the negated value
|
||||
*/
|
||||
public static BigDecimal negate(BigDecimal value) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
return value.negate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum of two values.
|
||||
*
|
||||
* @param a the first value
|
||||
* @param b the second value
|
||||
* @return the maximum value
|
||||
*/
|
||||
public static BigDecimal max(BigDecimal a, BigDecimal b) {
|
||||
Objects.requireNonNull(a, "a must not be null");
|
||||
Objects.requireNonNull(b, "b must not be null");
|
||||
return a.max(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum of two values.
|
||||
*
|
||||
* @param a the first value
|
||||
* @param b the second value
|
||||
* @return the minimum value
|
||||
*/
|
||||
public static BigDecimal min(BigDecimal a, BigDecimal b) {
|
||||
Objects.requireNonNull(a, "a must not be null");
|
||||
Objects.requireNonNull(b, "b must not be null");
|
||||
return a.min(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string that may contain currency symbols and commas.
|
||||
*
|
||||
* @param value the string to parse
|
||||
* @return the parsed BigDecimal
|
||||
*/
|
||||
public static BigDecimal parseAmount(String value) {
|
||||
Objects.requireNonNull(value, "value must not be null");
|
||||
String cleaned = value.replace(KOREAN_WON_SYMBOL, "")
|
||||
.replace(USDollar_SYMBOL, "")
|
||||
.replace(EURO_SYMBOL, "")
|
||||
.replace(",", "")
|
||||
.replace(" ", "")
|
||||
.trim();
|
||||
return new BigDecimal(cleaned);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if a string is a valid amount.
|
||||
*
|
||||
* @param value the string to validate
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
public static boolean isValidAmount(String value) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
parseAmount(value);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts cents/won to decimal amount.
|
||||
*
|
||||
* @param cents the amount in cents
|
||||
* @return the decimal amount
|
||||
*/
|
||||
public static BigDecimal fromCents(long cents) {
|
||||
return BigDecimal.valueOf(cents).divide(BigDecimal.valueOf(100), DEFAULT_SCALE, DEFAULT_ROUNDING_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts decimal amount to cents/won.
|
||||
*
|
||||
* @param amount the decimal amount
|
||||
* @return the amount in cents
|
||||
*/
|
||||
public static long toCents(BigDecimal amount) {
|
||||
Objects.requireNonNull(amount, "amount must not be null");
|
||||
return amount.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.DOWN).longValue();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,311 @@
|
|||
package com.klaro.acquirecore.framework.util;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Static utility class for date operations migrated from legacy/util_date.c
|
||||
* Uses java.time.LocalDate and java.time.LocalDateTime for date handling.
|
||||
*/
|
||||
public final class DateUtil {
|
||||
|
||||
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
|
||||
public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
public static final String KOREAN_DATE_FORMAT = "yyyy년 MM월 dd일";
|
||||
public static final String ISO_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
|
||||
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT);
|
||||
private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMAT);
|
||||
private static final DateTimeFormatter KOREAN_FORMATTER = DateTimeFormatter.ofPattern(KOREAN_DATE_FORMAT);
|
||||
private static final DateTimeFormatter ISO_FORMATTER = DateTimeFormatter.ofPattern(ISO_DATE_FORMAT);
|
||||
|
||||
private DateUtil() {
|
||||
throw new UnsupportedOperationException("Utility class cannot be instantiated");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a date string using the default format (yyyy-MM-dd).
|
||||
*
|
||||
* @param dateStr the date string to parse
|
||||
* @return the parsed LocalDate
|
||||
* @throws DateTimeParseException if the string cannot be parsed
|
||||
*/
|
||||
public static LocalDate parseDate(String dateStr) {
|
||||
Objects.requireNonNull(dateStr, "dateStr must not be null");
|
||||
return LocalDate.parse(dateStr, DATE_FORMATTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a date string using the specified format pattern.
|
||||
*
|
||||
* @param dateStr the date string to parse
|
||||
* @param pattern the date format pattern
|
||||
* @return the parsed LocalDate
|
||||
* @throws DateTimeParseException if the string cannot be parsed
|
||||
*/
|
||||
public static LocalDate parseDate(String dateStr, String pattern) {
|
||||
Objects.requireNonNull(dateStr, "dateStr must not be null");
|
||||
Objects.requireNonNull(pattern, "pattern must not be null");
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return LocalDate.parse(dateStr, formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a datetime string using the default format (yyyy-MM-dd HH:mm:ss).
|
||||
*
|
||||
* @param dateTimeStr the datetime string to parse
|
||||
* @return the parsed LocalDateTime
|
||||
* @throws DateTimeParseException if the string cannot be parsed
|
||||
*/
|
||||
public static LocalDateTime parseDateTime(String dateTimeStr) {
|
||||
Objects.requireNonNull(dateTimeStr, "dateTimeStr must not be null");
|
||||
return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a datetime string using the specified format pattern.
|
||||
*
|
||||
* @param dateTimeStr the datetime string to parse
|
||||
* @param pattern the datetime format pattern
|
||||
* @return the parsed LocalDateTime
|
||||
* @throws DateTimeParseException if the string cannot be parsed
|
||||
*/
|
||||
public static LocalDateTime parseDateTime(String dateTimeStr, String pattern) {
|
||||
Objects.requireNonNull(dateTimeStr, "dateTimeStr must not be null");
|
||||
Objects.requireNonNull(pattern, "pattern must not be null");
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return LocalDateTime.parse(dateTimeStr, formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a LocalDate using the default format (yyyy-MM-dd).
|
||||
*
|
||||
* @param date the date to format
|
||||
* @return the formatted date string
|
||||
*/
|
||||
public static String formatDate(LocalDate date) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
return date.format(DATE_FORMATTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a LocalDate using the specified format pattern.
|
||||
*
|
||||
* @param date the date to format
|
||||
* @param pattern the format pattern
|
||||
* @return the formatted date string
|
||||
*/
|
||||
public static String formatDate(LocalDate date, String pattern) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
Objects.requireNonNull(pattern, "pattern must not be null");
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return date.format(formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a LocalDateTime using the default format (yyyy-MM-dd HH:mm:ss).
|
||||
*
|
||||
* @param dateTime the datetime to format
|
||||
* @return the formatted datetime string
|
||||
*/
|
||||
public static String formatDateTime(LocalDateTime dateTime) {
|
||||
Objects.requireNonNull(dateTime, "dateTime must not be null");
|
||||
return dateTime.format(DATETIME_FORMATTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a LocalDateTime using the specified format pattern.
|
||||
*
|
||||
* @param dateTime the datetime to format
|
||||
* @param pattern the format pattern
|
||||
* @return the formatted datetime string
|
||||
*/
|
||||
public static String formatDateTime(LocalDateTime dateTime, String pattern) {
|
||||
Objects.requireNonNull(dateTime, "dateTime must not be null");
|
||||
Objects.requireNonNull(pattern, "pattern must not be null");
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return dateTime.format(formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a LocalDate in Korean date format (yyyy년 MM월 dd일).
|
||||
*
|
||||
* @param date the date to format
|
||||
* @return the formatted Korean date string
|
||||
*/
|
||||
public static String formatDateKorean(LocalDate date) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
return date.format(KOREAN_FORMATTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the number of days between two dates.
|
||||
*
|
||||
* @param startDate the start date
|
||||
* @param endDate the end date
|
||||
* @return the number of days between the dates
|
||||
*/
|
||||
public static long daysBetween(LocalDate startDate, LocalDate endDate) {
|
||||
Objects.requireNonNull(startDate, "startDate must not be null");
|
||||
Objects.requireNonNull(endDate, "endDate must not be null");
|
||||
return ChronoUnit.DAYS.between(startDate, endDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds days to a date.
|
||||
*
|
||||
* @param date the base date
|
||||
* @param days the number of days to add (can be negative)
|
||||
* @return the resulting date
|
||||
*/
|
||||
public static LocalDate addDays(LocalDate date, long days) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
return date.plusDays(days);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds months to a date.
|
||||
*
|
||||
* @param date the base date
|
||||
* @param months the number of months to add (can be negative)
|
||||
* @return the resulting date
|
||||
*/
|
||||
public static LocalDate addMonths(LocalDate date, long months) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
return date.plusMonths(months);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds years to a date.
|
||||
*
|
||||
* @param date the base date
|
||||
* @param years the number of years to add (can be negative)
|
||||
* @return the resulting date
|
||||
*/
|
||||
public static LocalDate addYears(LocalDate date, long years) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
return date.plusYears(years);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a date is before another date.
|
||||
*
|
||||
* @param date the date to check
|
||||
* @param dateToCompare the date to compare against
|
||||
* @return true if date is before dateToCompare
|
||||
*/
|
||||
public static boolean isBefore(LocalDate date, LocalDate dateToCompare) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
Objects.requireNonNull(dateToCompare, "dateToCompare must not be null");
|
||||
return date.isBefore(dateToCompare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a date is after another date.
|
||||
*
|
||||
* @param date the date to check
|
||||
* @param dateToCompare the date to compare against
|
||||
* @return true if date is after dateToCompare
|
||||
*/
|
||||
public static boolean isAfter(LocalDate date, LocalDate dateToCompare) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
Objects.requireNonNull(dateToCompare, "dateToCompare must not be null");
|
||||
return date.isAfter(dateToCompare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a date is between two other dates (inclusive).
|
||||
*
|
||||
* @param date the date to check
|
||||
* @param startDate the start of the range
|
||||
* @param endDate the end of the range
|
||||
* @return true if date is between startDate and endDate (inclusive)
|
||||
*/
|
||||
public static boolean isBetween(LocalDate date, LocalDate startDate, LocalDate endDate) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
Objects.requireNonNull(startDate, "startDate must not be null");
|
||||
Objects.requireNonNull(endDate, "endDate must not be null");
|
||||
return !date.isBefore(startDate) && !date.isAfter(endDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the start of the day for a given date.
|
||||
*
|
||||
* @param date the date
|
||||
* @return the start of the day as LocalDateTime (00:00:00)
|
||||
*/
|
||||
public static LocalDateTime startOfDay(LocalDate date) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
return date.atStartOfDay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the end of the day for a given date.
|
||||
*
|
||||
* @param date the date
|
||||
* @return the end of the day as LocalDateTime (23:59:59.999999999)
|
||||
*/
|
||||
public static LocalDateTime endOfDay(LocalDate date) {
|
||||
Objects.requireNonNull(date, "date must not be null");
|
||||
return date.atTime(23, 59, 59, 999999999);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets today's date.
|
||||
*
|
||||
* @return the current date
|
||||
*/
|
||||
public static LocalDate today() {
|
||||
return LocalDate.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current datetime.
|
||||
*
|
||||
* @return the current datetime
|
||||
*/
|
||||
public static LocalDateTime now() {
|
||||
return LocalDateTime.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if a string is a valid date in the default format.
|
||||
*
|
||||
* @param dateStr the date string to validate
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
public static boolean isValidDate(String dateStr) {
|
||||
if (dateStr == null || dateStr.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
parseDate(dateStr);
|
||||
return true;
|
||||
} catch (DateTimeParseException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if a string is a valid date in the specified format.
|
||||
*
|
||||
* @param dateStr the date string to validate
|
||||
* @param pattern the expected format pattern
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
public static boolean isValidDate(String dateStr, String pattern) {
|
||||
if (dateStr == null || dateStr.isEmpty() || pattern == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
parseDate(dateStr, pattern);
|
||||
return true;
|
||||
} catch (DateTimeParseException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,507 @@
|
|||
package com.klaro.acquirecore.framework.util;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Static utility class for message encoding/decoding migrated from legacy/util_msg.c
|
||||
* Uses java.util.Base64 and java.nio.charset for codec operations.
|
||||
*/
|
||||
public final class MessageUtil {
|
||||
|
||||
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
||||
public static final Charset EUC_KR_CHARSET = Charset.forName("EUC-KR");
|
||||
public static final Charset ISO_8859_1_CHARSET = StandardCharsets.ISO_8859_1;
|
||||
|
||||
private static final Pattern EMAIL_PATTERN = Pattern.compile(
|
||||
"^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$"
|
||||
);
|
||||
private static final Pattern PHONE_PATTERN = Pattern.compile(
|
||||
"^\\d{2,4}-\\d{3,4}-\\d{4}$|^\\d{10,11}$"
|
||||
);
|
||||
private static final Pattern KOREAN_PHONE_PATTERN = Pattern.compile(
|
||||
"^01[016789]-\\d{3,4}-\\d{4}$"
|
||||
);
|
||||
|
||||
private MessageUtil() {
|
||||
throw new UnsupportedOperationException("Utility class cannot be instantiated");
|
||||
}
|
||||
|
||||
// ==================== Base64 Encoding/Decoding ====================
|
||||
|
||||
/**
|
||||
* Encodes a string to Base64.
|
||||
*
|
||||
* @param input the string to encode
|
||||
* @return the Base64 encoded string
|
||||
*/
|
||||
public static String encodeBase64(String input) {
|
||||
Objects.requireNonNull(input, "input must not be null");
|
||||
return Base64.getEncoder().encodeToString(input.getBytes(DEFAULT_CHARSET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a string to Base64 with specified charset.
|
||||
*
|
||||
* @param input the string to encode
|
||||
* @param charset the charset to use
|
||||
* @return the Base64 encoded string
|
||||
*/
|
||||
public static String encodeBase64(String input, Charset charset) {
|
||||
Objects.requireNonNull(input, "input must not be null");
|
||||
Objects.requireNonNull(charset, "charset must not be null");
|
||||
return Base64.getEncoder().encodeToString(input.getBytes(charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes bytes to Base64.
|
||||
*
|
||||
* @param bytes the bytes to encode
|
||||
* @return the Base64 encoded string
|
||||
*/
|
||||
public static String encodeBase64(byte[] bytes) {
|
||||
Objects.requireNonNull(bytes, "bytes must not be null");
|
||||
return Base64.getEncoder().encodeToString(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a Base64 string to plain string.
|
||||
*
|
||||
* @param encoded the Base64 encoded string
|
||||
* @return the decoded string
|
||||
*/
|
||||
public static String decodeBase64(String encoded) {
|
||||
Objects.requireNonNull(encoded, "encoded must not be null");
|
||||
byte[] decoded = Base64.getDecoder().decode(encoded);
|
||||
return new String(decoded, DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a Base64 string to plain string with specified charset.
|
||||
*
|
||||
* @param encoded the Base64 encoded string
|
||||
* @param charset the charset to use for decoding
|
||||
* @return the decoded string
|
||||
*/
|
||||
public static String decodeBase64(String encoded, Charset charset) {
|
||||
Objects.requireNonNull(encoded, "encoded must not be null");
|
||||
Objects.requireNonNull(charset, "charset must not be null");
|
||||
byte[] decoded = Base64.getDecoder().decode(encoded);
|
||||
return new String(decoded, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a Base64 string to bytes.
|
||||
*
|
||||
* @param encoded the Base64 encoded string
|
||||
* @return the decoded bytes
|
||||
*/
|
||||
public static byte[] decodeBase64ToBytes(String encoded) {
|
||||
Objects.requireNonNull(encoded, "encoded must not be null");
|
||||
return Base64.getDecoder().decode(encoded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a URL-safe Base64 string.
|
||||
*
|
||||
* @param input the string to encode
|
||||
* @return the URL-safe Base64 encoded string
|
||||
*/
|
||||
public static String encodeBase64Url(String input) {
|
||||
Objects.requireNonNull(input, "input must not be null");
|
||||
return Base64.getUrlEncoder().encodeToString(input.getBytes(DEFAULT_CHARSET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a URL-safe Base64 string.
|
||||
*
|
||||
* @param encoded the URL-safe Base64 encoded string
|
||||
* @return the decoded string
|
||||
*/
|
||||
public static String decodeBase64Url(String encoded) {
|
||||
Objects.requireNonNull(encoded, "encoded must not be null");
|
||||
byte[] decoded = Base64.getUrlDecoder().decode(encoded);
|
||||
return new String(decoded, DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
// ==================== Hex Encoding/Decoding ====================
|
||||
|
||||
/**
|
||||
* Encodes bytes to hexadecimal string.
|
||||
*
|
||||
* @param bytes the bytes to encode
|
||||
* @return the hexadecimal string
|
||||
*/
|
||||
public static String encodeHex(byte[] bytes) {
|
||||
Objects.requireNonNull(bytes, "bytes must not be null");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a hexadecimal string to bytes.
|
||||
*
|
||||
* @param hex the hexadecimal string
|
||||
* @return the decoded bytes
|
||||
*/
|
||||
public static byte[] decodeHex(String hex) {
|
||||
Objects.requireNonNull(hex, "hex must not be null");
|
||||
if (hex.length() % 2 != 0) {
|
||||
throw new IllegalArgumentException("Hex string must have even length");
|
||||
}
|
||||
int len = hex.length();
|
||||
byte[] data = new byte[len / 2];
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
|
||||
+ Character.digit(hex.charAt(i + 1), 16));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// ==================== URL Encoding/Decoding ====================
|
||||
|
||||
/**
|
||||
* URL encodes a string using UTF-8.
|
||||
*
|
||||
* @param input the string to encode
|
||||
* @return the URL encoded string
|
||||
*/
|
||||
public static String urlEncode(String input) {
|
||||
Objects.requireNonNull(input, "input must not be null");
|
||||
try {
|
||||
return java.net.URLEncoder.encode(input, DEFAULT_CHARSET.name());
|
||||
} catch (java.io.UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Unsupported encoding", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URL decodes a string using UTF-8.
|
||||
*
|
||||
* @param encoded the URL encoded string
|
||||
* @return the decoded string
|
||||
*/
|
||||
public static String urlDecode(String encoded) {
|
||||
Objects.requireNonNull(encoded, "encoded must not be null");
|
||||
try {
|
||||
return java.net.URLDecoder.decode(encoded, DEFAULT_CHARSET.name());
|
||||
} catch (java.io.UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Unsupported encoding", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== String Manipulation ====================
|
||||
|
||||
/**
|
||||
* Masks a string with asterisks, showing only the first and last characters.
|
||||
*
|
||||
* @param input the string to mask
|
||||
* @return the masked string
|
||||
*/
|
||||
public static String mask(String input) {
|
||||
return mask(input, 1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Masks a string with asterisks, showing only specified first and last characters.
|
||||
*
|
||||
* @param input the string to mask
|
||||
* @param showFirst number of characters to show at the start
|
||||
* @param showLast number of characters to show at the end
|
||||
* @return the masked string
|
||||
*/
|
||||
public static String mask(String input, int showFirst, int showLast) {
|
||||
if (input == null || input.isEmpty()) {
|
||||
return input;
|
||||
}
|
||||
int length = input.length();
|
||||
if (length <= showFirst + showLast) {
|
||||
return input;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(input, 0, showFirst);
|
||||
for (int i = showFirst; i < length - showLast; i++) {
|
||||
sb.append('*');
|
||||
}
|
||||
sb.append(input.substring(length - showLast));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Masks an email address.
|
||||
*
|
||||
* @param email the email to mask
|
||||
* @return the masked email
|
||||
*/
|
||||
public static String maskEmail(String email) {
|
||||
if (email == null || !email.contains("@")) {
|
||||
return email;
|
||||
}
|
||||
String[] parts = email.split("@");
|
||||
String localPart = parts[0];
|
||||
String domain = parts[1];
|
||||
if (localPart.length() <= 2) {
|
||||
return mask(localPart, 1, 0) + "@" + domain;
|
||||
}
|
||||
return mask(localPart, 1, 1) + "@" + domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Masks a phone number.
|
||||
*
|
||||
* @param phone the phone number to mask
|
||||
* @return the masked phone number
|
||||
*/
|
||||
public static String maskPhone(String phone) {
|
||||
if (phone == null || phone.isEmpty()) {
|
||||
return phone;
|
||||
}
|
||||
String digitsOnly = phone.replaceAll("[^0-9]", "");
|
||||
if (digitsOnly.length() < 7) {
|
||||
return phone;
|
||||
}
|
||||
int length = digitsOnly.length();
|
||||
String masked = digitsOnly.substring(0, 3) + "****" + digitsOnly.substring(length - 4);
|
||||
if (phone.contains("-")) {
|
||||
return masked.substring(0, 3) + "-" + "****" + "-" + masked.substring(7);
|
||||
}
|
||||
return masked;
|
||||
}
|
||||
|
||||
// ==================== Validation ====================
|
||||
|
||||
/**
|
||||
* Validates if a string is a valid email address.
|
||||
*
|
||||
* @param email the email to validate
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
public static boolean isValidEmail(String email) {
|
||||
if (email == null || email.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return EMAIL_PATTERN.matcher(email).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if a string is a valid phone number.
|
||||
*
|
||||
* @param phone the phone number to validate
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
public static boolean isValidPhone(String phone) {
|
||||
if (phone == null || phone.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return PHONE_PATTERN.matcher(phone).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if a string is a valid Korean phone number.
|
||||
*
|
||||
* @param phone the phone number to validate
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
public static boolean isValidKoreanPhone(String phone) {
|
||||
if (phone == null || phone.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return KOREAN_PHONE_PATTERN.matcher(phone).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a string is null or empty.
|
||||
*
|
||||
* @param input the string to check
|
||||
* @return true if null or empty
|
||||
*/
|
||||
public static boolean isEmpty(String input) {
|
||||
return input == null || input.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a string is null, empty, or whitespace only.
|
||||
*
|
||||
* @param input the string to check
|
||||
* @return true if null, empty, or whitespace only
|
||||
*/
|
||||
public static boolean isBlank(String input) {
|
||||
return input == null || input.trim().isEmpty();
|
||||
}
|
||||
|
||||
// ==================== Charset Conversion ====================
|
||||
|
||||
/**
|
||||
* Converts a string from one charset to another.
|
||||
*
|
||||
* @param input the input string
|
||||
* @param fromCharset the source charset
|
||||
* @param toCharset the target charset
|
||||
* @return the converted string
|
||||
*/
|
||||
public static String convertCharset(String input, Charset fromCharset, Charset toCharset) {
|
||||
Objects.requireNonNull(input, "input must not be null");
|
||||
Objects.requireNonNull(fromCharset, "fromCharset must not be null");
|
||||
Objects.requireNonNull(toCharset, "toCharset must not be null");
|
||||
byte[] bytes = input.getBytes(fromCharset);
|
||||
return new String(bytes, toCharset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts EUC-KR encoded bytes to UTF-8 string.
|
||||
*
|
||||
* @param eucKrBytes the EUC-KR encoded bytes
|
||||
* @return the UTF-8 string
|
||||
*/
|
||||
public static String eucKrToUtf8(byte[] eucKrBytes) {
|
||||
Objects.requireNonNull(eucKrBytes, "eucKrBytes must not be null");
|
||||
return new String(eucKrBytes, EUC_KR_CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts UTF-8 string to EUC-KR encoded bytes.
|
||||
*
|
||||
* @param input the UTF-8 string
|
||||
* @return the EUC-KR encoded bytes
|
||||
*/
|
||||
public static byte[] utf8ToEucKr(String input) {
|
||||
Objects.requireNonNull(input, "input must not be null");
|
||||
return input.getBytes(EUC_KR_CHARSET);
|
||||
}
|
||||
|
||||
// ==================== Truncation and Padding ====================
|
||||
|
||||
/**
|
||||
* Truncates a string to the specified length.
|
||||
*
|
||||
* @param input the string to truncate
|
||||
* @param maxLength the maximum length
|
||||
* @return the truncated string
|
||||
*/
|
||||
public static String truncate(String input, int maxLength) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (input.length() <= maxLength) {
|
||||
return input;
|
||||
}
|
||||
return input.substring(0, maxLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads a string on the left with spaces to reach the specified length.
|
||||
*
|
||||
* @param input the string to pad
|
||||
* @param length the target length
|
||||
* @return the padded string
|
||||
*/
|
||||
public static String padLeft(String input, int length) {
|
||||
if (input == null) {
|
||||
input = "";
|
||||
}
|
||||
return String.format("%" + length + "s", input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads a string on the right with spaces to reach the specified length.
|
||||
*
|
||||
* @param input the string to pad
|
||||
* @param length the target length
|
||||
* @return the padded string
|
||||
*/
|
||||
public static String padRight(String input, int length) {
|
||||
if (input == null) {
|
||||
input = "";
|
||||
}
|
||||
return String.format("%- " + length + "s", input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads a string on the left with zeros to reach the specified length.
|
||||
*
|
||||
* @param input the string to pad
|
||||
* @param length the target length
|
||||
* @return the zero-padded string
|
||||
*/
|
||||
public static String padLeftWithZeros(String input, int length) {
|
||||
if (input == null) {
|
||||
input = "";
|
||||
}
|
||||
return String.format("%0" + length + "d", Long.parseLong(input));
|
||||
}
|
||||
|
||||
/**
|
||||
* Left pads a numeric string with zeros.
|
||||
*
|
||||
* @param value the numeric value
|
||||
* @param length the target length
|
||||
* @return the zero-padded string
|
||||
*/
|
||||
public static String zeroPad(long value, int length) {
|
||||
return String.format("%0" + length + "d", value);
|
||||
}
|
||||
|
||||
// ==================== Byte Array Utilities ====================
|
||||
|
||||
/**
|
||||
* Converts a string to bytes using the default charset.
|
||||
*
|
||||
* @param input the string to convert
|
||||
* @return the bytes
|
||||
*/
|
||||
public static byte[] toBytes(String input) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
return input.getBytes(DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string to bytes using the specified charset.
|
||||
*
|
||||
* @param input the string to convert
|
||||
* @param charset the charset to use
|
||||
* @return the bytes
|
||||
*/
|
||||
public static byte[] toBytes(String input, Charset charset) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
Objects.requireNonNull(charset, "charset must not be null");
|
||||
return input.getBytes(charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts bytes to string using the default charset.
|
||||
*
|
||||
* @param bytes the bytes to convert
|
||||
* @return the string
|
||||
*/
|
||||
public static String toString(byte[] bytes) {
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
return new String(bytes, DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts bytes to string using the specified charset.
|
||||
*
|
||||
* @param bytes the bytes to convert
|
||||
* @param charset the charset to use
|
||||
* @return the string
|
||||
*/
|
||||
public static String toString(byte[] bytes, Charset charset) {
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
Objects.requireNonNull(charset, "charset must not be null");
|
||||
return new String(bytes, charset);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
package com.klaro.acquirecore.framework.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class AmountUtilTest {
|
||||
|
||||
@Test
|
||||
void of_withStringValue_returnsBigDecimal() {
|
||||
BigDecimal result = AmountUtil.of("1234.56");
|
||||
assertEquals(new BigDecimal("1234.56"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void of_withLongValue_returnsBigDecimal() {
|
||||
BigDecimal result = AmountUtil.of(1000L);
|
||||
assertEquals(new BigDecimal("1000"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void of_withDoubleValue_returnsBigDecimal() {
|
||||
BigDecimal result = AmountUtil.of(1234.56);
|
||||
assertEquals(new BigDecimal("1234.56"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void add_addsTwoValues() {
|
||||
BigDecimal a = new BigDecimal("100.50");
|
||||
BigDecimal b = new BigDecimal("50.25");
|
||||
BigDecimal result = AmountUtil.add(a, b);
|
||||
assertEquals(new BigDecimal("150.75"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void subtract_subtractsValues() {
|
||||
BigDecimal a = new BigDecimal("100.50");
|
||||
BigDecimal b = new BigDecimal("50.25");
|
||||
BigDecimal result = AmountUtil.subtract(a, b);
|
||||
assertEquals(new BigDecimal("50.25"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void multiply_multipliesValues() {
|
||||
BigDecimal a = new BigDecimal("10.00");
|
||||
BigDecimal b = new BigDecimal("5.00");
|
||||
BigDecimal result = AmountUtil.multiply(a, b);
|
||||
assertEquals(new BigDecimal("50.00"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void divide_dividesValues() {
|
||||
BigDecimal dividend = new BigDecimal("100.00");
|
||||
BigDecimal divisor = new BigDecimal("4.00");
|
||||
BigDecimal result = AmountUtil.divide(dividend, divisor);
|
||||
assertEquals(new BigDecimal("25.00"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void divide_byZero_throwsException() {
|
||||
BigDecimal dividend = new BigDecimal("100.00");
|
||||
BigDecimal divisor = BigDecimal.ZERO;
|
||||
assertThrows(ArithmeticException.class, () -> AmountUtil.divide(dividend, divisor));
|
||||
}
|
||||
|
||||
@Test
|
||||
void round_roundsToDefaultScale() {
|
||||
BigDecimal value = new BigDecimal("123.456");
|
||||
BigDecimal result = AmountUtil.round(value);
|
||||
assertEquals(new BigDecimal("123.46"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void round_roundsWithCustomScaleAndRoundingMode() {
|
||||
BigDecimal value = new BigDecimal("123.456");
|
||||
BigDecimal result = AmountUtil.round(value, 3, RoundingMode.HALF_UP);
|
||||
assertEquals(new BigDecimal("123.456"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void percentage_calculatesCorrectPercentage() {
|
||||
BigDecimal value = new BigDecimal("1000.00");
|
||||
BigDecimal percentage = new BigDecimal("10");
|
||||
BigDecimal result = AmountUtil.percentage(value, percentage);
|
||||
assertEquals(new BigDecimal("100.00"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addPercentage_addsPercentageToValue() {
|
||||
BigDecimal value = new BigDecimal("1000.00");
|
||||
BigDecimal percentage = new BigDecimal("10");
|
||||
BigDecimal result = AmountUtil.addPercentage(value, percentage);
|
||||
assertEquals(new BigDecimal("1100.00"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void subtractPercentage_subtractsPercentageFromValue() {
|
||||
BigDecimal value = new BigDecimal("1000.00");
|
||||
BigDecimal percentage = new BigDecimal("10");
|
||||
BigDecimal result = AmountUtil.subtractPercentage(value, percentage);
|
||||
assertEquals(new BigDecimal("900.00"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void formatKoreanWon_formatsCorrectly() {
|
||||
BigDecimal amount = new BigDecimal("1234567");
|
||||
String result = AmountUtil.formatKoreanWon(amount);
|
||||
assertEquals("₩1,234,567", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void formatCurrency_formatsWithTwoDecimals() {
|
||||
BigDecimal amount = new BigDecimal("1234.5");
|
||||
String result = AmountUtil.formatCurrency(amount);
|
||||
assertEquals("1,234.50", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void compare_comparesValues() {
|
||||
BigDecimal a = new BigDecimal("100.00");
|
||||
BigDecimal b = new BigDecimal("200.00");
|
||||
assertEquals(-1, AmountUtil.compare(a, b));
|
||||
assertEquals(1, AmountUtil.compare(b, a));
|
||||
assertEquals(0, AmountUtil.compare(a, new BigDecimal("100.00")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isGreaterThan_returnsCorrectResult() {
|
||||
BigDecimal a = new BigDecimal("200.00");
|
||||
BigDecimal b = new BigDecimal("100.00");
|
||||
assertTrue(AmountUtil.isGreaterThan(a, b));
|
||||
assertFalse(AmountUtil.isGreaterThan(b, a));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLessThan_returnsCorrectResult() {
|
||||
BigDecimal a = new BigDecimal("100.00");
|
||||
BigDecimal b = new BigDecimal("200.00");
|
||||
assertTrue(AmountUtil.isLessThan(a, b));
|
||||
assertFalse(AmountUtil.isLessThan(b, a));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isZero_withZeroValue_returnsTrue() {
|
||||
assertTrue(AmountUtil.isZero(BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isPositive_withPositiveValue_returnsTrue() {
|
||||
assertTrue(AmountUtil.isPositive(new BigDecimal("1.00")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isNegative_withNegativeValue_returnsTrue() {
|
||||
assertTrue(AmountUtil.isNegative(new BigDecimal("-1.00")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void abs_returnsAbsoluteValue() {
|
||||
BigDecimal value = new BigDecimal("-100.00");
|
||||
BigDecimal result = AmountUtil.abs(value);
|
||||
assertEquals(new BigDecimal("100.00"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void negate_negatesValue() {
|
||||
BigDecimal value = new BigDecimal("100.00");
|
||||
BigDecimal result = AmountUtil.negate(value);
|
||||
assertEquals(new BigDecimal("-100.00"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void max_returnsMaximumValue() {
|
||||
BigDecimal a = new BigDecimal("100.00");
|
||||
BigDecimal b = new BigDecimal("200.00");
|
||||
BigDecimal result = AmountUtil.max(a, b);
|
||||
assertEquals(new BigDecimal("200.00"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void min_returnsMinimumValue() {
|
||||
BigDecimal a = new BigDecimal("100.00");
|
||||
BigDecimal b = new BigDecimal("200.00");
|
||||
BigDecimal result = AmountUtil.min(a, b);
|
||||
assertEquals(new BigDecimal("100.00"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseAmount_withCurrencySymbol_parsesCorrectly() {
|
||||
BigDecimal result = AmountUtil.parseAmount("₩1,000,000");
|
||||
assertEquals(new BigDecimal("1000000"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidAmount_withValidAmount_returnsTrue() {
|
||||
assertTrue(AmountUtil.isValidAmount("₩1,000,000"));
|
||||
assertTrue(AmountUtil.isValidAmount("1000.50"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidAmount_withInvalidAmount_returnsFalse() {
|
||||
assertFalse(AmountUtil.isValidAmount("invalid"));
|
||||
assertFalse(AmountUtil.isValidAmount(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromCents_convertsToDecimal() {
|
||||
BigDecimal result = AmountUtil.fromCents(123456);
|
||||
assertEquals(new BigDecimal("1234.56"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toCents_convertsToCents() {
|
||||
BigDecimal amount = new BigDecimal("1234.56");
|
||||
long result = AmountUtil.toCents(amount);
|
||||
assertEquals(123456, result);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
package com.klaro.acquirecore.framework.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class DateUtilTest {
|
||||
|
||||
@Test
|
||||
void parseDate_withValidDateString_returnsLocalDate() {
|
||||
LocalDate result = DateUtil.parseDate("2024-01-15");
|
||||
assertEquals(LocalDate.of(2024, 1, 15), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseDate_withNull_throwsException() {
|
||||
assertThrows(NullPointerException.class, () -> DateUtil.parseDate(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void formatDate_withValidDate_returnsFormattedString() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 15);
|
||||
String result = DateUtil.formatDate(date);
|
||||
assertEquals("2024-01-15", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void formatDate_withNull_throwsException() {
|
||||
assertThrows(NullPointerException.class, () -> DateUtil.formatDate(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void daysBetween_calculatesCorrectDays() {
|
||||
LocalDate start = LocalDate.of(2024, 1, 1);
|
||||
LocalDate end = LocalDate.of(2024, 1, 11);
|
||||
long result = DateUtil.daysBetween(start, end);
|
||||
assertEquals(10, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addDays_addsCorrectDays() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 15);
|
||||
LocalDate result = DateUtil.addDays(date, 5);
|
||||
assertEquals(LocalDate.of(2024, 1, 20), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addDays_withNegativeValue_subtractsDays() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 15);
|
||||
LocalDate result = DateUtil.addDays(date, -5);
|
||||
assertEquals(LocalDate.of(2024, 1, 10), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isBetween_withDateInRange_returnsTrue() {
|
||||
LocalDate date = LocalDate.of(2024, 6, 15);
|
||||
LocalDate start = LocalDate.of(2024, 1, 1);
|
||||
LocalDate end = LocalDate.of(2024, 12, 31);
|
||||
assertTrue(DateUtil.isBetween(date, start, end));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isBetween_withDateOutOfRange_returnsFalse() {
|
||||
LocalDate date = LocalDate.of(2025, 1, 1);
|
||||
LocalDate start = LocalDate.of(2024, 1, 1);
|
||||
LocalDate end = LocalDate.of(2024, 12, 31);
|
||||
assertFalse(DateUtil.isBetween(date, start, end));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidDate_withValidDate_returnsTrue() {
|
||||
assertTrue(DateUtil.isValidDate("2024-01-15"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidDate_withInvalidDate_returnsFalse() {
|
||||
assertFalse(DateUtil.isValidDate("invalid-date"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidDate_withNull_returnsFalse() {
|
||||
assertFalse(DateUtil.isValidDate(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void today_returnsCurrentDate() {
|
||||
LocalDate result = DateUtil.today();
|
||||
assertEquals(LocalDate.now(), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void now_returnsCurrentDateTime() {
|
||||
LocalDateTime result = DateUtil.now();
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseDateTime_withValidDateTimeString_returnsLocalDateTime() {
|
||||
LocalDateTime result = DateUtil.parseDateTime("2024-01-15 10:30:45");
|
||||
assertEquals(LocalDateTime.of(2024, 1, 15, 10, 30, 45), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void formatDateTime_withValidDateTime_returnsFormattedString() {
|
||||
LocalDateTime dateTime = LocalDateTime.of(2024, 1, 15, 10, 30, 45);
|
||||
String result = DateUtil.formatDateTime(dateTime);
|
||||
assertEquals("2024-01-15 10:30:45", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void formatDateKorean_withValidDate_returnsKoreanFormat() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 15);
|
||||
String result = DateUtil.formatDateKorean(date);
|
||||
assertEquals("2024년 01월 15일", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void startOfDay_returnsStartOfDayDateTime() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 15);
|
||||
LocalDateTime result = DateUtil.startOfDay(date);
|
||||
assertEquals(LocalDateTime.of(2024, 1, 15, 0, 0, 0), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void endOfDay_returnsEndOfDayDateTime() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 15);
|
||||
LocalDateTime result = DateUtil.endOfDay(date);
|
||||
assertEquals(LocalDateTime.of(2024, 1, 15, 23, 59, 59, 999999999), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addMonths_addsCorrectMonths() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 15);
|
||||
LocalDate result = DateUtil.addMonths(date, 3);
|
||||
assertEquals(LocalDate.of(2024, 4, 15), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addYears_addsCorrectYears() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 15);
|
||||
LocalDate result = DateUtil.addYears(date, 1);
|
||||
assertEquals(LocalDate.of(2025, 1, 15), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isBefore_withEarlierDate_returnsTrue() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 15);
|
||||
LocalDate dateToCompare = LocalDate.of(2024, 1, 20);
|
||||
assertTrue(DateUtil.isBefore(date, dateToCompare));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isAfter_withLaterDate_returnsTrue() {
|
||||
LocalDate date = LocalDate.of(2024, 1, 20);
|
||||
LocalDate dateToCompare = LocalDate.of(2024, 1, 15);
|
||||
assertTrue(DateUtil.isAfter(date, dateToCompare));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
package com.klaro.acquirecore.framework.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class MessageUtilTest {
|
||||
|
||||
@Test
|
||||
void encodeBase64_encodesString() {
|
||||
String input = "Hello, World!";
|
||||
String result = MessageUtil.encodeBase64(input);
|
||||
assertEquals("SGVsbG8sIFdvcmxkIQ==", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeBase64_decodesString() {
|
||||
String encoded = "SGVsbG8sIFdvcmxkIQ==";
|
||||
String result = MessageUtil.decodeBase64(encoded);
|
||||
assertEquals("Hello, World!", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void encodeBase64Url_encodesUrlSafe() {
|
||||
String input = "Hello+World/Test";
|
||||
String result = MessageUtil.encodeBase64Url(input);
|
||||
assertEquals("SGVsbG8rV29ybGQvVGVzdA==", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeBase64Url_decodesUrlSafe() {
|
||||
String encoded = "SGVsbG8rV29ybGQvVGVzdA==";
|
||||
String result = MessageUtil.decodeBase64Url(encoded);
|
||||
assertEquals("Hello+World/Test", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void encodeHex_encodesBytesToHex() {
|
||||
byte[] bytes = {(byte) 0x48, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, (byte) 0x6f};
|
||||
String result = MessageUtil.encodeHex(bytes);
|
||||
assertEquals("48656c6c6f", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeHex_decodesHexToBytes() {
|
||||
String hex = "48656c6c6f";
|
||||
byte[] result = MessageUtil.decodeHex(hex);
|
||||
assertArrayEquals(new byte[]{(byte) 0x48, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, (byte) 0x6f}, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlEncode_encodesString() {
|
||||
String input = "Hello World";
|
||||
String result = MessageUtil.urlEncode(input);
|
||||
assertEquals("Hello+World", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlDecode_decodesString() {
|
||||
String encoded = "Hello+World";
|
||||
String result = MessageUtil.urlDecode(encoded);
|
||||
assertEquals("Hello World", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mask_masksMiddleCharacters() {
|
||||
String input = "1234567890";
|
||||
String result = MessageUtil.mask(input);
|
||||
assertEquals("1********0", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mask_withCustomShowCount_masksCorrectly() {
|
||||
String input = "1234567890";
|
||||
String result = MessageUtil.mask(input, 2, 2);
|
||||
assertEquals("12******90", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void maskEmail_masksEmailCorrectly() {
|
||||
String email = "test@example.com";
|
||||
String result = MessageUtil.maskEmail(email);
|
||||
assertEquals("t***t@example.com", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void maskPhone_masksPhoneCorrectly() {
|
||||
String phone = "010-1234-5678";
|
||||
String result = MessageUtil.maskPhone(phone);
|
||||
assertEquals("010-****-5678", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidEmail_withValidEmail_returnsTrue() {
|
||||
assertTrue(MessageUtil.isValidEmail("test@example.com"));
|
||||
assertTrue(MessageUtil.isValidEmail("user.name+tag@domain.co.kr"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidEmail_withInvalidEmail_returnsFalse() {
|
||||
assertFalse(MessageUtil.isValidEmail("invalid-email"));
|
||||
assertFalse(MessageUtil.isValidEmail("@domain.com"));
|
||||
assertFalse(MessageUtil.isValidEmail(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidPhone_withValidPhone_returnsTrue() {
|
||||
assertTrue(MessageUtil.isValidPhone("010-1234-5678"));
|
||||
assertTrue(MessageUtil.isValidPhone("021234567"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidKoreanPhone_withValidKoreanPhone_returnsTrue() {
|
||||
assertTrue(MessageUtil.isValidKoreanPhone("010-1234-5678"));
|
||||
assertTrue(MessageUtil.isValidKoreanPhone("016-123-4567"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEmpty_withNullOrEmpty_returnsTrue() {
|
||||
assertTrue(MessageUtil.isEmpty(null));
|
||||
assertTrue(MessageUtil.isEmpty(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEmpty_withNonEmpty_returnsFalse() {
|
||||
assertFalse(MessageUtil.isEmpty("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isBlank_withWhitespace_returnsTrue() {
|
||||
assertTrue(MessageUtil.isBlank(" "));
|
||||
assertTrue(MessageUtil.isBlank(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertCharset_convertsCorrectly() {
|
||||
String input = "안녕하세요";
|
||||
String result = MessageUtil.convertCharset(input, StandardCharsets.UTF_8, StandardCharsets.ISO_8859_1);
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void truncate_truncatesLongString() {
|
||||
String input = "This is a long string";
|
||||
String result = MessageUtil.truncate(input, 10);
|
||||
assertEquals("This is a ", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void truncate_withShortString_returnsOriginal() {
|
||||
String input = "Short";
|
||||
String result = MessageUtil.truncate(input, 10);
|
||||
assertEquals("Short", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void padLeft_padsWithSpaces() {
|
||||
String input = "123";
|
||||
String result = MessageUtil.padLeft(input, 10);
|
||||
assertEquals(" 123", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void padRight_padsWithSpaces() {
|
||||
String input = "123";
|
||||
String result = MessageUtil.padRight(input, 10);
|
||||
assertEquals("123 ", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void zeroPad_padsWithZeros() {
|
||||
long value = 123;
|
||||
String result = MessageUtil.zeroPad(value, 10);
|
||||
assertEquals("0000000123", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toBytes_convertsStringToBytes() {
|
||||
String input = "Hello";
|
||||
byte[] result = MessageUtil.toBytes(input);
|
||||
assertArrayEquals(new byte[]{72, 101, 108, 108, 111}, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toString_convertsBytesToString() {
|
||||
byte[] bytes = {72, 101, 108, 108, 111};
|
||||
String result = MessageUtil.toString(bytes);
|
||||
assertEquals("Hello", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void encodeBase64_withKoreanCharacters_encodesCorrectly() {
|
||||
String input = "안녕하세요";
|
||||
String encoded = MessageUtil.encodeBase64(input);
|
||||
String decoded = MessageUtil.decodeBase64(encoded);
|
||||
assertEquals(input, decoded);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeHex_withInvalidHex_throwsException() {
|
||||
assertThrows(IllegalArgumentException.class, () -> MessageUtil.decodeHex("123"));
|
||||
}
|
||||
}
|
||||
Reference in a new issue