From: PJ Fanning Date: Sun, 17 Jul 2022 08:45:38 +0000 (+0000) Subject: [github-354] Add extra methods to StringUtil and refactor some code to use them.... X-Git-Tag: REL_5_2_3~167 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=50c40b61f72903693f5304767fdd337d7e685f50;p=poi.git [github-354] Add extra methods to StringUtil and refactor some code to use them. Thanks to XenoAmess. This closes #354 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1902801 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java index 9cab106a14..bc60130c76 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java @@ -398,14 +398,15 @@ public class XSSFSimpleShape extends XSSFShape implements Iterable 0) { modulo = (value - 1) % 26; - alpha = (char) (65 + modulo) + alpha; + alpha.append((char) (65 + modulo)); value = (value - modulo) / 26; } - return alpha; + alpha.reverse(); + return alpha.toString(); } private static String[] _romanChars = new String[] { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java index 2fdd7fa06d..70ee324c62 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java @@ -78,7 +78,7 @@ public class XSSFXmlColumnPr { String[] xPathTokens = ctXmlColumnPr.getXpath().split("/"); for (int i = numberOfCommonXPathAxis; i < xPathTokens.length; i++) { - localXPath.append("/" + xPathTokens[i]); + localXPath.append("/").append(xPathTokens[i]); } return localXPath.toString(); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/Chunk.java b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/Chunk.java index 5073771fc3..43d2fb65ea 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/Chunk.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/Chunk.java @@ -23,6 +23,7 @@ import java.io.OutputStream; import java.util.Locale; import org.apache.poi.hsmf.datatypes.Types.MAPIType; +import org.apache.poi.util.StringUtil; public abstract class Chunk { public static final String DEFAULT_NAME_PREFIX = "__substg1.0_"; @@ -62,13 +63,14 @@ public abstract class Chunk { public String getEntryName() { String type = this.type.asFileEnding(); - String chunkId = Integer.toHexString(this.chunkId); - while (chunkId.length() < 4) { - chunkId = "0" + chunkId; + StringBuilder chunkId = new StringBuilder(Integer.toHexString(this.chunkId)); + int need0count = 4 - chunkId.length(); + if (need0count > 0) { + chunkId.insert(0, StringUtil.repeat('0', need0count)); } return this.namePrefix - + chunkId.toUpperCase(Locale.ROOT) + + chunkId.toString().toUpperCase(Locale.ROOT) + type.toUpperCase(Locale.ROOT); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/MAPIProperty.java b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/MAPIProperty.java index 81c431b2b7..b09e39cc7a 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/MAPIProperty.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/MAPIProperty.java @@ -17,6 +17,15 @@ package org.apache.poi.hsmf.datatypes; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import org.apache.poi.hsmf.datatypes.Types.MAPIType; +import org.apache.poi.util.StringUtil; + import static org.apache.poi.hsmf.datatypes.Types.ASCII_STRING; import static org.apache.poi.hsmf.datatypes.Types.BINARY; import static org.apache.poi.hsmf.datatypes.Types.BOOLEAN; @@ -27,14 +36,6 @@ import static org.apache.poi.hsmf.datatypes.Types.LONG_LONG; import static org.apache.poi.hsmf.datatypes.Types.SHORT; import static org.apache.poi.hsmf.datatypes.Types.TIME; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import org.apache.poi.hsmf.datatypes.Types.MAPIType; - /** * Holds the list of MAPI Attributes, and allows lookup by friendly name, ID and * MAPI Property Name. @@ -1069,9 +1070,10 @@ public class MAPIProperty { } public String asFileName() { - String str = Integer.toHexString(id).toUpperCase(Locale.ROOT); - while (str.length() < 4) { - str = "0" + str; + StringBuilder str = new StringBuilder(Integer.toHexString(id).toUpperCase(Locale.ROOT)); + int need0count = 4 - str.length(); + if (need0count > 0) { + str.insert(0, StringUtil.repeat('0', need0count)); } return str + usualType.asFileEnding(); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/PropertiesChunk.java b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/PropertiesChunk.java index de28c70bbb..5d5cde36ec 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/PropertiesChunk.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/PropertiesChunk.java @@ -17,8 +17,6 @@ package org.apache.poi.hsmf.datatypes; -import static org.apache.logging.log4j.util.Unbox.box; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -48,6 +46,9 @@ import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian.BufferUnderrunException; +import org.apache.poi.util.StringUtil; + +import static org.apache.logging.log4j.util.Unbox.box; /** *

@@ -419,9 +420,10 @@ public abstract class PropertiesChunk extends Chunk { } private String getFileName(MAPIProperty property, MAPIType actualType) { - String str = Integer.toHexString(property.id).toUpperCase(Locale.ROOT); - while (str.length() < 4) { - str = "0" + str; + StringBuilder str = new StringBuilder(Integer.toHexString(property.id).toUpperCase(Locale.ROOT)); + int need0count = 4 - str.length(); + if (need0count > 0) { + str.insert(0, StringUtil.repeat('0', need0count)); } MAPIType type = getTypeMapping(actualType); return str + type.asFileEnding(); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/Types.java b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/Types.java index 4c92da4f0f..d11f3489da 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/Types.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/Types.java @@ -21,6 +21,8 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; +import org.apache.poi.util.StringUtil; + /** * The types list and details are available from * http://msdn.microsoft.com/en-us/library/microsoft.exchange.data.contenttypes.tnef.tnefpropertytype%28v=EXCHG.140%29.aspx @@ -148,11 +150,12 @@ public final class Types { } public static String asFileEnding(int type) { - String str = Integer.toHexString(type).toUpperCase(Locale.ROOT); - while (str.length() < 4) { - str = "0" + str; + StringBuilder str = new StringBuilder(Integer.toHexString(type).toUpperCase(Locale.ROOT)); + int need0count = 4 - str.length(); + if (need0count > 0) { + str.insert(0, StringUtil.repeat('0', need0count)); } - return str; + return str.toString(); } public static String asName(int typeId) { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/dev/TypesLister.java b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/dev/TypesLister.java index 6cb05b30fb..d29ffc2b94 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/dev/TypesLister.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/dev/TypesLister.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Comparator; import org.apache.poi.hsmf.datatypes.MAPIProperty; +import org.apache.poi.util.StringUtil; /** * Lists the different MAPI types @@ -49,8 +50,11 @@ public class TypesLister { } private void list(ArrayList list, PrintStream out) { for(MAPIProperty attr : list) { - String id = Integer.toHexString(attr.id); - while(id.length() < 4) { id = "0"+id; } + StringBuilder id = new StringBuilder(Integer.toHexString(attr.id)); + int need0count = 4 - id.length(); + if (need0count > 0) { + id.insert(0, StringUtil.repeat('0', need0count)); + } int typeId = attr.usualType.getId(); String typeIdStr = Integer.toString(typeId); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToHtmlUtils.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToHtmlUtils.java index 484d367788..6bda01ee31 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToHtmlUtils.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToHtmlUtils.java @@ -29,7 +29,7 @@ public class WordToHtmlUtils extends AbstractWordUtils { public static void addBold( final boolean bold, StringBuilder style ) { - style.append( "font-weight:" + ( bold ? "bold" : "normal" ) + ";" ); + style.append("font-weight:").append(bold ? "bold" : "normal").append(";"); } public static void addBorder( BorderCode borderCode, String where, @@ -71,13 +71,11 @@ public class WordToHtmlUtils extends AbstractWordUtils } if ( characterRun.getIco24() != -1 ) { - style.append( "color:" + getColor24( characterRun.getIco24() ) - + ";" ); + style.append("color:").append(getColor24(characterRun.getIco24())).append(";"); } if ( characterRun.isHighlighted() ) { - style.append( "background-color:" - + getColor( characterRun.getHighlightedColor() ) + ";" ); + style.append("background-color:").append(getColor(characterRun.getHighlightedColor())).append(";"); } if ( characterRun.isStrikeThrough() ) { @@ -85,8 +83,7 @@ public class WordToHtmlUtils extends AbstractWordUtils } if ( characterRun.isShadowed() ) { - style.append( "text-shadow:" + characterRun.getFontSize() / 24 - + "pt;" ); + style.append("text-shadow:").append(characterRun.getFontSize() / 24).append("pt;"); } if ( characterRun.isSmallCaps() ) { @@ -118,12 +115,12 @@ public class WordToHtmlUtils extends AbstractWordUtils if ( isEmpty( fontFamily ) ) return; - style.append( "font-family:" + fontFamily + ";" ); + style.append("font-family:").append(fontFamily).append(";"); } public static void addFontSize( final int fontSize, StringBuilder style ) { - style.append( "font-size:" + fontSize + "pt;" ); + style.append("font-size:").append(fontSize).append("pt;"); } public static void addIndent( Paragraph paragraph, StringBuilder style ) @@ -143,7 +140,7 @@ public class WordToHtmlUtils extends AbstractWordUtils if ( twipsValue == 0 ) return; - style.append( cssName + ":" + ( twipsValue / TWIPS_PER_INCH ) + "in;" ); + style.append(cssName).append(":").append(twipsValue / TWIPS_PER_INCH).append("in;"); } public static void addJustification( Paragraph paragraph, @@ -151,7 +148,7 @@ public class WordToHtmlUtils extends AbstractWordUtils { String justification = getJustification( paragraph.getJustification() ); if ( isNotEmpty( justification ) ) - style.append( "text-align:" + justification + ";" ); + style.append("text-align:").append(justification).append(";"); } public static void addParagraphProperties( Paragraph paragraph, @@ -170,8 +167,7 @@ public class WordToHtmlUtils extends AbstractWordUtils style.append( "break-before:page;" ); } - style.append( "hyphenate:" - + ( paragraph.isAutoHyphenated() ? "auto" : "none" ) + ";" ); + style.append("hyphenate:").append(paragraph.isAutoHyphenated() ? "auto" : "none").append(";"); if ( paragraph.keepOnPage() ) { @@ -188,12 +184,9 @@ public class WordToHtmlUtils extends AbstractWordUtils TableCell tableCell, boolean toppest, boolean bottomest, boolean leftest, boolean rightest, StringBuilder style ) { - style.append( "width:" + ( tableCell.getWidth() / TWIPS_PER_INCH ) - + "in;" ); - style.append( "padding-start:" - + ( tableRow.getGapHalf() / TWIPS_PER_INCH ) + "in;" ); - style.append( "padding-end:" - + ( tableRow.getGapHalf() / TWIPS_PER_INCH ) + "in;" ); + style.append("width:").append(tableCell.getWidth() / TWIPS_PER_INCH).append("in;"); + style.append("padding-start:").append(tableRow.getGapHalf() / TWIPS_PER_INCH).append("in;"); + style.append("padding-end:").append(tableRow.getGapHalf() / TWIPS_PER_INCH).append("in;"); BorderCode top = tableCell.getBrcTop() != null && tableCell.getBrcTop().getBorderType() != 0 ? tableCell @@ -224,8 +217,7 @@ public class WordToHtmlUtils extends AbstractWordUtils { if ( tableRow.getRowHeight() > 0 ) { - style.append( "height:" - + ( tableRow.getRowHeight() / TWIPS_PER_INCH ) + "in;" ); + style.append("height:").append(tableRow.getRowHeight() / TWIPS_PER_INCH).append("in;"); } if ( !tableRow.cantSplit() ) { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestFieldsTables.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestFieldsTables.java index 1e1b5b3841..6ee6537648 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestFieldsTables.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestFieldsTables.java @@ -83,7 +83,7 @@ public class TestFieldsTables extends HWPFTestCase { private String dumpPlexes(ArrayList fieldsPlexes) { StringBuilder dump = new StringBuilder(); for (PlexOfField flds : fieldsPlexes) { - dump.append(flds + "\n"); + dump.append(flds).append("\n"); } return dump.toString(); } diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPalette.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPalette.java index 3dcc5bccc0..61ca511c2e 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPalette.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPalette.java @@ -22,6 +22,7 @@ import java.util.Locale; import org.apache.poi.hssf.record.PaletteRecord; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined; +import org.apache.poi.util.StringUtil; /** * Represents a workbook color palette. @@ -218,22 +219,22 @@ public final class HSSFPalette { private String getGnumericPart(byte color) { - String s; + StringBuilder s; if (color == 0) { - s = "0"; + s = new StringBuilder("0"); } else { int c = color & 0xff; //as unsigned c = (c << 8) | c; //pad to 16-bit - s = Integer.toHexString(c).toUpperCase(Locale.ROOT); - while (s.length() < 4) - { - s = "0" + s; + s = new StringBuilder(Integer.toHexString(c).toUpperCase(Locale.ROOT)); + int need0count = 4 - s.length(); + if (need0count > 0) { + s.insert(0, StringUtil.repeat('0', need0count)); } } - return s; + return s.toString(); } } } diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Bin2Dec.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Bin2Dec.java index 1ad45ea75e..7096f91567 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Bin2Dec.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Bin2Dec.java @@ -22,6 +22,7 @@ import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.OperandResolver; import org.apache.poi.ss.formula.eval.RefEval; import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.util.StringUtil; /** * Implementation for Excel Bin2Dec() function. @@ -109,9 +110,12 @@ public class Bin2Dec extends Fixed1ArgFunction implements FreeRefFunction { private static String toggleBits(String s) { long i = Long.parseLong(s, 2); long i2 = i ^ ((1L << s.length()) - 1); - String s2 = Long.toBinaryString(i2); - while (s2.length() < s.length()) s2 = '0' + s2; - return s2; + StringBuilder s2 = new StringBuilder(Long.toBinaryString(i2)); + int need0count = s.length() - s2.length(); + if (need0count > 0) { + s2.insert(0, StringUtil.repeat('0', need0count)); + } + return s2.toString(); } @Override diff --git a/poi/src/main/java/org/apache/poi/util/StringUtil.java b/poi/src/main/java/org/apache/poi/util/StringUtil.java index e0ac29b4cd..190d8dc99c 100644 --- a/poi/src/main/java/org/apache/poi/util/StringUtil.java +++ b/poi/src/main/java/org/apache/poi/util/StringUtil.java @@ -21,6 +21,7 @@ import static java.nio.charset.StandardCharsets.ISO_8859_1; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Locale; /** @@ -759,4 +760,34 @@ public final class StringUtil { return !isBlank(cs); } + /** + *

Returns padding using the specified delimiter repeated + * to a given length.

+ * + *
+     * StringUtil.repeat('e', 0)  = ""
+     * StringUtil.repeat('e', 3)  = "eee"
+     * StringUtil.repeat('e', -2) = ""
+     * 
+ * + *

Note: this method does not support padding with + * Unicode Supplementary Characters + * as they require a pair of {@code char}s to be represented. + *

+ * + * copied from commons-lang3 + * + * @param ch character to repeat + * @param repeat number of times to repeat char, negative treated as zero + * @return String with repeated character + */ + public static String repeat(final char ch, final int repeat) { + if (repeat <= 0) { + return ""; + } + final char[] buf = new char[repeat]; + Arrays.fill(buf, ch); + return new String(buf); + } + } diff --git a/poi/src/test/java/org/apache/poi/hssf/eventusermodel/TestMissingRecordAwareHSSFListener.java b/poi/src/test/java/org/apache/poi/hssf/eventusermodel/TestMissingRecordAwareHSSFListener.java index 1dfd056ab6..c2f8d8486b 100644 --- a/poi/src/test/java/org/apache/poi/hssf/eventusermodel/TestMissingRecordAwareHSSFListener.java +++ b/poi/src/test/java/org/apache/poi/hssf/eventusermodel/TestMissingRecordAwareHSSFListener.java @@ -212,7 +212,7 @@ final class TestMissingRecordAwareHSSFListener { dig = "ur"; } if (lastRow != row && row > -1) { - sb.append((lastRow > -1 ? "," : "") + row + ":"); + sb.append(lastRow > -1 ? "," : "").append(row).append(":"); lastRow = row; } sb.append(dig); diff --git a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestIrr.java b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestIrr.java index b4830e09d3..8071b8d8cd 100644 --- a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestIrr.java +++ b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestIrr.java @@ -106,7 +106,7 @@ final class TestIrr { assertFormulaResult(cv, cellA); } catch (Throwable e){ if(failures.length() > 0) failures.append('\n'); - failures.append("Row[" + (cellA.getRowIndex() + 1)+ "]: " + cellA.getCellFormula() + " "); + failures.append("Row[").append(cellA.getRowIndex() + 1).append("]: ").append(cellA.getCellFormula()).append(" "); failures.append(e.getMessage()); } @@ -116,7 +116,7 @@ final class TestIrr { assertEquals(0, cv.getNumberValue(), 0.0001); // should agree within 0.01% } catch (Throwable e){ if(failures.length() > 0) failures.append('\n'); - failures.append("Row[" + (cellC.getRowIndex() + 1)+ "]: " + cellC.getCellFormula() + " "); + failures.append("Row[").append(cellC.getRowIndex() + 1).append("]: ").append(cellC.getCellFormula()).append(" "); failures.append(e.getMessage()); } }