下面列出了怎么用java.util.FormattableFlags的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Returns a string representation of the user supplied formattable, accounting for any possible
* runtime exceptions.
*
* @param value the value to be formatted.
* @return a best-effort string representation of the given value, even if exceptions were thrown.
*/
private static void safeFormatTo(Formattable value, StringBuilder out, FormatOptions options) {
// Only care about 3 specific flags for Formattable.
int formatFlags = options.getFlags() & (FLAG_LEFT_ALIGN | FLAG_UPPER_CASE | FLAG_SHOW_ALT_FORM);
if (formatFlags != 0) {
// TODO: Maybe re-order the options flags to make this step easier or use a lookup table.
// Note that reordering flags would require a rethink of how they are parsed.
formatFlags = ((formatFlags & FLAG_LEFT_ALIGN) != 0 ? FormattableFlags.LEFT_JUSTIFY : 0)
| ((formatFlags & FLAG_UPPER_CASE) != 0 ? FormattableFlags.UPPERCASE : 0)
| ((formatFlags & FLAG_SHOW_ALT_FORM) != 0 ? FormattableFlags.ALTERNATE : 0);
}
// We may need to undo an arbitrary amount of appending if there is an error.
int originalLength = out.length();
Formatter formatter = new Formatter(out, FORMAT_LOCALE);
try {
value.formatTo(formatter, formatFlags, options.getWidth(), options.getPrecision());
} catch (RuntimeException e) {
out.setLength(originalLength);
// We only use a StringBuilder to create the Formatter instance.
try {
formatter.out().append(getErrorString(value, e));
} catch (IOException impossible) { }
}
}
@Override
public void writeTo(final Formatter f, final Object aValueToWrite, final Appendable aOut) throws IOException {
if (aValueToWrite == null) {
if ((flags & FormattableFlags.UPPERCASE) > 0) {
aOut.append("NULL");
} else {
aOut.append("null");
}
} else if (aValueToWrite instanceof Boolean) {
if ((flags & FormattableFlags.UPPERCASE) > 0) {
aOut.append(String.valueOf(((Boolean) aValueToWrite).booleanValue()).toUpperCase());
} else {
aOut.append(String.valueOf(((Boolean) aValueToWrite).booleanValue()));
}
} else {
if ((flags & FormattableFlags.UPPERCASE) > 0) {
aOut.append("true");
} else {
aOut.append("true");
}
}
}
@Override
public void writeTo(final Formatter f, final Object aValueToWrite, final Appendable aOut) throws IOException {
if (aValueToWrite == null) {
if ((flags & FormattableFlags.UPPERCASE) > 0) {
aOut.append("NULL");
} else {
aOut.append("null");
}
} else if (aValueToWrite instanceof Formattable) {
final Formattable formattable = (Formattable) aValueToWrite;
formattable.formatTo(f, flags, width, precision);
} else {
if ((flags & FormattableFlags.UPPERCASE) > 0) {
aOut.append(aValueToWrite.toString().toUpperCase());
} else {
aOut.append(aValueToWrite.toString());
}
}
}
@Override
public void formatTo(Formatter formatter, int flags, int width, int precision) {
final boolean alt = (flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE;
final boolean upper = (flags & FormattableFlags.UPPERCASE) == FormattableFlags.UPPERCASE;
final boolean leftJustified = (flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY;
String out;
if (!alt) {
out = getAsMention();
} else if (upper) {
out = getAsTag().toUpperCase();
} else {
out = getAsTag();
}
MiscUtil.appendTo(formatter, width, precision, leftJustified, out);
}
@Override
public void formatTo(Formatter formatter, int flags, int width, int precision)
{
boolean alt = (flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE;
boolean upper = (flags & FormattableFlags.UPPERCASE) == FormattableFlags.UPPERCASE;
boolean leftJustified = (flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY;
String out;
if (!alt)
out = getAsMention();
else if (upper)
out = getAsTag().toUpperCase();
else
out = getAsTag();
MiscUtil.appendTo(formatter, width, precision, leftJustified, out);
}
@Override
default void formatTo(Formatter formatter, int flags, int width, int precision) {
boolean alternate = (flags & FormattableFlags.ALTERNATE) != 0;
String representation = alternate ? this.toString() : this.getName();
boolean uppercase = (flags & FormattableFlags.UPPERCASE) != 0;
boolean leftAlign = (flags & FormattableFlags.LEFT_JUSTIFY) != 0;
boolean doPad = representation.length() < width;
String padString = null;
if (doPad) {
char[] spaces = new char[width - representation.length()];
Arrays.fill(spaces, ' ');
padString = new String(spaces);
}
try {
if (doPad && !leftAlign) {
formatter.out().append(padString);
}
formatter.out().append(uppercase ? representation.toUpperCase() : representation);
if (doPad && leftAlign) {
formatter.out().append(padString);
}
} catch (IOException e) {
ExceptionLogger.getConsumer().accept(e);
}
}
@Override
default void formatTo(Formatter formatter, int flags, int width, int precision) {
boolean alternate = (flags & FormattableFlags.ALTERNATE) != 0;
String representation = alternate ? this.toString() : this.getName();
boolean uppercase = (flags & FormattableFlags.UPPERCASE) != 0;
boolean leftAlign = (flags & FormattableFlags.LEFT_JUSTIFY) != 0;
boolean doPad = representation.length() < width;
String padString = null;
if (doPad) {
char[] spaces = new char[width - representation.length()];
Arrays.fill(spaces, ' ');
padString = new String(spaces);
}
try {
if (doPad && !leftAlign) {
formatter.out().append(padString);
}
formatter.out().append(uppercase ? representation.toUpperCase() : representation);
if (doPad && leftAlign) {
formatter.out().append(padString);
}
} catch (IOException e) {
ExceptionLogger.getConsumer().accept(e);
}
}
@Override
default void formatTo(Formatter formatter, int flags, int width, int precision)
{
boolean leftJustified = (flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY;
boolean upper = (flags & FormattableFlags.UPPERCASE) == FormattableFlags.UPPERCASE;
String out = upper ? getAsMention().toUpperCase(formatter.locale()) : getAsMention();
MiscUtil.appendTo(formatter, width, precision, leftJustified, out);
}
@Override
default void formatTo(Formatter formatter, int flags, int width, int precision)
{
boolean leftJustified = (flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY;
boolean upper = (flags & FormattableFlags.UPPERCASE) == FormattableFlags.UPPERCASE;
boolean alt = (flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE;
String out;
if (alt)
out = "#" + (upper ? getName().toUpperCase(formatter.locale()) : getName());
else
out = getAsMention();
MiscUtil.appendTo(formatter, width, precision, leftJustified, out);
}
@Override
public void formatTo(Formatter formatter, int flags, int width, int precision)
{
boolean upper = (flags & FormattableFlags.UPPERCASE) == FormattableFlags.UPPERCASE;
boolean leftJustified = (flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY;
String out = content;
if (upper)
out = out.toUpperCase(formatter.locale());
appendFormat(formatter, width, precision, leftJustified, out);
}
/**
* Returns a {@link Formattable} object that can be used with {@link String#format(String, Object...)}.
* <p>
* When used as the argument for a {@literal %s} format string element, the {@literal bytes} value
* will be formatted using the current {@link ByteSizeStrings} values, or if the alternative
* flag is set (using the {@literal %#s} format string) it will use the {@link ByteSizeStrings#metric()}
* formatter. Finally, the precision of the formatted value can be adjusted using format string
* argumenbts like {@literal %.6s}.
*
* @see http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax
*/
public Formattable formatted(final long bytes) {
return new Formattable() {
@Override
public void formatTo(Formatter formatter, int flags, int width, int precision) {
boolean alternate = (flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE;
ByteSizeStrings strings = alternate ? ByteSizeStrings.metric() : ByteSizeStrings.this;
if (precision != -1) {
formatter.format("%s", strings.makeSizeString(bytes, precision));
} else {
formatter.format("%s", strings.makeSizeString(bytes));
}
}
};
}
public void formatTo(Formatter formatter, int flags, int width,
int precision) throws IllegalFormatException {
if ((flags & FormattableFlags.UPPERCASE) != 0) {
formatter.format("CUSTOMIZED FORMAT FUNCTION" + " WIDTH: "
+ width + " PRECISION: " + precision);
} else {
formatter.format("customized format function" + " width: "
+ width + " precision: " + precision);
}
}
FormatSpecifier parseFormatSpecifier() {
final FormatSpecifier spec = new FormatSpecifier();
char c = pattern.charAt(parsePosition);
int width = -1;
int precision = -1;
int flags = 0;
boolean hasWidth = false;
handler: while (true) {
if (Character.isDigit(c)) {
final int startPosition = parsePosition;
while (Character.isDigit(c)) {
parsePosition++;
c = pattern.charAt(parsePosition);
}
if (c == '$') {
spec.valueIndex = Integer.parseInt(pattern.substring(startPosition, parsePosition)) - 1;
} else if (!hasWidth) {
width = Integer.parseInt(pattern.substring(startPosition, parsePosition));
hasWidth = true;
} else if (precision == -1) {
precision = Integer.parseInt(pattern.substring(startPosition, parsePosition));
} else {
throw new IllegalStateException(pattern);
}
}
switch (c) {
case '.':
hasWidth = true;
break;
case 'b':
spec.conversion = new BooleanConversion(width, precision, flags);
parsePosition++;
break handler;
case 'B':
spec.conversion = new BooleanConversion(width, precision, flags | FormattableFlags.UPPERCASE);
parsePosition++;
break handler;
case 'h':
throw new IllegalArgumentException(pattern);
case 'H':
throw new IllegalArgumentException(pattern);
case 's':
spec.conversion = new StringConversion(width, precision, flags);
parsePosition++;
break handler;
case 'S':
spec.conversion = new StringConversion(width, precision, flags | FormattableFlags.UPPERCASE);
parsePosition++;
break handler;
case '%':
spec.conversion = new PercentConversion(width, precision, flags);
parsePosition++;
break handler;
case 'n':
spec.conversion = new LinefeedConversion(width, precision, flags);
parsePosition++;
break handler;
case 'c':
case 'C':
case 'd':
case 'o':
case 'x':
case 'X':
case 'e':
case 'E':
case 'f':
case 'g':
case 'G':
case 'a':
case 'A':
throw new IllegalArgumentException(pattern);
case 't':
case 'T':
throw new IllegalArgumentException(pattern);
}
parsePosition++;
c = pattern.charAt(parsePosition);
}
if (spec.valueIndex == -1) {
spec.valueIndex = valueIndex;
}
return spec;
}
public void test_ConstantFieldValues() {
assertEquals(1, FormattableFlags.LEFT_JUSTIFY);
assertEquals(2, FormattableFlags.UPPERCASE);
assertEquals(4, FormattableFlags.ALTERNATE);
}
/**
* Formats the given character sequence to the given formatter. This method takes in account
* the {@link FormattableFlags#UPPERCASE} and {@link FormattableFlags#LEFT_JUSTIFY} flags.
*
* @param formatter the formatter in which to format the value.
* @param flags the formatting flags.
* @param width minimal number of characters to write, padding with {@code ' '} if necessary.
* @param precision number of characters to keep before truncation, or -1 if no limit.
* @param value the text to format.
*/
public static void formatTo(final Formatter formatter, final int flags, int width, int precision, String value) {
/*
* Converting to upper cases may change the string length in some locales.
* So we need to perform this conversion before to check the length.
*/
boolean isUpperCase = (flags & FormattableFlags.UPPERCASE) != 0;
if (isUpperCase && (width > 0 || precision >= 0)) {
value = value.toUpperCase(formatter.locale());
isUpperCase = false; // Because conversion has already been done.
}
/*
* If the string is longer than the specified "precision", truncate
* and add "…" for letting user know that there is missing characters.
* This loop counts the number of Unicode code points rather than characters.
*/
int length = value.length();
if (precision >= 0) {
for (int i=0,n=0; i<length; i += n) {
if (--precision < 0) {
/*
* Found the amount of characters to keep. The 'n' variable can be
* zero only if precision == 0, in which case the string is empty.
*/
if (n == 0) {
value = "";
} else {
length = (i -= n) + 1;
final StringBuilder buffer = new StringBuilder(length);
value = buffer.append(value, 0, i).append('…').toString();
}
break;
}
n = Character.charCount(value.codePointAt(i));
}
}
/*
* If the string is shorter than the minimal width, add spaces on the left or right side.
* We double check with `width > length` since it is faster than codePointCount(…).
*/
final String format;
final Object[] args;
if (width > length && (width -= value.codePointCount(0, length)) > 0) {
format = "%s%s";
args = new Object[] {value, value};
args[(flags & FormattableFlags.LEFT_JUSTIFY) != 0 ? 1 : 0] = CharSequences.spaces(width);
} else {
format = isUpperCase ? "%S" : "%s";
args = new Object[] {value};
}
formatter.format(format, args);
}
/**
* Formats the name or identifier of this object using the provider formatter.
* This method is invoked when an {@code IdentifiedObject} object is formatted
* using the {@code "%s"} conversion specifier of {@link java.util.Formatter}.
* Users don't need to invoke this method explicitly.
*
* <p>If the alternate flags is present (as in {@code "%#s"}), then this method
* will format the identifier (if present) instead than the object name.</p>
*
* @param formatter the formatter in which to format this identified object.
* @param flags whether to apply left alignment, use upper-case letters and/or use alternate form.
* @param width minimal number of characters to write, padding with {@code ' '} if necessary.
* @param precision maximal number of characters to write, or -1 if no limit.
*
* @see IdentifiedObjects#getName(IdentifiedObject, Citation)
* @see IdentifiedObjects#getIdentifierOrName(IdentifiedObject)
*
* @since 1.1
*/
@Override
public void formatTo(final java.util.Formatter formatter, final int flags, final int width, final int precision) {
final String value;
if ((flags & FormattableFlags.ALTERNATE) != 0) {
value = IdentifiedObjects.getIdentifierOrName(this);
} else {
value = IdentifiedObjects.getName(this, null);
}
Strings.formatTo(formatter, flags, width, precision, value);
}
/**
* Formats this range using the provider formatter. This method is invoked when a
* {@code Range} object is formatted using the {@code "%s"} conversion specifier of
* {@link Formatter}. Users don't need to invoke this method explicitly.
*
* <p>If the alternate flags is present (as in {@code "%#s"}), then the range will
* be formatted using the {@linkplain RangeFormat#isAlternateForm() alternate form}
* for exclusive bounds.</p>
*
* @param formatter the formatter in which to format this range.
* @param flags {@link FormattableFlags#LEFT_JUSTIFY} for left alignment, or 0 for right alignment.
* @param width minimal number of characters to write, padding with {@code ' '} if necessary.
* @param precision maximal number of characters to write, or -1 if no limit.
*/
@Override
public void formatTo(final Formatter formatter, final int flags, final int width, int precision) {
final String value;
if (precision == 0) {
value = "";
} else {
final RangeFormat format = new RangeFormat(formatter.locale(), elementType);
format.setAlternateForm((flags & FormattableFlags.ALTERNATE) != 0);
value = format.format(this, new StringBuffer(), null).toString();
}
Strings.formatTo(formatter, flags, width, precision, value);
}