I was recently looking at implementing a parameter substitution routine, along the lines of what Ant does for ${}-style properties. I initially picked up Spring’s PropertyPlaceholderConfigurer implementation, and created a modified version of the parseStringValue() routine, which is a recursive routine that unwraps delimited properties and resolves them. This did mostly what I want, but there were a few issues with it, mainly that it doesn’t handle truly recursive properties. For instance, if I want to do a Bash-style eval of a property ${FOO${BAR}}
, where $BAR
is mapped to "def"
, then I want the ultimate evaluation of this property to be ${FOOdef}
.
This seems pretty simple to do in theory, as it would lend itself well to a recursive method, or an iterative method, possibly using a stack to store nested property names as we extract them from the string.
What I came up with was (if PREFIX
is a property start delimiter, e.g. '{'
, and SUFFIX
is a property end delimiter, e.g. '}'
):
void recurse(StringBuilder str, int index) { if (str.indexOf(PREFIX, index) != -1) recurse(str, str.indexOf(PREFIX, index)+1); if (str.indexOf(PREFIX) == -1) return; String resolved = (str.substring(index, str.indexOf(SUFFIX, index))); str.replace(index-PREFIX.length(), str.indexOf(SUFFIX, index)+SUFFIX.length(), lookup(resolved)); } private String lookup(String key) { System.out.println("looking up [" + key+ "] => [" + map.get(key) + "]"); return map.get(key); }
Which does the job, although it could still be more elegant (not to mention efficient). The explicit check to str.indexOf(PREFIX)
in order to exit the routine bugs me a little bit – I’m sure its possible to rearrange this to be more concise and skip the explicit check like that. Still this routine can now parse strings like TEXT{FOO}MORETEXT{BAR{GOO}}
and resolve nested properties. I’m trrying to find a nicer recursive representation for this. maybe I should ask on #haskell
.