Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.codefilarete.tool;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import org.codefilarete.tool.bean.Objects;
/**
* @author Guillaume Mary
*/
public abstract class Strings {
public static boolean isEmpty(CharSequence charSequence) {
return charSequence == null || charSequence.length() == 0;
}
public static C preventEmpty(C charSequence, C replacement) {
return isEmpty(charSequence) ? replacement : charSequence;
}
public static String capitalize(final CharSequence cs) {
return (String) doWithDelegate(cs, new DefaultNullOrEmptyDelegate() {
@Override
public CharSequence onNotNullNotEmpty(CharSequence cs) {
return Character.toUpperCase(cs.charAt(0)) + cs.subSequence(1, cs.length()).toString();
}
});
}
public static String uncapitalize(final CharSequence cs) {
return (String) doWithDelegate(cs, new DefaultNullOrEmptyDelegate() {
@Override
public CharSequence onNotNullNotEmpty(CharSequence cs) {
return Character.toLowerCase(cs.charAt(0)) + cs.subSequence(1, cs.length()).toString();
}
});
}
/**
* Concatenate count (positive) times parameter s.
* Optional Strings in prebuildStrings are used to speed concatenation for large count numbers if you already have
* large snippets of s pre-concatenated. For instance, you want 3456 times "a" and you already got constants with
* a*500, a*100, a*10, then this method will only cat 6*a*500, 4*a*100, 5*a*10 and 6*a. Instead of 3456 times "a".
*
* @param count expected repeatition of s
* @param s the String to be concatenated
* @param prebuiltStrings optional pre-concatenated "s" strings, in descent size order.
* @return s repeated count times
*/
public static StringBuilder repeat(int count, CharSequence s, String... prebuiltStrings) {
StringBuilder result = new StringBuilder(count * s.length());
repeat(result, count, s, prebuiltStrings);
return result;
}
/**
* Concatenates count (positive) times parameter s.
* Optional Strings in prebuildStrings are used to speed concatenation for large count numbers if you already have
* large snippets of s pre-concatenated. For instance, you want 3456 times "a" and you already got constants with
* a*500, a*100, a*10, then this method will only cat 6*a*500, 4*a*100, 5*a*10 and 6*a. Instead of 3456 times "a".
*
* @param result destination of the concatenation
* @param count expected repetition of s
* @param s the {@link CharSequence} to be concatenated to result
* @param prebuiltStrings optional pre-concatenated "s" strings, in descent size order.
* @return result with s repeated count times appended
*/
public static StringBuilder repeat(StringBuilder result, int count, CharSequence s, CharSequence... prebuiltStrings) {
result.ensureCapacity(result.length() + count * s.length()); // to avoid extra allocation cycles
int snippetCount, remainer = count;
for (CharSequence snippet : prebuiltStrings) {
int snippetLength = snippet.length();
snippetCount = remainer / snippetLength;
for (int i = 0; i < snippetCount; i++) {
result.append(snippet);
}
remainer = remainer % snippetLength;
}
for (int i = 0; i < remainer; i++) {
result.append(s);
}
return result;
}
/**
* Equivalent to {@link String#split(String)} without regexp which is unnecessary for char separator
* @param stringToBeSplit
* @param separator
* @param keepSeparatorInResult
* @return a {@link String} split into pieces each time separator is found in it
*/
public static List split(String stringToBeSplit, char separator, boolean keepSeparatorInResult) {
List result = new ArrayList<>();
int separatorIndex = stringToBeSplit.indexOf(separator);
int previousSeparatorIndex = 0;
int substringPadding = keepSeparatorInResult ? 1 : 0;
while (separatorIndex != -1) {
result.add(stringToBeSplit.substring(previousSeparatorIndex, separatorIndex + substringPadding));
previousSeparatorIndex = separatorIndex + 1;
separatorIndex = stringToBeSplit.indexOf(separator, previousSeparatorIndex);
}
if (previousSeparatorIndex < stringToBeSplit.length()) {
result.add(stringToBeSplit.substring(previousSeparatorIndex));
}
return result;
}
public static CharSequence head(@Nullable CharSequence cs, @Nonnegative int headSize) {
return doWithDelegate(cs, new DefaultNullOrEmptyDelegate() {
@Override
public CharSequence onNotNullNotEmpty(@Nonnull CharSequence cs) {
return cs.subSequence(0, Math.min(cs.length(), headSize));
}
});
}
public static CharSequence head(@Nullable String cs, @Nonnull String untilIncluded) {
return doWithDelegate(cs, new DefaultNullOrEmptyDelegate() {
@Override
public CharSequence onNotNullNotEmpty(@Nonnull CharSequence cs) {
int index = ((String) cs).indexOf(untilIncluded);
return cs.subSequence(0, Math.min(cs.length(), Objects.fallback(index, -1, 0)));
}
});
}
public static CharSequence cutHead(@Nullable CharSequence cs, @Nonnegative int headSize) {
return doWithDelegate(cs, new DefaultNullOrEmptyDelegate() {
@Override
public CharSequence onNotNullNotEmpty(@Nonnull CharSequence cs) {
return cs.subSequence(Math.min(headSize, cs.length()), cs.length());
}
});
}
public static CharSequence tail(@Nullable CharSequence cs, @Nonnegative int tailSize) {
return doWithDelegate(cs, new DefaultNullOrEmptyDelegate() {
@Override
public CharSequence onNotNullNotEmpty(@Nonnull CharSequence cs) {
return cs.subSequence(Math.max(0, cs.length() - tailSize), cs.length());
}
});
}
public static CharSequence cutTail(@Nullable CharSequence cs, @Nonnegative int tailSize) {
return doWithDelegate(cs, new DefaultNullOrEmptyDelegate() {
@Override
public CharSequence onNotNullNotEmpty(@Nonnull CharSequence cs) {
return cs.subSequence(0, preventNegative(cs.length() - tailSize));
}
});
}
/**
* Cuts a {@link CharSequence} and appends 3 dots ("...") at the end if its length is strictly greater than length
*
* @param cs any {@link CharSequence}
* @param length length at which given {@link CharSequence} must be cut and appended "..."
* @return length-firsts characters of given {@link CharSequence} appended with "...", therefore its size is length+3
*/
public static CharSequence ellipsis(@Nullable CharSequence cs, @Nonnegative int length) {
return doWithDelegate(cs, new DefaultNullOrEmptyDelegate() {
@Override
public CharSequence onNotNullNotEmpty(@Nonnull CharSequence cs) {
if (cs.length() > length) {
return cs.subSequence(0, length) + "...";
} else {
return cs;
}
}
});
}
/**
* @param i any integer
* @return 0 if i < 0
*/
private static int preventNegative(int i) {
return Math.max(i, 0);
}
private static CharSequence doWithDelegate(@Nullable CharSequence cs, INullOrEmptyDelegate emptyDelegate) {
if (cs == null) {
return emptyDelegate.onNull();
} else if (cs.length() == 0) {
return emptyDelegate.onEmpty();
} else {
return emptyDelegate.onNotNullNotEmpty(cs);
}
}
/**
* Give a printable view of an object through method references of any of its properties. These will be concatenated to each other
* with comma (", ").
* Result of method references are printed by {@link StringBuilder#append(Object)} contract.
*
* @param object any object (not null)
* @param printableProperties functions that give a properties to be concatenated
* @param object type
* @return the concatenation of the results of functions invocation on the given object
*/
@SafeVarargs
public static String footPrint(O object, Function ... printableProperties) {
StringAppender result = new StringAppender();
for (Function printableProperty : printableProperties) {
result.cat(printableProperty.apply(object), ", ");
}
return result.cutTail(2).toString();
}
private interface INullOrEmptyDelegate {
CharSequence onNull();
CharSequence onEmpty();
CharSequence onNotNullNotEmpty(@Nonnull CharSequence cs);
}
private static abstract class DefaultNullOrEmptyDelegate implements INullOrEmptyDelegate {
@Override
public CharSequence onNull() {
return null;
}
@Override
public CharSequence onEmpty() {
return "";
}
}
private Strings() {}
}