thekid/rfc — Issue #79: RFC 0079: Preferences API
Author: thekid
Created: 2011-10-09 14:55:27+00:00
State: open
Labels: rfc

Scope of Change
====
Type-safe preferences with exchangeable backing storages will be added
as a new API.

Rationale
====
* util.Properties is not type-safe and not checked. Mistakes can easily
go unnoticed.
* Because util.Properties does not provide information about the values
we cannot easily create a generic property editor (without having to
have properties defining the layout of each and every property file).

Functionality
====

Storage
----
Windows:
* Local storage: .\etc\[preferences].ini
* User storage: ${System.Environment.SpecialFolder.LocalApplicationData}\Xp\[preferences].ini
* Per virtualhost: ${WEBROOT}\etc\[preferences.ini]
* System storage: \Path\To\Where\Xp\Is\Installed\etc\[preferences].ini

Un*x:
* Local storage: ./etc/[preferences].ini
* User storage: ~/.xp/[preferences.ini]
* Per virtualhost: ${WEBROOT}/etc/[preferences.ini]
* System storage: /path/to/where/xp/is/installed/etc/[preferences.ini]

```php
getClass());
?>
```

File format
----
The file format is basically modeled after .ini files:

```
; Comment
[section]
string1="value"
string2='value'
int=1
double=0.5
bool1=true ; Comment
bool2=false
class=lang.types.String::class

[lists]
list[]="string"
list[]="string"
list[]="string"

[maps]
map[color]="green"
map[price]=12.99

[object]
category=util.log.LogCategory("default")

```

Encoding
----
File encoding is defined to be `iso-8859-1`. Unicode encodings may
be indicated by placing a Unicode BOM at the beginning of the file.

See also:
* http://de.wikipedia.org/wiki/Byte_Order_Mark
* http://unicode.org/faq/utf_bom.html

Inheritance
----
Sections may inherit other sections:

```
[web]
route[/]=com.example.scriptlet.DefaultRoute::class
route[/rss]=com.example.scriptlet.RssRoute::class

[myweb : web]
route[/pdf]=com.example.my.scriptlet.PdfRoute::class

```

Variables
----
Variables start with a dollar sign and are surrounded by curly braces:

```
[default]
path="${DOCUMENT_ROOT}/../lib" ; Environment variable
coin=${com.example.Coin::$penny} ; Static class member
level=${util.log.LogLevel::INFO} ; Class constant

[v1]
path="${default:path}/v1" ; Reference to other section

[v2 : default]
path="${parent:path}/v2" ; Reference to parent section
extra="${this:path}/extra" ; Reference to this section

```

Programmatic access
----
Modeled after util.Properties with slight improvements

```php
() raises exception if the entry cannot be found
// * read() returns default value if non-existant, default NULL
$string= $p->getString('section', 'string');
$string= $p->readString('section', 'string', 'green');

// Accessors per type
$int= $p->getInt('section', 'int');
$double= $p->getDouble('section', 'double');
$bool= $p->getBool('section', 'bool1');
$class= $p->getXPClass('section', 'class');
$list= $p->getArray('lists', 'list');
$map= $p->getMap('maps', 'map');
$cat= $p->getObject('object', 'category', XPClass::forName('util.log.LogCategory'));;

// Variable expansion
$path= $p->getString('default', 'path');
$penny= $p->getObject('default', 'coin', XPClass::forName('com.example.Coin'));
$level= $p->getInt('default', 'level');

// Accessing by section, saving repetition
$string= $p->getSection('section')->getString('string');
?>
```

Security considerations
====
n/a

Speed impact
====
n/a

Dependencies
====
n/a

Related documents
====
* http://en.wikipedia.org/wiki/INI_file
* http://www.cloanto.com/specs/ini/
* http://www.chaoslizard.org/devel/bohr/wiki/Docs/Ni/FileFormat
* http://search.cpan.org/~jvbsoft/Config-IniFiles-Import-1.100/Import_DE.pod
* http://ini4j.sourceforge.net/
* http://www.codeproject.com/KB/cs/cs_ini.aspx
* http://commons.apache.org/configuration/userguide/user_guide.html

Comments
====