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