Skip to content

Commit

Permalink
Add escaping of single quotes and basic support for .net style escaping
Browse files Browse the repository at this point in the history
DEVSIX-6308
  • Loading branch information
glenn.volckaert authored and Ubuntu committed Apr 5, 2022
1 parent d5b0e93 commit d4c6741
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,82 +61,31 @@ private MessageFormatUtil() {
* Indexed arguments can be referred with {index},
* to escape curly braces you have to double them.
*
* <p>
* Only basic escaping is allowed, single quotes in a set of curly braces are not supported and
* multiple escaped braces in a row are also not supported
*
* <p>
* Allowed {{{0}}}
* Allowed '{0}'
* Allowed '{{{0}}}'
*
* <p>
* Not allowed {{'{0}'}}
* Not allowed {{{{{0}}}}}
*
* @param pattern to format
* @param arguments arguments
*
* @return The formatted string
*/
public static String format(String pattern, Object... arguments) {
boolean mustClose = false;
StringBuilder result = new StringBuilder(pattern.length());
int i = 0;
int n = pattern.length();
while (i < n) {
char current = pattern.charAt(i);
switch (current) {
case '{': {
int curlyCount = 0;
int j;
for (j = i; j < n && pattern.charAt(j) == '{'; j++, curlyCount++)
;
i += curlyCount - 1;
if (curlyCount > 1) {
if (!mustClose) {
result.append("'");
}
while (curlyCount >= 2) {
result.append('{');
curlyCount -= 2;
}
mustClose = true;
}
if (curlyCount == 1) {
if (mustClose) {
result.append('\'');
}
result.append('{');
mustClose = false;
}
}
break;
case '}': {
int curlyCount = 0;
int j;
for (j = i; j < n && pattern.charAt(j) == '}'; j++, curlyCount++)
;
i += curlyCount - 1;
if (curlyCount % 2 == 1) {
if (mustClose) {
result.append('\'');
}
result.append('}');
mustClose = false;
}
if (curlyCount > 1) {
result.append("'");
while (curlyCount >= 2) {
result.append('}');
curlyCount -= 2;
}
mustClose = true;
}
}
break;
case '\'':
result.append("''");
break;
default:
if (mustClose) {
result.append('\'');
mustClose = false;
}
result.append(current);
}
i++;
}
if (mustClose) {
result.append('\'');
}
return new MessageFormat(result.toString(), Locale.ROOT).format(arguments);
return new MessageFormat(
pattern.replace("'", "''")
.replace("{{{","'{'{" )
.replace("}}}","}'}'" )
.replace("{{","'{'" )
.replace("}}","'}'" )
,Locale.ROOT).format(arguments);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,30 @@ public class MessageFormatUtilTest extends ExtendedITextTest {
private String pattern;
private Object[] arguments;


public MessageFormatUtilTest(Object expectedResult, Object pattern, Object arguments, Object name) {
this.expectedResult = (String)expectedResult;
this.pattern = (String)pattern;
this.arguments = (Object[]) arguments;
}


@Parameterized.Parameters(name = "{index}: {3} format: {1}; {0}")
public static Iterable<Object[]> dataSource() {
return Arrays.asList(new Object[][]{
{"Plain message with params 1 test", "Plain message with params {0} {1}", new Object[] {1, "test"},"test with simple params"},
{"Message with 'single quotes'", "Message with 'single quotes'", new Object[0],"test with single quotes"},
{"Message with ''doubled single quotes''", "Message with ''doubled single quotes''", new Object[0],"test with doubled single quotes"},
{"Message with {curly braces} and a parameter {I'm between curly braces too}", "Message with {{curly braces}} and a parameter {{{0}}}", new Object[]{"I'm between curly braces too"},"Test with curly braces"},
{"Message with {{multiple curly braces}}", "Message with {{{{multiple curly braces}}}}", new Object[]{},"Test with multiple curly braces"},
{"Message with {Value between brackets} and {{Value between double brackets}}", "Message with {{{0}}} and {{{{{1}}}}}", new Object[]{"Value between brackets", "Value between double brackets"},"Test with multiple curly braces"},
{"Lets go wild 'value 1', {value 2}, '{value 3}', {'{value 4}'}", "Lets go wild '{0}', {{{1}}}, '{{{2}}}', {{'{{{3}}}'}}", new Object[]{"value 1", "value 2","value 3","value 4"},"Some of all"},
{"{'{value}'}", "{{'{{{0}}}'}}", new Object[]{"value"},"Mix om multiple brackets and quotes 1"},
{"'{value}'", "'{{{0}}}'", new Object[]{"value"},"Mix om multiple brackets and quotes 1"},
{"a '{'{123}'}''' b", "a '{{'{{{0}}}'}}''' b", new Object[]{123},"Mix om multiple brackets and quotes 1"},
{"'value'", "'{0}'", new Object[]{"value"},"Mix of brackets and quotes"},
{"{'0'}", "{{'0'}}", new Object[0],"Mix of multiple brackets and quotes 2"},
{"single opening brace {0 test" , "single opening brace {{0 test", new Object[0],"Test single opening brace"},
{"single closing brace 0} test", "single closing brace 0}} test", new Object[0],"Test single closing brace"},
{"single opening + closing brace { test }", "single opening + closing brace {{ {0} }}", new Object[]{"test"},"Test single opening and closing brace"},
});
}

@Test
public void testFormatting() {
Assert.assertEquals(expectedResult, MessageFormatUtil.format(pattern, arguments));
}

}

0 comments on commit d4c6741

Please sign in to comment.