package com.taobao.tddl.rule.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 一个简单的有名字的占位符替换器 类似java.text.MessageFormat, 只是占位符是{name1} {name2} 而不是{0} {2}
*
* @author linxuan
*/
public class SimpleNamedMessageFormat {
private static final String DEFAULT_PLACEHOLDER_PREFIX = "{";
private static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
private final String pattern;
private final String placeholderPrefix;
private final String placeholderSuffix;
private volatile boolean parsed;
private volatile List<Frag> frags;
private static class Frag {
public final String value;
public final boolean isPlaceHolderName;
public Frag(String piece, boolean isPlaceHolderName){
this.value = piece;
this.isPlaceHolderName = isPlaceHolderName;
}
}
public SimpleNamedMessageFormat(String pattern){
this.pattern = pattern;
this.placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
this.placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;
}
public SimpleNamedMessageFormat(String pattern, String placeholderPrefix, String placeholderSuffix){
this.pattern = pattern;
this.placeholderPrefix = placeholderPrefix;
this.placeholderSuffix = placeholderSuffix;
}
public String format(Map<String, ? extends Object> args) {
if (parsed && frags != null) {
return buildByParsedFrags(args);
} else {
return format0(args);
}
}
private String buildByParsedFrags(Map<String, ? extends Object> args) {
// 实际上这个sb的长度可以提前算出来(guangxia)
StringBuilder sb = new StringBuilder();
for (Frag frag : frags) {
if (!frag.isPlaceHolderName) {
sb.append(frag.value);
continue;
}
Object arg = args.get(frag.value);
if (arg != null) sb.append(arg);
else {
sb.append(this.placeholderPrefix).append(frag.value).append(this.placeholderSuffix);
}
}
return sb.toString();
}
/**
* 不支持嵌套
*/
private String format0(Map<String, ? extends Object> args) {
List<Frag> initfrags = new ArrayList<Frag>();
int cursor = 0;
int index0 = this.pattern.indexOf(placeholderPrefix);
int index1 = this.pattern.indexOf(placeholderSuffix);
while (index0 != -1 && index1 != -1) {
initfrags.add(new Frag(this.pattern.substring(cursor, index0), false));
initfrags.add(new Frag(this.pattern.substring(index0 + placeholderPrefix.length(), index1), true));
cursor = index1 + placeholderSuffix.length();
index0 = this.pattern.indexOf(placeholderPrefix, cursor);
index1 = this.pattern.indexOf(placeholderSuffix, index0 + placeholderPrefix.length());
}
initfrags.add(new Frag(this.pattern.substring(cursor), false));
this.frags = initfrags;
this.parsed = true;
return buildByParsedFrags(args);
}
}