@Getter @RequiredArgsConstructor @AllArgsConstructor public class Placeholder { private String placeholder; private final Function replacement; @Setter private boolean expensiveLookup = false; @Setter private boolean cacheValue = false; private String cachedValue; public Placeholder(String placeholder, Function replacement) { this.placeholder = placeholder; this.replacement = replacement; } public Placeholder(String placeholder, String replacement) { this(placeholder, (object) -> replacement); } public String replace(String text, T object) { if(!placeholder.startsWith("%")) placeholder = "%" + placeholder; if(!placeholder.endsWith("%")) placeholder = placeholder + "%"; if(cacheValue && cachedValue != null) { return text.replace(placeholder, cachedValue); } if(expensiveLookup) { int substringIndex = text.indexOf(placeholder); while(substringIndex != -1) { String before = text.substring(0, substringIndex); String after = text.substring(substringIndex + placeholder.length()); text = before + replace(object) + after; substringIndex = text.indexOf(placeholder); } tryCache(text); return text; } String value = replace(object); tryCache(value); return text.replace(placeholder, value); } private String replace(T object) { return replacement.apply(object); } private void tryCache(String value) { if(cacheValue) { cachedValue = value; } } }