Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make string formatting mechanism in Java?

Tags:

java

tokenize

I'm trying to make a string formatting mechanism, which pretty much looks like the Winamp Advanced Title Formatting.

I have some 'variables' (or metadata fields) bound to object properties, in the form %varname%. So, for example, the %title% metadata field is bound to a song title, say 'Conquest of Paradise', the %artist% metadata field is bound to the song artist, say 'Vangelis', and the %feat% metadata field is bound to the featuring artists, say 'English Chamber Choir'.

Now I want to display the song depending on a given formatting, for example:

%title%[ (by %artist%[ featuring %feat%])]

Square brackets mean don't display unless (all) metadata inside the brackets were set. Nesting of square brackets should be possible.
So abovementioned formatting string says: display the metadata field %title% and, if %artist% is set (not an empty string), display (by %artist%), but if the %feat% metadata field is also non-empty, then display that field also. In the abovementioned example, it would become:

Conquest of Paradise (by Vangelis featuring English Chamber Choir)

Now how do I make such mechanism? Where do I start?

I guess that I have to tokenize the string and then per 'section' search for metadata tags?

like image 777
MC Emperor Avatar asked Nov 16 '25 17:11

MC Emperor


1 Answers

I would build up a tree structure that represents the pattern. For your example, it would look like:

root
 + variable (title)
 + group 
   + text (" (by ")
   + variable (artist)
   + group
     + text (" featuring ")
     + variable (feat)
   + text (")")

Then when you evaluate meta data against your tree, you store at the group level whether all variables and sub-groups in the group evaluated, and if so use the text.

Your tree classes would look something like:

interface Node { String evaluate(Map<String, String> metaData); }

class Group implements Node 
{
  private final List<Node> _children;

  Group(final List<Node> children) { _children = children; }

  @Override
  public String evaluate(final Map<String, String> metaData)
  {
    final StringBuilder sb = new StringBuilder(); 
    for (final Node node : _children)
    {
      final String subText = node.evaluate(metaData);
      if (subText == null)
        return null;
      sb.append(subText);
    }
    return sb.toString();
  }
}

class Text implements Node 
{
  private final String _text;

  Text(final String text) { _text = text; }

  @Override
  public String evaluate(final Map<String, String> metaData)
  {
    return _text;
  }
}

class Variable implements Node 
{
  private final String _variable;

  Variable(final String variable) { _variable = variable; }

  @Override
  public String evaluate(final Map<String, String> metaData)
  {
    return metaData.get(_variable);
  }
}

All that's left to do is to work out how to parse your string to create the tree structure.

like image 187
SimonC Avatar answered Nov 19 '25 05:11

SimonC