private static String replaceMap(String input, Map map, boolean ignoreCase, boolean doResolveInternals) throws PageException {
	if (doResolveInternals) map = resolveInternals(map, ignoreCase, 0);

	String result = input;
	Iterator<Map.Entry> it = map.entrySet().iterator();
	Map.Entry e;
	while (it.hasNext()) {
	    e = it.next();
	    result = replace(result, Caster.toString(e.getKey()), Caster.toString(e.getValue()), false, ignoreCase);
	}
	return result;
    }
private static String replaceMap ( String input , Map map , boolean ignoreCase , boolean doResolveInternals ) throws PageException { if ( doResolveInternals ) map = resolveInternals ( map , ignoreCase , 0 ) ; String result = input ; Iterator < Map . Entry > it = map . entrySet ( ) . iterator ( ) ; Map . Entry e ; while ( it . hasNext ( ) ) { e = it . next ( ) ; result = replace ( result , Caster . toString ( e . getKey ( ) ) , Caster . toString ( e . getValue ( ) ) , false , ignoreCase ) ; } return result ; }
this is the core of the replaceMap() method.

it is called once from the public entry point and then internally from resolveInternals()

when doResolveInternals is true -- this method calls resolveInternals. therefore, calls from
resolveInternals() must pass false to that param to avoid an infinite ping-pong loop

@param input - the string on which the replacements should be performed.
@param map - a java.util.Map with key/value pairs where the key is the substring to find and the
value is the substring with which to replace the matched key
@param ignoreCase - if true then matches will not be case sensitive
@param doResolveInternals - only the initial call (from the public entry point) should pass true
@return
@throws PageException