[slf4j-dev] svn commit: r953 - in slf4j/trunk/slf4j-api/src: main/java/org/slf4j/helpers test/java/org/slf4j/helpers
ceki at slf4j.org
ceki at slf4j.org
Tue Jan 29 20:19:00 CET 2008
Author: ceki
Date: Tue Jan 29 20:19:00 2008
New Revision: 953
Modified:
slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java
slf4j/trunk/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java
Log:
- fixing bug 61.
Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java
==============================================================================
--- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java (original)
+++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java Tue Jan 29 20:19:00 2008
@@ -24,30 +24,38 @@
package org.slf4j.helpers;
-
/**
- * Formats messages according to very simple substitution rules. Substitutions can be
- * made 1, 2 or more arguments.
- * <p>
- * For example,
- * <pre>MessageFormatter.format("Hi {}.", "there");</pre> will
- * return the string "Hi there.".
- * <p>
- * The {} pair is called the <em>formatting anchor</em>. It serves to designate the
- * location where arguments need to be substituted within the message pattern.
- * <p>
- * In the rare case where you need to place the '{' or '}' in the message pattern
- * itself but do not want them to be interpreted as a formatting anchors, you can
- * espace the '{' character with '\', that is the backslash character. Only the
- * '{' character should be escaped. There is no need to escape the '}' character.
- * For example, <pre>MessageFormatter.format("File name is \\{{}}.", "App folder.zip");</pre>
- * will return the string "File name is {App folder.zip}.".
- *
- * See {@link #format(String, Object)}, {@link #format(String, Object, Object)}
- * and {@link #arrayFormat(String, Object[])} methods for more details.
- *
- * @author Ceki Gülcü
- */
+ * Formats messages according to very simple substitution rules. Substitutions
+ * can be made 1, 2 or more arguments.
+ * <p>
+ * For example,
+ * <pre>MessageFormatter.format("Hi {}.", "there");</pre>
+ * will return the string "Hi there.".
+ * <p>
+ * The {} pair is called the <em>formatting anchor</em>. It serves to
+ * designate the location where arguments need to be substituted within the
+ * message pattern.
+ * <p>
+ * In the rare case where you need to place the '{' or '}' in the message
+ * pattern itself but do not want them to be interpreted as a formatting
+ * anchors, you can espace the '{' character with '\', that is the backslash
+ * character. Only the '{' character should be escaped. There is no need to
+ * escape the '}' character. For example,
+ * <pre>MessageFormatter.format("Set \\{1,2,3} is not equal to {}.", "1,2");</pre>
+ * will return the string "Set {1,2,3} is not equal to 1,2.".
+ *
+ * <p>
+ * The escaping behaviour just described can be overridden by
+ * escaping the escape character '\'. Calling
+ * <pre>MessageFormatter.format("File name is C:\\\\{}.", "file.zip");</pre>
+ * will return the string "File name is C:\file.zip".
+ *
+ * <p>
+ * See {@link #format(String, Object)}, {@link #format(String, Object, Object)}
+ * and {@link #arrayFormat(String, Object[])} methods for more details.
+ *
+ * @author Ceki Gülcü
+ */
public class MessageFormatter {
static final char DELIM_START = '{';
static final char DELIM_STOP = '}';
@@ -56,81 +64,104 @@
* Performs single argument substitution for the 'messagePattern' passed as
* parameter.
* <p>
- * For example, <pre>MessageFormatter.format("Hi {}.", "there");</pre> will
- * return the string "Hi there.".
+ * For example,
+ *
+ * <pre>
+ * MessageFormatter.format("Hi {}.", "there");
+ * </pre>
+ *
+ * will return the string "Hi there.".
* <p>
- * @param messagePattern The message pattern which will be parsed and formatted
- * @param argument The argument to be substituted in place of the formatting anchor
+ *
+ * @param messagePattern
+ * The message pattern which will be parsed and formatted
+ * @param argument
+ * The argument to be substituted in place of the formatting anchor
* @return The formatted message
*/
public static String format(String messagePattern, Object arg) {
- return arrayFormat(messagePattern, new Object[] {arg});
- }
-
+ return arrayFormat(messagePattern, new Object[] { arg });
+ }
+
/**
- *
+ *
* Performs a two argument substitution for the 'messagePattern' passed as
* parameter.
* <p>
- * For example,
- * <pre>MessageFormatter.format("Hi {}. My name is {}.", "Alice", "Bob");</pre> will
- * return the string "Hi Alice. My name is Bob.".
- *
- * @param messagePattern The message pattern which will be parsed and formatted
- * @param arg1 The argument to be substituted in place of the first formatting anchor
- * @param arg2 The argument to be substituted in place of the second formatting anchor
+ * For example,
+ *
+ * <pre>
+ * MessageFormatter.format("Hi {}. My name is {}.", "Alice", "Bob");
+ * </pre>
+ *
+ * will return the string "Hi Alice. My name is Bob.".
+ *
+ * @param messagePattern
+ * The message pattern which will be parsed and formatted
+ * @param arg1
+ * The argument to be substituted in place of the first formatting
+ * anchor
+ * @param arg2
+ * The argument to be substituted in place of the second formatting
+ * anchor
* @return The formatted message
*/
public static String format(String messagePattern, Object arg1, Object arg2) {
- return arrayFormat(messagePattern, new Object[] {arg1, arg2});
+ return arrayFormat(messagePattern, new Object[] { arg1, arg2 });
}
-
+
/**
- * Same principle as the {@link #format(String, Object)} and
- * {@link #format(String, Object, Object)} methods except that
- * any number of arguments can be passed in an array.
+ * Same principle as the {@link #format(String, Object)} and
+ * {@link #format(String, Object, Object)} methods except that any number of
+ * arguments can be passed in an array.
*
- * @param messagePattern The message pattern which will be parsed and formatted
- * @param argArray An array of arguments to be substituted in place of formatting anchors
+ * @param messagePattern
+ * The message pattern which will be parsed and formatted
+ * @param argArray
+ * An array of arguments to be substituted in place of formatting
+ * anchors
* @return The formatted message
*/
public static String arrayFormat(String messagePattern, Object[] argArray) {
- if(messagePattern == null) {
+ if (messagePattern == null) {
return null;
}
int i = 0;
int len = messagePattern.length();
int j = messagePattern.indexOf(DELIM_START);
-
-
-
+
StringBuffer sbuf = new StringBuffer(messagePattern.length() + 50);
for (int L = 0; L < argArray.length; L++) {
-
- char escape = 'x';
-
+
j = messagePattern.indexOf(DELIM_START, i);
- if (j == -1 || (j+1 == len)) {
+ if (j == -1 || (j + 1 == len)) {
// no more variables
if (i == 0) { // this is a simple string
return messagePattern;
- } else { // add the tail string which contains no variables and return the result.
+ } else { // add the tail string which contains no variables and return
+ // the result.
sbuf.append(messagePattern.substring(i, messagePattern.length()));
return sbuf.toString();
}
} else {
char delimStop = messagePattern.charAt(j + 1);
- if (j > 0) {
- escape = messagePattern.charAt(j - 1);
- }
-
- if(escape == '\\') {
- L--; // DELIM_START was escaped, thus should not be incremented
- sbuf.append(messagePattern.substring(i, j-1));
- sbuf.append(DELIM_START);
- i = j + 1;
+
+ if (isEscapedDelimeter(messagePattern, j)) {
+ if(!isDoubleEscaped(messagePattern, j)) {
+ L--; // DELIM_START was escaped, thus should not be incremented
+ sbuf.append(messagePattern.substring(i, j - 1));
+ sbuf.append(DELIM_START);
+ i = j + 1;
+ } else {
+ // The escape character preceding the delemiter start is
+ // itself escaped: "abc x:\\{}"
+ // we have to consume one backward slash
+ sbuf.append(messagePattern.substring(i, j-1));
+ sbuf.append(argArray[L]);
+ i = j + 2;
+ }
} else if ((delimStop != DELIM_STOP)) {
// invalid DELIM_START/DELIM_STOP pair
sbuf.append(messagePattern.substring(i, messagePattern.length()));
@@ -147,4 +178,27 @@
sbuf.append(messagePattern.substring(i, messagePattern.length()));
return sbuf.toString();
}
+
+ static boolean isEscapedDelimeter(String messagePattern,
+ int delimeterStartIndex) {
+
+ if (delimeterStartIndex == 0) {
+ return false;
+ }
+ char potentialEscape = messagePattern.charAt(delimeterStartIndex - 1);
+ if (potentialEscape == '\\') {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ static boolean isDoubleEscaped(String messagePattern, int delimeterStartIndex) {
+ if (delimeterStartIndex >= 2
+ && messagePattern.charAt(delimeterStartIndex - 2) == '\\') {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
Modified: slf4j/trunk/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java
==============================================================================
--- slf4j/trunk/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java (original)
+++ slf4j/trunk/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java Tue Jan 29 20:19:00 2008
@@ -80,7 +80,7 @@
}
- public void test1Param() {
+ public void testOneParameter() {
String result;
result = MessageFormatter.format("Value is {}.", i3);
@@ -98,6 +98,9 @@
result = MessageFormatter.format("Incorrect {subst", i3);
assertEquals("Incorrect {subst", result);
+ result = MessageFormatter.format("Value is \\{bla} {}", i3);
+ assertEquals("Value is {bla} 3", result);
+
result = MessageFormatter.format("Escaped \\{} subst", i3);
assertEquals("Escaped {} subst", result);
@@ -109,9 +112,13 @@
result = MessageFormatter.format("File name is \\{{}}.", "App folder.zip");
assertEquals("File name is {App folder.zip}.", result);
+
+ // escaping the escape character
+ result = MessageFormatter.format("File name is C:\\\\{}.", "App folder.zip");
+ assertEquals("File name is C:\\App folder.zip.", result);
}
- public void test2Param() {
+ public void testTwoParameters() {
String result;
More information about the slf4j-dev
mailing list