public static String abbreviate(String str, int offset, int maxWidth) {
        if (str == null) {
            return null;
        }
        if (maxWidth < 4) {
            throw new IllegalArgumentException("Minimum abbreviation width is 4");
        }
        if (str.length() <= maxWidth) {
            return str;
        }
        if (offset > str.length()) {
            offset = str.length();
        }
        if (str.length() - offset < maxWidth - 3) {
            offset = str.length() - (maxWidth - 3);
        }
        final String abrevMarker = "...";
        if (offset <= 4) {
            return str.substring(0, maxWidth - 3) + abrevMarker;
        }
        if (maxWidth < 7) {
            throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
        }
        if (offset + maxWidth - 3 < str.length()) {
            return abrevMarker + abbreviate(str.substring(offset), maxWidth - 3);
        }
        return abrevMarker + str.substring(str.length() - (maxWidth - 3));
    }
<p>Abbreviates a String using ellipses. This will turn
"Now is the time for all good men" into "...is the time for..."</p>

<p>Works like {@code abbreviate(String, int)}, but allows you to specify
a "left edge" offset.  Note that this left edge is not necessarily going to
be the leftmost character in the result, or the first character following the
ellipses, but it will appear somewhere in the result.

<p>In no case will it return a String of length greater than
{@code maxWidth}.</p>

<pre>
StringUtils.abbreviate(null, *, *)                = null
StringUtils.abbreviate("", 0, 4)                  = ""
StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
</pre>

@param str  the String to check, may be null
@param offset  left edge of source String
@param maxWidth  maximum length of result String, must be at least 4
@return abbreviated String, {@code null} if null String input
@throws IllegalArgumentException if the width is too small
@since 2.0
android/android_framework/base/src/main/java/lang3/StringUtils.java