diff --git a/README.md b/README.md
index 08ed3ba..c9a1523 100644
--- a/README.md
+++ b/README.md
@@ -107,6 +107,6 @@ Just add this to your **pom.xml**
com.hijackermax
utils
- 0.0.8
+ 0.0.9
```
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index d4def85..cd2ad9a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.hijackermax
utils
- 0.0.8
+ 0.0.9
utils
A set of utils that can help in app development
diff --git a/src/main/java/com/hijackermax/utils/lang/CollectionUtils.java b/src/main/java/com/hijackermax/utils/lang/CollectionUtils.java
index ad02f2a..e2f2886 100644
--- a/src/main/java/com/hijackermax/utils/lang/CollectionUtils.java
+++ b/src/main/java/com/hijackermax/utils/lang/CollectionUtils.java
@@ -789,4 +789,43 @@ public static boolean isEmpty(Enumeration> value) {
public static Stream safeStreamOf(Enumeration input) {
return isEmpty(input) ? Stream.empty() : EnumerationSpliterator.ofOrdered(input).stream();
}
+
+ /**
+ * Checks if any of input {@link Collection} elements satisfies provided {@link Predicate}
+ *
+ * @param values collection that should be checked
+ * @param valuesPredicate the predicate that should be applied to source elements collection
+ * @param collection elements type
+ * @return true if collection contains at least one element that satisfies provided predicate
+ * @since 0.0.9
+ */
+ public static boolean safeAnyMatch(Collection extends T> values, Predicate super T> valuesPredicate) {
+ return safeStreamOf(values).anyMatch(valuesPredicate);
+ }
+
+ /**
+ * Checks if all of input {@link Collection} elements satisfy provided {@link Predicate}
+ *
+ * @param values collection that should be checked
+ * @param valuesPredicate the predicate that should be applied to source elements collection
+ * @param collection elements type
+ * @return true if collection contains all elements that satisfy provided predicate
+ * @since 0.0.9
+ */
+ public static boolean safeAllMatch(Collection extends T> values, Predicate super T> valuesPredicate) {
+ return isNotEmpty(values) && values.stream().allMatch(valuesPredicate);
+ }
+
+ /**
+ * Checks if none of input {@link Collection} elements satisfy provided {@link Predicate}
+ *
+ * @param values collection that should be checked
+ * @param valuesPredicate the predicate that should be applied to source elements collection
+ * @param collection elements type
+ * @return true if collection contains no elements that satisfy provided predicate
+ * @since 0.0.9
+ */
+ public static boolean safeNoneMatch(Collection extends T> values, Predicate super T> valuesPredicate) {
+ return isEmpty(values) || values.stream().noneMatch(valuesPredicate);
+ }
}
diff --git a/src/main/java/com/hijackermax/utils/lang/DateUtils.java b/src/main/java/com/hijackermax/utils/lang/DateUtils.java
index d891937..c58eb21 100644
--- a/src/main/java/com/hijackermax/utils/lang/DateUtils.java
+++ b/src/main/java/com/hijackermax/utils/lang/DateUtils.java
@@ -1,9 +1,11 @@
package com.hijackermax.utils.lang;
import java.time.Instant;
+import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
+import java.time.chrono.ChronoLocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Objects;
@@ -186,6 +188,106 @@ public static boolean inRange(Date value, Date target, long offsetMs) {
return between(value, shiftDateByMs(target, -offsetMs), shiftDateByMs(target, offsetMs));
}
+ /**
+ * Checks if provided {@link ChronoLocalDate} value is before {@link ChronoLocalDate} point in time
+ *
+ * @param value the value that should be checked
+ * @param pointInTime some date that value should be compared to
+ * @return true if both dates are not null and provided value is before provided point of time, otherwise false
+ * @since 0.0.9
+ */
+ public static boolean safeBefore(ChronoLocalDate value, ChronoLocalDate pointInTime) {
+ return Objects.nonNull(value) && Objects.nonNull(pointInTime) && value.isBefore(pointInTime);
+ }
+
+ /**
+ * Checks if provided {@link ChronoLocalDate} value is after {@link ChronoLocalDate} point in time
+ *
+ * @param value the value that should be checked
+ * @param pointInTime some date that value should be compared to
+ * @return true if both dates are not null and provided value is after provided point of time, otherwise false
+ * @since 0.0.9
+ */
+ public static boolean safeAfter(ChronoLocalDate value, ChronoLocalDate pointInTime) {
+ return Objects.nonNull(value) && Objects.nonNull(pointInTime) && value.isAfter(pointInTime);
+ }
+
+ /**
+ * Checks if provided {@link ChronoLocalDate} value is after or the same as {@link ChronoLocalDate} point in time
+ *
+ * @param value the value that should be checked
+ * @param pointInTime some date that value should be compared to
+ * @return true if both dates are not null and provided value is after or equal to provided point of time, otherwise false
+ * @since 0.0.9
+ */
+ public static boolean safeAfterOrSame(ChronoLocalDate value, ChronoLocalDate pointInTime) {
+ return Objects.nonNull(value) && Objects.nonNull(pointInTime) && !value.isBefore(pointInTime);
+ }
+
+ /**
+ * Checks if provided {@link ChronoLocalDate} value is before or the same as {@link ChronoLocalDate} point in time
+ *
+ * @param value the value that should be checked
+ * @param pointInTime some date that value should be compared to
+ * @return true if both dates are not null and provided value is before or equal to provided point of time, otherwise false
+ * @since 0.0.9
+ */
+ public static boolean safeBeforeOrSame(ChronoLocalDate value, ChronoLocalDate pointInTime) {
+ return Objects.nonNull(value) && Objects.nonNull(pointInTime) && !value.isAfter(pointInTime);
+ }
+
+ /**
+ * Provides null-safe check if provided value {@link ChronoLocalDate} between two provided boundary {@link ChronoLocalDate} or equal to one of them
+ *
+ * @param value date that should be checked
+ * @param leftBound start boundary date
+ * @param rightBound end boundary date
+ * @return true if date between provided boundaries, false if not or one of the provided dates is null
+ * @since 0.0.9
+ */
+ public static boolean between(ChronoLocalDate value, ChronoLocalDate leftBound, ChronoLocalDate rightBound) {
+ if (Objects.isNull(value) || Objects.isNull(leftBound) || Objects.isNull(rightBound)) {
+ return false;
+ }
+ return !leftBound.isAfter(value) && !rightBound.isBefore(value);
+ }
+
+ /**
+ * Shifts provided {@link LocalDate} with provided amount of days
+ *
+ * @param source source date
+ * @param shiftValue amount of days that should be used to shift source date
+ * @return shifted date, or null if source is null
+ * @since 0.0.9
+ */
+ public static LocalDate shiftDateByDays(LocalDate source, long shiftValue) {
+ return Objects.isNull(source) ? null : source.plusDays(shiftValue);
+ }
+
+ /**
+ * Shifts provided {@link LocalDate} with provided amount of months
+ *
+ * @param source source date
+ * @param shiftValue amount of months that should be used to shift source date
+ * @return shifted date, or null if source is null
+ * @since 0.0.9
+ */
+ public static LocalDate shiftDateByMonths(LocalDate source, long shiftValue) {
+ return Objects.isNull(source) ? null : source.plusMonths(shiftValue);
+ }
+
+ /**
+ * Shifts provided {@link LocalDate} with provided amount of years
+ *
+ * @param source source date
+ * @param shiftValue amount of years that should be used to shift source date
+ * @return shifted date, or null if source is null
+ * @since 0.0.9
+ */
+ public static LocalDate shiftDateByYears(LocalDate source, long shiftValue) {
+ return Objects.isNull(source) ? null : source.plusYears(shiftValue);
+ }
+
private static ZonedDateTime getZonedDateTime(Date source) {
return ZonedDateTime.ofInstant(source.toInstant(), ZoneOffset.UTC);
}
diff --git a/src/main/java/com/hijackermax/utils/lang/FunctionalUtils.java b/src/main/java/com/hijackermax/utils/lang/FunctionalUtils.java
index b5ecdb6..c215503 100644
--- a/src/main/java/com/hijackermax/utils/lang/FunctionalUtils.java
+++ b/src/main/java/com/hijackermax/utils/lang/FunctionalUtils.java
@@ -89,4 +89,16 @@ public static Predicate mappedPredicate(Function transformer, Pr
return source -> Objects.nonNull(source) &&
Objects.requireNonNull(transformer).andThen(Objects.requireNonNull(extractedPredicate)::test).apply(source);
}
+
+ /**
+ * Provides empty value {@link Consumer}
+ *
+ * @param supplied value type
+ * @return empty value consumer
+ * @since 0.0.9
+ */
+ public static Consumer emptyConsumer() {
+ return v -> {
+ };
+ }
}
diff --git a/src/main/java/com/hijackermax/utils/lang/OptionalUtils.java b/src/main/java/com/hijackermax/utils/lang/OptionalUtils.java
index f3a9f30..65de605 100644
--- a/src/main/java/com/hijackermax/utils/lang/OptionalUtils.java
+++ b/src/main/java/com/hijackermax/utils/lang/OptionalUtils.java
@@ -4,8 +4,11 @@
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import static java.util.Optional.empty;
+import static java.util.Optional.ofNullable;
/**
* Useful optional providers
@@ -99,4 +102,19 @@ public static Optional ofBlank(String value) {
public static > Optional ofEmptyCollection(C value) {
return CollectionUtils.isEmpty(value) ? Optional.empty() : Optional.of(value);
}
+
+ /**
+ * Returns an {@link Optional} describing the given pattern matcher against provided {@link CharSequence}
+ *
+ * @param pattern a compiled representation of a regular expression
+ * @param value a character sequence to be matched
+ * @return an {@link Optional} with a matcher as value if a subsequence of the input sequence matches the input pattern,
+ * otherwise an empty {@link Optional}
+ * @since 0.0.9
+ */
+ public static Optional ofFind(Pattern pattern, CharSequence value) {
+ return Objects.isNull(value) ? Optional.empty() : ofNullable(pattern)
+ .map(p -> p.matcher(value))
+ .filter(Matcher::find);
+ }
}
diff --git a/src/main/java/com/hijackermax/utils/lang/StringUtils.java b/src/main/java/com/hijackermax/utils/lang/StringUtils.java
index 7ed579e..f8cf353 100644
--- a/src/main/java/com/hijackermax/utils/lang/StringUtils.java
+++ b/src/main/java/com/hijackermax/utils/lang/StringUtils.java
@@ -9,13 +9,18 @@
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import static com.hijackermax.utils.lang.CollectionUtils.safeStreamOf;
import static com.hijackermax.utils.lang.NumberUtils.requireGreaterThanZero;
/**
@@ -205,7 +210,7 @@ public static Function, String> join(String delimiter, Functio
public static String join(Collection extends T> collection,
String delimiter,
Function super T, String> toStringConverter) {
- return CollectionUtils.safeStreamOf(collection)
+ return safeStreamOf(collection)
.filter(Objects::nonNull)
.map(toStringConverter)
.map(StringUtils::trimToEmpty)
@@ -488,4 +493,128 @@ public static Predicate contains(String fragment) {
public static Predicate hasLength(ComparisonOperators operator, int reference) {
return source -> isNotEmpty(source) && NumberUtils.compare(source.length(), requireGreaterThanZero(reference), operator);
}
+
+ /**
+ * Passes provided {@link String} if not empty to the provided string {@link Consumer}
+ *
+ * @param value the value to check
+ * @param valueConsumer non-empty value consumer
+ * @since 0.0.9
+ */
+ public static void ifNotEmpty(String value, Consumer valueConsumer) {
+ if (isNotEmpty(value)) {
+ valueConsumer.accept(value);
+ }
+ }
+
+ /**
+ * Passes provided {@link String} if not blank to the provided string {@link Consumer}
+ *
+ * @param value the value to check
+ * @param valueConsumer non-blank value consumer
+ * @since 0.0.9
+ */
+ public static void ifNotBlank(String value, Consumer valueConsumer) {
+ if (isNotBlank(value)) {
+ valueConsumer.accept(value);
+ }
+ }
+
+ /**
+ * Returns capitalized variant of provided {@link String} with space as default word delimiter
+ *
+ * @param source the value to capitalize
+ * @return capitalized string or empty string if null or blank string is provided
+ * @since 0.0.9
+ */
+ public static String capitalize(String source) {
+ return capitalize(source, ' ');
+ }
+
+ /**
+ * Returns capitalized variant of provided {@link String} with provided words delimiters
+ *
+ * @param source the value to capitalize
+ * @param delimiters the words delimiters
+ * @return capitalized string or empty string if null or blank string is provided or source string if no delimiters provided
+ * @since 0.0.9
+ */
+ public static String capitalize(String source, char... delimiters) {
+ if (isBlank(source)) {
+ return EMPTY;
+ }
+ if (Objects.isNull(delimiters) || 0 == delimiters.length) {
+ return source;
+ }
+
+ Set delimiterValues = IntStream.range(0, delimiters.length)
+ .mapToObj(idx -> Character.codePointAt(delimiters, idx))
+ .collect(Collectors.toSet());
+
+ String lowerCaseSource = source.trim().toLowerCase();
+ int sourceLength = lowerCaseSource.length();
+ int[] resultValues = new int[sourceLength];
+ int resultEndIdx = 0;
+ boolean capitalizeNext = false;
+ for (int idx = 0; idx < sourceLength; ) {
+ int charAt = lowerCaseSource.codePointAt(idx);
+ if (delimiterValues.contains(charAt)) {
+ capitalizeNext = true;
+ idx += Character.charCount(charAt);
+ resultValues[resultEndIdx++] = charAt;
+ continue;
+ }
+ if (capitalizeNext || 0 == idx) {
+ int newValue = Character.toTitleCase(charAt);
+ idx += Character.charCount(newValue);
+ resultValues[resultEndIdx++] = newValue;
+ capitalizeNext = false;
+ continue;
+ }
+ idx += Character.charCount(charAt);
+ resultValues[resultEndIdx++] = charAt;
+ }
+ return new String(resultValues, 0, resultEndIdx);
+ }
+
+ /**
+ * Joins provided {@link Collection} of {@link CharSequence} with provided delimiter
+ *
+ * @param elements collection of charSequences to join
+ * @param delimiter the delimiter
+ * @return joint {@link String} or empty string if provided collection is empty or null
+ * @since 0.0.9
+ */
+ public static String safeJoin(Collection extends CharSequence> elements, CharSequence delimiter) {
+ return CollectionUtils.safeStreamOf(elements)
+ .collect(Collectors.joining(delimiter));
+ }
+
+ /**
+ * Passes provided {@link String} pair if both of them not empty to the provided string {@link BiConsumer}
+ *
+ * @param left the first value to check
+ * @param right the second value to check
+ * @param valuesConsumer non-empty values consumer
+ * @since 0.0.9
+ */
+ public static void ifBothNotEmpty(String left, String right, BiConsumer valuesConsumer) {
+ if (isNotEmpty(left) && isNotEmpty(right)) {
+ valuesConsumer.accept(left, right);
+ }
+ }
+
+ /**
+ * Passes provided {@link String} pair if both of them not blank to the provided string {@link BiConsumer}
+ *
+ * @param left the first value to check
+ * @param right the second value to check
+ * @param valuesConsumer non-blank values consumer
+ * @since 0.0.9
+ */
+ public static void ifBothNotBlank(String left, String right, BiConsumer valuesConsumer) {
+ if (isNotBlank(left) && isNotBlank(right)) {
+ valuesConsumer.accept(left, right);
+ }
+ }
}
diff --git a/src/test/java/com/hijackermax/utils/lang/CollectionUtilsTest.java b/src/test/java/com/hijackermax/utils/lang/CollectionUtilsTest.java
index 341e202..15ecd7a 100644
--- a/src/test/java/com/hijackermax/utils/lang/CollectionUtilsTest.java
+++ b/src/test/java/com/hijackermax/utils/lang/CollectionUtilsTest.java
@@ -543,4 +543,30 @@ void testSafeStreamOfEnumeration() {
assertEquals(0L, CollectionUtils.safeStreamOf(new Vector<>().elements()).count());
assertEquals(3L, CollectionUtils.safeStreamOf(new Vector<>(List.of(true, false, true))).count());
}
+
+ @Test
+ void testSafeAnyMatch() {
+ assertFalse(CollectionUtils.safeAnyMatch(null, Objects::nonNull));
+ assertFalse(CollectionUtils.safeAnyMatch(List.of(), Objects::nonNull));
+ assertTrue(CollectionUtils.safeAnyMatch(List.of(1, 2, 3), Objects::nonNull));
+ assertTrue(CollectionUtils.safeAnyMatch(List.of(1), Objects::nonNull));
+ }
+
+ @Test
+ void testSafeAllMatch() {
+ assertFalse(CollectionUtils.safeAllMatch(null, Objects::nonNull));
+ assertFalse(CollectionUtils.safeAllMatch(List.of(), Objects::nonNull));
+ assertFalse(CollectionUtils.safeAllMatch(List.of(1, 2, 4, 10), v -> v < 5));
+ assertTrue(CollectionUtils.safeAllMatch(List.of(1, 2, 3), Objects::nonNull));
+ assertTrue(CollectionUtils.safeAllMatch(List.of(1), Objects::nonNull));
+ }
+
+ @Test
+ void testSafeNoneMatch() {
+ assertFalse(CollectionUtils.safeNoneMatch(List.of(1, 2, 4, 10), v -> v < 5));
+ assertTrue(CollectionUtils.safeNoneMatch(List.of(), Objects::nonNull));
+ assertTrue(CollectionUtils.safeNoneMatch(null, Objects::nonNull));
+ assertTrue(CollectionUtils.safeNoneMatch(List.of(1, 2, 3), v -> v > 5));
+ assertTrue(CollectionUtils.safeNoneMatch(List.of(1), v -> v > 5));
+ }
}
diff --git a/src/test/java/com/hijackermax/utils/lang/DateUtilsTest.java b/src/test/java/com/hijackermax/utils/lang/DateUtilsTest.java
index 64732c7..c19fcbb 100644
--- a/src/test/java/com/hijackermax/utils/lang/DateUtilsTest.java
+++ b/src/test/java/com/hijackermax/utils/lang/DateUtilsTest.java
@@ -2,6 +2,7 @@
import org.junit.jupiter.api.Test;
+import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
@@ -70,7 +71,7 @@ void testShiftDayByHours() {
@Test
void testShiftDayByDays() {
- assertNull(DateUtils.shiftDateByDays(null, 10));
+ assertNull(DateUtils.shiftDateByDays((Date) null, 10));
long timeMillis = 1679970309662L; //Tue Mar 28 02:25:09.662 GMT 2023
long plusMillis = 1680056709662L; //Tue Mar 29 02:25:09.662 GMT 2023
long minusMillis = 1679883909662L; //Tue Mar 27 02:25:09.662 GMT 2023
@@ -80,7 +81,7 @@ void testShiftDayByDays() {
@Test
void testShiftDayByMoths() {
- assertNull(DateUtils.shiftDateByDays(null, 10));
+ assertNull(DateUtils.shiftDateByMonths((Date) null, 10));
long timeMillis = 1679970309662L; //Tue Mar 28 02:25:09.662 GMT 2023
long plusMillis = 1682648709662L; //Fri Apr 28 29 02:25:09.662 GMT 2023
long minusMillis = 1677551109662L; //Tue Feb 28 02:25:09.662 GMT 2023
@@ -90,7 +91,7 @@ void testShiftDayByMoths() {
@Test
void testShiftDayByYears() {
- assertNull(DateUtils.shiftDateByDays(null, 10));
+ assertNull(DateUtils.shiftDateByYears((Date) null, 10));
long timeMillis = 1679970309662L; //Tue Mar 28 02:25:09.662 GMT 2023
long plusMillis = 1711592709662L; //Thu Mar 28 02:25:09.662 GMT 2024
long minusMillis = 1648434309662L; //Mon Mar 28 02:25:09.662 GMT 2022
@@ -121,4 +122,87 @@ void testInRange() {
assertTrue(DateUtils.inRange(new Date(timeMillis), new Date(timeMillis), 86400000));
assertFalse(DateUtils.inRange(new Date(timeMillis), new Date(targetMiddle), 86400000));
}
+
+ @Test
+ void testLocalShiftDayByDays() {
+ assertNull(DateUtils.shiftDateByDays((LocalDate) null, 10));
+ LocalDate source = LocalDate.of(2023, 9, 16);
+ LocalDate plusDay = LocalDate.of(2023, 9, 17);
+ LocalDate minusDay = LocalDate.of(2023, 9, 15);
+ assertEquals(plusDay, DateUtils.shiftDateByDays(source, 1));
+ assertEquals(minusDay, DateUtils.shiftDateByDays(source, -1));
+ }
+
+ @Test
+ void testLocalShiftDayByMoths() {
+ assertNull(DateUtils.shiftDateByMonths((LocalDate) null, 10));
+ LocalDate source = LocalDate.of(2023, 9, 16);
+ LocalDate plusMonth = LocalDate.of(2023, 10, 16);
+ LocalDate minusMonth = LocalDate.of(2023, 8, 16);
+ assertEquals(plusMonth, DateUtils.shiftDateByMonths(source, 1));
+ assertEquals(minusMonth, DateUtils.shiftDateByMonths(source, -1));
+ }
+
+ @Test
+ void testLocalShiftDayByYears() {
+ assertNull(DateUtils.shiftDateByYears((LocalDate) null, 10));
+ LocalDate source = LocalDate.of(2023, 9, 16);
+ LocalDate plusYear = LocalDate.of(2024, 9, 16);
+ LocalDate minusYear = LocalDate.of(2022, 9, 16);
+ assertEquals(plusYear, DateUtils.shiftDateByYears(source, 1));
+ assertEquals(minusYear, DateUtils.shiftDateByYears(source, -1));
+ }
+
+ @Test
+ void testLocalBetween() {
+ assertFalse(DateUtils.between(null, LocalDate.now(), LocalDate.now()));
+ assertFalse(DateUtils.between(LocalDate.now(), null, LocalDate.now()));
+ assertFalse(DateUtils.between(LocalDate.now(), LocalDate.now(), null));
+ LocalDate source = LocalDate.of(2023, 9, 16);
+ LocalDate plusYear = LocalDate.of(2024, 9, 16);
+ LocalDate minusYear = LocalDate.of(2022, 9, 16);
+ assertTrue(DateUtils.between(source, minusYear, plusYear));
+ assertFalse(DateUtils.between(minusYear, source, plusYear));
+ assertFalse(DateUtils.between(source, plusYear, minusYear));
+ }
+
+ @Test
+ void testSafeBefore() {
+ assertFalse(DateUtils.safeBefore(null, LocalDate.now()));
+ assertFalse(DateUtils.safeBefore(null, LocalDate.now()));
+ assertFalse(DateUtils.safeBefore(null, null));
+ assertFalse(DateUtils.safeBefore(LocalDate.of(2023, 9, 17), LocalDate.of(2023, 9, 16)));
+ assertTrue(DateUtils.safeBefore(LocalDate.of(2023, 9, 10), LocalDate.of(2023, 9, 16)));
+ assertTrue(DateUtils.safeBefore(LocalDate.of(2023, 9, 11), LocalDate.of(2023, 9, 16)));
+ }
+
+ @Test
+ void testSafeAfter() {
+ assertFalse(DateUtils.safeAfter(null, LocalDate.now()));
+ assertFalse(DateUtils.safeAfter(null, LocalDate.now()));
+ assertFalse(DateUtils.safeAfter(null, null));
+ assertFalse(DateUtils.safeAfter(LocalDate.of(2023, 9, 10), LocalDate.of(2023, 9, 16)));
+ assertTrue(DateUtils.safeAfter(LocalDate.of(2023, 9, 17), LocalDate.of(2023, 9, 16)));
+ assertTrue(DateUtils.safeAfter(LocalDate.of(2023, 9, 18), LocalDate.of(2023, 9, 16)));
+ }
+
+ @Test
+ void testSafeBeforeOrSame() {
+ assertFalse(DateUtils.safeBeforeOrSame(null, LocalDate.now()));
+ assertFalse(DateUtils.safeBeforeOrSame(null, LocalDate.now()));
+ assertFalse(DateUtils.safeBeforeOrSame(null, null));
+ assertFalse(DateUtils.safeBeforeOrSame(LocalDate.of(2023, 9, 17), LocalDate.of(2023, 9, 16)));
+ assertTrue(DateUtils.safeBeforeOrSame(LocalDate.of(2023, 9, 16), LocalDate.of(2023, 9, 16)));
+ assertTrue(DateUtils.safeBeforeOrSame(LocalDate.of(2023, 9, 15), LocalDate.of(2023, 9, 16)));
+ }
+
+ @Test
+ void testSafeAfterOrSame() {
+ assertFalse(DateUtils.safeAfterOrSame(null, LocalDate.now()));
+ assertFalse(DateUtils.safeAfterOrSame(null, LocalDate.now()));
+ assertFalse(DateUtils.safeAfterOrSame(null, null));
+ assertFalse(DateUtils.safeAfterOrSame(LocalDate.of(2023, 9, 10), LocalDate.of(2023, 9, 16)));
+ assertTrue(DateUtils.safeAfterOrSame(LocalDate.of(2023, 9, 16), LocalDate.of(2023, 9, 16)));
+ assertTrue(DateUtils.safeAfterOrSame(LocalDate.of(2023, 9, 18), LocalDate.of(2023, 9, 16)));
+ }
}
diff --git a/src/test/java/com/hijackermax/utils/lang/OptionalUtilsTest.java b/src/test/java/com/hijackermax/utils/lang/OptionalUtilsTest.java
index 685565e..74df4b2 100644
--- a/src/test/java/com/hijackermax/utils/lang/OptionalUtilsTest.java
+++ b/src/test/java/com/hijackermax/utils/lang/OptionalUtilsTest.java
@@ -5,6 +5,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -55,4 +56,13 @@ void testOfBlank() {
assertTrue(OptionalUtils.ofBlank(" ").isEmpty());
assertTrue(OptionalUtils.ofBlank("Test").isPresent());
}
+
+ @Test
+ void ofFind() {
+ assertTrue(OptionalUtils.ofFind(Pattern.compile("[^\\D.]"), null).isEmpty());
+ assertTrue(OptionalUtils.ofFind(null, "12345abc").isEmpty());
+ assertTrue(OptionalUtils.ofFind(null, null).isEmpty());
+ assertTrue(OptionalUtils.ofFind(Pattern.compile("[^\\D.]"), "12345abc").isPresent());
+ assertTrue(OptionalUtils.ofFind(Pattern.compile("[^\\D.]"), "abc").isEmpty());
+ }
}
diff --git a/src/test/java/com/hijackermax/utils/lang/StringUtilsTest.java b/src/test/java/com/hijackermax/utils/lang/StringUtilsTest.java
index 8fe3787..e876b05 100644
--- a/src/test/java/com/hijackermax/utils/lang/StringUtilsTest.java
+++ b/src/test/java/com/hijackermax/utils/lang/StringUtilsTest.java
@@ -1,6 +1,8 @@
package com.hijackermax.utils.lang;
import com.hijackermax.utils.encoders.Base122;
+import com.hijackermax.utils.entities.Single;
+import com.hijackermax.utils.entities.Tuple;
import com.hijackermax.utils.enums.ComparisonOperators;
import org.junit.jupiter.api.Test;
@@ -326,4 +328,91 @@ void testHasLength() {
.collect(Collectors.toList());
assertLinesMatch(List.of("Foo", "Bar"), filteredList);
}
+
+ @Test
+ void testIfNotEmpty() {
+ Single valueHolder = new Single<>("Original");
+ StringUtils.ifNotEmpty(null, valueHolder::setValue);
+ assertEquals("Original", valueHolder.getValue());
+ StringUtils.ifNotEmpty(StringUtils.EMPTY, valueHolder::setValue);
+ assertEquals("Original", valueHolder.getValue());
+ StringUtils.ifNotEmpty(StringUtils.BLANK, valueHolder::setValue);
+ assertEquals(StringUtils.BLANK, valueHolder.getValue());
+ StringUtils.ifNotEmpty("Foo", valueHolder::setValue);
+ assertEquals("Foo", valueHolder.getValue());
+ }
+
+ @Test
+ void testIfNotBlank() {
+ Single valueHolder = new Single<>("Original");
+ StringUtils.ifNotBlank(null, valueHolder::setValue);
+ assertEquals("Original", valueHolder.getValue());
+ StringUtils.ifNotBlank(StringUtils.EMPTY, valueHolder::setValue);
+ assertEquals("Original", valueHolder.getValue());
+ StringUtils.ifNotBlank(StringUtils.BLANK, valueHolder::setValue);
+ assertEquals("Original", valueHolder.getValue());
+ StringUtils.ifNotBlank("Foo", valueHolder::setValue);
+ assertEquals("Foo", valueHolder.getValue());
+ }
+
+ @Test
+ void testCapitalizeDefault() {
+ assertEquals(StringUtils.EMPTY, StringUtils.capitalize(null));
+ assertEquals("Foo Bar", StringUtils.capitalize("foo bar"));
+ assertEquals("Foo Bar", StringUtils.capitalize("FOO BAR"));
+ assertEquals("Foo Bar", StringUtils.capitalize("fOO bAR"));
+ assertEquals("Foo Bar", StringUtils.capitalize("fOo bAr"));
+ }
+
+ @Test
+ void testCapitalize() {
+ assertEquals(StringUtils.EMPTY, StringUtils.capitalize(null, ' '));
+ assertEquals("Foo@Bar", StringUtils.capitalize("foo@bar", ' ', '@'));
+ assertEquals("Foo Bar-Test", StringUtils.capitalize("FOO BAR-TEST", ' ', '-'));
+ assertEquals("Foo B$Ar", StringUtils.capitalize("fOO b$AR", ' ', '$'));
+ assertEquals("Foo Ba$R", StringUtils.capitalize("fOo bA$r", ' ', '$'));
+ }
+
+ @Test
+ void testSafeJoin() {
+ assertEquals(StringUtils.EMPTY, StringUtils.safeJoin(null, ","));
+ assertEquals(StringUtils.EMPTY, StringUtils.safeJoin(Collections.emptyList(), ","));
+ assertEquals("Foo", StringUtils.safeJoin(List.of("Foo"), ","));
+ assertEquals("Foo,Bar", StringUtils.safeJoin(List.of("Foo", "Bar"), ","));
+ assertEquals("Foo$Bar$Test", StringUtils.safeJoin(List.of("Foo", "Bar", "Test"), "$"));
+ }
+
+ @Test
+ void testIfBothNotEmpty() {
+ Tuple valueHolder = new Tuple<>("OriginalL", "OriginalR");
+ StringUtils.ifBothNotEmpty(null, null, valueHolder::setPair);
+ assertEquals("OriginalL", valueHolder.getKey());
+ assertEquals("OriginalR", valueHolder.getValue());
+ StringUtils.ifBothNotEmpty(StringUtils.EMPTY, StringUtils.EMPTY, valueHolder::setPair);
+ assertEquals("OriginalL", valueHolder.getKey());
+ assertEquals("OriginalR", valueHolder.getValue());
+ StringUtils.ifBothNotEmpty(StringUtils.BLANK, StringUtils.BLANK, valueHolder::setPair);
+ assertEquals(StringUtils.BLANK, valueHolder.getKey());
+ assertEquals(StringUtils.BLANK, valueHolder.getValue());
+ StringUtils.ifBothNotEmpty("Foo", "Bar", valueHolder::setPair);
+ assertEquals("Foo", valueHolder.getKey());
+ assertEquals("Bar", valueHolder.getValue());
+ }
+
+ @Test
+ void testIfBothNotBlank() {
+ Tuple valueHolder = new Tuple<>("OriginalL", "OriginalR");
+ StringUtils.ifBothNotBlank(null, null, valueHolder::setPair);
+ assertEquals("OriginalL", valueHolder.getKey());
+ assertEquals("OriginalR", valueHolder.getValue());
+ StringUtils.ifBothNotBlank(StringUtils.EMPTY, StringUtils.EMPTY, valueHolder::setPair);
+ assertEquals("OriginalL", valueHolder.getKey());
+ assertEquals("OriginalR", valueHolder.getValue());
+ StringUtils.ifBothNotBlank(StringUtils.BLANK, StringUtils.BLANK, valueHolder::setPair);
+ assertEquals("OriginalL", valueHolder.getKey());
+ assertEquals("OriginalR", valueHolder.getValue());
+ StringUtils.ifBothNotBlank("Foo", "Bar", valueHolder::setPair);
+ assertEquals("Foo", valueHolder.getKey());
+ assertEquals("Bar", valueHolder.getValue());
+ }
}