Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions paimon-api/src/main/java/org/apache/paimon/utils/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,101 @@ public static boolean isNotEmpty(CharSequence cs) {
return !isEmpty(cs);
}

public static boolean isBlank(final CharSequence cs) {
final int strLen = cs == null ? 0 : cs.length();
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(cs.charAt(i))) {
return false;
}
}
return true;
}

public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
if (cs1 == cs2) {
return true;
}
if (cs1 == null || cs2 == null || cs1.length() != cs2.length()) {
return false;
}

for (int i = 0; i < cs1.length(); i++) {
if (cs1.charAt(i) != cs2.charAt(i)) {
return false;
}
}
return true;
}

public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
if (str == null || prefix == null) {
return str == null && prefix == null;
}
return str.toString().startsWith(prefix.toString());
}

public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
if (str == null || suffix == null) {
return str == null && suffix == null;
}
return str.toString().endsWith(suffix.toString());
}

public static String substringBeforeLast(final String str, final String separator) {
if (isEmpty(str) || isEmpty(separator)) {
return str;
}

int pos = str.lastIndexOf(separator);
if (pos == INDEX_NOT_FOUND) {
return str;
}

return str.substring(0, pos);
}

public static String substringAfterLast(final String str, final String separator) {
if (isEmpty(str)) {
return str;
}
if (isEmpty(separator)) {
return EMPTY;
}

int pos = str.lastIndexOf(separator);
if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) {
return EMPTY;
}

return str.substring(pos + separator.length());
}

public static String stripEnd(final String str, final String stripChars) {
if (isEmpty(str)) {
return str;
}

int end = str.length();
if (stripChars == null) {
while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
end--;
}
} else if (stripChars.isEmpty()) {
return str;
} else {
while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
end--;
}
}

return str.substring(0, end);
}

public static String trimToNull(final String str) {
String trimmed = trim(str);
return isEmpty(trimmed) ? null : trimmed;
}

public static String randomNumericString(int len) {
StringBuilder builder = new StringBuilder();
ThreadLocalRandom rnd = ThreadLocalRandom.current();
Expand Down Expand Up @@ -445,6 +540,68 @@ public static String[] split(
return list.toArray(new String[list.size()]);
}

/**
* Joins the elements of the provided array into a single String containing the provided list of
* elements.
*
* <p>No delimiter is added before or after the list. A {@code null} separator is the same as an
* empty String ("").
*
* @param array the array of values to join together, may be null
* @param delimiter the separator character to use, null treated as ""
* @return the joined String, {@code null} if null array input
*/
public static String join(final Object[] array, final String delimiter) {
if (array == null) {
return null;
}
return join(array, delimiter, 0, array.length);
}

/**
* Joins the elements of the provided array into a single String containing the provided list of
* elements.
*
* <p>No delimiter is added before or after the list. A {@code null} separator is the same as an
* empty String ("").
*
* @param array the array of values to join together, may be null
* @param delimiter the separator character to use, null treated as ""
* @param startIndex the first index to start joining from
* @param endIndex the index to stop joining from (exclusive)
* @return the joined String, {@code null} if null array input
*/
public static String join(
final Object[] array,
final String delimiter,
final int startIndex,
final int endIndex) {
if (array == null) {
return null;
}
if (startIndex < 0 || startIndex >= array.length) {
throw new ArrayIndexOutOfBoundsException(startIndex);
}
if (endIndex < 0 || endIndex > array.length) {
throw new ArrayIndexOutOfBoundsException(endIndex);
}
final int noOfItems = endIndex - startIndex;
if (noOfItems <= 0) {
return EMPTY;
}
Objects.requireNonNull(delimiter, "The delimiter must not be null");
final StringBuilder buf = new StringBuilder(noOfItems * 16);
for (int i = startIndex; i < endIndex; i++) {
if (i > startIndex) {
buf.append(delimiter);
}
if (array[i] != null) {
buf.append(array[i]);
}
}
return buf.toString();
}

/**
* Joins the elements of the provided {@code Iterable} into a single String containing the
* provided elements.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@

import org.apache.paimon.benchmark.metric.cpu.clock.Clock;
import org.apache.paimon.benchmark.metric.cpu.clock.SystemClock;
import org.apache.paimon.utils.StringUtils;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.AndFileFilter;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.File;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

package org.apache.paimon.benchmark;

import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
import org.apache.paimon.utils.StringUtils;

import org.apache.paimon.shade.org.apache.commons.lang3.SystemUtils;

import java.io.BufferedReader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,58 @@ void testNonEmptyStringBuilder() {
}
}

@Nested
class CommonsCompatibilityTests {

@Test
void testIsBlank() {
assertThat(StringUtils.isBlank(null)).isTrue();
assertThat(StringUtils.isBlank("")).isTrue();
assertThat(StringUtils.isBlank(" \t")).isTrue();
assertThat(StringUtils.isBlank("paimon")).isFalse();
}

@Test
void testEquals() {
assertThat(StringUtils.equals(null, null)).isTrue();
assertThat(StringUtils.equals(null, "paimon")).isFalse();
assertThat(StringUtils.equals("paimon", "paimon")).isTrue();
assertThat(StringUtils.equals("paimon", "Paimon")).isFalse();
}

@Test
void testStartsWithAndEndsWith() {
assertThat(StringUtils.startsWith("manifest-1", "manifest")).isTrue();
assertThat(StringUtils.startsWith(null, "manifest")).isFalse();
assertThat(StringUtils.startsWith(null, null)).isTrue();
assertThat(StringUtils.endsWith("part-0.parquet", ".parquet")).isTrue();
assertThat(StringUtils.endsWith("part-0.orc", ".parquet")).isFalse();
assertThat(StringUtils.endsWith(null, null)).isTrue();
}

@Test
void testSubstringBeforeAndAfterLast() {
assertThat(StringUtils.substringBeforeLast("a/b/c", "/")).isEqualTo("a/b");
assertThat(StringUtils.substringBeforeLast("abc", "/")).isEqualTo("abc");
assertThat(StringUtils.substringAfterLast("a/b/c", "/")).isEqualTo("c");
assertThat(StringUtils.substringAfterLast("abc/", "/")).isEmpty();
}

@Test
void testStripEnd() {
assertThat(StringUtils.stripEnd("cpu\n", null)).isEqualTo("cpu");
assertThat(StringUtils.stripEnd("abccc", "c")).isEqualTo("ab");
assertThat(StringUtils.stripEnd("abc", "")).isEqualTo("abc");
}

@Test
void testTrimToNull() {
assertThat(StringUtils.trimToNull(null)).isNull();
assertThat(StringUtils.trimToNull(" ")).isNull();
assertThat(StringUtils.trimToNull(" paimon ")).isEqualTo("paimon");
}
}

@Nested
class RandomNumericStringTests {

Expand Down Expand Up @@ -330,6 +382,30 @@ void testJoinIterableBasicCases() {
assertThat(StringUtils.join(Arrays.asList("a", null, "c"), ",")).isEqualTo("a,,c");
}

@Test
void testJoinArrayNullDelimiter() {
assertThatThrownBy(() -> StringUtils.join(new Object[] {"a", "b", "c"}, null))
.isInstanceOf(NullPointerException.class)
.hasMessage("The delimiter must not be null");
}

@Test
void testJoinArrayStartAndEndIndex() {
assertThat(StringUtils.join(new Object[] {"a", "b", "c"}, "--", 1, 3))
.isEqualTo("b--c");
assertThat(StringUtils.join(new Object[] {"a", "b", "c"}, "--", 2, 2)).isEmpty();
}

@Test
void testJoinArrayInvalidIndex() {
assertThatThrownBy(() -> StringUtils.join(new Object[] {"a", "b", "c"}, ",", 0, -1))
.isInstanceOf(ArrayIndexOutOfBoundsException.class);
assertThatThrownBy(() -> StringUtils.join(new Object[] {"a", "b", "c"}, ",", 3, 3))
.isInstanceOf(ArrayIndexOutOfBoundsException.class);
assertThatThrownBy(() -> StringUtils.join(new Object[] {"a", "b", "c"}, ",", 0, 4))
.isInstanceOf(ArrayIndexOutOfBoundsException.class);
}

@Test
void testJoinIterableEdgeCases() {
assertThat(StringUtils.join((Iterable<?>) null, ",")).isNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
import org.apache.paimon.types.RowType;
import org.apache.paimon.utils.InternalRowUtils;
import org.apache.paimon.utils.JsonSerdeUtil;

import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
import org.apache.paimon.utils.StringUtils;

import javax.annotation.Nullable;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,12 @@
import org.apache.paimon.table.system.SystemTableLoader;
import org.apache.paimon.utils.Pair;
import org.apache.paimon.utils.SnapshotNotExistException;
import org.apache.paimon.utils.StringUtils;
import org.apache.paimon.view.View;
import org.apache.paimon.view.ViewChange;
import org.apache.paimon.view.ViewImpl;
import org.apache.paimon.view.ViewSchema;

import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;

import javax.annotation.Nullable;

import java.io.IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
import org.apache.paimon.utils.LazyField;
import org.apache.paimon.utils.Pair;
import org.apache.paimon.utils.SnapshotManager;
import org.apache.paimon.utils.StringUtils;
import org.apache.paimon.utils.TagManager;
import org.apache.paimon.utils.TimeUtils;
import org.apache.paimon.view.View;
Expand All @@ -120,7 +121,6 @@

import org.apache.paimon.shade.guava30.com.google.common.collect.ImmutableMap;
import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;

import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@
import org.apache.paimon.types.DataTypes;
import org.apache.paimon.utils.SnapshotManager;
import org.apache.paimon.utils.SnapshotNotExistException;
import org.apache.paimon.utils.StringUtils;
import org.apache.paimon.view.View;
import org.apache.paimon.view.ViewChange;

import org.apache.paimon.shade.guava30.com.google.common.collect.ImmutableList;
import org.apache.paimon.shade.guava30.com.google.common.collect.ImmutableMap;
import org.apache.paimon.shade.guava30.com.google.common.collect.Lists;
import org.apache.paimon.shade.guava30.com.google.common.collect.Maps;
import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;

import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Assertions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
import org.apache.paimon.catalog.Catalog;
import org.apache.paimon.catalog.Identifier;
import org.apache.paimon.table.Table;

import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
import org.apache.paimon.utils.StringUtils;

import org.apache.flink.table.procedure.ProcedureContext;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

package org.apache.paimon.flink.action;

import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
import org.apache.paimon.utils.StringUtils;

import java.util.Map;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
import org.apache.paimon.catalog.Catalog;
import org.apache.paimon.catalog.Identifier;
import org.apache.paimon.table.Table;

import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
import org.apache.paimon.utils.StringUtils;

import org.apache.flink.table.annotation.ArgumentHint;
import org.apache.flink.table.annotation.DataTypeHint;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
import org.apache.paimon.table.FileStoreTable;
import org.apache.paimon.utils.BlockingIterator;
import org.apache.paimon.utils.SnapshotManager;

import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
import org.apache.paimon.utils.StringUtils;

import org.apache.flink.types.Row;
import org.apache.flink.types.RowKind;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@

import org.apache.paimon.catalog.Catalog;
import org.apache.paimon.utils.BlockingIterator;

import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
import org.apache.paimon.utils.StringUtils;

import org.apache.flink.table.catalog.CatalogPartition;
import org.apache.flink.table.catalog.CatalogPartitionSpec;
Expand Down
Loading