Skip to content

Commit

Permalink
[Refactor] CollectionUtils, Iterators, and String methods to core lib (
Browse files Browse the repository at this point in the history
…opensearch-project#9120)

This commit refactors the CollectionUtils, and Iterators utility classes
to the core and common libraries, respectively. Several other base
Strings utility methods are also refactored to the core Strings utility
library. This is done to incrementally move the remaining Strings
methods in server to the core String utility.

Signed-off-by: Nicholas Walter Knize <nknize@apache.org>
Signed-off-by: Shivansh Arora <hishiv@amazon.com>
  • Loading branch information
nknize authored and shiv0408 committed Apr 25, 2024
1 parent a532a4a commit 5778ff8
Show file tree
Hide file tree
Showing 83 changed files with 302 additions and 297 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
import org.opensearch.core.common.bytes.BytesReference;
import org.opensearch.common.lucene.uid.Versions;
import org.opensearch.common.unit.TimeValue;
import org.opensearch.common.util.CollectionUtils;
import org.opensearch.core.common.util.CollectionUtils;
import org.opensearch.common.xcontent.XContentHelper;
import org.opensearch.common.xcontent.XContentType;
import org.opensearch.core.common.Strings;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import org.opensearch.client.cluster.RemoteInfoRequest;
import org.opensearch.cluster.health.ClusterHealthStatus;
import org.opensearch.common.Priority;
import org.opensearch.common.util.CollectionUtils;
import org.opensearch.core.common.util.CollectionUtils;
import org.opensearch.test.OpenSearchTestCase;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPut;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
import org.opensearch.common.CheckedFunction;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.unit.TimeValue;
import org.opensearch.common.util.CollectionUtils;
import org.opensearch.core.common.util.CollectionUtils;
import org.opensearch.common.xcontent.XContentType;
import org.opensearch.core.common.Strings;
import org.opensearch.test.OpenSearchTestCase;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public void testRandomSingleton() {
int numberOfIterators = randomIntBetween(1, 1000);
int singletonIndex = randomIntBetween(0, numberOfIterators - 1);
int value = randomInt();
@SuppressWarnings("rawtypes")
Iterator<Integer>[] iterators = new Iterator[numberOfIterators];
for (int i = 0; i < numberOfIterators; i++) {
iterators[i] = i != singletonIndex ? empty() : singletonIterator(value);
Expand All @@ -92,6 +93,7 @@ public void testRandomSingleton() {

public void testRandomIterators() {
int numberOfIterators = randomIntBetween(1, 1000);
@SuppressWarnings("rawtypes")
Iterator<Integer>[] iterators = new Iterator[numberOfIterators];
List<Integer> values = new ArrayList<>();
for (int i = 0; i < numberOfIterators; i++) {
Expand Down
225 changes: 168 additions & 57 deletions libs/core/src/main/java/org/opensearch/core/common/Strings.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package org.opensearch.core.common;

import org.opensearch.common.Nullable;
import org.opensearch.core.common.util.CollectionUtils;

import java.io.BufferedReader;
import java.io.StringReader;
Expand All @@ -35,18 +36,6 @@ public class Strings {
public static final String UNKNOWN_UUID_VALUE = "_na_";
public static final String[] EMPTY_ARRAY = new String[0];

/**
* Split the specified string by commas to an array.
*
* @param s the string to split
* @return the array of split values
* @see String#split(String)
*/
public static String[] splitStringByCommaToArray(final String s) {
if (s == null || s.isEmpty()) return Strings.EMPTY_ARRAY;
else return s.split(",");
}

/**
* Convenience method to return a Collection as a delimited (e.g. CSV)
* String. E.g. useful for <code>toString()</code> implementations.
Expand Down Expand Up @@ -341,47 +330,6 @@ public static String[] toStringArray(final Collection<String> collection) {
return collection.toArray(new String[0]);
}

/**
* Take a String which is a delimited list and convert it to a String array.
* <p>A single delimiter can consists of more than one character: It will still
* be considered as single delimiter string, rather than as bunch of potential
* delimiter characters - in contrast to <code>tokenizeToStringArray</code>.
*
* @param str the input String
* @param delimiter the delimiter between elements (this is a single delimiter,
* rather than a bunch individual delimiter characters)
* @param charsToDelete a set of characters to delete. Useful for deleting unwanted
* line breaks: e.g. "\r\n\f" will delete all new lines and line feeds in a String.
* @return an array of the tokens in the list
* @see #tokenizeToStringArray
*/
public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {
if (str == null) {
return Strings.EMPTY_ARRAY;
}
if (delimiter == null) {
return new String[] { str };
}
List<String> result = new ArrayList<>();
if ("".equals(delimiter)) {
for (int i = 0; i < str.length(); i++) {
result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
}
} else {
int pos = 0;
int delPos;
while ((delPos = str.indexOf(delimiter, pos)) != -1) {
result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
pos = delPos + delimiter.length();
}
if (str.length() > 0 && pos <= str.length()) {
// Add rest of String, but not in case of empty input.
result.add(deleteAny(str.substring(pos), charsToDelete));
}
}
return toStringArray(result);
}

/**
* Tokenize the specified string by commas to a set, trimming whitespace and ignoring empty tokens.
*
Expand All @@ -393,6 +341,41 @@ public static Set<String> tokenizeByCommaToSet(final String s) {
return tokenizeToCollection(s, ",", HashSet::new);
}

/**
* Split the specified string by commas to an array.
*
* @param s the string to split
* @return the array of split values
* @see String#split(String)
*/
public static String[] splitStringByCommaToArray(final String s) {
if (s == null || s.isEmpty()) return Strings.EMPTY_ARRAY;
else return s.split(",");
}

/**
* Split a String at the first occurrence of the delimiter.
* Does not include the delimiter in the result.
*
* @param toSplit the string to split
* @param delimiter to split the string up with
* @return a two element array with index 0 being before the delimiter, and
* index 1 being after the delimiter (neither element includes the delimiter);
* or <code>null</code> if the delimiter wasn't found in the given input String
*/
public static String[] split(String toSplit, String delimiter) {
if (hasLength(toSplit) == false || hasLength(delimiter) == false) {
return null;
}
int offset = toSplit.indexOf(delimiter);
if (offset < 0) {
return null;
}
String beforeDelimiter = toSplit.substring(0, offset);
String afterDelimiter = toSplit.substring(offset + delimiter.length());
return new String[] { beforeDelimiter, afterDelimiter };
}

/**
* Tokenize the given String into a String array via a StringTokenizer.
* Trims tokens and omits empty tokens.
Expand Down Expand Up @@ -446,6 +429,47 @@ private static <T extends Collection<String>> T tokenizeToCollection(
return tokens;
}

/**
* Take a String which is a delimited list and convert it to a String array.
* <p>A single delimiter can consists of more than one character: It will still
* be considered as single delimiter string, rather than as bunch of potential
* delimiter characters - in contrast to <code>tokenizeToStringArray</code>.
*
* @param str the input String
* @param delimiter the delimiter between elements (this is a single delimiter,
* rather than a bunch individual delimiter characters)
* @param charsToDelete a set of characters to delete. Useful for deleting unwanted
* line breaks: e.g. "\r\n\f" will delete all new lines and line feeds in a String.
* @return an array of the tokens in the list
* @see #tokenizeToStringArray
*/
public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {
if (str == null) {
return Strings.EMPTY_ARRAY;
}
if (delimiter == null) {
return new String[] { str };
}
List<String> result = new ArrayList<>();
if ("".equals(delimiter)) {
for (int i = 0; i < str.length(); i++) {
result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
}
} else {
int pos = 0;
int delPos;
while ((delPos = str.indexOf(delimiter, pos)) != -1) {
result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
pos = delPos + delimiter.length();
}
if (str.length() > 0 && pos <= str.length()) {
// Add rest of String, but not in case of empty input.
result.add(deleteAny(str.substring(pos), charsToDelete));
}
}
return toStringArray(result);
}

/**
* Take a String which is a delimited list and convert it to a String array.
* <p>A single delimiter can consists of more than one character: It will still
Expand Down Expand Up @@ -486,10 +510,6 @@ public static Set<String> commaDelimitedListToSet(String str) {
return set;
}

public static boolean isNullOrEmpty(@Nullable String s) {
return s == null || s.isEmpty();
}

/**
* Capitalize a <code>String</code>, changing the first letter to
* upper case as per {@link Character#toUpperCase(char)}.
Expand Down Expand Up @@ -538,4 +558,95 @@ public static String format1Decimals(double value, String suffix) {
}
}
}

/**
* Return substring(beginIndex, endIndex) that is impervious to string length.
*/
public static String substring(String s, int beginIndex, int endIndex) {
if (s == null) {
return s;
}

int realEndIndex = s.length() > 0 ? s.length() - 1 : 0;

if (endIndex > realEndIndex) {
return s.substring(beginIndex);
} else {
return s.substring(beginIndex, endIndex);
}
}

/**
* If an array only consists of zero or one element, which is "*" or "_all" return an empty array
* which is usually used as everything
*/
public static boolean isAllOrWildcard(String[] data) {
return CollectionUtils.isEmpty(data) || data.length == 1 && isAllOrWildcard(data[0]);
}

/**
* Returns `true` if the string is `_all` or `*`.
*/
public static boolean isAllOrWildcard(String data) {
return "_all".equals(data) || "*".equals(data);
}

/**
* Truncates string to a length less than length. Backtracks to throw out
* high surrogates.
*/
public static String cleanTruncate(String s, int length) {
if (s == null) {
return s;
}
/*
* Its pretty silly for you to truncate to 0 length but just in case
* someone does this shouldn't break.
*/
if (length == 0) {
return "";
}
if (length >= s.length()) {
return s;
}
if (Character.isHighSurrogate(s.charAt(length - 1))) {
length--;
}
return s.substring(0, length);
}

public static boolean isNullOrEmpty(@Nullable String s) {
return s == null || s.isEmpty();
}

public static String padStart(String s, int minimumLength, char c) {
if (s == null) {
throw new NullPointerException("s");
}
if (s.length() >= minimumLength) {
return s;
} else {
StringBuilder sb = new StringBuilder(minimumLength);
for (int i = s.length(); i < minimumLength; i++) {
sb.append(c);
}

sb.append(s);
return sb.toString();
}
}

public static String toLowercaseAscii(String in) {
StringBuilder out = new StringBuilder();
Iterator<Integer> iter = in.codePoints().iterator();
while (iter.hasNext()) {
int codepoint = iter.next();
if (codepoint > 128) {
out.appendCodePoint(codepoint);
} else {
out.appendCodePoint(Character.toLowerCase(codepoint));
}
}
return out.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* GitHub history for details.
*/

package org.opensearch.common.util;
package org.opensearch.core.common.util;

import org.opensearch.common.collect.Iterators;
import org.opensearch.core.common.Strings;
Expand Down Expand Up @@ -217,6 +217,7 @@ public int size() {
}
}

@SuppressWarnings("unchecked")
public static <E> ArrayList<E> iterableAsArrayList(Iterable<? extends E> elements) {
if (elements == null) {
throw new NullPointerException("elements");
Expand All @@ -232,13 +233,15 @@ public static <E> ArrayList<E> iterableAsArrayList(Iterable<? extends E> element
}
}

@SuppressWarnings("unchecked")
public static <E> ArrayList<E> arrayAsArrayList(E... elements) {
if (elements == null) {
throw new NullPointerException("elements");
}
return new ArrayList<>(Arrays.asList(elements));
}

@SuppressWarnings("unchecked")
public static <E> ArrayList<E> asArrayList(E first, E... other) {
if (other == null) {
throw new NullPointerException("other");
Expand All @@ -249,6 +252,7 @@ public static <E> ArrayList<E> asArrayList(E first, E... other) {
return list;
}

@SuppressWarnings("unchecked")
public static <E> ArrayList<E> asArrayList(E first, E second, E... other) {
if (other == null) {
throw new NullPointerException("other");
Expand Down
Loading

0 comments on commit 5778ff8

Please sign in to comment.