...
Also a helper class will be added that can provide variable substitutions using ConfigProvider
instances. Here is an example implementation :(it only provides one level of indirection).
Code Block |
---|
/** * This class wraps a set of {@link ConfigProvider} instances and uses them to perform * transformations. */ public class ConfigTransformer { private static final Logger log = LoggerFactory.getLogger(ConfigTransformer.class); private static final Pattern DEFAULT_PATTERN = Pattern.compile("\\$\\{(.*?):(.*?)\\}"); private final Map<String, ConfigProvider> configProviders; private final Pattern pattern; public ConfigTransformer(Map<String, ConfigProvider> configProviders) { this(configProviders, DEFAULT_PATTERN); } public ConfigTransformer(Map<String, ConfigProvider> configProviders, Pattern pattern) { this.configProviders = configProviders; this.pattern = pattern; } public Map<String, String> transform(ConfigContext ctx, Map<String, String> configs) { Map<String, Set<String>> keysByProvider = new HashMap<>(); Map<String, Map<String, String>> lookupsByProvider = new HashMap<>(); // Collect the variables that need transformation for (Map.Entry<String, String> config : configs.entrySet()) { List<ConfigVariable> vars = getVars(config.getKey(), config.getValue(), pattern); for (ConfigVariable var : vars) { Set<String> keys = keysByProvider.get(var.providerName); if (keys == null) { keys = new HashSet<>(); keysByProvider.put(var.providerName, keys); } keys.add(var.valueVariable); } } // Lookup requested variables from the ConfigProviders for (Map.Entry<String, Set<String>> entry : keysByProvider.entrySet()) { ConfigProvider provider = configProviders.get(entry.getKey()); ConfigData configData = provider.lookup(ctx, null, new HashSet<>(entry.getValue())); Map<String, String> data = configData.data(); lookupsByProvider.put(entry.getKey(), data); } // Perform the transformations Map<String, String> result = new HashMap<>(configs); for (Map.Entry<String, String> config : configs.entrySet()) { result.put(config.getKey(), replace(lookupsByProvider, config.getValue(), pattern)); } return result; } private static List<ConfigVariable> getVars(String key, String value, Pattern pattern) { List<ConfigVariable> configVars = new ArrayList<>(); Matcher matcher = pattern.matcher(value); while (matcher.find()) { configVars.add(new ConfigVariable(matcher.group(1), matcher.group(2))); } return configVars; } private static String replace(Map<String, Map<String, String>> lookupsByProvider, String value, Pattern pattern) { Matcher matcher = pattern.matcher(value); StringBuilder builder = new StringBuilder(); int i = 0; while (matcher.find()) { Map<String, String> map = lookupsByProvider.get(matcher.group(1)); String replacement = map.get(matcher.group(2)); builder.append(value, i, matcher.start()); if (replacement == null) builder.append(matcher.group(0)); else builder.append(replacement); i = matcher.end(); } builder.append(value, i, value.length()); return builder.toString(); } private static class ConfigVariable { final String providerName; final String valueVariable; ConfigVariable(String providerName, String valueVariable) { this.providerName = providerName; this.valueVariable = valueVariable; } public String toString() { return "(" + providerName + ":" + valueVariable + ")"; } } } |
...