The basic idea here is to let you keep all your configuration knowledge in your configuration object, and to automate as much as possible. Reflection is used to convert public fields and setters on your configuration object into settable vars. There are a few key concepts:
- You should be able to configure absolutely any object.
- Child configuration variables in your config become a dotted hierarchy of varnames
- All sources of configuration data are buffered and merged (as string var/vals) before committing to the final configuration. This class acts as the buffer.
- Hyphenated variables (i.e. "some-var") are automatically configured by calling your matching setter (i.e. setSomeVar)
- Implementing an getSomeVarInfo() method on your class lets you set up more complicated config objects
- You can make variables depend on other variables having been set first. This lets you set a root directory in one var and then use its value in another.
- Per-variable validation can be performed in setters. Overall validation should take place as a post-process step.
- You can keep ConfigurationBuffers around and merge multiple buffers together before committing. Most recent definitions always win.
The contract with your configuration class:
- You must provide a method with the signature "void setYourVar(ConfigurationValue val)" to set your config var. Your setter method should accept either a single arg of type List or String[], or else an arglist of simple types. For example "void myvar(int a, boolean b, String c")".
- You can implement a function with the signature "int yourvar_argcount()" to require a different number of arguments. This limit will be enforced by configurators (command line, file, etc.)
- If you provide a setter and explicit parameters (i.e. not List or String[]) the number of arguments will be automatically determined.
- Each argument to your configuration variable is assumed to have a (potentially non-unique) name. The default is the simple type of the argument (boolean, int, string). If the var takes an undetermined number of args via List or String[], the argname defaults to string.
- You can implement a function with the signature "String yourvar_argnames(int)" to provide names for each of the parameters. The integer passed in is the argument number. Return the same name (i.e. "item") for infinite lists.
- You can implement a function with the signature "String[] yourvar_deps()" to provide a list of other prerequisites for this var. You will be guaranteed that the deps are committed before your var, or else a configurationexception will be thrown if a prerequsite was unset. (Note that infinite cycles are not checked, so be careful.)