001package io.avaje.config;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006import java.math.BigDecimal;
007import java.net.URL;
008import java.util.Optional;
009import java.util.Properties;
010import java.util.function.Consumer;
011
012/**
013 * Provides application Configuration based on loading properties and yaml files
014 * as well as plugins that supply properties (like dynamic configuration loaded from a db).
015 * <p>
016 * The application can register onChange listeners to handle changes to configuration
017 * properties at runtime. Plugins or code can dynamically load and change properties and
018 * this can fire any registered callback handlers.
019 * </p>
020 *
021 * <h3>Examples</h3>
022 * <pre>{@code
023 *
024 *  int port = Config.getInt("app.port", 8090);
025 *
026 *  String topicName = Config.get("app.topic.name");
027 *
028 *  List<Integer> codes = Config.getList().ofInt("my.codes", 42, 54);
029 *
030 * }</pre>
031 */
032public class Config {
033
034  static final Logger log = LoggerFactory.getLogger("io.avaje.config");
035
036  private static final Configuration data = CoreConfiguration.initialise();
037
038  /**
039   * Hide constructor.
040   */
041  private Config() {
042  }
043
044  /**
045   * Return the loaded properties as standard Properties map.
046   */
047  public static Properties asProperties() {
048    return data.asProperties();
049  }
050
051  /**
052   * Return the underlying configuration.
053   */
054  public static Configuration asConfiguration() {
055    return data;
056  }
057
058  /**
059   * Put all loaded properties into System properties.
060   */
061  public static void loadIntoSystemProperties() {
062    data.loadIntoSystemProperties();
063  }
064
065  /**
066   * Return a required configuration value as String.
067   * <p>
068   * IllegalStateException is thrown if the value is not defined in configuration.
069   * </p>
070   *
071   * @param key The configuration key
072   * @return The configured value
073   */
074  public static String get(String key) {
075    return data.get(key);
076  }
077
078  /**
079   * Return a configuration string value with a given default.
080   *
081   * @param key          The configuration key
082   * @param defaultValue The default value used
083   * @return The configured or default value
084   */
085  public static String get(String key, String defaultValue) {
086    return data.get(key, defaultValue);
087  }
088
089  /**
090   * Return a configuration value that might not exist.
091   *
092   * @param key The configuration key
093   * @return The configured value wrapped as optional
094   */
095  public static Optional<String> getOptional(String key) {
096    return data.getOptional(key);
097  }
098
099  /**
100   * Return boolean configuration value with the given default value.
101   * <p>
102   * IllegalStateException is thrown if the value is not defined in configuration.
103   * </p>
104   *
105   * <pre>{@code
106   *
107   *   if (Config.enabled("feature.cleanup")) {
108   *     ...
109   *   }
110   *
111   * }</pre>
112   *
113   * @param key The configuration key
114   * @return True when configuration value is true
115   */
116  public static boolean enabled(String key) {
117    return getBool(key);
118  }
119
120  /**
121   * Return boolean configuration value with the given default value.
122   *
123   * <pre>{@code
124   *
125   *   if (Config.enabled("feature.cleanup", true)) {
126   *     ...
127   *   }
128   *
129   * }</pre>
130   *
131   * @param key The configuration key
132   * @return True when configuration value is true
133   */
134  public static boolean enabled(String key, boolean enabledDefault) {
135    return getBool(key, enabledDefault);
136  }
137
138  /**
139   * Return a required boolean configuration value.
140   * <p>
141   * IllegalStateException is thrown if the value is not defined in configuration.
142   * </p>
143   *
144   * @param key The configuration key
145   * @return The configured value
146   */
147  public static boolean getBool(String key) {
148    return data.getBool(key);
149  }
150
151  /**
152   * Return a configuration value as boolean given a default value.
153   *
154   * @param key          The configuration key
155   * @param defaultValue The default value used
156   * @return The configured or default value
157   */
158  public static boolean getBool(String key, boolean defaultValue) {
159    return data.getBool(key, defaultValue);
160  }
161
162  /**
163   * Return a required int configuration value.
164   * <p>
165   * IllegalStateException is thrown if the value is not defined in configuration.
166   * </p>
167   *
168   * @param key The configuration key
169   * @return The configured value
170   */
171  public static int getInt(String key) {
172    return data.getInt(key);
173  }
174
175  /**
176   * Return a configuration value as int given a default value.
177   *
178   * @param key          The configuration key
179   * @param defaultValue The default value used
180   * @return The configured or default value
181   */
182  public static int getInt(String key, int defaultValue) {
183    return data.getInt(key, defaultValue);
184  }
185
186  /**
187   * Return a required long configuration value.
188   * <p>
189   * IllegalStateException is thrown if the value is not defined in configuration.
190   * </p>
191   *
192   * @param key The configuration key
193   * @return The configured value
194   */
195  public static long getLong(String key) {
196    return data.getLong(key);
197  }
198
199  /**
200   * Return a configuration value as long given a default value.
201   *
202   * @param key          The configuration key
203   * @param defaultValue The default value used
204   * @return The configured or default value
205   */
206  public static long getLong(String key, long defaultValue) {
207    return data.getLong(key, defaultValue);
208  }
209
210  /**
211   * Return a decimal configuration value.
212   *
213   * @param key The configuration key
214   * @return The configured value
215   */
216  public static BigDecimal getDecimal(String key) {
217    return data.getDecimal(key);
218  }
219
220  /**
221   * Return a decimal configuration value with a default value.
222   * <p>
223   * IllegalStateException is thrown if the value is not defined in configuration.
224   * </p>
225   *
226   * @param key          The configuration key
227   * @param defaultValue The default value
228   * @return The configured value
229   */
230  public static BigDecimal getDecimal(String key, String defaultValue) {
231    return data.getDecimal(key, defaultValue);
232  }
233
234  /**
235   * Return a URL configuration value.
236   *
237   * @param key The configuration key
238   * @return The configured value
239   */
240  public static URL getURL(String key) {
241    return data.getURL(key);
242  }
243
244  /**
245   * Return a URL configuration value with a default value.
246   * <p>
247   * IllegalStateException is thrown if the value is not defined in configuration.
248   * </p>
249   *
250   * @param key          The configuration key
251   * @param defaultValue The default value
252   * @return The configured value
253   */
254  public static URL getURL(String key, String defaultValue) {
255    return data.getURL(key, defaultValue);
256  }
257
258  /**
259   * Return the enum configuration value.
260   * <p>
261   * IllegalStateException is thrown if the value is not defined in configuration.
262   * </p>
263   *
264   * @param type The enum type
265   * @param key  The configuration key
266   * @return The configured value
267   */
268  public static <T extends Enum<T>> T getEnum(Class<T> type, String key) {
269    return data.getEnum(type, key);
270  }
271
272  /**
273   * Return the enum configuration value with a default value.
274   *
275   * @param type         The enum type
276   * @param key          The configuration key
277   * @param defaultValue The default value
278   * @return The configured value
279   */
280  public static <T extends Enum<T>> T getEnum(Class<T> type, String key, T defaultValue) {
281    return data.getEnum(type, key, defaultValue);
282  }
283
284  /**
285   * Return a List of values configured.
286   *
287   * <pre>{@code
288   *
289   *  List<Integer> codes = Config.getList().ofInt("my.codes", 97, 45);
290   *
291   * }</pre>
292   */
293  public static Configuration.ListValue getList() {
294    return data.getList();
295  }
296
297  /**
298   * Return a Set of values configured.
299   *
300   * <pre>{@code
301   *
302   *  Set<String> operations = Config.getSet().of("my.operations", "put","delete");
303   *
304   * }</pre>
305   */
306  public static Configuration.SetValue getSet() {
307    return data.getSet();
308  }
309
310  /**
311   * Set a configuration value.
312   * <p>
313   * This will fire an configuration callback listeners that are registered
314   * for this key.
315   * </p>
316   */
317  public static void setProperty(String key, String value) {
318    data.setProperty(key, value);
319  }
320
321  /**
322   * Register a callback for a change to the given configuration key.
323   *
324   * @param key      The configuration key we want to detect changes to
325   * @param callback The callback handling to fire when the configuration changes.
326   */
327  public static void onChange(String key, Consumer<String> callback) {
328    data.onChange(key, callback);
329  }
330
331  /**
332   * Register a callback for a change to the given configuration key as an Int value.
333   *
334   * @param key      The configuration key we want to detect changes to
335   * @param callback The callback handling to fire when the configuration changes.
336   */
337  public static void onChangeInt(String key, Consumer<Integer> callback) {
338    data.onChangeInt(key, callback);
339  }
340
341  /**
342   * Register a callback for a change to the given configuration key as an Long value.
343   *
344   * @param key      The configuration key we want to detect changes to
345   * @param callback The callback handling to fire when the configuration changes.
346   */
347  public static void onChangeLong(String key, Consumer<Long> callback) {
348    data.onChangeLong(key, callback);
349  }
350
351  /**
352   * Register a callback for a change to the given configuration key as an Boolean value.
353   *
354   * @param key      The configuration key we want to detect changes to
355   * @param callback The callback handling to fire when the configuration changes.
356   */
357  public static void onChangeBool(String key, Consumer<Boolean> callback) {
358    data.onChangeBool(key, callback);
359  }
360}