From f7a41d51abac09abe97dbabc2d6c9e53c09a697f Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 13 Aug 2021 11:31:03 +0200 Subject: [PATCH] [jOOQ/jOOQ#12304] Use FormattingProvider::width in formatting logic --- .../java/org/jooq/impl/AbstractResult.java | 47 +++++++++--------- .../jooq/impl/DefaultFormattingProvider.java | 2 + jOOQ/src/main/java/org/jooq/impl/Tools.java | 9 ++-- .../main/java/org/jooq/tools/StringUtils.java | 48 ++++++++++++++++--- 4 files changed, 69 insertions(+), 37 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java index dc6e58fee5..4cf79d398b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java @@ -78,6 +78,7 @@ import org.jooq.DSLContext; import org.jooq.EnumType; import org.jooq.Field; import org.jooq.Formattable; +import org.jooq.FormattingProvider; import org.jooq.JSON; import org.jooq.JSONB; import org.jooq.JSONFormat; @@ -141,6 +142,8 @@ abstract class AbstractResult extends AbstractFormattable impl public final void format(Writer writer, TXTFormat format) { try { + final FormattingProvider fp = Tools.configuration(this).formattingProvider(); + // Numeric columns have greater max width because values are aligned final int NUM_COL_MAX_WIDTH = format.maxColWidth() == Integer.MAX_VALUE ? Integer.MAX_VALUE : 2 * format.maxColWidth(); @@ -187,7 +190,7 @@ abstract class AbstractResult extends AbstractFormattable impl List widthList = new ArrayList<>(1 + buffer.size()); // Add column name width first - widthList.add(min(colMaxWidth, max(format.minColWidth(), fields.field(index).getName().length()))); + widthList.add(min(colMaxWidth, max(format.minColWidth(), fp.width(fields.field(index).getName())))); // Add column values width for (R record : buffer) { @@ -197,7 +200,7 @@ abstract class AbstractResult extends AbstractFormattable impl if (isNumCol) value = alignNumberValue(decimalPlaces[index], value); - widthList.add(min(colMaxWidth, value.length())); + widthList.add(min(colMaxWidth, fp.width(value))); } // Find max @@ -223,11 +226,13 @@ abstract class AbstractResult extends AbstractFormattable impl writer.append(' '); String padded; + String name = fields.field(index).getName(); + int width = fp.width(name); if (Number.class.isAssignableFrom(fields.field(index).getType())) - padded = leftPad(fields.field(index).getName(), widths[index]); + padded = leftPad(name, width, widths[index]); else - padded = rightPad(fields.field(index).getName(), widths[index]); + padded = rightPad(name, width, widths[index]); if (widths[index] < 4) writer.append(padded); @@ -281,17 +286,10 @@ abstract class AbstractResult extends AbstractFormattable impl ); String padded; - if (Number.class.isAssignableFrom(fields.field(index).getType())) { - // Align number value before left pad - value = alignNumberValue(decimalPlaces[index], value); - - // Left pad - padded = leftPad(value, widths[index]); - } - else { - // Right pad - padded = rightPad(value, widths[index]); - } + if (Number.class.isAssignableFrom(fields.field(index).getType())) + padded = leftPad(alignNumberValue(decimalPlaces[index], value), widths[index]); + else + padded = rightPad(value, fp.width(value), widths[index]); if (widths[index] < 4) writer.append(padded); @@ -359,13 +357,11 @@ abstract class AbstractResult extends AbstractFormattable impl int decimalPlaces = decimalPlaces(value); int rightPadSize = value.length() + columnDecimalPlaces - decimalPlaces; - if (decimalPlaces == 0) { - // If integer value, add one for decimal point + // If integer value, add one for decimal point + if (decimalPlaces == 0) value = rightPad(value, rightPadSize + 1); - } - else { + else value = rightPad(value, rightPadSize); - } } return value; @@ -877,6 +873,7 @@ abstract class AbstractResult extends AbstractFormattable impl try { DSLContext ctx = configuration.dsl(); + FormattingProvider fp = configuration.formattingProvider(); Field category = fields.field(format.category()); TreeMap> groups = new TreeMap<>(result.intoGroups(format.category())); @@ -896,7 +893,7 @@ abstract class AbstractResult extends AbstractFormattable impl int categoryPadding = 1; int categoryWidth = 0; for (Object o : categories) - categoryWidth = Math.max(categoryWidth, ("" + o).length()); + categoryWidth = Math.max(categoryWidth, fp.width("" + o)); double axisMin = Double.POSITIVE_INFINITY; double axisMax = Double.NEGATIVE_INFINITY; @@ -946,7 +943,7 @@ abstract class AbstractResult extends AbstractFormattable impl ? format.numericFormat().format(axisLegendPercent * 100.0) + "%" : format.numericFormat().format(axisLegend); - for (int x = axisLegendString.length(); x < verticalLegendWidth; x++) + for (int x = fp.width(axisLegendString); x < verticalLegendWidth; x++) writer.write(' '); writer.write(axisLegendString); @@ -1017,16 +1014,16 @@ abstract class AbstractResult extends AbstractFormattable impl double rounding = 0.0; for (double x = 0.0; x < chartWidth;) { String label = "" + categories.get((int) (x / barWidth)); - int length = label.length(); + int width = fp.width(label); - double padding = Math.max(categoryPadding, (barWidth - length) / 2); + double padding = Math.max(categoryPadding, (barWidth - width) / 2); rounding = (rounding + padding - Math.floor(padding)) % 1; x = x + (padding + rounding); for (int i = 0; i < (int) (padding + rounding); i++) writer.write(' '); - x = x + length; + x = x + width; if (x >= chartWidth) break; writer.write(label); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultFormattingProvider.java b/jOOQ/src/main/java/org/jooq/impl/DefaultFormattingProvider.java index 438e28f1d2..c4810ac246 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultFormattingProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultFormattingProvider.java @@ -88,6 +88,8 @@ public class DefaultFormattingProvider implements FormattingProvider { @Override public int width(String string) { + + // [#12275] TODO Calculate string display width in presence of ideographic characters return string.length(); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index bb93ccc6e2..131e4dc313 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -4450,16 +4450,13 @@ final class Tools { for (int i = 0; i < fields.length; i++) { int[] position = positions.get(i); - if (position[0] < length) { + if (position[0] < length) fields[i] = string.substring(position[0], Math.min(position[1], length)).trim(); - } - else { + else fields[i] = null; - } - if (StringUtils.equals(fields[i], nullLiteral)) { + if (StringUtils.equals(fields[i], nullLiteral)) fields[i] = null; - } } } diff --git a/jOOQ/src/main/java/org/jooq/tools/StringUtils.java b/jOOQ/src/main/java/org/jooq/tools/StringUtils.java index 65c4dc71b1..356f505225 100644 --- a/jOOQ/src/main/java/org/jooq/tools/StringUtils.java +++ b/jOOQ/src/main/java/org/jooq/tools/StringUtils.java @@ -335,6 +335,10 @@ public final class StringUtils { return rightPad(str, size, ' '); } + public static String rightPad(String str, int strSize, int size) { + return rightPad(str, strSize, size, ' '); + } + /** *

Right pad a String with a specified character.

* @@ -357,15 +361,22 @@ public final class StringUtils { * @since 2.0 */ public static String rightPad(String str, int size, char padChar) { + if (str == null) + return null; + + return rightPad(str, str.length(), size, padChar); + } + + public static String rightPad(String str, int strSize, int size, char padChar) { if (str == null) { return null; } - int pads = size - str.length(); + int pads = size - strSize; if (pads <= 0) { return str; // returns original String when possible } if (pads > PAD_LIMIT) { - return rightPad(str, size, String.valueOf(padChar)); + return rightPad(str, strSize, size, String.valueOf(padChar)); } return str.concat(padding(pads, padChar)); } @@ -394,6 +405,13 @@ public final class StringUtils { * null if null String input */ public static String rightPad(String str, int size, String padStr) { + if (str == null) + return null; + + return rightPad(str, str.length(), size, padStr); + } + + public static String rightPad(String str, int strSize, int size, String padStr) { if (str == null) { return null; } @@ -401,7 +419,7 @@ public final class StringUtils { padStr = " "; } int padLen = padStr.length(); - int strLen = str.length(); + int strLen = strSize; int pads = size - strLen; if (pads <= 0) { return str; // returns original String when possible @@ -447,6 +465,10 @@ public final class StringUtils { return leftPad(str, size, ' '); } + public static String leftPad(String str, int strSize, int size) { + return leftPad(str, strSize, size, ' '); + } + /** *

Left pad a String with a specified character.

* @@ -469,15 +491,22 @@ public final class StringUtils { * @since 2.0 */ public static String leftPad(String str, int size, char padChar) { + if (str == null) + return null; + + return leftPad(str, str.length(), size, padChar); + } + + public static String leftPad(String str, int strSize, int size, char padChar) { if (str == null) { return null; } - int pads = size - str.length(); + int pads = size - strSize; if (pads <= 0) { return str; // returns original String when possible } if (pads > PAD_LIMIT) { - return leftPad(str, size, String.valueOf(padChar)); + return leftPad(str, strSize, size, String.valueOf(padChar)); } return padding(pads, padChar).concat(str); } @@ -506,6 +535,13 @@ public final class StringUtils { * null if null String input */ public static String leftPad(String str, int size, String padStr) { + if (str == null) + return null; + + return leftPad(str, str.length(), size, padStr); + } + + public static String leftPad(String str, int strSize, int size, String padStr) { if (str == null) { return null; } @@ -513,7 +549,7 @@ public final class StringUtils { padStr = " "; } int padLen = padStr.length(); - int strLen = str.length(); + int strLen = strSize; int pads = size - strLen; if (pads <= 0) { return str; // returns original String when possible