diff --git a/src/main/java/org/jabref/logic/layout/AbstractParamLayoutFormatter.java b/src/main/java/org/jabref/logic/layout/AbstractParamLayoutFormatter.java index bbd1344ddf93..44209654bb6c 100644 --- a/src/main/java/org/jabref/logic/layout/AbstractParamLayoutFormatter.java +++ b/src/main/java/org/jabref/logic/layout/AbstractParamLayoutFormatter.java @@ -26,34 +26,38 @@ protected static List parseArgument(String arg) { StringBuilder current = new StringBuilder(); boolean escaped = false; for (int i = 0; i < arg.length(); i++) { - if ((arg.charAt(i) == AbstractParamLayoutFormatter.SEPARATOR) && !escaped) { - parts.add(current.toString()); - current = new StringBuilder(); - } else if (arg.charAt(i) == '\\') { - if (escaped) { - escaped = false; - current.append(arg.charAt(i)); - } else { - escaped = true; - } - } else if (escaped) { - // Handle newline and tab: - if (arg.charAt(i) == 'n') { - current.append('\n'); - } else if (arg.charAt(i) == 't') { - current.append('\t'); - } else { - if ((arg.charAt(i) != ',') && (arg.charAt(i) != '"')) { - current.append('\\'); - } - current.append(arg.charAt(i)); - } + char currentChar = arg.charAt(i); + if (escaped) { + handleEscapedCharacter(current, currentChar); escaped = false; + } else if (currentChar == '\\') { + escaped = true; + } else if (currentChar == AbstractParamLayoutFormatter.SEPARATOR) { + addPart(parts, current); } else { - current.append(arg.charAt(i)); + current.append(currentChar); } } - parts.add(current.toString()); + addPart(parts, current); return parts; } + + private static void handleEscapedCharacter(StringBuilder current, char currentChar) { + switch (currentChar) { + case 'n' -> current.append('\n'); + case 't' -> current.append('\t'); + case ',' -> current.append(','); + case '"' -> current.append('"'); + case '\\' -> current.append('\\'); + default -> { + current.append('\\'); + current.append(currentChar); + } + } + } + + private static void addPart(List parts, StringBuilder current) { + parts.add(current.toString()); + current.setLength(0); + } } diff --git a/src/test/java/org/jabref/logic/layout/format/AbstractParamLayoutFormatterTest.java b/src/test/java/org/jabref/logic/layout/format/AbstractParamLayoutFormatterTest.java new file mode 100644 index 000000000000..6cc2ede6ed0f --- /dev/null +++ b/src/test/java/org/jabref/logic/layout/format/AbstractParamLayoutFormatterTest.java @@ -0,0 +1,88 @@ +package org.jabref.logic.layout.format; + +import java.util.List; + +import org.jabref.logic.layout.AbstractParamLayoutFormatter; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AbstractParamLayoutFormatterTest { + static class ParseArgumentTester extends AbstractParamLayoutFormatter { + public static List callParseArgument(String arg) { + return parseArgument(arg); + } + + @Override + public String format(String fieldText) { + return null; + } + + @Override + public void setArgument(String arg) { + } + } + + @Test + void simpleArguments() { + String input = "arg1,arg2,arg3"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1", "arg2", "arg3"), result, + "Simple arguments should be split correctly by commas"); + } + + @Test + void escapedCommas() { + String input = "arg1\\,arg2,arg3"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1,arg2", "arg3"), result, + "Escaped commas should be treated as literal commas"); + } + + @Test + void escapedBackslash() { + String input = "arg1\\\\,arg2"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1\\", "arg2"), result, "Escaped backslashes should be treated correctly"); + } + + @Test + void emptyArgument() { + String input = ""; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of(""), result, "Empty string should return a list with an empty string"); + } + + @Test + void singleArgument() { + String input = "singleArg"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("singleArg"), result, + "Single argument should return a list with the argument itself"); + } + + @Test + void newlineAndTabEscapeSequences() { + String input = "arg1\\narg2\\targ3"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1\narg2\targ3"), result, + "Escape sequences like newline and tab should be handled correctly"); + } + + @Test + void multipleEscapedCharacters() { + String input = "arg1\\n,arg2\\t,arg3\\,arg4"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1\n", "arg2\t", "arg3,arg4"), result, + "Multiple escaped characters should be handled correctly"); + } + + @Test + void mixedCases() { + String input = "arg1,arg2\\,withComma,arg3\\nnewline,arg4\\\\backslash"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1", "arg2,withComma", "arg3\nnewline", "arg4\\backslash"), result, + "Mixed cases should be parsed correctly"); + } +}