code: public static String processMacros(String message, Map<String, Object> macros)
      {
          if (message.isEmpty())
          {
              return message;
          }
          StringBuilder out = new StringBuilder(message.length() * 2);
  
          int i = 0;
          final int len = message.length();
          char current;
          boolean expectPlain = false;
  
          while (i < len)
          {
              current = message.charAt(i);
  
              if (!expectPlain && current == MACRO_BEGIN)
              {
                  final int start = i + 1;
                  final int end = message.indexOf(MACRO_END, start);
                  if (end == -1 || end == start)
                  {
                      expectPlain = true;
                  }
                  else
                  {
                      String name = message.substring(start, end).intern();
                      Object arg = macros.get(name);
                      if (arg != null)
                      {
                          out.append(arg);
                          i = end + 1;
                      }
                      else
                      {
                          expectPlain = true;
                      }
                  }
              }
              else
              {
                  int start = i;
                  if (expectPlain)
                  {
                      ++i;
                  }
                  expectPlain = false;
                  boolean escaped = false;
                  while (i < message.length())
                  {
                      current = message.charAt(i);
                      if (current == ESCAPE && i + 1 < message.length())
                      {
                          i++;
                          current = message.charAt(i++);
                          escaped = current == ESCAPE || current == MACRO_BEGIN;
                      }
                      else if (current == MACRO_BEGIN)
                      {
                          break;
                      }
                      else
                      {
                          ++i;
                      }
                  }
  
                  if (escaped)
                  {
                      unescape(message, start, i, out);
                  }
                  else
                  {
                      out.append(message, start, i);
                  }
              }
          }
  
          return out.toString();
      }
docs: Processes named macros in a message.
  <p>e.g.: Replaces {key} with the value of "key" in arguments.
  Macros names will be intern'ed by the parser, so IdentityHashMaps can be used.
  
  @param message the message
  @param macros  the arguments
  
  @return the processed message