package com.github.wangxuehui.rpc.snrpc.util;
import java.util.HashMap;
import java.util.Map;
/**
* @author skyim E-mail:wxh64788665@gmail.com
* 类说明
*/
public class MessageFormatter {
public static final String DEFAULT_PLACE_HOLDER = "{}";
public static final char DEFAULT_ESCAPE_CHAR = '\\';
/**
* equivalent to
* <code>LogFormatter.format(msgPattern, "{}", '\\', args)</code>
*
* @param msgPattern
* @param args
* @return
*/
public static String format(String msgPattern, Object[] args) {
return format(msgPattern, DEFAULT_PLACE_HOLDER, DEFAULT_ESCAPE_CHAR,
args);
}
/**
* equivalent to
* <code>LogFormatter.format(msgPattern, placeholder, '\\', args)</code>
*
* @param msgPattern
* @param placeholder
* @param args
* @return
*/
public static String format(String msgPattern, String placeholder,
Object[] args) {
return format(msgPattern, placeholder, DEFAULT_ESCAPE_CHAR, args);
}
/**
* @param msgPattern
* @param placeholder
* @param escapeChar
* @param args
* @return
*/
@SuppressWarnings("rawtypes")
public static String format(String msgPattern, String placeholder,
char escapeChar, Object[] args) {
if (null == msgPattern || msgPattern.length() == 0) {
return null;
}
if (null == args || args.length == 0) {
return msgPattern;
}
if (null == placeholder || "".equals(placeholder)) {
return msgPattern;
}
int lastMatchedIndex = 0, currentMatchedIndex = 0;
StringBuilder strbuf = new StringBuilder(msgPattern.length() + 64);
for (int argIndex = 0; argIndex < args.length; argIndex++) {
currentMatchedIndex = msgPattern.indexOf(placeholder,
lastMatchedIndex);
if (-1 == currentMatchedIndex) {
// no more variables
if (0 == lastMatchedIndex) {
// this is a simple string
return msgPattern;
} else {
// add the tail string which contains no variables
strbuf.append(msgPattern.substring(lastMatchedIndex,
msgPattern.length()));
return strbuf.toString();
}
} else {
// successive escape chars before the placeholder
int cnt = countSuccessiveEscapeChar(msgPattern, escapeChar,
currentMatchedIndex, lastMatchedIndex);
if (0 == cnt) { // all escaped itself
strbuf.append(msgPattern.substring(lastMatchedIndex,
currentMatchedIndex));
deeplyAppendParameter(strbuf, args[argIndex], new HashMap());
lastMatchedIndex = currentMatchedIndex
+ placeholder.length();
} else {
int escapeItselfCnt = cnt / 2;
strbuf.append(msgPattern.substring(lastMatchedIndex,
(currentMatchedIndex - cnt + escapeItselfCnt)));
if (cnt % 2 != 0) {
argIndex--;// placeholder was escaped, thus should not
// be incremented
strbuf.append(placeholder.charAt(0));
lastMatchedIndex = currentMatchedIndex + 1;
} else {
deeplyAppendParameter(strbuf, args[argIndex],
new HashMap());
lastMatchedIndex = currentMatchedIndex
+ placeholder.length();
}
}
}
}
// append the characters following the last {} pair.
strbuf.append(msgPattern.substring(lastMatchedIndex,
msgPattern.length()));
return strbuf.toString();
}
private static int countSuccessiveEscapeChar(String msgPattern,
char escapeChar, int delimeterStartIndex, int delimeterStopIndex) {
if (0 == delimeterStartIndex) {
return 0;
}
int cnt = 0;
for (int i = delimeterStartIndex - 1; i >= delimeterStopIndex; i--) {
if (msgPattern.charAt(i) == escapeChar) {
++cnt;
} else {
break;
}
}
return cnt;
}
@SuppressWarnings("rawtypes")
private static void deeplyAppendParameter(StringBuilder sbuf, Object o,
Map seenMap) {
if (o == null) {
sbuf.append("null");
return;
}
if (!o.getClass().isArray()) {
safeObjectAppend(sbuf, o);
} else {
// check for primitive array types because they
// unfortunately cannot be cast to Object[]
if (o instanceof boolean[]) {
booleanArrayAppend(sbuf, (boolean[]) o);
} else if (o instanceof byte[]) {
byteArrayAppend(sbuf, (byte[]) o);
} else if (o instanceof char[]) {
charArrayAppend(sbuf, (char[]) o);
} else if (o instanceof short[]) {
shortArrayAppend(sbuf, (short[]) o);
} else if (o instanceof int[]) {
intArrayAppend(sbuf, (int[]) o);
} else if (o instanceof long[]) {
longArrayAppend(sbuf, (long[]) o);
} else if (o instanceof float[]) {
floatArrayAppend(sbuf, (float[]) o);
} else if (o instanceof double[]) {
doubleArrayAppend(sbuf, (double[]) o);
} else {
objectArrayAppend(sbuf, (Object[]) o, seenMap);
}
}
}
private static void safeObjectAppend(StringBuilder sbuf, Object o) {
try {
String oAsString = o.toString();
sbuf.append(oAsString);
} catch (Throwable t) {
System.err
.println("Failed toString() invocation on an object of type ["
+ o.getClass().getName() + "]");
t.printStackTrace();
sbuf.append("[FAILED toString()]");
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static void objectArrayAppend(StringBuilder sbuf, Object[] a,
Map seenMap) {
sbuf.append('[');
if (!seenMap.containsKey(a)) {
seenMap.put(a, null);
final int len = a.length;
for (int i = 0; i < len; i++) {
deeplyAppendParameter(sbuf, a[i], seenMap);
if (i != len - 1) {
sbuf.append(", ");
}
}
// allow repeats in siblings
seenMap.remove(a);
} else {
sbuf.append("...");
}
sbuf.append(']');
}
private static void booleanArrayAppend(StringBuilder sbuf, boolean[] a) {
sbuf.append('[');
final int len = a.length;
for (int i = 0; i < len; i++) {
sbuf.append(a[i]);
if (i != len - 1) {
sbuf.append(", ");
}
}
sbuf.append(']');
}
private static void byteArrayAppend(StringBuilder sbuf, byte[] a) {
sbuf.append('[');
final int len = a.length;
for (int i = 0; i < len; i++) {
sbuf.append(a[i]);
if (i != len - 1)
sbuf.append(", ");
}
sbuf.append(']');
}
private static void charArrayAppend(StringBuilder sbuf, char[] a) {
sbuf.append('[');
final int len = a.length;
for (int i = 0; i < len; i++) {
sbuf.append(a[i]);
if (i != len - 1)
sbuf.append(", ");
}
sbuf.append(']');
}
private static void shortArrayAppend(StringBuilder sbuf, short[] a) {
sbuf.append('[');
final int len = a.length;
for (int i = 0; i < len; i++) {
sbuf.append(a[i]);
if (i != len - 1) {
sbuf.append(", ");
}
}
sbuf.append(']');
}
private static void intArrayAppend(StringBuilder sbuf, int[] a) {
sbuf.append('[');
final int len = a.length;
for (int i = 0; i < len; i++) {
sbuf.append(a[i]);
if (i != len - 1) {
sbuf.append(", ");
}
}
sbuf.append(']');
}
private static void longArrayAppend(StringBuilder sbuf, long[] a) {
sbuf.append('[');
final int len = a.length;
for (int i = 0; i < len; i++) {
sbuf.append(a[i]);
if (i != len - 1) {
sbuf.append(", ");
}
}
sbuf.append(']');
}
private static void floatArrayAppend(StringBuilder sbuf, float[] a) {
sbuf.append('[');
final int len = a.length;
for (int i = 0; i < len; i++) {
sbuf.append(a[i]);
if (i != len - 1) {
sbuf.append(", ");
}
}
sbuf.append(']');
}
private static void doubleArrayAppend(StringBuilder sbuf, double[] a) {
sbuf.append('[');
final int len = a.length;
for (int i = 0; i < len; i++) {
sbuf.append(a[i]);
if (i != len - 1) {
sbuf.append(", ");
}
}
sbuf.append(']');
}
}