com.bbn.bue.common.StringUtils Maven / Gradle / Ivy
The newest version!
package com.bbn.bue.common;
import com.bbn.bue.common.strings.offsets.CharOffset;
import com.bbn.bue.common.strings.offsets.OffsetRange;
import com.google.common.annotations.Beta;
import com.google.common.base.CharMatcher;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.CharSource;
import com.google.common.io.Files;
import com.google.common.io.LineProcessor;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Beta
public final class StringUtils {
private StringUtils() {
throw new UnsupportedOperationException();
}
/**
* Returns a string which is the result of replacing every match of regex in the input string with
* the results of applying replacementFunction to the matched string. This is a candidate to be
* moved to a more general utility package.
*
* @param replacementFunction May not return null.
*/
public static String replaceAll(final String input, final String regex,
final Function replacementFunction) {
return replaceAll(input, Pattern.compile(regex), replacementFunction);
}
/**
* Returns a string which is the result of replacing every match of regex in the input string with
* the results of applying replacementFunction to the matched string. This is a candidate to be
* moved to a more general utility package.
*
* @param replacementFunction May not return null.
*/
public static String replaceAll(final String input, final Pattern regex,
final Function replacementFunction) {
final StringBuffer output = new StringBuffer();
final Matcher matcher = regex.matcher(input);
while (matcher.find()) {
final MatchResult match = matcher.toMatchResult();
final String replacement = replacementFunction.apply(match);
if (replacement == null) {
throw new IllegalArgumentException(
String.format("Replacement function returned null for match %s", match.group()));
}
if (!replacement.equals(match.group())) {
matcher.appendReplacement(output, replacement);
}
}
matcher.appendTail(output);
return output.toString();
}
/**
* * Returns the index of the {@code n}-th occurence of {@code needle} in {@code s}. If {@code needle}
* does not appear in {@code s}, returns -1.
*
* @param s The string to search. Cannot be null.
* @param needle The character to search for.
* @param n Return the {@code n}-th occurence
*/
public static int nthOccurrenceOf(final String s, final char needle, int n) {
checkNotNull(s);
checkArgument(n > 0);
for (int i = 0; i < s.length(); ++i) {
if (needle == s.charAt(i)) {
--n;
if (n == 0) {
return i;
}
}
}
return -1;
}
public static Set stringSetFrom(final File stringFile) throws IOException {
return stringSetFrom(Files.asCharSource(stringFile, Charsets.UTF_8));
}
public static Set stringSetFrom(final CharSource supplier) throws IOException {
final LineProcessor> callback = new LineProcessor>() {
private final ImmutableSet.Builder builder = ImmutableSet.builder();
@Override
public boolean processLine(final String s) {
builder.add(s.trim());
return true;
}
@Override
public Set getResult() {
return builder.build();
}
};
supplier.readLines(callback);
return callback.getResult();
}
/**
* Returns a Function which will join the string with the specified separator
*/
public static final Function, String> joinFunction(final Joiner joiner) {
return new Function, String>() {
@Override
public String apply(final Iterable> list) {
return joiner.join(list);
}
};
}
@SuppressWarnings("deprecation")
public static final Joiner spaceJoiner() {
return SpaceJoiner;
}
/**
* @deprecated Prefer {@link #spaceJoiner()}
*/
@Deprecated
public static final Joiner SpaceJoiner = Joiner.on(" ");
@SuppressWarnings("deprecation")
public static final Joiner unixNewlineJoiner() {
return NewlineJoiner;
}
/**
* @deprecated Prefer {@link #unixNewlineJoiner()}
*/
@Deprecated
public static final Joiner NewlineJoiner = Joiner.on("\n");
@SuppressWarnings("deprecation")
public static final Joiner commaJoiner() {
return CommaJoiner;
}
@SuppressWarnings("deprecation")
public static final Joiner dotJoiner() {
return DotJoiner;
}
/**
* @deprecated Prefer {@link #commaJoiner()}.
*/
@Deprecated
public static final Joiner CommaJoiner = Joiner.on(",");
public static final Function, String> CommaJoin =
JoinFunction(CommaJoiner);
public static final Joiner CommaSpaceJoiner = Joiner.on(", ");
public static final Function, String> CommaSpaceJoin =
JoinFunction(CommaSpaceJoiner);
public static final Joiner SemicolonJoiner = Joiner.on(";");
public static final Function, String> SemicolonJoin =
JoinFunction(SemicolonJoiner);
public static final Joiner SemicolonSpaceJoiner = Joiner.on("; ");
public static final Function, String> SemicolonSpaceJoin =
JoinFunction(SemicolonSpaceJoiner);
@Deprecated
/**
* Prefer {@link #dotJoiner()}
*/
public static final Joiner DotJoiner = Joiner.on(".");
/************* Splitters ********************/
/**
* Splits on tab, omitting empty strings and trimming results.
*/
public static Splitter onTabs() {
return OnTabs;
}
/**
* Splits on spaces, omitting empty strings and trimming results.
*/
public static Splitter onSpaces() {
return OnSpaces;
}
/**
* Splits on Unix newlines, omitting empty strings and trimming results.
*/
public static Splitter onUnixNewlines() {
return OnUnixNewlines;
}
/**
* Splits on commas, omitting empty strings and trimming results.
*/
public static Splitter onCommas() {
return OnCommas;
}
private static final Splitter onDots = Splitter.on(".").trimResults().omitEmptyStrings();
/**
* Splits on periods, omitting empty strings and trimming results.
*/
public static Splitter onDots() {
return onDots;
}
private static final Splitter onDashes = Splitter.on("-").trimResults().omitEmptyStrings();
/**
* Splits on dashes, omitting empty strings and trimming results.
*/
public static Splitter onDashes() {
return onDashes;
}
/********************** Wrapping functions ********************/
/**
* Returns a Function which will wrap a string in the specified wrappers string (e.g. if the
* wrappers are "[", "]", it will transform "foo" to "[foo]"
*/
public static Function WrapFunction(final String leftWrapper,
final String rightWrapper) {
Preconditions.checkNotNull(leftWrapper);
Preconditions.checkNotNull(rightWrapper);
return new Function() {
@Override
public String apply(final String s) {
return leftWrapper + s + rightWrapper;
}
};
}
public static final Function WrapInDoubleQuotes = WrapFunction("\"", "\"");
public static final Function WrapInSingleQuotes = WrapFunction("'", "'");
public static final Function WrapInSquareBrackets = WrapFunction("[", "]");
public static final Function WrapInAngleBrackets = WrapFunction("<", ">");
public static final Function WrapInParens = WrapFunction("(", ")");
public static final Function ToLowerCase = new Function() {
@Override
public String apply(final String s) {
return s.toLowerCase();
}
};
public static final Predicate ContainsLetterOrDigit = new Predicate() {
@Override
public boolean apply(final String s) {
for (int i = 0; i < s.length(); ++i) {
if (Character.isLetterOrDigit(s.charAt(i))) {
return true;
}
}
return false;
}
};
public static final Function Trim = new Function() {
@Override
public String apply(final String s) {
return s.trim();
}
};
public static final Function PrefixWith(final String prefix) {
return new Function() {
@Override
public String apply(final String s) {
return prefix + s;
}
};
}
public static final Predicate startsWith(final String prefix) {
return new Predicate() {
@Override
public boolean apply(final String x) {
return x.startsWith(prefix);
}
};
}
public static final String removeSuffixIfPresent(final String name, final String badSuffix) {
if (name.endsWith(badSuffix)) {
return name.substring(0, name.length() - badSuffix.length());
} else {
return name;
}
}
/**
* Gets a predicate which returns true for a {@code String} iff it contains {@code probe} as a substring.
*/
@SuppressWarnings("unchecked")
public static final Predicate containsPredicate(final String probe) {
return Contains(probe);
}
/**
* A predicate which returns true for a {@code String} iff at least one of its characters
* matches the provided {@link CharMatcher}
*/
public static final Predicate anyCharMatches(final CharMatcher matcher) {
return new Predicate() {
@Override
public boolean apply(@Nullable final String input) {
return matcher.matchesAnyOf(input);
}
};
}
public static final Predicate isEmpty() {
return new Predicate() {
@Override
public boolean apply(final String input) {
checkArgument(input != null);
return input.isEmpty();
}
};
}
/**
* Just like {@link java.lang.String#indexOf(String, int)}, except it searches for all strings in
* {@code probes}. If none are found, returns -1. If any are found, returns the earliest index of
* a match. The current implementation naively searches for each string separately. If speed is
* important, consider an alternative approach.
*/
public static int earliestIndexOfAny(String s, Iterable probes, int from) {
int earliestIdx = -1;
for (final String probe : probes) {
final int probeIdx = s.indexOf(probe, from);
// if we found something for this probe
if (probeIdx >= 0
// and either we haven't found anything else yet or
// this is earlier than anything we've found yet
&& (earliestIdx == -1 || probeIdx < earliestIdx)) {
// then this is our new earliest match
earliestIdx = probeIdx;
}
}
return earliestIdx;
}
public static final Function ToLength = new Function() {
@Override
public Integer apply(String input) {
checkNotNull(input);
return input.length();
}
};
public static String substring(String s, OffsetRange substringBounds) {
return s.substring(substringBounds.startInclusive().value(),
substringBounds.endInclusive().value() + 1);
}
/**
* Acts just like {@link String#substring(int, int)} except that if either index is out-of-bounds,
* it is clipped to the most extreme legal value. This guarantees that as long as {@code s} is
* non-null and {@code endIndexExclusive>=startIndexInclusive}, no exception will be thrown when
* calling this method.
*/
public static String safeSubstring(String s, int startIndexInclusive, int endIndexExclusive) {
final int trueStartIndex = Math.max(0, startIndexInclusive);
final int trueEndIndex = Math.min(endIndexExclusive, s.length());
return s.substring(trueStartIndex, trueEndIndex);
}
/**
* Checks that the supplied string is non-empty. If it is empty, an {@link
* java.lang.IllegalArgumentException} is thrown with the supplied message.
*/
public static String checkNonEmpty(String s, String msg) {
checkArgument(!s.isEmpty(), msg);
return s;
}
/**
* Produces a string representation of a positive integer padded with leading zeros. Enough zeros
* are adding so that the supplied {@code maxValue} would have the same number of digits.
*/
public static String padWithMax(final int numToPad, final int maxValue) {
checkArgument(numToPad >= 0);
checkArgument(numToPad <= maxValue);
final int maxLength = Integer.toString(maxValue).length();
final String baseString = Integer.toString(numToPad);
final String padding = Strings.repeat("0", maxLength - baseString.length());
return padding + numToPad;
}
/******************************** Deprecated code ************************************/
/**
* @deprecated Just use Guava's {@link Joiner} as normal.
*/
@Deprecated
public static String join(final Iterable> list, final String separator) {
return Joiner.on(separator).join(list);
}
/**
* @deprecated Just use Guava's {@link Joiner} as normal.
*/
@Deprecated
public static String joinSkipNulls(final Iterable> list, final String separator) {
return Joiner.on(separator).skipNulls().join(list);
}
/**
* @deprecated Prefer {@link #joinFunction(Joiner)}'s more consistent capitalization.
*/
@Deprecated
public static final Function, String> JoinFunction(final Joiner joiner) {
return joinFunction(joiner);
}
/**
* @deprecated Prefer {@link #joinFunction(Joiner)} applies to {@link #spaceJoiner()}.
*/
@Deprecated
public static final Function, String> SpaceJoin =
JoinFunction(SpaceJoiner);
/**
* @deprecated Prefer {@link #joinFunction(Joiner)} applied to {@link #unixNewlineJoiner()}
*/
@Deprecated
public static final Function, String> NewlineJoin =
JoinFunction(NewlineJoiner);
/**
* @deprecated Use {@link #onSpaces()}
*/
@Deprecated
public static final Splitter OnSpaces = Splitter.on(" ").trimResults().omitEmptyStrings();
/**
* @deprecated Use {@link #onTabs()}
*/
@Deprecated
public static final Splitter OnTabs = Splitter.on("\t").trimResults().omitEmptyStrings();
/**
* @deprecated Use {@link #onUnixNewlines()}
*/
@Deprecated
public static final Splitter OnUnixNewlines = Splitter.on("\n").trimResults().omitEmptyStrings();
/**
* @deprecated Use {@link #onCommas()}
*/
@Deprecated
public static final Splitter OnCommas = Splitter.on(",").trimResults().omitEmptyStrings();
@Deprecated
/**
* @deprecated Prefer {@link #joinFunction(Joiner)} on {@link #dotJoiner()}
*/
public static final Function, String> DotJoin =
JoinFunction(DotJoiner);
/**
* @deprecated Prefer {@link #containsPredicate(String)}
*/
@Deprecated
public static final Predicate Contains(final String probe) {
checkNotNull(probe);
return new Predicate() {
@Override
public boolean apply(String input) {
return input.contains(probe);
}
};
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy