Skip to content

Instantly share code, notes, and snippets.

@compustar
Last active August 29, 2015 14:23
Show Gist options
  • Select an option

  • Save compustar/b41694b90f920a39075a to your computer and use it in GitHub Desktop.

Select an option

Save compustar/b41694b90f920a39075a to your computer and use it in GitHub Desktop.
Enhanced version of java.text.MessageFormat and String.Format() using named parameters instead of index numbers. e.g.: Java - "{now,date,yyyy-MM-dd HH:mm:ss.SSS}: Hello {name}!", C# - "{now:yyyy-MM-dd HH:mm:ss.fff}: Hello {name}!"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Text {
public class MessageTemplate {
private static Dictionary<string, MessageTemplate> cache = new Dictionary<string, MessageTemplate>();
private string format;
private Dictionary<string, int> parameters = new Dictionary<string, int>();
public MessageTemplate(string formatExpression) {
this.format = Compile(formatExpression);
}
public string Format(IDictionary<string, object> arguments) {
object[] args = new object[parameters.Count()];
foreach (var entry in parameters){
args[entry.Value] = arguments[entry.Key];
}
return string.Format(format, args);
}
public static string Format(string formatExpression, IDictionary<String, Object> arguments) {
if (!cache.ContainsKey(formatExpression)) {
cache[formatExpression] = new MessageTemplate(formatExpression);
}
MessageTemplate instance = cache[formatExpression];
return instance.Format(arguments);
}
private string Compile(string s) {
StringBuilder buffer = new StringBuilder();
char previousCharacter = char.MinValue;
bool isInParamState = false;
int braceCount = 0;
int paramIndex = 0;
for (int i = 0; i < s.Length; i++) {
char c = s[i];
if (c == '{') {
if (braceCount > 0 && c == previousCharacter) {
braceCount = 0;
isInParamState = false;
}
else {
braceCount++;
isInParamState = true;
}
}
if (isInParamState && c != '{' && previousCharacter == '{') {
StringBuilder paramName = new StringBuilder();
for (int j = i; j < s.Length; j++) {
if (s[j] == '}' || s[j] == ':') {
i = j;
c = s[i];
isInParamState = false;
String key = paramName.ToString();
if (parameters.ContainsKey(key)) {
buffer.Append(parameters[key]);
}
else {
parameters[key] = paramIndex;
buffer.Append(paramIndex++);
}
break;
}
paramName.Append(s[j]);
}
}
buffer.Append(c);
previousCharacter = c;
}
return buffer.ToString();
}
}
}
import java.text.*;
import java.util.*;
public class MessageTemplate {
private String formatExpression;
private HashMap<String, Integer> parameters = new HashMap<String, Integer>();
private static Map<String, MessageTemplate> cache = new WeakHashMap<String, MessageTemplate>();
public MessageTemplate(String formatExpression) throws IllegalArgumentException {
this.compile(formatExpression);
}
public String format(Map<String, Object> arguments) {
Object[] args = new Object[parameters.size()];
for (String key : parameters.keySet()){
args[parameters.get(key)] = arguments.get(key);
}
return MessageFormat.format(this.formatExpression, args);
}
public static String format(String formatExpression, Map<String, Object> arguments) throws IllegalArgumentException {
MessageTemplate instance = cache.get(formatExpression);
if (instance == null) {
instance = new MessageTemplate(formatExpression);
cache.put(formatExpression, instance);
}
return instance.format(arguments);
}
private void compile(String s) {
StringBuilder buffer = new StringBuilder();
char previousCharacter = Character.MIN_VALUE;
boolean isInParamState = false;
boolean isInLiteral = false;
int quoteCount = 0;
int paramIndex = 0;
for (int i = 0; i < s.length();i++) {
char c = s.charAt(i);
if (c == '\'') {
if (quoteCount > 0 && c == previousCharacter) {
isInLiteral = false;
}
else {
quoteCount++;
isInLiteral = !isInLiteral;
}
if (!isInLiteral) {
quoteCount = 0;
}
}
if (c == '{' && !isInLiteral) {
isInParamState = true;
}
if (isInParamState && c != '{' && previousCharacter == '{') {
StringBuilder paramName = new StringBuilder();
for (int j = i;j < s.length();j++) {
if (s.charAt(j) == '}' || s.charAt(j) == ',') {
i = j;
c = s.charAt(i);
isInParamState = false;
String key = paramName.toString();
if (parameters.containsKey(key)){
buffer.append(parameters.get(key));
} else {
parameters.put(key, paramIndex);
buffer.append(paramIndex++);
}
break;
}
paramName.append(s.charAt(j));
}
}
buffer.append(c);
previousCharacter = c;
}
this.formatExpression = buffer.toString();
}
}
import java.util.*;
public class Test{
public static void main(String []args) throws Exception{
String formatExpression = "{now,date,yyyy-MM-dd HH:mm:ss.SSS}: Hello {name}!";
HashMap<String, Object> arguments = new HashMap<String, Object>();
arguments.put("name", "Foo");
arguments.put("now", new Date());
System.out.println(MessageTemplate.format(formatExpression, arguments));
arguments.put("name", "Bar");
arguments.put("now", new Date());
System.out.println(MessageTemplate.format(formatExpression, arguments));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment