| :jbake-type: page |
| :jbake-status: published |
| |
| = Apache Tamaya -- Extension: Collection Support |
| |
| toc::[] |
| |
| [[Optional]] |
| == Tamaya Collection Support (Extension Module) |
| === Overview |
| |
| All configuration in Tamaya is expressed as simple key, value pairs. Nevertheless this concept allows similarly |
| the modelling of collection typed values such as lists, sets, maps or simple collections of things. The Tamaya |
| Collections extension adds this functionality to the Tamaya eco-system. |
| |
| === Compatibility |
| |
| The module is based on Java 7, so it will not run on Java 7 and beyond. |
| |
| |
| === Installation |
| |
| To use Tamaya collection support you only must add the corresponding dependency to your module: |
| |
| [source, xml] |
| ----------------------------------------------- |
| <dependency> |
| <groupId>org.apache.tamaya.ext</groupId> |
| <artifactId>tamaya-collections</artifactId> |
| <version>{tamaya_version}</version> |
| </dependency> |
| ----------------------------------------------- |
| |
| |
| === Overview |
| |
| Tamaya Collections adds +PropertyConverter+ implementations that are able to access configuration data |
| as lists, maps or sets. By default this works out of the box as easy as accessing any other type of |
| configuration data, e.g. |
| |
| [source, java] |
| ----------------------------------------------- |
| Configuration config = ConfigurationProvider.getConfiguration(); |
| |
| // Without any content specification, a list of String is returned. |
| List<String> simpleList = config.get("my.list.config.entry", List.class); |
| |
| // Using a TypeLiteral allows to use every convertible sub type supported by the system. |
| List<Integer> intList = config.get("my.list.config.entry", new TypeLiteral<List<Integer>>(){}); |
| ----------------------------------------------- |
| |
| Configuration in that case, by default, is a simple comma-separated list of entries, e.g. |
| |
| [source, properties] |
| ----------------------------------------------- |
| my.list.config.entry=1,34454,23,344545,3445 |
| ----------------------------------------------- |
| |
| Additionally the module allows adding additional meta-entries, which allows to tweak some of the |
| inner-workings, e.g. |
| |
| * using your own +PropertyConverter+ implementation for parsing entries. |
| * specifying a custom separator String to be used to split the items (default is {{','}}. |
| * specifying a custom separator String to be used to split key/value paris when parsing map entries. |
| * specifying the implementation type of the collection instance to be returned. |
| * specifying if the resulting collection should be returned as a modifiable collection. |
| |
| === Supported Types |
| |
| This module supports the following types: |
| |
| * +java.util.Collection+ |
| * +java.util.List+ |
| * +java.util.ArrayList+ |
| * +java.util.LinkedList+ |
| * +java.util.Set+ |
| * +java.util.SortedSet+ |
| * +java.util.TreeSet+ |
| * +java.util.HashSet+ |
| * +java.util.Map+ |
| * +java.util.SortedMap+ |
| * +java.util.HashMap+ |
| * +java.util.TreeMap+ |
| |
| Hereby the type is determined primarly by the parameter type accessed, e.g. |
| +config.get("mylist", ArrayList.class)+ will always return an +ArrayList+ |
| as result. |
| |
| ==== Configuring the target implementation type |
| |
| Tamaya Collections allows you to configure the target collection type by adding the |
| following meta-configuration entry (shown for the +mylist+ entry). Hereby the package part +java.util.+ |
| can be ommitted: |
| |
| [ source, properties] |
| ----------------------------------------------- |
| mylist=a,b,c |
| _mylist.collection-type=LinkedList |
| ----------------------------------------------- |
| |
| When calling +config.get("mylist", ArrayList.class)+ this parameter does not have any effect, so you will still |
| get an +ArrayList+ as a result. However when you call +config.get("mylist", List.class)+ you will |
| get a +LinkedList+ as implementation type. |
| |
| This mechanism similarly applies to all kind of collections, so you can use it similarly to define the implementation |
| type returned when accessing +List+, +Map+ or +Collection+. |
| |
| |
| === Collecting Configuration Entries instead of Overriding |
| |
| By default Tamaya applies always an overriding +CombinationPolicy+, where only the configuration entry for |
| the most significant configuration entry is used. In case of collections (and maybe also other use cases), |
| overriding is not always the mechanism of choice. E.g. when you want to have all entries added to your |
| configuration to be *combined* to a new entry containing all values provided by any property sources. |
| |
| Therefore Tamaya Collections also provides a more sophistiated +CombinationPolicy+ (automatically configured) |
| that allows to adapt the way how configuration entries are combined. All you must do is declaring |
| the mechanism to be applied by an according meta-configuration parameter, e.g. for +my.list+ your config may |
| look as follows: |
| |
| [source, properties] |
| ----------------------------------------------- |
| # from PropertSource 1 |
| my.list=1,2,3 |
| |
| # from PropertSource 2 |
| my.list=4,5,6 |
| |
| # without any additional meta-info these entries would be combined to |
| my.list=4,5,6 |
| ----------------------------------------------- |
| |
| With Tamaya Collections you can now configure the combination policy as follows: |
| |
| [source, properties] |
| ----------------------------------------------- |
| # use one of the default policies: override / collect |
| _my.list.combination-policy=collect |
| |
| # use an custom CombinationPolicy to combine the values |
| _my.list.combination-policy=com.mycomp.app.MyCombincationPolicy |
| ----------------------------------------------- |
| |
| So declaring the +collect+ policy the resulting raw output of the entry looks as follows: |
| |
| [source, properties] |
| ----------------------------------------------- |
| # result when applying the collect policy: |
| my.list=1,2,3,4,5,6 |
| ----------------------------------------------- |
| |
| The customizable policy mechanism of Tamaya Collections also honors the +item-separator+ meta-configuration |
| parameter explained later in this document. |
| |
| |
| === Format of Collection Configuration |
| |
| By default collections are modelled as simple String values, that are tokenized into individual parts using a |
| defined +item-separator+ (by default +','+). So a given configuration entry of +1,2,3+ is mapped to +"1","2","3". |
| If the target context type is something different than String the smae conversion logic is used as when mapping |
| configuration parameters directly to non-String target types (implemented as +PropertyConverter+ classes, manahed |
| within the current +ConfigurationContext+. The procedure is identical for all collection types, including +Map+ types, |
| with the difference that each token in the list is parsed once more for separating it into a +key+ and a +value+. |
| The default separator for map entries hereby is +"::"+. Map keys, as of now, are always of type +String+, whereas |
| for values the same logic is applied as for non-map collection types. |
| |
| [source, properties] |
| ----------------------------------------------- |
| # a list, using the default format |
| list=1,2,3,4,5,6 |
| |
| # a map, using the default format |
| map=a::b, c::d |
| ----------------------------------------------- |
| |
| ==== Trimming of entries |
| |
| By default all tokens parsed are trimmed _before_ adding them to the final collection. In case of map entries this is |
| also the case for key/value entries. So the following configuration results in the identical values for |
| +list1,list2+ and +map1,map2+: |
| |
| [source, properties] |
| ----------------------------------------------- |
| # a list, using the default format |
| list1=1,2,3,4,5,6 |
| list2=1, 2, 3, 4, 5, 6 |
| |
| # a map, using the default format |
| map1=a::b, c::d |
| map2=a :: b, c :: d |
| ----------------------------------------------- |
| |
| Nevertheless truncation can be controlled by the usage of brackets, e.g. the last list or map entry will have a single |
| space character as value: |
| |
| [source, properties] |
| ----------------------------------------------- |
| # a list, with a ' ' value at the end |
| list3=1, 2, 3, 4, 5, [ ] |
| |
| # a map, with a ' ' value for key '0' |
| map3=1 :: a, 2 :: b, 0::[ ] |
| ----------------------------------------------- |
| |
| Hereby +\[+ escapes the sequence. |
| |
| |
| ==== Customizing the format |
| |
| The item and entry separators (by default +','+ and +"::"+) can be customized by setting corresponding meta-data |
| entries as follows, resulting in the same values as in the prevoius listing: |
| |
| [source, properties] |
| ----------------------------------------------- |
| # a list, with a ' ' value at the end |
| list3=1__2__3__ 4__ 5__[ ] |
| _list3.item-separator=__ |
| |
| # a map, with a ' ' value for key '0' |
| map3=1->a, 2->b, 0->[ ] |
| _map3.map-entry-separator=-> |
| ----------------------------------------------- |
| |
| Of course these settings also can be combined: |
| |
| [source, properties] |
| ----------------------------------------------- |
| # a reformatted map |
| redefined-map=0==none | 1==single | 2==any |
| _redefined-map.map-entry-separator=== |
| _redefined-map.item-separator=| |
| ----------------------------------------------- |