package chatty.util; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; /** * Replaces Strings based on a Map. Creates a single regex to search for parts * that should be replaced. * * @author tduva */ public class Replacer { private final String[] replacementValues; private final Pattern pattern; /** * Create a Replacer that replaces the keys in the Map with their values. * The keys are compiled into a Pattern as alternatives, so each key has to * be a valid regex as to not interfere with the other keys. * * @param replacements The map of replacements * @throws IllegalArgumentException when one of the replacement keys does * not compile to a Pattern */ public Replacer(Map<String, String> replacements) { this.replacementValues = new String[replacements.size()]; StringBuilder sb = new StringBuilder(""); int i = 0; for (String item : replacements.keySet()) { try { Pattern.compile(item); } catch (PatternSyntaxException ex) { throw new IllegalArgumentException("Invalid replacement pattern.", ex); } if (sb.length() != 0) { sb.append("|"); } sb.append("(").append(item).append(")"); // Add the replacement values to the array in the same order as the // groups replacementValues[i] = replacements.get(item); i++; } pattern = Pattern.compile(sb.toString()); } /** * Replaces anything in the input String, based on the Map specified for * this Replacer. * * @param input * @return */ public String replace(String input) { int lastAppendPos = 0; Matcher matcher = pattern.matcher(input); StringBuilder sb = new StringBuilder(); while (matcher.find()) { sb.append(input, lastAppendPos, matcher.start()); sb.append(getReplacement(matcher)); lastAppendPos = matcher.end(); } sb.append(input, lastAppendPos, input.length()); return sb.toString(); } /** * Gets the replacement for the given Matcher. Gets the index of the group * that matched and returns the replacement value for that index from the * array of replacements. * * @param matcher * @return */ private String getReplacement(Matcher matcher) { for (int i = 1; i <= matcher.groupCount(); i++) { if (matcher.group(i) != null) { return replacementValues[--i]; } } return null; } }