package net.sssubtlety.leaves_us_in_peace.text;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringSubstituter {
private static final String ILLEGAL_CHARACTERS = "${}";
private static final Pattern ILLEGAL_CHARACTER_PATTERN = Pattern.compile(Pattern.quote(ILLEGAL_CHARACTERS));
private final ImmutableMap<String, String> substitutions;
private final ImmutableMap<Pattern, String> patternSubstitutions;
private final Pattern namesPattern;
public StringSubstituter(Map<String, String> substitutions) {
this.substitutions = makeSubstitutionMap(substitutions);
this.patternSubstitutions = makePatternSubstitutionMap();
this.namesPattern = makeNamesPatternAndGroups2Values();
}
private static ImmutableMap<String, String> makeSubstitutionMap(Map<String, String> replacements) {
final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
replacements.forEach((name, value) -> {
final Matcher matcher = ILLEGAL_CHARACTER_PATTERN.matcher(name);
if (matcher.find()) throw new IllegalArgumentException(
"Name \"" + name + "\" contains illegal character: '" + matcher.group() + "'");
builder.put("${" + name + "}", value);
});
return builder.build();
}
private ImmutableMap<Pattern, String> makePatternSubstitutionMap() {
final ImmutableMap.Builder<Pattern, String> builder = ImmutableMap.builder();
this.substitutions.forEach((key, value) -> builder.put(Pattern.compile(Pattern.quote(key)), Matcher.quoteReplacement(value)));
return builder.build();
}
private Pattern makeNamesPatternAndGroups2Values() {
final StringBuilder namesPatternBuilder = new StringBuilder(Pattern.quote("${")).append("(");
int i = 1;
final var replacementsItr = substitutions.entrySet().iterator();
Map.Entry<String, String> entry;
while (replacementsItr.hasNext()) {
entry = replacementsItr.next();
if (i > 1) namesPatternBuilder.append("|");
namesPatternBuilder.append(Pattern.quote(entry.getKey()));
i++;
}
return Pattern.compile(namesPatternBuilder.append(")").toString());
}
public String substitute1(String string) {
for (var entry : substitutions.entrySet()) {
string = string.replace(entry.getKey(), entry.getValue());
}
return string;
}
public String substitute2(String string) {
for (var entry : patternSubstitutions.entrySet()) {
string = entry.getKey().matcher(string).replaceAll(Matcher.quoteReplacement(entry.getValue()));
}
return string;
}
public String substitute3(String string) {
final Matcher matcher = namesPattern.matcher(string);
return matcher.replaceAll(matchResult -> substitutions.get(matchResult.group()));
}
}