You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Goal: Give users more control over how configurations are updated.
The load process currently has the following properties over which developers have little control:
If a configuration file contains a node that does not correspond to some configuration element, this node is simply discarded.
If a node that corresponds to some configuration element is missing in the configuration file, the default value of that configuration element is used.
If a node contains an invalid value or a value that is not supported any longer (e.g. some enum constant), there is no way to replace that value during the loading process.
In many cases, the current behavior is not a problem as users can manually update a configuration file to a newer version. However, it would be convenient for users if this library allowed developers to implement automatic updates for their configurations.
A simple example is the renaming of configuration elements: Currently, if a configuration element (e.g. a class field) of some configuration type is renamed without manually updating the configuration file prior to loading a configuration of that configuration type, the information that was stored in the configuration file for that element is simply lost, as there is no way for developers to access this information during loading.
Implementation-wise, the easiest way to change all three properties listed above is to give developers full access to the Map instance returned by the YAML parser and let them do whatever they want with it. While this solution is easy to implement, it has two major drawbacks: First, accessing (deeply) nested values involves quite a lot of casting. Second, map keys used by developers might not have a mapping even though they appear to have one, possibly causing errors at runtime or confusion at development. The second problem is mostly caused by number types: Because the map instance returned by the YAML parser would, once this feature is implemented, only contain valid target types as map keys (in the case of numbers Long, and Double), a call like, for example map.get(1) would always return null, as 1 is of type int and would, therefore, never have a mapping.
A proper solution would be to transform the Map instance returned by the YAML parser to some internal tree-like or node-based representation and to then give developers access to this representation only. While this might result a clean API that abstracts away the underlying map and remedies the problems mentioned above, implementing such an API requires a lot of effort as major parts of the current implementation of this library would have to be rewritten. Also, the transformation of map instances to such a node-based representation might add a lot of computation and memory overhead at runtime.
A middle way can be reached by providing a small wrapper around the map instance. That wrapper can provide an API for accessing nested values without the need for casting and also support common operations like put or rename for adding or moving values around, respectively.
For example, this new Update-API could introduce a MapView interface whose implementation serves as a wrapper for the Map instance returned by the YAML parser, and a MapViewActions class that contains factories for common operations. These factories could return Consumers which allows chaining them together via the andThen method of the Consumer interface (see second example).
Using these two classes, developers could write a custom Consumer that serves as an update function for a given configuration. Once written, that Consumer could then be passed to this library via a ConfigurationProperties object. For example, for a configuration type that has a configuration element (i.e. a class field or a record component) with name version, the update function could use that field to bring some configuration file up-to-date to the newest version, as shown below.
@Emibergo02 I don't, sorry. Other than writing down my idea and thinking about a suitable API, I haven't started working on this feature yet. I try to spend my time only on things that are requested, but since already two of you would like such an API, I can start working on it these days.
As I'm not sure whether what I've come up with will indeed result in a developer-friendly API, I'd be happy I you guys could provide feedback along the way!
Goal: Give users more control over how configurations are updated.
The
load
process currently has the following properties over which developers have little control:enum
constant), there is no way to replace that value during the loading process.In many cases, the current behavior is not a problem as users can manually update a configuration file to a newer version. However, it would be convenient for users if this library allowed developers to implement automatic updates for their configurations.
A simple example is the renaming of configuration elements: Currently, if a configuration element (e.g. a class field) of some configuration type is renamed without manually updating the configuration file prior to loading a configuration of that configuration type, the information that was stored in the configuration file for that element is simply lost, as there is no way for developers to access this information during loading.
Implementation-wise, the easiest way to change all three properties listed above is to give developers full access to the
Map
instance returned by the YAML parser and let them do whatever they want with it. While this solution is easy to implement, it has two major drawbacks: First, accessing (deeply) nested values involves quite a lot of casting. Second, map keys used by developers might not have a mapping even though they appear to have one, possibly causing errors at runtime or confusion at development. The second problem is mostly caused by number types: Because the map instance returned by the YAML parser would, once this feature is implemented, only contain valid target types as map keys (in the case of numbersLong
, andDouble
), a call like, for examplemap.get(1)
would always returnnull
, as1
is of typeint
and would, therefore, never have a mapping.A proper solution would be to transform the
Map
instance returned by the YAML parser to some internal tree-like or node-based representation and to then give developers access to this representation only. While this might result a clean API that abstracts away the underlying map and remedies the problems mentioned above, implementing such an API requires a lot of effort as major parts of the current implementation of this library would have to be rewritten. Also, the transformation of map instances to such a node-based representation might add a lot of computation and memory overhead at runtime.A middle way can be reached by providing a small wrapper around the map instance. That wrapper can provide an API for accessing nested values without the need for casting and also support common operations like
put
orrename
for adding or moving values around, respectively.For example, this new Update-API could introduce a
MapView
interface whose implementation serves as a wrapper for theMap
instance returned by the YAML parser, and aMapViewActions
class that contains factories for common operations. These factories could returnConsumer
s which allows chaining them together via theandThen
method of theConsumer
interface (see second example).Using these two classes, developers could write a custom
Consumer
that serves as an update function for a given configuration. Once written, thatConsumer
could then be passed to this library via aConfigurationProperties
object. For example, for a configuration type that has a configuration element (i.e. a class field or a record component) with nameversion
, the update function could use that field to bring some configuration file up-to-date to the newest version, as shown below.An API to make version updates easier could additionally be added as part of this new Update-API or in a future release.
The text was updated successfully, but these errors were encountered: