class StringUtils {

    public static String replaceWildcardConfigs(String contentWithWildcards, Map<String, Object> properties) {
        if(properties == null || contentWithWildcards == null) {
            return contentWithWildcards;
        }
        Engine engine = new Engine();
        engine.setModelAdaptor(new DefaultModelAdaptor() {
            @Override
            public Object getValue(TemplateContext context, Token arg1, List<String> arg2, String expression) {
                // First look in model map. Needed for dot-separated properties
                Object value = context.model.get(expression);
                if (value != null) {
                    return value;
                } else {
                    return super.getValue(context, arg1, arg2, expression);
                }
            }

            @Override
            protected Object traverse(Object obj, List<String> arg1, int arg2, ErrorHandler arg3, Token token) {
                // Throw exception if a token cannot be resolved instead of returning empty string.
                if (obj == null) {
                    throw new IllegalArgumentException("Could not resolve " + token);
                }
                return super.traverse(obj, arg1, arg2, arg3, token);
            }
        });
        try {
            return engine.transform(contentWithWildcards, properties);
        } catch (com.floreysoft.jmte.message.ParseException e) {
            throw new IllegalArgumentException(e);
        }
    }

    private  StringUtils();

}