From 14ba56d8ce19b80a53b1a22b10bb2d9da783f29a Mon Sep 17 00:00:00 2001 From: leaf-soba Date: Tue, 10 Sep 2024 23:28:29 +0800 Subject: [PATCH] refactor BstTextPrefixer.textPrefix (#11746) * refactor BstTextPrefixer.textPrefix 1. add more unit test about nested brace cases 2. refactor the `textPrefix` method to make it clear * rewrite unit test use @ParameterizedTest and @CsvSource to rewrite unit test --- .../logic/bst/util/BstTextPrefixer.java | 88 +++++++++++-------- .../logic/bst/util/BstTextPrefixerTest.java | 42 +++++---- 2 files changed, 76 insertions(+), 54 deletions(-) diff --git a/src/main/java/org/jabref/logic/bst/util/BstTextPrefixer.java b/src/main/java/org/jabref/logic/bst/util/BstTextPrefixer.java index 31cbc71de9b..ffe123ec68e 100644 --- a/src/main/java/org/jabref/logic/bst/util/BstTextPrefixer.java +++ b/src/main/java/org/jabref/logic/bst/util/BstTextPrefixer.java @@ -23,49 +23,65 @@ public class BstTextPrefixer { private BstTextPrefixer() { } - public static String textPrefix(int inNumOfChars, String toPrefix) { - int numOfChars = inNumOfChars; + public static String textPrefix(int numOfChars, String toPrefix) { StringBuilder sb = new StringBuilder(); - + PrefixState prefixState = new PrefixState(0, 0, numOfChars); char[] cs = toPrefix.toCharArray(); - int n = cs.length; - int i = 0; - - int braceLevel = 0; + while (prefixState.index < cs.length && prefixState.numOfChars > 0) { + char c = cs[prefixState.index++]; + handleOpeningBrace(cs, prefixState, c); + handleClosingBrace(prefixState, toPrefix, c); + boolean isNormalCharacter = c != '{' && c != '}'; + if (isNormalCharacter) { + prefixState.numOfChars--; + } + } + sb.append(toPrefix, 0, prefixState.index); + // Append any remaining closing braces if unbalanced + while (prefixState.braceLevel-- > 0) { + sb.append('}'); + } + return sb.toString(); + } - while ((i < n) && (numOfChars > 0)) { - char c = cs[i]; - i++; - if (c == '{') { - braceLevel++; - if ((braceLevel == 1) && (i < n) && (cs[i] == '\\')) { - i++; // skip backslash - while ((i < n) && (braceLevel > 0)) { - if (cs[i] == '}') { - braceLevel--; - } else if (cs[i] == '{') { - braceLevel++; - } - i++; - } - numOfChars--; - } - } else if (c == '}') { - if (braceLevel > 0) { - braceLevel--; - } else { - LOGGER.warn("Unbalanced brace in string for purify$: {}", toPrefix); + private static void handleOpeningBrace(char[] cs, PrefixState prefixState, char c) { + if (c != '{') { + return; + } + prefixState.braceLevel++; + if ((prefixState.braceLevel == 1) && (prefixState.index < cs.length) && (cs[prefixState.index] == '\\')) { + prefixState.index++; // skip backslash + while ((prefixState.index < cs.length) && (prefixState.braceLevel > 0)) { + if (cs[prefixState.index] == '}') { + prefixState.braceLevel--; + } else if (cs[prefixState.index] == '{') { + prefixState.braceLevel++; } - } else { - numOfChars--; + prefixState.index++; } + prefixState.numOfChars--; } - sb.append(toPrefix, 0, i); - while (braceLevel > 0) { - sb.append('}'); - braceLevel--; + } + + private static void handleClosingBrace(PrefixState prefixState, String toPrefix, char c) { + if (c != '}') { + return; } + if (prefixState.braceLevel > 0) { + prefixState.braceLevel--; + } else { + LOGGER.warn("Unbalanced brace in string for purify$: {}", toPrefix); + } + } - return sb.toString(); + private static class PrefixState { + public int index; + public int braceLevel; + public int numOfChars; + public PrefixState(int index, int braceLevel, int numOfChars) { + this.index = index; + this.braceLevel = braceLevel; + this.numOfChars = numOfChars; + } } } diff --git a/src/test/java/org/jabref/logic/bst/util/BstTextPrefixerTest.java b/src/test/java/org/jabref/logic/bst/util/BstTextPrefixerTest.java index 0122378fedd..8f35589c639 100644 --- a/src/test/java/org/jabref/logic/bst/util/BstTextPrefixerTest.java +++ b/src/test/java/org/jabref/logic/bst/util/BstTextPrefixerTest.java @@ -1,25 +1,31 @@ package org.jabref.logic.bst.util; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import static org.junit.jupiter.api.Assertions.assertEquals; -class BstTextPrefixerTest { - - @Test - void prefix() { - assertPrefix("i", "i"); - assertPrefix("0I~ ", "0I~ "); - assertPrefix("Hi Hi", "Hi Hi "); - assertPrefix("{\\oe}", "{\\oe}"); - assertPrefix("Hi {\\oe }H", "Hi {\\oe }Hi "); - assertPrefix("Jonat", "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin"); - assertPrefix("{\\'e}", "{\\'e}"); - assertPrefix("{\\'{E}}doua", "{\\'{E}}douard Masterly"); - assertPrefix("Ulric", "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot"); - } - - private static void assertPrefix(final String string, final String string2) { - assertEquals(string, BstTextPrefixer.textPrefix(5, string2)); +public class BstTextPrefixerTest { + @ParameterizedTest + @CsvSource({ + "i, i", + "0I~ , 0I~ ", + "Hi Hi, Hi Hi ", + "{\\oe}, {\\oe}", + "Hi {\\oe }H, Hi {\\oe }Hi ", + "Jonat, Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin", + "{\\'e}, {\\'e}", + "{\\'{E}}doua, {\\'{E}}douard Masterly", + "Ulric, Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot", + "abcd{e}, abcd{efg}hi", + "ab{cd}e, ab{cd}efghi", + "ab{cd}e, ab{cd}efghi{}", + "Hi {{\\o}}, Hi {{\\oe }}Hi ", + "Hi {\\{oe }}H, Hi {\\{oe }}Hi ", + "Hi {\\\"oe }H, Hi {\\\"oe }Hi ", + "Hi {\\{\\oe }}H, Hi {\\{\\oe }}Hi " + }) + void assertPrefix(final String expectedResult, final String toPrefixInput) { + assertEquals(expectedResult, BstTextPrefixer.textPrefix(5, toPrefixInput)); } }