3434import java .lang .reflect .Array ;
3535import java .util .Arrays ;
3636import java .util .List ;
37+ import java .util .Map ;
3738import java .util .Optional ;
39+ import java .util .function .Function ;
3840
3941import org .eclipse .microprofile .config .spi .ConfigSource ;
4042import org .eclipse .microprofile .config .spi .Converter ;
@@ -129,7 +131,9 @@ public interface Config {
129131 * if the property cannot be converted to the specified type
130132 * @throws java.util.NoSuchElementException
131133 * if the property is not defined or is defined as an empty string or the converter returns {@code null}
134+ * @deprecated use {@link #get(String)} and {@link #as(Class)} instead
132135 */
136+ @ Deprecated
133137 <T > T getValue (String propertyName , Class <T > propertyType );
134138
135139 /**
@@ -148,7 +152,9 @@ public interface Config {
148152 * @param propertyName
149153 * The configuration property name
150154 * @return the resolved property value as a {@link ConfigValue}
155+ * @deprecated use {@link #get(String)} and methods on the config node
151156 */
157+ @ Deprecated
152158 ConfigValue getConfigValue (String propertyName );
153159
154160 /**
@@ -171,7 +177,9 @@ public interface Config {
171177 * @throws java.util.NoSuchElementException
172178 * if the property isn't present in the configuration or is defined as an empty string or the converter
173179 * returns {@code null}
180+ * @deprecated use {@link #get(String)} and #asList(Class)
174181 */
182+ @ Deprecated
175183 default <T > List <T > getValues (String propertyName , Class <T > propertyType ) {
176184 @ SuppressWarnings ("unchecked" )
177185 Class <T []> arrayType = (Class <T []>) Array .newInstance (propertyType , 0 ).getClass ();
@@ -198,7 +206,9 @@ default <T> List<T> getValues(String propertyName, Class<T> propertyType) {
198206 *
199207 * @throws IllegalArgumentException
200208 * if the property cannot be converted to the specified type
209+ * @deprecated use {@link #get(String)} and {@link #as(Class)} instead
201210 */
211+ @ Deprecated
202212 <T > Optional <T > getOptionalValue (String propertyName , Class <T > propertyType );
203213
204214 /**
@@ -219,7 +229,9 @@ default <T> List<T> getValues(String propertyName, Class<T> propertyType) {
219229 *
220230 * @throws java.lang.IllegalArgumentException
221231 * if the property cannot be converted to the specified type
232+ * @deprecated use {@link #get(String)} and #asList(Class)
222233 */
234+ @ Deprecated
223235 default <T > Optional <List <T >> getOptionalValues (String propertyName , Class <T > propertyType ) {
224236 @ SuppressWarnings ("unchecked" )
225237 Class <T []> arrayType = (Class <T []>) Array .newInstance (propertyType , 0 ).getClass ();
@@ -257,7 +269,7 @@ default <T> Optional<List<T>> getOptionalValues(String propertyName, Class<T> pr
257269 * The returned sources will be sorted by descending ordinal value and name, which can be iterated in a thread-safe
258270 * manner. The {@link java.lang.Iterable Iterable} contains a fixed number of {@linkplain ConfigSource configuration
259271 * sources}, determined at application start time, and the config sources themselves may be static or dynamic.
260- *
272+ *
261273 * @return the configuration sources
262274 */
263275 Iterable <ConfigSource > getConfigSources ();
@@ -291,4 +303,181 @@ default <T> Optional<List<T>> getOptionalValues(String propertyName, Class<T> pr
291303 * If the current provider does not support unwrapping to the given type
292304 */
293305 <T > T unwrap (Class <T > type );
306+
307+ /*
308+ * Tree handling methods
309+ */
310+
311+ /**
312+ * Fully qualified key of this config node (such as {@code server.port}).
313+ * Returns an empty String for root config.
314+ *
315+ * @return key of this config
316+ */
317+ String key ();
318+
319+ /**
320+ * Name of this node - the last element of a fully qualified key.
321+ * <p>
322+ * For example for key {@code server.port} this method would return {@code port}.
323+ *
324+ * @return name of this node
325+ */
326+ String name ();
327+
328+ /**
329+ * Single sub-node for the specified name.
330+ * For example if requested for key {@code server}, this method would return a config
331+ * representing the {@code server} node, which would have for example a child {@code port}.
332+ *
333+ * @param name name of the nested node to retrieve
334+ * @return sub node, never null
335+ */
336+ Config get (String name );
337+
338+ /**
339+ * A detached node removes prefixes of each sub-node of the current node.
340+ * <p>
341+ * Let's assume this node is {@code server} and contains {@code host} and {@code port}.
342+ * The method {@link #key()} for {@code host} would return {@code server.host}.
343+ * If we call a method {@link #key()} on a detached instance, it would return just {@code host}.
344+ *
345+ * @return a detached config instance
346+ */
347+ Config detach ();
348+
349+ /**
350+ * Type of this node.
351+ *
352+ * @return type
353+ */
354+ Type type ();
355+
356+ /**
357+ * Returns {@code true} if the node exists, whether an object, a list, or a
358+ * value node.
359+ *
360+ * @return {@code true} if the node exists
361+ */
362+ default boolean exists () {
363+ return type () != Type .MISSING ;
364+ }
365+
366+ /**
367+ * Returns {@code true} if this configuration node has a direct value.
368+ * <p>
369+ * Example (using properties files) for each node type:
370+ * <p>
371+ * {@link Type#OBJECT} - the node {@code server.tls} is an object node with direct value:
372+ * <pre>
373+ * # this is not recommended, yet it is possible:
374+ * server.tls=true
375+ * server.tls.version=1.2
376+ * server.tls.keystore=abc.p12
377+ * </pre>
378+ * <p>
379+ * {@link Type#LIST} - the node {@code server.ports} is a list node with direct value:
380+ * TODO this may actually not be supported by the spec, as it can only be achieved through properties
381+ * <pre>
382+ * # this is not recommended, yet it is possible:
383+ * server.ports=8080
384+ * server.ports.0=8081
385+ * server.ports.1=8082
386+ * </pre>
387+ * <p>
388+ * {@link Type#VALUE} - the nodes {@code server.port} and {@code server.host} are values
389+ * <pre>
390+ * server.port=8080
391+ * server.host=localhost
392+ * </pre>
393+ *
394+ * @return {@code true} if the node has direct value, {@code false} otherwise.
395+ */
396+ boolean hasValue ();
397+
398+ /**
399+ * Typed value created using a converter function.
400+ * The converter is called only if this config node exists.
401+ *
402+ * @param converter to create an instance from config node
403+ * @param <T> type of the object
404+ * @return converted value of this node, or an empty optional if this node does not exist
405+ * @throws java.lang.IllegalArgumentException if this config node cannot be converted to the desired type
406+ */
407+ <T > Optional <T > as (Function <Config , T > converter );
408+
409+ /**
410+ * Typed value created using a configured converter.
411+ *
412+ * @param type class to convert to
413+ * @param <T> type of the object
414+ * @return converted value of this node, or empty optional if this node does not exist
415+ * @throws java.lang.IllegalArgumentException if this config node cannot be converted to the desired type
416+ */
417+ <T > Optional <T > as (Class <T > type );
418+
419+ /**
420+ * Map to a list of typed values.
421+ * This method is only available if the current node is a {@link org.eclipse.microprofile.config.Config.Type#LIST}
422+ * or if it has a direct value. In case a direct value of type String exists, it expects comma separated elements.
423+ *
424+ * @param type class to convert each element to
425+ * @param <T> type of the object
426+ * @return list of typed values
427+ * @throws java.lang.IllegalArgumentException if this config node cannot be converted to the desired type
428+ */
429+ <T > Optional <List <T >> asList (Class <T > type );
430+
431+ /**
432+ * Contains the (known) config values as a map of key->value pairs.
433+ *
434+ * @return map of sub keys of this config node, or empty if this node does not exist
435+ */
436+ Optional <Map <String , String >> asMap ();
437+
438+ /**
439+ * A list of child nodes.
440+ * In case this node is {@link org.eclipse.microprofile.config.Config.Type#LIST} returns the list in the correct order.
441+ * In case this node is {@link org.eclipse.microprofile.config.Config.Type#OBJECT} returns all direct child nodes
442+ * (in an unknown order)
443+ *
444+ * @return list of child nodes, or empty if this node does not exist
445+ */
446+ Optional <List <Config >> asNodeList ();
447+
448+ /*
449+ * Shortcut helper methods
450+ */
451+ default Optional <String > asString () {
452+ return as (String .class );
453+ }
454+
455+ default Optional <Integer > asInt () {
456+ return as (Integer .class );
457+ }
458+
459+ /**
460+ * Config node type.
461+ */
462+ enum Type {
463+ /**
464+ * Object node with named members and a possible direct value.
465+ */
466+ OBJECT ,
467+ /**
468+ * List node with a list of indexed parameters.
469+ * Note that a list node can also be accessed as an object node - child elements
470+ * have indexed keys starting from {@code 0}.
471+ * List nodes may also have a direct value.
472+ */
473+ LIST ,
474+ /**
475+ * Value node is a leaf node - it does not have any child nodes, only direct value.
476+ */
477+ VALUE ,
478+ /**
479+ * Node is missing, it will return only empty values.
480+ */
481+ MISSING
482+ }
294483}
0 commit comments