You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2014/12/26 01:56:08 UTC

[1/4] incubator-tamaya git commit: TAMAYA-19: Streamlined API and impl.

Repository: incubator-tamaya
Updated Branches:
  refs/heads/master 0b5d4feef -> a60570e8e


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/design/4_Extensions.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/design/4_Extensions.adoc b/docs/src/main/asciidoc/design/4_Extensions.adoc
new file mode 100644
index 0000000..db949ac
--- /dev/null
+++ b/docs/src/main/asciidoc/design/4_Extensions.adoc
@@ -0,0 +1,841 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+<<<
+[[CoreConcepts]]
+== {name} Core Concepts
+Though {name} is a very powerful and flexible solution there are basically only a few simple core concepts required that build
+the base of all the other mechanisms:
+
+The API contains the following core concepts/artifacts:
+
+* Literal Key/Value Pairs
+* _PropertyProvider:_ is the the SPI for a source that provides configuration data. A +PropertyProvider+
+     hereby defines
+     ** a minimalistic SPI to be implemented by the config data source
+     ** provides data key/value pairs in raw format as String key/values only
+     ** providers should not have any dependencies other than to the datasource
+     ** providers may read context dependent data, but basically providers themselves are not contextual.
+        Context management should be done by the ConfigurationProvider implementation that also is responsible
+        for combining a set of property providers to a Configuration.
+  _Configuration_ is the API that users of Tamaya will see, when they access configuration in raw format. Hereby +Configuration+
+     ** adds type support for non String types
+     ** provides functional extension points (+with,query+)
+     ** allows registering/deregistering of change listeners
+     ** is the entry point for evaluating the current +Configuration+
+     ** each +PropertyProvider+ can be easily converted into a +Configuration+
+     ** allows configuration entries to be injected
+     ** to access configuration _templates_ (annotated interfaces).
+     ** Configuration may support mutability by allowing instances of +ConfigChangeSet+ to be passed.
+* _PropertyProviders_ allows to aggregate different property providers. Hereby property providers are
+  seen as sets, which can be combined to new providers using set styled operations (aggregate, intersect, subtract).
+  This allows to model and create composite container providers, to build up more complex configuration models
+  step by step.
+* _MetaInfo_ is provided by each +Configuration, PropertyProvider+ and describes the configuration/provider and its entries.
+* _Environment_ is the base model for modelling the environment and the accessor for getting the current +Environment+ instance.
+* _Annotations_ a set of annotations allows to configure configuration injection on classes or interface (aka config templates).
+
+The SPI contains the following core concepts/artifacts:
+
+* _Bootstrap_ is the delegate singleton that is used by the framework to resolve components. The effective component
+  loading can be accessed by implementing and registering an instance of +ServiceProvider+ using +java.util.ServiceLoader+.
+* All the singleton used explicitly (+PropertyAdapters,PropertyProviders+ are backed up corresponding API interfaces.
+  To override a singleton's behaviour the corresponding SPI has to be implemented and registered, so it can be loaded
+  by the current +Bootstrap+ setup (by default ServiceLoader based).
+* Also the singleton used implicitly by +Configuration, Environment, Stage+ are backed up corresponding SPI interfaces.
+  To override a singleton's behaviour the corresponding SPI has to be implemented and registered, so it can be loaded
+  by the current +Bootstrap+ setup (by default ServiceLoader based).
+
+This is also reflected in the main parts of the API, which is quite small:
+
+* +org.apache.tamaya+ contains the main abstractions +Configuration, ConfigOperator, ConfigQuery, PropertyAdapter, Stage,
+  Environment, PropertyProvider, MetaInfo+
+* +org.apache.tamaya.spi+ contains the SPI interfaces to be implemented by implementations and the +Bootstrap+ mechanism.
++ +org.apache.tamaya.annot+ contains the annotations defined.
+
+In the implementation are there are additional projects:
+
+* +org.apache.tamaya.core+ contains the core implementation of the API. Deploying it together with the API results in a
+  flexible framework that can be easily used for configuration of different complexity. But out of the box this framework
+  will not do much more than exposing system and environment properties, its power comes when an additional meta-model
+  is defined and deployed. Hereby you can write your own, or use on e of the provided ones (see later).
+* the core part is extended by multiple additional modules
+  ** CDI integration
+  ** Default configuration meta-models and providers for the most common usage scenarios
+    *** standalone applications
+    *** Java EE
+    *** ...
+
+These parts are explained in the following sections. It is recommended that user's of the API read through this part.
+All subsequent parts are building upon this concepts and may be more difficult to understand without having read
+this section.
+
+
+[[APIKeyValues]]
+=== Key/Value Pairs
+
+Basically configuration is a very generic concept. Therefore it should be modelled in a generic way. The most simple
+and similarly most commonly used are simple literal key/value pairs. So the core building block of {name} are key/value pairs.
+You can think of a common +.properties+ file, e.g.
+
+[source,properties]
+.A simple properties file
+--------------------------------------------
+a.b.c=cVal
+a.b.c.1=cVal1
+a.b.c.2=cVal2
+a=aVal
+a.b=abVal
+a.b2=abVal
+--------------------------------------------
+
+Now you can use +java.util.Properties+ to read this file and access the corresponding properties, e.g.
+
+[source,properties]
+.Accessing some properties
+--------------------------------------------
+Properties props = new Properties();
+props.readProperties(...);
+String val = props.getProperty("a.b.c");
+val = props.getProperty("a.b.c.1");
+...
+--------------------------------------------
+
+This looks familiar to most of you. Nevertheless when looking closer to the above key/value pairs,
+there are more concepts in place: looking at the keys +a.b.c+, +a.b.c.1+, +a.b.c.2+, +a+, +a.b+ we
+see that the key names build up a flattened tree structure. So we can define the following:
+
+Given a key +p1.p2.p3.k=value+:
+
+* +p1.p2.p3.k+ is called the _qualified key_
+* +p1.p2.p3+ is the key's _area_
+* the child areas +p1.p2", "p1+ are called _areas_ as well
+* +k+ is the _(unqualified) key_
+
+Given that you can perform some very useful actions:
+
+* you can filter the keys with an area. E.g. in the example before you can query for all keys within the area +a.b.c+
+  and map them to new properties set as follows:
+
+[source,properties]
+.Accessing an area
+--------------------------------------------
+1=cVal1
+2=cVal2
+--------------------------------------------
+
+Similarly accessing the area +a+ results in the following properties:
+
+[source,properties]
+.Accessing the area +a+
+--------------------------------------------
+b=abVal
+b2=abVal
+--------------------------------------------
+
+Additionally you can access all values of an area recursively, so accessing +a+ recursively results in
+the following properties:
+
+[source,properties]
+.Accessing area +a+ recursively
+--------------------------------------------
+b.c=cVal
+b.c.1=cVal1
+b.c.2=cVal2
+b=abVal
+b2=abVal
+--------------------------------------------
+
+Why this is useful? Well there are different use cases:
+
+* you can segregate your configuration properties, e.g. a module can access its module configuration by
+  querying all properties under the area +config.modules.myModule+ (or whatever would be appropriate).
+* you can use this mechanism to configure maps (or more generally: collections).
+* you can easily filter parts of configuration
+* ...and more.
+
+==== Why Using Strings Only
+
+Using Strings as base representation of configuration comes with several huge advantages:
+
+* Strings are simple to understand
+* Strings are human readable and therefore easy to prove for correctness
+* Strings can easily be used within different language, different VMs, files or network communications.
+* Strings can easily be compared and manipulated
+* Strings can easily be searched, indexed and cached
+* It is very easy to provide Strings as configuration, which gives much flexibility for providing configuration in
+  production as well in testing.
+* and more
+
+On the other side there are also disadvantages:
+
+* Strings are inherently not type safe, they do not provide validation out of the box for special types, such as
+numbers,
+  dates etc.
+* Often you want not to work with Strings, but with according types.
+* Strings are not hierarchical, so mapping hierarchical structures requires some extra efforts.
+
+Nevertheless most of these advantages can be mitigated easily, hereby still keeping all the benefits from above:
+
+* Adding type safe converters on top of String allow to add any type easily, that can be directly mapped out of Strings.
+  This includes all common base types such as numbers, dates, time, but also timezones, formatting patterns and more.
+* Even more complex mappings can be easily realized, by using String not as a direct representation of configuration,
+  but a reference that defines where the more complex configuration artifact is available. This mechanism is similarly
+  easy to understand as parsing Strings to numbers, but is powerful enough to provide e.g. all kind of deployment
+  descriptors in Java EE.
+* Hierarchical and collection types can be mapped in different ways:
+** The keys of configuration can have additional syntax/semantics. E.g. when adding dor-separating path semantics
+*** trees/maps can also simply be mapped.
+
+[APIPropertyProviders]
+=== Property Providers
+==== Basic Model
+
+We have seen that constrain configuration aspects to simple literal key/value pairs provides us with an easy to
+understand, generic, flexible, yet expendable mechanism. Looking at the Java language features a +vava.util.Map<String,
+String>+ and +java.util.Properties+ basically model these quite well out of the box.
+So it makes sense to build configuration on top of the JDK's +Map+ interface. This creates immediately additional
+benefits:
+
+* we inherit full Lambda and collection support
+* Maps are widely known and well understood
+
+Nevertheless there are some things to be considered:
+
+* Configuration also requires meta-data, such as
+** the origin of a certain configuration entry and how it was derived from other values
+** the sensitivity of some data
+** the provider that have read the data
+** the time, when the data was read
+** the timestamp, when some data may be outdated
+** ...
+
+Basically the same is also the not related to some single configuration key, but also to a whole map.
+The +PropertyProvider+ interface models exact these aspects and looks as illustrated below:
+
+[source,java]
+.Interface PropertyProvider
+--------------------------------------------
+public interface PropertyProvider{
+
+      Optional<String> get(String key);
+      boolean containsKey(String key);
+      Map<String, String> toMap();
+      MetaInfo getMetaInfo();
+
+      default Set<String> keySet();
+      default ConfigChangeSet load();
+      default boolean isMutable();
+      default void apply(ConfigChangeSet change);
+}
+--------------------------------------------
+
+Hereby
+
+* +getMetaInfo()+ return the meta information for the property provider, as well as for individual property key/value pairs.
+* +get, containsKey, keySet+ look similar to the methods on +Map+, though +get+ uses the +Optional+ type introduced
+  with Java 8. This avoids returning +null+ or throwing exceptions in case no such entry is available and also
+  reduced the API's footprint, since default values can be easily implemented by calling +Optional.orElse+.
+* +isMutable()+ allows to easy check, if a property provider is mutable, which is more elegant than catching
+  +NonSupportedOperation+ exception thrown on the according methods of +Map+.
+* +load()+ finally allows to (re)load a property map. It depends on the implementing source, if this operation
+  has any effect. If the map changes an according +ConfigChange+ must be returned, describing the
+  changes applied.
+* +hasSameProperties+ allows to perform a comparison with another provider.
+* +toMap+ allows to extract thing to a +Map+.
+
+This simple model will be used within the spi, where configuration can be injected/provided from external resources.
+But we have seen, that we have to consider additional aspects, such as extendability and type safety. Therefore we
+extend +PropertyMap+ and hereby also apply the 'composite pattern', which results in the following key abstraction.
+
+==== Meta Information
+
+Each instance also provides an instance of +MetaInfo+, which provides meta information for the providers and its properties:
+
+[source,java]
+.Accessing Meta Information
+--------------------------------------------
+PropertyProvider prov = ...;
+MetaInfo metaInfo = prov.getMetaInfo();
+Set<String> keys = metaInfo.keySet();  // returns the attribute keys, for which meta-information is accessible.
+String metaData = metaInfo.get("a.b.c.value"); // access meta information
+String itemName = metaInfo.getName(); // access meta information for the provider
+--------------------------------------------
+
+As we have seen above there is as well a +MetaInfoBuilder+, which must be used to create instances of
++MetaInfo+.
+
+==== Mutability
+
+Property providers optionally may be mutable. This can be checked by calling +boolean isMutable()+. If a provider
+is mutable a +ConfigChangeSet+ can be passed. This change set can then be applied by the provider. On creation
+of the +ConfigChangeSetBuilder+ a provider can pass version information, so _optimistic locking_ can be implemented
+easily:
+
+[source,java]
+.Creating and applying a +ConfigChangeSet+ to a provider
+--------------------------------------------
+PropertyProvider prov = ...;
+ConfigChangeSet changeSet = ConfigChangeSetBuilder.of(provider)  // creating a default version
+   .remove("key1ToBeRemoved", +key2ToBeRemoved")
+   .put("key2", "key2Value")
+   .put("key3", 12345)
+   .put("key4", 123.45)
+   .build();
+provider.apply(changeSet);
+--------------------------------------------
+
+[[API CombineProviders]]
+==== Combining Property Providers
+
+Looking at the structures of configuration system used by large companies we typically encounter some kind of configuration
+hierarchies that are combined in arbitrary ways. Users of the systems are typically not aware of the complexities in this
+area, since they simply know the possible locations, formats and the overriding policies. Framework providers on the other
+side must face the complexities and it would be very useful if Tamaya can support here by providing prebuilt functionality
+that helps implementing these aspects. All this leads to the feature set of combining property providers. Hereby the following
+strategies are useful:
+
+* aggregating providers, hereby later providers added
+  ** override any existing entries from earlier providers
+  ** combine conflicting entries from earlier providers, e.g. into a comma-separated structure.
+  ** may throw a ConfigExcepotion ig entries are conflicting
+  ** may only add entries not yet defined by former providers, preventing entries that are already present to be overwritte
+  ** any custom aggregation strategy, which may be a mix of above
+* intersecting providers
+* subtracting providers
+* filtering providers
+
+These common functionality is provided by the +PropertyProviders+ singleton. Additionally to the base strategies above a +MetaInfo+
+instance can be passed optionally as well to define the meta information for the newly created provider instances.
+Let's assume we have two property providers with the following data:
+
+[source,properties]
+.Provider 1
+--------------------------------------------
+a=a
+b=b
+c=c
+g=g
+h=h
+i=i
+--------------------------------------------
+
+[source,properties]
+.Provider 2
+--------------------------------------------
+a=A
+b=B
+c=C
+d=D
+e=E
+f=F
+--------------------------------------------
+
+Looking in detail you see that the entries +a,b,c+ are present in both providers, whereas +d,e,f+ are only present in provider 1,
+and +g,h,i+ only in provider 2.
+
+[source,java]
+.Example Combining PropertyProviders
+--------------------------------------------
+PropertyProvider provider1 = ...
+PropertyProvider provider2 = ...
+
+// aggregate, hereby values from provider 2 override values from provider 1
+PropertyProvider unionOverriding = PropertyProviders.aggregate(AggregationPolicy.OVERRIDE(), provider1, provider2);
+System.out.println("unionOverriding: " + unionOverriding);
+
+// ignore duplicates, values present in provider 1 are not overriden by provider 2
+PropertyProvider unionIgnoringDuplicates = PropertyProviders.aggregate(AggregationPolicy.IGNORE_DUPLICATES(), provider1, provider2);
+System.out.println("unionIgnoringDuplicates: " + unionIgnoringDuplicates);
+
+// this variant combines/maps duplicate values into a new value
+PropertyProvider unionCombined = PropertyProviders.aggregate(AggregationPolicy.COMBINE(), provider1, provider2);
+System.out.println("unionCombined: " + unionCombined);
+
+// This variant throws an exception since there are key/value paris in both providers, but with different values
+try{
+    PropertyProviders.aggregate(AggregationPolicy.EXCEPTION(), provider1, provider2);
+}
+catch(ConfigException e){
+    // expected!
+}
+--------------------------------------------
+
+The example above produces the following outpout:
+
+[source,listing]
+.Example Combining PropertyProviders
+--------------------------------------------
+AggregatedPropertyProvider{
+  (name = dynamicAggregationTests)
+  a = "[a][A]"
+  b = "[b][B]"
+  c = "[c][C]"
+  d = "[D]"
+  e = "[E]"
+  f = "[F]"
+  g = "[g]"
+  h = "[h]"
+  i = "[i]"
+}
+unionOverriding: AggregatedPropertyProvider{
+  (name = <noname>)
+  a = "A"
+  b = "B"
+  c = "C"
+  d = "D"
+  e = "E"
+  f = "F"
+  g = "g"
+  h = "h"
+  i = "i"
+}
+unionIgnoringDuplicates: AggregatedPropertyProvider{
+  (name = <noname>)
+  a = "a"
+  b = "b"
+  c = "c"
+  d = "D"
+  e = "E"
+  f = "F"
+  g = "g"
+  h = "h"
+  i = "i"
+}
+unionCombined: AggregatedPropertyProvider{
+  (name = <noname>)
+  a = "a,A"
+  b = "b,B"
+  c = "c,C"
+  d = "D"
+  e = "E"
+  f = "F"
+  g = "g"
+  h = "h"
+  i = "i"
+}
+--------------------------------------------
+
+No +AggregationPolicy+ is also an interface that can be implemented:
+
+[source,java]
+.AggregationPolicy Interface
+--------------------------------------------
+@FunctionalInterface
+public interface AggregationPolicy {
+    String aggregate(String key, String value1, String value2);
+}
+--------------------------------------------
+
+So we can also define our own aggregation strategy using a Lambda expression:
+
+[source,java]
+.Use a Custom AggregationPolicy
+--------------------------------------------
+PropertyProvider provider1 = ...;
+PropertyProvider provider2 = ...;
+PropertyProvider props = PropertyProviders.aggregate(
+      (k, v1, v2) -> (v1 != null ? v1 : "") + '[' + v2 + "]",
+      MetaInfo.of("dynamicAggregationTests"),
+      props1, props2);
+System.out.println(props);
+--------------------------------------------
+
+Additionally we also pass here an instance of +MetaInfo+. The output of this code snippet is as follows:
+
+[source,listing]
+.Listing of dynamic aggregation policy
+--------------------------------------------
+AggregatedPropertyProvider{
+  (name = dynamicAggregationTests)
+  a = "[a][A]"
+  b = "[b][B]"
+  c = "[c][C]"
+  d = "[D]"
+  e = "[E]"
+  f = "[F]"
+  g = "[g]"
+  h = "[h]"
+  i = "[i]"
+}
+--------------------------------------------
+
+Summarizing the +PropertyProviders+ singleton allows to combine providers in various forms:
+
+[source,listing]
+.Methods provided on PropertyProviders
+--------------------------------------------
+public final class PropertyProviders {
+
+    private PropertyProviders() {}
+
+    public static PropertyProvider fromArgs(String... args) {
+    public static PropertyProvider fromArgs(MetaInfo metaInfo, String... args) {
+    public static PropertyProvider fromPaths(AggregationPolicy aggregationPolicy, String... paths) {
+    public static PropertyProvider fromPaths(String... paths) {
+    public static PropertyProvider fromPaths(List<String> paths) {
+    public static PropertyProvider fromPaths(AggregationPolicy aggregationPolicy, List<String> paths) {
+    public static PropertyProvider fromPaths(MetaInfo metaInfo, List<String> paths) {
+    public static PropertyProvider fromPaths(AggregationPolicy aggregationPolicy, MetaInfo metaInfo, List<String> paths) {
+    public static PropertyProvider fromUris(URI... uris) {
+    public static PropertyProvider fromUris(AggregationPolicy aggregationPolicy, URI... uris) {
+    public static PropertyProvider fromUris(List<URI> uris) {
+    public static PropertyProvider fromUris(AggregationPolicy aggregationPolicy, List<URI> uris) {
+    public static PropertyProvider fromUris(MetaInfo metaInfo, URI... uris) {
+    public static PropertyProvider fromUris(AggregationPolicy aggregationPolicy, MetaInfo metaInfo, URI... uris) {
+    public static PropertyProvider fromUris(MetaInfo metaInfo, List<URI> uris) {
+    public static PropertyProvider fromUris(AggregationPolicy aggregationPolicy, MetaInfo metaInfo, List<URI> uris) {
+    public static PropertyProvider fromMap(Map<String, String> map) {
+    public static PropertyProvider fromMap(MetaInfo metaInfo, Map<String, String> map) {
+    public static PropertyProvider empty() {
+    public static PropertyProvider emptyMutable() {
+    public static PropertyProvider empty(MetaInfo metaInfo) {
+    public static PropertyProvider emptyMutable(MetaInfo metaInfo) {
+    public static PropertyProvider fromEnvironmentProperties() {
+    public static PropertyProvider fromSystemProperties() {
+    public static PropertyProvider freezed(PropertyProvider provider) {
+    public static PropertyProvider aggregate(AggregationPolicy mapping, MetaInfo metaInfo, PropertyProvider... providers){
+    public static PropertyProvider aggregate(PropertyProvider... providers) {
+    public static PropertyProvider aggregate(List<PropertyProvider> providers) {
+    public static PropertyProvider aggregate(AggregationPolicy mapping, PropertyProvider... propertyMaps) {
+    public static PropertyProvider aggregate(AggregationPolicy mapping, List<PropertyProvider> providers) {
+    public static PropertyProvider mutable(PropertyProvider provider) {
+    public static PropertyProvider intersected(AggregationPolicy aggregationPolicy, PropertyProvider... providers) {
+    public static PropertyProvider intersected(PropertyProvider... providers) {
+    public static PropertyProvider subtracted(PropertyProvider target, PropertyProvider... providers) {
+    public static PropertyProvider filtered(Predicate<String> filter, PropertyProvider provider) {
+    public static PropertyProvider contextual(Supplier<PropertyProvider> mapSupplier,
+                                              Supplier<String> isolationKeySupplier) {
+    public static PropertyProvider delegating(PropertyProvider mainMap, Map<String, String> parentMap) {
+    public static PropertyProvider replacing(PropertyProvider mainMap, Map<String, String> replacementMap) {
+}
+--------------------------------------------
+
+
+[[API Configuration]]
+=== Configuration
+==== Basic Model
+
+Configuration inherits all basic features from +PropertyProvider+, but additionally adds functionality for
+type safety and extension mechanisms:
+
+[source,java]
+.Interface Configuration
+--------------------------------------------
+public interface Configuration extends PropertyProvider{
+
+    default OptionalBoolean getBoolean(String key);
+    default OptionalInt getInteger(String key);
+    default OptionalLong getLong(String key);
+    default OptionalDouble getDouble(String key);
+    default <T> Optional<T> getAdapted(String key, PropertyAdapter<T> adapter);
+    <T> Optional<T> get(String key, Class<T> type);
+
+    // accessing areas
+    default Set<String> getAreas();
+    default Set<String> getTransitiveAreas();
+    default Set<String> getAreas(final Predicate<String> predicate);
+    default Set<String> getTransitiveAreas(Predicate<String> predicate);
+    default boolean containsArea(String key);
+
+    // extension points
+    default Configuration with(ConfigOperator operator);
+    default <T> T query(ConfigQuery<T> query);
+
+    // versioning
+    default String getVersion(){return "N/A";}
+    void addPropertyChangeListener(PropertyChangeListener l);
+    void removePropertyChangeListener(PropertyChangeListener l);
+
+    // singleton accessors
+    public static boolean isDefined(String name);
+    public static <T> T current(String name, Class<T> template);
+    public static Configuration current(String name);
+    public static Configuration current();
+    public static <T> T current(Class<T> type){
+    public static void configure(Object instance);
+    public static String evaluateValue(String expression);
+    public static String evaluateValue(Configuration config, String expression);
+    public static void addGlobalPropertyChangeListener(PropertyChangeListener listener);
+    public static void removeGlobalPropertyChangeListener(PropertyChangeListener listener);
+}
+--------------------------------------------
+
+Hereby
+
+* +XXX getXXX(String)+ provide type safe accessors for all basic wrapper types of the JDK.
+* +getAdapted+ allow accessing any type, hereby also passing a +PropertyAdapter+ that converts
+  the configured literal value to the type required.
+* +getAreas()+, +getTransitiveAreas()+ allow to examine the hierarchical tree modeled by the configuration tree.
+  Optionally also predicates can be passed to select only part of the tree to be returned.
+* +containsArea+ allows to check, if an area is defined.
+* +with, query+ provide the extension points for adding additional functionality.
+
+* the static accessor methods define:
+  ** +current(), current(Class), current(String), current(String, Class)+ return the configuration valid for the current runtime environment.
+  ** +addPropertyChangeListener, removePropertyChangeListener+ allow to register or unregister
+     global config change listener instances.
+  ** evaluateValue allows to evaluate a configuration expression based on a given configuration.
+  ** +configure+ performs injection of configured values.
+
+[[TypeConversion]]
+==== Type Conversion
+
+Configuration extend +PropertyProvider+ and add additional support for non String types. This is achieved
+with the help of +PropertyAdapter+ instances:
+
+[source,java]
+.PropertyAdapter
+--------------------------------------------
+@FunctionalInterface
+public interface PropertyAdapter<T>{
+    T adapt(String value);
+}
+--------------------------------------------
+
+PropertyAdapter instances can be implemented manually or registered and accessed from the
++PropertyAdapers+ singleton. Hereby the exact mechanism is determined by the API backing up the singleton.
+By default corresponding +PropertyAdapter+ instances can be registered using the Java +ServiceLoader+
+mechanism, or programmatically ba calling the +register(Class, PropertyAdapter)+ method.
+
+[source,java]
+--------------------------------------------
+public final class PropertyAdapters{
+    public static <T> PropertyAdapter<T> register(Class<T> targetType, PropertyAdapter<T> adapter);
+    public static boolean isTargetTypeSupported(Class<?> targetType);
+    public static  <T> PropertyAdapter<T> getAdapter(Class<T> targetType);
+    public static  <T> PropertyAdapter<T> getAdapter(Class<T> targetType, WithPropertyAdapter annotation);
+}
+--------------------------------------------
+
+Whereas this mechanism per se looks not very useful it's power shows up when combining it with the annotations
+API provided, e.g. look at the following annotated class:
+
+[source,java]
+.Annotated Example Class
+--------------------------------------------
+public class ConfiguredClass{
+
+    @ConfiguredProperty
+    private String testProperty;
+
+    @ConfiguredProperty("a.b.c.key1")
+    @DefaultValue("The current \\${JAVA_HOME} env property is ${env:JAVA_HOME}.")
+    String value1;
+
+    @ConfiguredProperty("a.b.c.key2")
+    private int value2;
+
+    @ConfiguredProperty
+    @DefaultValue("http://127.0.0.1:8080/res/api/v1/info.json")
+    private URL accessUrl;
+
+    @ConfiguredProperty
+    @DefaultValue("5")
+    private Integer int1;
+
+    @ConfiguredProperty("a.b.customType")
+    private MyCustomType myCustomType;
+
+    @ConfiguredProperty("BD")
+    private BigDecimal bigNumber;
+
+    ...
+}
+--------------------------------------------
+
+The class does not show all the possibilities that are provided, but it shows that arbitrary types can be supported easily.
+This applied similarly to collection types, whereas collections are more advanced and therefore described in a separate section
+later.
+
+Given the class above and the current configuration can provide the values required, configuring an instance of the
+class is simple:
+
+[source,java]
+.Configuring the Example Class
+--------------------------------------------
+ConfiguredClass classInstance = new ConfiguredClass();
+Configuration.configure(configuredClass);
+--------------------------------------------
+
+Additional types can transparently be supported by implementing and registering corresponding SPI instances. This is explained
+in the SPI documentation of {name}.
+
+==== Extension Points
+
+We are well aware of the fact that this library will not be able to cover all kinds of use cases. Therefore
+we have added similar functional extension mechanisms that were used in other areas of the Java eco-system as well:
+
+* +ConfigOperator+ define unary operations on +Configuration+. They can be used for filtering, implementing
+  configuration views, security interception etc.
+* +ConfigQuery+ defines a function returning any kind of result based on a configuration instance. Typical
+  use cases of queries could be the implementation of configuration SPI instances that are required
+  by other libraries or frameworks.
+
+Both interfaces hereby are defined as functional interfaces:
+
+[source,java]
+.ConfigOperator and ConfigQuery
+--------------------------------------------
+@FunctionalInterface
+public interface ConfigOperator{
+    Configuration operate(Configuration config);
+}
+
+@FunctionalInterface
+public interface ConfigQuery<T>{
+    T query(Configuration config);
+}
+--------------------------------------------
+
+Both interfaces can be applied on a +Configuration+ instance:
+
+[source,java]
+.Applying Config operators and queries
+--------------------------------------------
+Configuration secured = Configuration.of().apply(ConfigSecurity::secure);
+ConfigSecurity securityContext = Configuration.of().query(ConfigSecurity::targetSecurityContext);
+--------------------------------------------
+
+NOTE: +ConfigSecurity+ is an arbitrary class.
+
+=== Configuration Injection
+
+The +Configuration+ interface provides static methods that allow to anykind of instances be configured
+ny just passing the instances calling +Configuration.configure(instance);+. The classes passed hereby must
+be annotated with +@ConfiguredProperty+ to define the configured properties. Hereby this annotation can be
+used in multiple ways and combined with other annotations such as +@DefaultValue+,
++@WithLoadPolicy+, +@WithConfig+, +@WithConfigOperator+, +@WithPropertyAdapter+.
+
+To illustrate the mechanism below the most simple variant of a configured class is given:
+
+[source,java]
+.Most simple configured class
+--------------------------------------------
+pubic class ConfiguredItem{
+  @ConfiguredProperty
+  private String aValue;
+}
+--------------------------------------------
+
+When this class is configured, e.g. by passing it to +Configuration.configure(Object)+,
+the following is happening:
+
+* The current valid +Configuration+ is evaluated by calling +Configuration cfg = Configuration.of();+
+* The current property value (String) is evaluated by calling +cfg.get("aValue");+
+* if not successful, an error is thrown (+ConfigException+)
+* On success, since no type conversion is involved, the value is injected.
+* The configured bean is registered as a weak change listener in the config system's underlying
+  configuration, so future config changes can be propagated (controllable by applying the
+  +@WithLoadPolicy+ annotation).
+
+In the next example we explicitly define the property value:
+[source,java]
+--------------------------------------------
+pubic class ConfiguredItem{
+
+  @ConfiguredProperty
+  @ConfiguredProperty("a.b.value")
+  @configuredProperty("a.b.deprecated.value")
+  @DefaultValue("${env:java.version}")
+  private String aValue;
+}
+--------------------------------------------
+
+Within this example we evaluate multiple possible keys. Evaluation is aborted if a key could be successfully
+resolved. Hereby the ordering of the annotations define the ordering of resolution, so in the example above
+resolution equals to +"aValue", "a.b.value", "a.b.deprecated.value"+. If no value could be read
+from the configuration, it uses the value from the +@DefaultValue+ annotation. Interesting here
+is that this value is not static, it is evaluated by calling +Configuration.evaluateValue(Configuration, String)+.
+
+=== Environment
+
+The environment basically is also a kind of property/value provider similar to +System.getProperties()+ and +System
+.getenv()+ in the JDK. Nevertheless it provides additional functionality:
+
+[source,java]
+.Interface Environment
+--------------------------------------------
+public interface Environments {
+
+    String getEnvironmentType();
+    String getEnvironmentId();
+    Environment getParentEnvironment();
+
+    Optional<String> get(String key);
+    boolean containsKey(String key);
+    Set<String> keySet();
+    Map<String,String> toMap();
+
+    public static Environment current(){
+    public static Environment getRootEnvironment(){
+    public static List<String> getEnvironmentTypeOrder(){
+    public static List<String> getEnvironmentHierarchy(){
+    public static Optional<Environment> getInstance(String environmentType, String contextId){
+    public static Set<String> getEnvironmentContexts(String environmentType){
+    public static boolean isEnvironmentActive(String environmentType){
+--------------------------------------------
+
+* environments are hierarchical. Hereby all environments inherit from the root environment. The root environment
+  hereby must contain
+  ** all JDK's system properties, with same keys, values
+  ** all JDK's environment properties, prefixed with +env:+.
+  ** additional root properties are allowed as well.
+* the root environment is always directly accessible by calling +Environment.getRootEnvironment()+
+* the current environment can be accessed by calling +Environment.of()+.
+* each environment also defines a +Stage+ (implementing +StageSupplier+). Hereby, if not set explicitly the +Stage+ is inherited from the root
+  environment. Consequently the root environment must provide a +Stage+, which by default is +Stage.development()+.
+
+Additionally each environment instance is uniquely identified by the environment type (accessible from
++getEnvironmentType()+ and the environment id (accessible from +getEnvironmentId()+). So it is possible to access
+an +Environment+ by calling +of(String environmentType, String environmentId)+. Implementations may restrict access
+to environments depending on the current runtime environment (runtime context) active. The API does
+not require further aspects.
+
+The call to +getEnvironmentIds(String)+ returns all context ids of the known +Environment+ instances
+of a given type. E.g. assuming there is an environment type +war+ calling +Environment.getEnvironmentIds("war")+
+may return +"/web/app1", "/web/app2"+ (assuming the war context ids equal the web applications root contexts).
+
+All environments are basically ordered. The ordering can be accessed by calling +getEnvironmentTypeOrder()+. Hereby
+not every environment type in a hierarchy must necessarily present. This is reflected by +getEnvironmentHierarchy()+
+which returns the environment type ids in order, but only containing the types of the environments
+currently present and accessible in the hierarchy. As an example an environment type order in an advanced
+use case could be something like +"root","ear","war","saas","user"+, whereas the concrete environment type hierarchy
+may be +"root","war","saas"+, because the application was not included
+in an additional ear archive and no user is currently active (anonymous). The call to +isEnvironmentActive(String)+
+allows to determine if an environment of the given type is currently active.
+Finally the environment hierarchy is of course similarly reflected by the relationship (+getParentEnvironment()+).
+The following code should illustrate some of these concepts:
+
+[source,java]
+.Interface Environment
+--------------------------------------------
+List<String> envHierarchy = Environment.getEnvironmentHierarchy();
+  // -> "root","war","saas"
+Environment env = Environment.of();
+System.out.println(env.getEnvironmentContext()); // saas
+System.out.println(env.getEnvironmentId());      // mysolution_pro
+env = env.getParentEnvironment();
+System.out.println(env.getEnvironmentContext()); // war
+System.out.println(env.getEnvironmentId());      // pro
+env = env.getParentEnvironment();
+System.out.println(env.getEnvironmentContext()); // root
+System.out.println(env.getEnvironmentId());      // system
+env = env.getParentEnvironment();
+// env is null now!
+--------------------------------------------
+
+

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/combine-configs.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/combine-configs.adoc b/docs/src/main/asciidoc/usecases/se/combine-configs.adoc
new file mode 100644
index 0000000..2d83ab7
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/combine-configs.adoc
@@ -0,0 +1,14 @@
+=== Combine Configurations
+
+Users want to be able to combine different configurations to a new configuration instance.
+Hereby the resulting configuration can be
+
+* a union of both, ignoring duplicates (and optionally log them)
+* a union of both, duplicates are ignored
+* a union of both, conflicts are thrown as ConfigException
+* an intersection of both, containing only keys present and equal in both configurations
+* an arbitrary mapping or filter, modelled by an +CombinationPolicy+, which basically can be modelled
+  as +BiFunction<String, String, String>+, hereby
+  ** a result of +null+ will remove the key
+  ** any other result will use the value returned as final value of the combination.
+

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/context-dependent-configuration.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/context-dependent-configuration.adoc b/docs/src/main/asciidoc/usecases/se/context-dependent-configuration.adoc
new file mode 100644
index 0000000..737232f
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/context-dependent-configuration.adoc
@@ -0,0 +1,7 @@
+=== Context Dependent Configuration
+
+In multi tenancy setups or complex systems a hierarchical/graph model of contexts for configurations is required, or different runtime contexts are executed in parallel
+within the same VN. What sounds normal for EE also may be the case for pure SE environments:
+
+* Users want to be able to model different layers of runtime context
+* Users want to identiofy the current layer, so configuration used may be adapted.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/dynamic-provisioning.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/dynamic-provisioning.adoc b/docs/src/main/asciidoc/usecases/se/dynamic-provisioning.adoc
new file mode 100644
index 0000000..2facc67
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/dynamic-provisioning.adoc
@@ -0,0 +1,17 @@
+=== Dynamic Provisioning (UC8)
+
+In Cloud Computing, especially the PaaS and SaaS areas a typical use case would be that an application (or server)
+is deployed, configured and started dynamically. Typically things are controlled by some "active controller components",
+which are capable of
+* creating new nodes (using IaaS services)
+* deploying and starting the required runtime platform , e.g. as part of a PaaS solution.
+* deploying and starting the application modules.
+
+All these steps require some kind of configuration. As of today required files are often created on the target node
+before the systems are started, using proprietary formats and mechanism. Similarly accessing the configuration in place
+may require examining the file system or using again proprietary management functions. Of course, a configuration
+solution should not try to solve that, but it can provide a significant bunch of functionality useful in such scenarios:
+
+* provide remote capabilities for configuration
+* allow configuration to be updated remotely.
+* allow client code to listen for configuration changes and react as needed.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/external-configuration.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/external-configuration.adoc b/docs/src/main/asciidoc/usecases/se/external-configuration.adoc
new file mode 100644
index 0000000..ea2e687
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/external-configuration.adoc
@@ -0,0 +1,6 @@
+=== External Configuration
+
+Users want to be able to replace, override, extend or adapt any parts or all of an existing configuration from
+external sources.
+This also must be the case for multi-context environments, where the context identifiers are
+the only way to link to the correct remote configuration.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/formats.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/formats.adoc b/docs/src/main/asciidoc/usecases/se/formats.adoc
new file mode 100644
index 0000000..7383b0d
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/formats.adoc
@@ -0,0 +1,7 @@
+=== Configuration Formats
+
+Users want to be able to use the format they prefer.
+* properties, xml-properties and ini-format should be supported by default
+* Other/custom formats should be easily addable by registering or providing the format on configuration evaluation (read).
+* When possible Tamaya should figure out which format to be used and how the InputStream should be correctly
+  interpreted.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/injection.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/injection.adoc b/docs/src/main/asciidoc/usecases/se/injection.adoc
new file mode 100644
index 0000000..4468d6c
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/injection.adoc
@@ -0,0 +1,31 @@
+=== Configuration Injection
+
+Users want to be able to polulate configured items by injecting configured values. Hereby
+
+* the lifecycle of the instances is not managed by Tamaya
+* all references to items configured are managed as weak references, to prevent memoryleaks.
+* Injection should if possible evaluate the properties by defaults. Even properties without
+  any annotations are possible.
+* Users expect to exclude certain properties from calculation
+* Beside injection of properties it is also possible to call setter methods with one parameter similarly.
+* Basically injection is performed, when the instance is passed to the Tamaya configuration system. It should also
+  be possible to inject/provide final values, especially Strings. Changes on configured values should be
+  reflected in the current value. Setters methods similarly can be called again, with the new values, on changes.
+* Users expect to control dynamic values and recall of setter methods, basically the following strategies should be
+  supported:
+  ** inject only once and ignore further changes.
+  ** reinject/reinitialize on each change
+
+* Dynamic Values can easily be modeled as +ConfiguredValue+ instances, which should have the following functionality:
+  ** access the current value
+  ** access the new value
+  ** access the latest value access time in ms
+  ** access the latest value update time in ms
+  ** evaluate easily if the value has changed since the last access
+  ** accept the change
+  *** as a shortcut it should be possible to accept the change on access of the value implicitly, hereby always accessing
+      the latest valid value.
+  ** ignore the change
+  ** register +Consumer<DynamicValue>+ liasteners to listen on the changes (ans also removing them later again).
+
+All observing functionality can be done completely asynchronously and in parallel.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/java8.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/java8.adoc b/docs/src/main/asciidoc/usecases/se/java8.adoc
new file mode 100644
index 0000000..fe892cb
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/java8.adoc
@@ -0,0 +1,13 @@
+=== Java 8 Functional Support
+
+Users want to be able to benefit from the new programming styles introduced with Java 8. Configuration
+should provide extension points for different aspects, where additional code can be hooked in easily.
+In short: were possible functional interfaces should be modelled.
+
+Examples:
+* code that converts a configuration to another kind of configuration: +UnaryOperator<Configuration>+
+* code that creates any kind of result based on a configuration: +Function<Configuration,T>+
+* Adapters for type conversion are defined as +Function<String,T>+
+* Key, value filters ccan be modelled as +BiFunction<String,String,String>+
+* etc.
+

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/locations.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/locations.adoc b/docs/src/main/asciidoc/usecases/se/locations.adoc
new file mode 100644
index 0000000..f18d7f6
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/locations.adoc
@@ -0,0 +1,9 @@
+=== Configuration Locations
+
+Users want to be able to
+* read configuration from different locations.
+* By default classpath and file resources are
+  supported. But similarly remote access using a JSON ReST call should be possible.
+* Tamaya should define a JSON and XML format for configuration.
+* Configuration locations should be scannable using ant-styled resource patterns, if possible.
+* Scanning and reading logic can be modularized by using a +ConfigReader+ interface.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/management.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/management.adoc b/docs/src/main/asciidoc/usecases/se/management.adoc
new file mode 100644
index 0000000..ff997a5
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/management.adoc
@@ -0,0 +1,7 @@
+=== MX/ReST Management
+
+Users want to be have comprehensive management support, which should allow
+
+* to change configuration
+* to remove configuration
+* to view configuration and its provider details
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/minimal-propertysource.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/minimal-propertysource.adoc b/docs/src/main/asciidoc/usecases/se/minimal-propertysource.adoc
new file mode 100644
index 0000000..ee185a0
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/minimal-propertysource.adoc
@@ -0,0 +1,6 @@
+=== Minimal Property Source SPI
+
+Users expect that implementing an additional configuration property source is as easy as possible.
+So there should be an SPI defined that allows any kind of data source to be used for providing configuration data.
+The interface to be implemented is expected to be minimal to reduce the implementation burden. Default
+methods should be used where possible, so only a few methods are expected to be required to implement.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/multiple-configurations.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/multiple-configurations.adoc b/docs/src/main/asciidoc/usecases/se/multiple-configurations.adoc
new file mode 100644
index 0000000..2ee133f
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/multiple-configurations.adoc
@@ -0,0 +1,14 @@
+=== Multiple Configurations
+
+When systems grow they must be modularized to keep control. Whereas that sounds not really fancy, it leads to additional
+aspects to be considered by a configuration system.
+
+* Different code modules, libraries, plugins or products want to have their "own" separated configuration.
+* Similar it should be possible to add fully specific additional configurations.
+
+The default configuration hereby should always be present, whereas additional configurations are optional.
+Users want to be able to check the availability of such an additional configuration.
+
+Of course, additional configuration must be identifiable. The best way to do is to be discussed, nevertheless the
+mechanism must not depend on Java EE and the identifying keys must be serializable easily.
+Basically simple names are sufficient and woukld provide exact this required functionality.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/scannable-properties.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/scannable-properties.adoc b/docs/src/main/asciidoc/usecases/se/scannable-properties.adoc
new file mode 100644
index 0000000..e2a6b64
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/scannable-properties.adoc
@@ -0,0 +1,4 @@
+=== Scannable Properties
+
+If possible configuration should be scannable, meaning it should be possible to evaluate the keys available.
+The corresponding capabilities should be accessible by a +isScannable()+ method.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/service-context.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/service-context.adoc b/docs/src/main/asciidoc/usecases/se/service-context.adoc
new file mode 100644
index 0000000..31ffaaa
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/service-context.adoc
@@ -0,0 +1,14 @@
+=== Adaptable Service Context
+
+Tamaya should support an adaptable +ServiceContext+ to resolve any kind of implememntation services, both API services as core
+framework services. The +ServiceContext+ should be dynamically replecable by configuring an alternate instance of
+using the Java *ServiceContet+.
+This decouples component usage from its load and management part and als greatly simplifies integration with
+new/alternate runtime environments.
+The service context is exptected to provide
+
+* single singleton instances: these service can be cached.
+* access to multiple instances which implement some commons SPI interface.
+* as useful priorization of components is done by the model itself.
+
+

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/simple-access.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/simple-access.adoc b/docs/src/main/asciidoc/usecases/se/simple-access.adoc
new file mode 100644
index 0000000..bc1bf59
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/simple-access.adoc
@@ -0,0 +1,18 @@
+=== Simple Access
+
+Users want to be able to access configuration in a unified way both in SE and EE. EE may provide additional
+mechanism, such as injection, but the SE mechanisms should work as well, so any code written in SE is fully
+portable to EE as well.
+This can only be achieved by providing a static accessor, e.g.
+
+Configuration config = Configuration.current();
+
+The call above should work exactly the same in EE. To enable this the static call must be delegated in the
+internals of the singleton, depending on the runtime. In EE the executing component can behave contextually,
+or even be loaded within the CDI environment (at least for post loading, application runtime aspects, but not earlier).
+
+Additionally in EE it should also be possible to inject Configuration, which gives you the same results as the call
+above:
+
+@Inject
+private Configuration cfg;

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/simple-property-access.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/simple-property-access.adoc b/docs/src/main/asciidoc/usecases/se/simple-property-access.adoc
index 32c2389..81fb879 100644
--- a/docs/src/main/asciidoc/usecases/se/simple-property-access.adoc
+++ b/docs/src/main/asciidoc/usecases/se/simple-property-access.adoc
@@ -1,2 +1,9 @@
 === Simple Lookup of Properties
 
+Users just want to create a configuration ad hoc, from given property files. The
+files could be locally in the file system, on the classpath.
+
+Tamaya should provide a simple Java API for accessing key/value based configuration. Hereby users want to access
+properties as simple String values.
+
+Hereby returning Java 8 Optional values must be considered as well, instead of returning +null+.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/templates.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/templates.adoc b/docs/src/main/asciidoc/usecases/se/templates.adoc
new file mode 100644
index 0000000..0aff6c3
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/templates.adoc
@@ -0,0 +1,11 @@
+=== Configuration Templates
+
+Users want to be able to let Tamaya implement an interface template based on configuration.
+This use case is pretty similar to the injection use case. Basically the values are not injected,
+but cached within the template proxy returned, e.g. as +DynamicValue+.
+Similarly it could even be possible to define callback methods (default methods)
+or register listeners to DynamicValue instances returned.
+
+Templates hereby can easily be managed, but provide a excellent mechanism to provide type-safe configuration
+to clients in a very transparent way. Details can be controlled by using the same annotations as for
+normal configuration injection.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/type-safe-properties.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/type-safe-properties.adoc b/docs/src/main/asciidoc/usecases/se/type-safe-properties.adoc
new file mode 100644
index 0000000..e71d31c
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/type-safe-properties.adoc
@@ -0,0 +1,10 @@
+=== Type Safe Properties
+
+Users just want to access properties not only as Strings, but let Tamaya do the conversion to the required
+or the configred target type. By defauklt all java.lang wrapper and primitive types should be supported, but also
+other common types like date/time types, math numeric types and more.
+
+It must be possible that users can register their own custom types.
+
+Finally users also want to be able to dynamically provide or override type adaption (conversion), when reading a value,
+for a certain key/value pair.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/se/value-placeholders.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/se/value-placeholders.adoc b/docs/src/main/asciidoc/usecases/se/value-placeholders.adoc
new file mode 100644
index 0000000..57857a8
--- /dev/null
+++ b/docs/src/main/asciidoc/usecases/se/value-placeholders.adoc
@@ -0,0 +1,8 @@
+=== Value Placeholders
+
+Users just want to to be able to add placeholders to the values of configuration (not the keys). The mechanisms for
+resolving the placeholders hereby should be not constraint to one single lanmguage like EL. Instead of different
+replacement strategies should be selectable, e.g. by prefixing an expression with the name of the resolver that
+should do the work (eg +"blabla ${env:HOME} using Java version ${sys:java.version}."+.
+This allows resolution mechanism to be isolated easily and also allows to use simpler mechanisms, if no more complex
+ones like EL are required. This is especially useful to deal with low resource environment like ME.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/usecases/usecases.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/usecases/usecases.adoc b/docs/src/main/asciidoc/usecases/usecases.adoc
index b3bad6b..3fd8ef2 100644
--- a/docs/src/main/asciidoc/usecases/usecases.adoc
+++ b/docs/src/main/asciidoc/usecases/usecases.adoc
@@ -24,4 +24,23 @@ toc::[]
 
 == Use Cases for Java SE Environments
 
+include::se/simple-access.adoc[]
 include::se/simple-property-access.adoc[]
+include::se/value-placeholders.adoc[]
+include::se/type-safe-properties.adoc[]
+include::se/templates.adoc[]
+include::se/java8.adoc[]
+include::se/locations.adoc[]
+include::se/formats.adoc[]
+include::se/multiple-configurations.adoc[]
+include::se/external-configuration.adoc[]
+include::se/context-dependent-configuration.adoc[]
+include::se/dynamic-provisioning.adoc[]
+include::se/minimal-propertysource.adoc[]
+include::se/scannable-properties.adoc[]
+include::se/combine-configs.adoc[]
+include::se/management.adoc[]
+include::se/service-context.adoc[]
+include::se/injection.adoc[]
+
+


[2/4] incubator-tamaya git commit: TAMAYA-19: Streamlined API and impl.

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/design/3_Core.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/design/3_Core.adoc b/docs/src/main/asciidoc/design/3_Core.adoc
new file mode 100644
index 0000000..90794be
--- /dev/null
+++ b/docs/src/main/asciidoc/design/3_Core.adoc
@@ -0,0 +1,356 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+<<<
+[[Core]]
+== Tamaya Core
+=== Overview
+
+Tamaya Core provides an implementation of the Tamaya Configuration API and adds additional functionality and
+building blocks for supporting SPI implementations.
+
+Tamaya Core contains the following artifacts:
+
+* +DefaultConfigurationSpi, DefaultPropertyAdapterSpi+ implement the main API interfaces, backing up +Configuration+ and
+  +PropertyAdapter+
+* tbd
+
+The SPI contains the following core concepts/artifacts:
+
+* tbd
+
+* +org.apache.tamaya.core+ contains the main abstractions +Configuration, ConfigQuery, PropertyAdapter,
+  PropertySource+
+* +org.apache.tamaya.core.spi+ contains the SPI interfaces to be implemented by implementations and the +ServiceContext+ mechanism.
+
+
+[[CorePropertyAdapterSpi]]
+=== PropertyAdapter (PropertyAdapterSpi) Implementation
+
+tbd
+
+[[CoreConfigurationSpi]]
+=== Configuration (ConfigurationSpi) Implementation
+
+tbd
+
+
+[[Core ConfigurationBuilder]]
+=== Building Simple Configuration
+
+Looking at the structures of configuration system used by large companies we typically encounter some kind of configuration
+hierarchies that are combined in arbitrary ways. Users of the systems are typically not aware of the complexities in this
+area, since they simply know the possible locations, formats and the overriding policies. Framework providers on the other
+side must face the complexities and it would be very useful if Tamaya can support here by providing prebuilt functionality
+that helps implementing these aspects. All this leads to the feature set of combining property sources. Hereby the following
+strategies are useful:
+
+* aggregating configurations, hereby later configurations added
+  ** override any existing entries from earlier configurations
+  ** combine conflicting entries from earlier configurations, e.g. into a comma-separated structure.
+  ** may throw a ConfigException ig entries are conflicting
+  ** may only add entries not yet defined by former providers, preventing entries that are already present to be overwrite
+  ** any custom aggregation strategy, which may be a mix of above
+* intersecting configurations
+* subtracting configurations
+* filtering configurations
+
+These common functionality is provided by +ConfigurationBuilder+ instances. Additionally to the base strategies above a
++MetaInfo+ instance can be passed optionally as well to define the meta information for the newly created configuration.
+Let's assume we have two configurations with the following data:
+
+[source,properties]
+.Configuration 1
+--------------------------------------------
+a=a
+b=b
+c=c
+g=g
+h=h
+i=i
+--------------------------------------------
+
+[source,properties]
+.Configuration 2
+--------------------------------------------
+a=A
+b=B
+c=C
+d=D
+e=E
+f=F
+--------------------------------------------
+
+Looking in detail you see that the entries +a,b,c+ are present in both configurations, whereas +d,e,f+ are only present in Configuration 1,
+and +g,h,i+ only in Configuration 2.
+
+[source,java]
+.Example Combining Configurations
+--------------------------------------------
+Configuration cfg1 = ...
+Configuration cfg2 = ...
+
+// aggregate, hereby values from Configuration 2 override values from Configuration 1
+Configuration unionOverriding = ConfigurationBuilder.of().aggregate(cfg1, cfg2).build();
+System.out.println("unionOverriding: " + unionOverriding);
+
+// ignore duplicates, values present in Configuration 1 are not overriden by Configuration 2
+Configuration unionIgnoringDuplicates = ConfigurationBuilder.of()
+                       .withAggregationPolicy(AggregationPolicy.IGNORE_DUPLICATES).aggregate(cfg1, cfg2).build();
+System.out.println("unionIgnoringDuplicates: " + unionIgnoringDuplicates);
+
+// this variant combines/maps duplicate values into a new value
+Configuration unionCombined = ConfigurationBuilder.of().withAggregationPolicy(AggregationPolicy.COMBINE)
+                       .aggregate(cfg1, cfg2);
+System.out.println("unionCombined: " + unionCombined);
+
+// This variant throws an exception since there are key/value paris in both providers, but with different values
+try{
+    ConfigurationBuilder.of().withAggregationPolicy(AggregationPolicy.EXCEPTION).aggregate(provider1, provider2)
+                       .build();
+}
+catch(ConfigException e){
+    // expected!
+}
+--------------------------------------------
+
+The example above produces the following outpout:
+
+[source,listing]
+.Example Combining Configurations
+--------------------------------------------
+AggregatedConfiguration{
+  (name = dynamicAggregationTests)
+  a = "[a][A]"
+  b = "[b][B]"
+  c = "[c][C]"
+  d = "[D]"
+  e = "[E]"
+  f = "[F]"
+  g = "[g]"
+  h = "[h]"
+  i = "[i]"
+}
+unionOverriding: AggregatedConfigurations{
+  (name = <noname>)
+  a = "A"
+  b = "B"
+  c = "C"
+  d = "D"
+  e = "E"
+  f = "F"
+  g = "g"
+  h = "h"
+  i = "i"
+}
+unionIgnoringDuplicates: AggregatedConfigurations{
+  (name = <noname>)
+  a = "a"
+  b = "b"
+  c = "c"
+  d = "D"
+  e = "E"
+  f = "F"
+  g = "g"
+  h = "h"
+  i = "i"
+}
+unionCombined: AggregatedConfigurations{
+  (name = <noname>)
+  a = "a,A"
+  b = "b,B"
+  c = "c,C"
+  d = "D"
+  e = "E"
+  f = "F"
+  g = "g"
+  h = "h"
+  i = "i"
+}
+--------------------------------------------
+
+No +AggregationPolicy+ is also a functional interface that can be implemented:
+
+[source,java]
+.AggregationPolicy Interface
+--------------------------------------------
+@FunctionalInterface
+public interface AggregationPolicy {
+    String aggregate(String key, String value1, String value2);
+}
+--------------------------------------------
+
+So we can also define our own aggregation strategy using a Lambda expression:
+
+[source,java]
+.Use a Custom AggregationPolicy
+--------------------------------------------
+Configuration cfg1 = ...;
+Configuration cfg2 = ...;
+Configuration config = ConfigurationBuilder.of("dynamicAggregationTests")
+      .withAggregationPolicy((k, v1, v2) -> (v1 != null ? v1 : "") + '[' + v2 + "]")
+      .aggregate(cfg1, cfg2).build();
+System.out.println(config);
+--------------------------------------------
+
+The output of this code snippet is as follows:
+
+[source,listing]
+.Listing of dynamic aggregation policy
+--------------------------------------------
+AggregatedConfiguration{
+  (name = dynamicAggregationTests)
+  a = "[a][A]"
+  b = "[b][B]"
+  c = "[c][C]"
+  d = "[D]"
+  e = "[E]"
+  f = "[F]"
+  g = "[g]"
+  h = "[h]"
+  i = "[i]"
+}
+--------------------------------------------
+
+Summarizing the +ConfigurationBuilder+ allows to combine providers in various forms:
+
+[source,listing]
+.Methods provided on PropertySources
+--------------------------------------------
+public final class ConfigurationBuilder {
+
+    private ConfigurationBuilder() {}
+
+    public static ConfigurationBuilder of();
+    public static ConfigurationBuilder of(PropertySource config);
+    public static ConfigurationBuilder of(String name);
+
+    public ConfigurationBuilder withAggregationPolicy(AggregationPolicy aggregationPolicy);
+    public ConfigurationBuilder withName(String name);
+
+    public ConfigurationBuilder addArgs(String... args);
+    public ConfigurationBuilder addPaths(List<String> paths);
+    public ConfigurationBuilder addUrls(URL... urls);
+    public ConfigurationBuilder addUrls(List<URL> urls);
+    public ConfigurationBuilder addMap(Map<String, String> map);
+
+    public Configuration empty();
+    public Configuration empty(String name);
+    public ConfigurationBuilder addEnvironmentProperties();
+    public ConfigurationBuilder addSystemProperties();
+    public ConfigurationBuilder aggregate(AggregationPolicy policy, Configuration... configs){
+    public ConfigurationBuilder aggregate(AggregationPolicy policy, List<Configuration> configs) {
+    public ConfigurationBuilder intersected(Configuration... providers) {
+    public ConfigurationBuilder subtracted(Configuration target, Configuration... providers) {
+    public ConfigurationBuilder filtered(Predicate<String> filter, Configuration config) {
+    public ConfigurationBuilder contextual(Supplier<Configuration> mapSupplier,
+                                              Supplier<String> isolationKeySupplier) {
+    public ConfigurationBuilder delegating(Configuration mainMap, Map<String, String> parentMap) {
+    public ConfigurationBuilder replacing(Configuration mainMap, Map<String, String> replacementMap);
+
+    public Configuration build();
+    public Configuration buildFrozen();
+}
+--------------------------------------------
+
+
+
+=== Environment
+
+The environment basically is also a kind of property/value provider similar to +System
+.getenv()+ in the JDK. Nevertheless it provides additional functionality:
+
+[source,java]
+.Interface Environment
+--------------------------------------------
+public interface Environment {
+
+    Optional<String> get(String key);
+    boolean containsKey(String key);
+    Set<String> keySet();
+    Map<String,String> toMap();
+
+    public static Environment current();
+    public static Environment root();
+--------------------------------------------
+
+* Basically an environment can contain any properties. The root environment
+  hereby must contain at least
+  ** all JDK's environment properties.
+  ** additional root properties are allowed as well.
+* the root environment is always directly accessible by calling +Environment.root()+
+* the current environment can be accessed by calling +Environment.current()+.
+
+Summarizing the Environment can be seen as a runtime context. This also implies, that this context changes
+depending on the current runtime context. Developers implementing an environment mechanism should be aware that
+an environment can be accessed very frequently, so evaluation and access of an +Environment+ must be fast. For
+further details we recommend the SPI details section of the core implementation.
+
+
+== SPI
+
+[[API PropertySourceBuilder]]
+==== Building Property Sources
+
+In [[PropertSource]] we have outlines that the essence of a property key store for configuration can be modelled by
+the +PropertySource+ interface. Similarly to the +ConfigurationBuilder+ you can also combine several +PropertySource+
+instances to assemble more complex configuration scenarios. Typically assembling is done within a +ConfigProvider+,
+which is responsible for providing correct Configuration corresponding to the current environment.
+
+Summarizing you can
+* aggregate providers, hereby later providers added
+  ** override any existing entries from earlier providers
+  ** combine conflicting entries from earlier providers, e.g. into a comma-separated structure.
+  ** may throw a ConfigException ig entries are conflicting
+  ** may only add entries not yet defined by former providers, preventing entries that are already present to be overwritten
+  ** any custom aggregation strategy, which may be a mix of above
+* intersecting providers
+* subtracting providers
+* filtering providers
+
+The following code snippet gives a couple of examples:
+
+[source,java]
+.Example Combining PropertySources
+--------------------------------------------
+PropertySource provider1 = ...
+PropertySource provider2 = ...
+
+// aggregate, hereby values from provider 2 override values from provider 1
+PropertySource unionOverriding = PropertySourceBuilder.of()
+             .aggregate(provider1, provider2).build(); // OVERRIDE policy is default
+System.out.println("unionOverriding: " + unionOverriding);
+
+// ignore duplicates, values present in provider 1 are not overriden by provider 2
+PropertySource unionIgnoringDuplicates = PropertySources
+             .aggregate(AggregationPolicy.IGNORE_DUPLICATES(), provider1, provider2).build();
+System.out.println("unionIgnoringDuplicates: " + unionIgnoringDuplicates);
+
+// this variant combines/maps duplicate values into a new value
+PropertySource unionCombined = PropertySourceBuilder.of().withAggregationPolicy(AggregationPolicy.COMBINE))
+            .aggregate(provider1, provider2).build();
+System.out.println("unionCombined: " + unionCombined);
+
+// This variant throws an exception since there are key/value paris in both providers, but with different values
+try{
+    PropertySourceBuilder.of().withAggregationPolicy(AggregationPolicy.EXCEPTION).aggregate(provider1, provider2);
+}
+catch(ConfigException e){
+    // expected!
+}
+--------------------------------------------
+
+

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/design/3_Extensions.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/design/3_Extensions.adoc b/docs/src/main/asciidoc/design/3_Extensions.adoc
deleted file mode 100644
index db949ac..0000000
--- a/docs/src/main/asciidoc/design/3_Extensions.adoc
+++ /dev/null
@@ -1,841 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-<<<
-[[CoreConcepts]]
-== {name} Core Concepts
-Though {name} is a very powerful and flexible solution there are basically only a few simple core concepts required that build
-the base of all the other mechanisms:
-
-The API contains the following core concepts/artifacts:
-
-* Literal Key/Value Pairs
-* _PropertyProvider:_ is the the SPI for a source that provides configuration data. A +PropertyProvider+
-     hereby defines
-     ** a minimalistic SPI to be implemented by the config data source
-     ** provides data key/value pairs in raw format as String key/values only
-     ** providers should not have any dependencies other than to the datasource
-     ** providers may read context dependent data, but basically providers themselves are not contextual.
-        Context management should be done by the ConfigurationProvider implementation that also is responsible
-        for combining a set of property providers to a Configuration.
-  _Configuration_ is the API that users of Tamaya will see, when they access configuration in raw format. Hereby +Configuration+
-     ** adds type support for non String types
-     ** provides functional extension points (+with,query+)
-     ** allows registering/deregistering of change listeners
-     ** is the entry point for evaluating the current +Configuration+
-     ** each +PropertyProvider+ can be easily converted into a +Configuration+
-     ** allows configuration entries to be injected
-     ** to access configuration _templates_ (annotated interfaces).
-     ** Configuration may support mutability by allowing instances of +ConfigChangeSet+ to be passed.
-* _PropertyProviders_ allows to aggregate different property providers. Hereby property providers are
-  seen as sets, which can be combined to new providers using set styled operations (aggregate, intersect, subtract).
-  This allows to model and create composite container providers, to build up more complex configuration models
-  step by step.
-* _MetaInfo_ is provided by each +Configuration, PropertyProvider+ and describes the configuration/provider and its entries.
-* _Environment_ is the base model for modelling the environment and the accessor for getting the current +Environment+ instance.
-* _Annotations_ a set of annotations allows to configure configuration injection on classes or interface (aka config templates).
-
-The SPI contains the following core concepts/artifacts:
-
-* _Bootstrap_ is the delegate singleton that is used by the framework to resolve components. The effective component
-  loading can be accessed by implementing and registering an instance of +ServiceProvider+ using +java.util.ServiceLoader+.
-* All the singleton used explicitly (+PropertyAdapters,PropertyProviders+ are backed up corresponding API interfaces.
-  To override a singleton's behaviour the corresponding SPI has to be implemented and registered, so it can be loaded
-  by the current +Bootstrap+ setup (by default ServiceLoader based).
-* Also the singleton used implicitly by +Configuration, Environment, Stage+ are backed up corresponding SPI interfaces.
-  To override a singleton's behaviour the corresponding SPI has to be implemented and registered, so it can be loaded
-  by the current +Bootstrap+ setup (by default ServiceLoader based).
-
-This is also reflected in the main parts of the API, which is quite small:
-
-* +org.apache.tamaya+ contains the main abstractions +Configuration, ConfigOperator, ConfigQuery, PropertyAdapter, Stage,
-  Environment, PropertyProvider, MetaInfo+
-* +org.apache.tamaya.spi+ contains the SPI interfaces to be implemented by implementations and the +Bootstrap+ mechanism.
-+ +org.apache.tamaya.annot+ contains the annotations defined.
-
-In the implementation are there are additional projects:
-
-* +org.apache.tamaya.core+ contains the core implementation of the API. Deploying it together with the API results in a
-  flexible framework that can be easily used for configuration of different complexity. But out of the box this framework
-  will not do much more than exposing system and environment properties, its power comes when an additional meta-model
-  is defined and deployed. Hereby you can write your own, or use on e of the provided ones (see later).
-* the core part is extended by multiple additional modules
-  ** CDI integration
-  ** Default configuration meta-models and providers for the most common usage scenarios
-    *** standalone applications
-    *** Java EE
-    *** ...
-
-These parts are explained in the following sections. It is recommended that user's of the API read through this part.
-All subsequent parts are building upon this concepts and may be more difficult to understand without having read
-this section.
-
-
-[[APIKeyValues]]
-=== Key/Value Pairs
-
-Basically configuration is a very generic concept. Therefore it should be modelled in a generic way. The most simple
-and similarly most commonly used are simple literal key/value pairs. So the core building block of {name} are key/value pairs.
-You can think of a common +.properties+ file, e.g.
-
-[source,properties]
-.A simple properties file
---------------------------------------------
-a.b.c=cVal
-a.b.c.1=cVal1
-a.b.c.2=cVal2
-a=aVal
-a.b=abVal
-a.b2=abVal
---------------------------------------------
-
-Now you can use +java.util.Properties+ to read this file and access the corresponding properties, e.g.
-
-[source,properties]
-.Accessing some properties
---------------------------------------------
-Properties props = new Properties();
-props.readProperties(...);
-String val = props.getProperty("a.b.c");
-val = props.getProperty("a.b.c.1");
-...
---------------------------------------------
-
-This looks familiar to most of you. Nevertheless when looking closer to the above key/value pairs,
-there are more concepts in place: looking at the keys +a.b.c+, +a.b.c.1+, +a.b.c.2+, +a+, +a.b+ we
-see that the key names build up a flattened tree structure. So we can define the following:
-
-Given a key +p1.p2.p3.k=value+:
-
-* +p1.p2.p3.k+ is called the _qualified key_
-* +p1.p2.p3+ is the key's _area_
-* the child areas +p1.p2", "p1+ are called _areas_ as well
-* +k+ is the _(unqualified) key_
-
-Given that you can perform some very useful actions:
-
-* you can filter the keys with an area. E.g. in the example before you can query for all keys within the area +a.b.c+
-  and map them to new properties set as follows:
-
-[source,properties]
-.Accessing an area
---------------------------------------------
-1=cVal1
-2=cVal2
---------------------------------------------
-
-Similarly accessing the area +a+ results in the following properties:
-
-[source,properties]
-.Accessing the area +a+
---------------------------------------------
-b=abVal
-b2=abVal
---------------------------------------------
-
-Additionally you can access all values of an area recursively, so accessing +a+ recursively results in
-the following properties:
-
-[source,properties]
-.Accessing area +a+ recursively
---------------------------------------------
-b.c=cVal
-b.c.1=cVal1
-b.c.2=cVal2
-b=abVal
-b2=abVal
---------------------------------------------
-
-Why this is useful? Well there are different use cases:
-
-* you can segregate your configuration properties, e.g. a module can access its module configuration by
-  querying all properties under the area +config.modules.myModule+ (or whatever would be appropriate).
-* you can use this mechanism to configure maps (or more generally: collections).
-* you can easily filter parts of configuration
-* ...and more.
-
-==== Why Using Strings Only
-
-Using Strings as base representation of configuration comes with several huge advantages:
-
-* Strings are simple to understand
-* Strings are human readable and therefore easy to prove for correctness
-* Strings can easily be used within different language, different VMs, files or network communications.
-* Strings can easily be compared and manipulated
-* Strings can easily be searched, indexed and cached
-* It is very easy to provide Strings as configuration, which gives much flexibility for providing configuration in
-  production as well in testing.
-* and more
-
-On the other side there are also disadvantages:
-
-* Strings are inherently not type safe, they do not provide validation out of the box for special types, such as
-numbers,
-  dates etc.
-* Often you want not to work with Strings, but with according types.
-* Strings are not hierarchical, so mapping hierarchical structures requires some extra efforts.
-
-Nevertheless most of these advantages can be mitigated easily, hereby still keeping all the benefits from above:
-
-* Adding type safe converters on top of String allow to add any type easily, that can be directly mapped out of Strings.
-  This includes all common base types such as numbers, dates, time, but also timezones, formatting patterns and more.
-* Even more complex mappings can be easily realized, by using String not as a direct representation of configuration,
-  but a reference that defines where the more complex configuration artifact is available. This mechanism is similarly
-  easy to understand as parsing Strings to numbers, but is powerful enough to provide e.g. all kind of deployment
-  descriptors in Java EE.
-* Hierarchical and collection types can be mapped in different ways:
-** The keys of configuration can have additional syntax/semantics. E.g. when adding dor-separating path semantics
-*** trees/maps can also simply be mapped.
-
-[APIPropertyProviders]
-=== Property Providers
-==== Basic Model
-
-We have seen that constrain configuration aspects to simple literal key/value pairs provides us with an easy to
-understand, generic, flexible, yet expendable mechanism. Looking at the Java language features a +vava.util.Map<String,
-String>+ and +java.util.Properties+ basically model these quite well out of the box.
-So it makes sense to build configuration on top of the JDK's +Map+ interface. This creates immediately additional
-benefits:
-
-* we inherit full Lambda and collection support
-* Maps are widely known and well understood
-
-Nevertheless there are some things to be considered:
-
-* Configuration also requires meta-data, such as
-** the origin of a certain configuration entry and how it was derived from other values
-** the sensitivity of some data
-** the provider that have read the data
-** the time, when the data was read
-** the timestamp, when some data may be outdated
-** ...
-
-Basically the same is also the not related to some single configuration key, but also to a whole map.
-The +PropertyProvider+ interface models exact these aspects and looks as illustrated below:
-
-[source,java]
-.Interface PropertyProvider
---------------------------------------------
-public interface PropertyProvider{
-
-      Optional<String> get(String key);
-      boolean containsKey(String key);
-      Map<String, String> toMap();
-      MetaInfo getMetaInfo();
-
-      default Set<String> keySet();
-      default ConfigChangeSet load();
-      default boolean isMutable();
-      default void apply(ConfigChangeSet change);
-}
---------------------------------------------
-
-Hereby
-
-* +getMetaInfo()+ return the meta information for the property provider, as well as for individual property key/value pairs.
-* +get, containsKey, keySet+ look similar to the methods on +Map+, though +get+ uses the +Optional+ type introduced
-  with Java 8. This avoids returning +null+ or throwing exceptions in case no such entry is available and also
-  reduced the API's footprint, since default values can be easily implemented by calling +Optional.orElse+.
-* +isMutable()+ allows to easy check, if a property provider is mutable, which is more elegant than catching
-  +NonSupportedOperation+ exception thrown on the according methods of +Map+.
-* +load()+ finally allows to (re)load a property map. It depends on the implementing source, if this operation
-  has any effect. If the map changes an according +ConfigChange+ must be returned, describing the
-  changes applied.
-* +hasSameProperties+ allows to perform a comparison with another provider.
-* +toMap+ allows to extract thing to a +Map+.
-
-This simple model will be used within the spi, where configuration can be injected/provided from external resources.
-But we have seen, that we have to consider additional aspects, such as extendability and type safety. Therefore we
-extend +PropertyMap+ and hereby also apply the 'composite pattern', which results in the following key abstraction.
-
-==== Meta Information
-
-Each instance also provides an instance of +MetaInfo+, which provides meta information for the providers and its properties:
-
-[source,java]
-.Accessing Meta Information
---------------------------------------------
-PropertyProvider prov = ...;
-MetaInfo metaInfo = prov.getMetaInfo();
-Set<String> keys = metaInfo.keySet();  // returns the attribute keys, for which meta-information is accessible.
-String metaData = metaInfo.get("a.b.c.value"); // access meta information
-String itemName = metaInfo.getName(); // access meta information for the provider
---------------------------------------------
-
-As we have seen above there is as well a +MetaInfoBuilder+, which must be used to create instances of
-+MetaInfo+.
-
-==== Mutability
-
-Property providers optionally may be mutable. This can be checked by calling +boolean isMutable()+. If a provider
-is mutable a +ConfigChangeSet+ can be passed. This change set can then be applied by the provider. On creation
-of the +ConfigChangeSetBuilder+ a provider can pass version information, so _optimistic locking_ can be implemented
-easily:
-
-[source,java]
-.Creating and applying a +ConfigChangeSet+ to a provider
---------------------------------------------
-PropertyProvider prov = ...;
-ConfigChangeSet changeSet = ConfigChangeSetBuilder.of(provider)  // creating a default version
-   .remove("key1ToBeRemoved", +key2ToBeRemoved")
-   .put("key2", "key2Value")
-   .put("key3", 12345)
-   .put("key4", 123.45)
-   .build();
-provider.apply(changeSet);
---------------------------------------------
-
-[[API CombineProviders]]
-==== Combining Property Providers
-
-Looking at the structures of configuration system used by large companies we typically encounter some kind of configuration
-hierarchies that are combined in arbitrary ways. Users of the systems are typically not aware of the complexities in this
-area, since they simply know the possible locations, formats and the overriding policies. Framework providers on the other
-side must face the complexities and it would be very useful if Tamaya can support here by providing prebuilt functionality
-that helps implementing these aspects. All this leads to the feature set of combining property providers. Hereby the following
-strategies are useful:
-
-* aggregating providers, hereby later providers added
-  ** override any existing entries from earlier providers
-  ** combine conflicting entries from earlier providers, e.g. into a comma-separated structure.
-  ** may throw a ConfigExcepotion ig entries are conflicting
-  ** may only add entries not yet defined by former providers, preventing entries that are already present to be overwritte
-  ** any custom aggregation strategy, which may be a mix of above
-* intersecting providers
-* subtracting providers
-* filtering providers
-
-These common functionality is provided by the +PropertyProviders+ singleton. Additionally to the base strategies above a +MetaInfo+
-instance can be passed optionally as well to define the meta information for the newly created provider instances.
-Let's assume we have two property providers with the following data:
-
-[source,properties]
-.Provider 1
---------------------------------------------
-a=a
-b=b
-c=c
-g=g
-h=h
-i=i
---------------------------------------------
-
-[source,properties]
-.Provider 2
---------------------------------------------
-a=A
-b=B
-c=C
-d=D
-e=E
-f=F
---------------------------------------------
-
-Looking in detail you see that the entries +a,b,c+ are present in both providers, whereas +d,e,f+ are only present in provider 1,
-and +g,h,i+ only in provider 2.
-
-[source,java]
-.Example Combining PropertyProviders
---------------------------------------------
-PropertyProvider provider1 = ...
-PropertyProvider provider2 = ...
-
-// aggregate, hereby values from provider 2 override values from provider 1
-PropertyProvider unionOverriding = PropertyProviders.aggregate(AggregationPolicy.OVERRIDE(), provider1, provider2);
-System.out.println("unionOverriding: " + unionOverriding);
-
-// ignore duplicates, values present in provider 1 are not overriden by provider 2
-PropertyProvider unionIgnoringDuplicates = PropertyProviders.aggregate(AggregationPolicy.IGNORE_DUPLICATES(), provider1, provider2);
-System.out.println("unionIgnoringDuplicates: " + unionIgnoringDuplicates);
-
-// this variant combines/maps duplicate values into a new value
-PropertyProvider unionCombined = PropertyProviders.aggregate(AggregationPolicy.COMBINE(), provider1, provider2);
-System.out.println("unionCombined: " + unionCombined);
-
-// This variant throws an exception since there are key/value paris in both providers, but with different values
-try{
-    PropertyProviders.aggregate(AggregationPolicy.EXCEPTION(), provider1, provider2);
-}
-catch(ConfigException e){
-    // expected!
-}
---------------------------------------------
-
-The example above produces the following outpout:
-
-[source,listing]
-.Example Combining PropertyProviders
---------------------------------------------
-AggregatedPropertyProvider{
-  (name = dynamicAggregationTests)
-  a = "[a][A]"
-  b = "[b][B]"
-  c = "[c][C]"
-  d = "[D]"
-  e = "[E]"
-  f = "[F]"
-  g = "[g]"
-  h = "[h]"
-  i = "[i]"
-}
-unionOverriding: AggregatedPropertyProvider{
-  (name = <noname>)
-  a = "A"
-  b = "B"
-  c = "C"
-  d = "D"
-  e = "E"
-  f = "F"
-  g = "g"
-  h = "h"
-  i = "i"
-}
-unionIgnoringDuplicates: AggregatedPropertyProvider{
-  (name = <noname>)
-  a = "a"
-  b = "b"
-  c = "c"
-  d = "D"
-  e = "E"
-  f = "F"
-  g = "g"
-  h = "h"
-  i = "i"
-}
-unionCombined: AggregatedPropertyProvider{
-  (name = <noname>)
-  a = "a,A"
-  b = "b,B"
-  c = "c,C"
-  d = "D"
-  e = "E"
-  f = "F"
-  g = "g"
-  h = "h"
-  i = "i"
-}
---------------------------------------------
-
-No +AggregationPolicy+ is also an interface that can be implemented:
-
-[source,java]
-.AggregationPolicy Interface
---------------------------------------------
-@FunctionalInterface
-public interface AggregationPolicy {
-    String aggregate(String key, String value1, String value2);
-}
---------------------------------------------
-
-So we can also define our own aggregation strategy using a Lambda expression:
-
-[source,java]
-.Use a Custom AggregationPolicy
---------------------------------------------
-PropertyProvider provider1 = ...;
-PropertyProvider provider2 = ...;
-PropertyProvider props = PropertyProviders.aggregate(
-      (k, v1, v2) -> (v1 != null ? v1 : "") + '[' + v2 + "]",
-      MetaInfo.of("dynamicAggregationTests"),
-      props1, props2);
-System.out.println(props);
---------------------------------------------
-
-Additionally we also pass here an instance of +MetaInfo+. The output of this code snippet is as follows:
-
-[source,listing]
-.Listing of dynamic aggregation policy
---------------------------------------------
-AggregatedPropertyProvider{
-  (name = dynamicAggregationTests)
-  a = "[a][A]"
-  b = "[b][B]"
-  c = "[c][C]"
-  d = "[D]"
-  e = "[E]"
-  f = "[F]"
-  g = "[g]"
-  h = "[h]"
-  i = "[i]"
-}
---------------------------------------------
-
-Summarizing the +PropertyProviders+ singleton allows to combine providers in various forms:
-
-[source,listing]
-.Methods provided on PropertyProviders
---------------------------------------------
-public final class PropertyProviders {
-
-    private PropertyProviders() {}
-
-    public static PropertyProvider fromArgs(String... args) {
-    public static PropertyProvider fromArgs(MetaInfo metaInfo, String... args) {
-    public static PropertyProvider fromPaths(AggregationPolicy aggregationPolicy, String... paths) {
-    public static PropertyProvider fromPaths(String... paths) {
-    public static PropertyProvider fromPaths(List<String> paths) {
-    public static PropertyProvider fromPaths(AggregationPolicy aggregationPolicy, List<String> paths) {
-    public static PropertyProvider fromPaths(MetaInfo metaInfo, List<String> paths) {
-    public static PropertyProvider fromPaths(AggregationPolicy aggregationPolicy, MetaInfo metaInfo, List<String> paths) {
-    public static PropertyProvider fromUris(URI... uris) {
-    public static PropertyProvider fromUris(AggregationPolicy aggregationPolicy, URI... uris) {
-    public static PropertyProvider fromUris(List<URI> uris) {
-    public static PropertyProvider fromUris(AggregationPolicy aggregationPolicy, List<URI> uris) {
-    public static PropertyProvider fromUris(MetaInfo metaInfo, URI... uris) {
-    public static PropertyProvider fromUris(AggregationPolicy aggregationPolicy, MetaInfo metaInfo, URI... uris) {
-    public static PropertyProvider fromUris(MetaInfo metaInfo, List<URI> uris) {
-    public static PropertyProvider fromUris(AggregationPolicy aggregationPolicy, MetaInfo metaInfo, List<URI> uris) {
-    public static PropertyProvider fromMap(Map<String, String> map) {
-    public static PropertyProvider fromMap(MetaInfo metaInfo, Map<String, String> map) {
-    public static PropertyProvider empty() {
-    public static PropertyProvider emptyMutable() {
-    public static PropertyProvider empty(MetaInfo metaInfo) {
-    public static PropertyProvider emptyMutable(MetaInfo metaInfo) {
-    public static PropertyProvider fromEnvironmentProperties() {
-    public static PropertyProvider fromSystemProperties() {
-    public static PropertyProvider freezed(PropertyProvider provider) {
-    public static PropertyProvider aggregate(AggregationPolicy mapping, MetaInfo metaInfo, PropertyProvider... providers){
-    public static PropertyProvider aggregate(PropertyProvider... providers) {
-    public static PropertyProvider aggregate(List<PropertyProvider> providers) {
-    public static PropertyProvider aggregate(AggregationPolicy mapping, PropertyProvider... propertyMaps) {
-    public static PropertyProvider aggregate(AggregationPolicy mapping, List<PropertyProvider> providers) {
-    public static PropertyProvider mutable(PropertyProvider provider) {
-    public static PropertyProvider intersected(AggregationPolicy aggregationPolicy, PropertyProvider... providers) {
-    public static PropertyProvider intersected(PropertyProvider... providers) {
-    public static PropertyProvider subtracted(PropertyProvider target, PropertyProvider... providers) {
-    public static PropertyProvider filtered(Predicate<String> filter, PropertyProvider provider) {
-    public static PropertyProvider contextual(Supplier<PropertyProvider> mapSupplier,
-                                              Supplier<String> isolationKeySupplier) {
-    public static PropertyProvider delegating(PropertyProvider mainMap, Map<String, String> parentMap) {
-    public static PropertyProvider replacing(PropertyProvider mainMap, Map<String, String> replacementMap) {
-}
---------------------------------------------
-
-
-[[API Configuration]]
-=== Configuration
-==== Basic Model
-
-Configuration inherits all basic features from +PropertyProvider+, but additionally adds functionality for
-type safety and extension mechanisms:
-
-[source,java]
-.Interface Configuration
---------------------------------------------
-public interface Configuration extends PropertyProvider{
-
-    default OptionalBoolean getBoolean(String key);
-    default OptionalInt getInteger(String key);
-    default OptionalLong getLong(String key);
-    default OptionalDouble getDouble(String key);
-    default <T> Optional<T> getAdapted(String key, PropertyAdapter<T> adapter);
-    <T> Optional<T> get(String key, Class<T> type);
-
-    // accessing areas
-    default Set<String> getAreas();
-    default Set<String> getTransitiveAreas();
-    default Set<String> getAreas(final Predicate<String> predicate);
-    default Set<String> getTransitiveAreas(Predicate<String> predicate);
-    default boolean containsArea(String key);
-
-    // extension points
-    default Configuration with(ConfigOperator operator);
-    default <T> T query(ConfigQuery<T> query);
-
-    // versioning
-    default String getVersion(){return "N/A";}
-    void addPropertyChangeListener(PropertyChangeListener l);
-    void removePropertyChangeListener(PropertyChangeListener l);
-
-    // singleton accessors
-    public static boolean isDefined(String name);
-    public static <T> T current(String name, Class<T> template);
-    public static Configuration current(String name);
-    public static Configuration current();
-    public static <T> T current(Class<T> type){
-    public static void configure(Object instance);
-    public static String evaluateValue(String expression);
-    public static String evaluateValue(Configuration config, String expression);
-    public static void addGlobalPropertyChangeListener(PropertyChangeListener listener);
-    public static void removeGlobalPropertyChangeListener(PropertyChangeListener listener);
-}
---------------------------------------------
-
-Hereby
-
-* +XXX getXXX(String)+ provide type safe accessors for all basic wrapper types of the JDK.
-* +getAdapted+ allow accessing any type, hereby also passing a +PropertyAdapter+ that converts
-  the configured literal value to the type required.
-* +getAreas()+, +getTransitiveAreas()+ allow to examine the hierarchical tree modeled by the configuration tree.
-  Optionally also predicates can be passed to select only part of the tree to be returned.
-* +containsArea+ allows to check, if an area is defined.
-* +with, query+ provide the extension points for adding additional functionality.
-
-* the static accessor methods define:
-  ** +current(), current(Class), current(String), current(String, Class)+ return the configuration valid for the current runtime environment.
-  ** +addPropertyChangeListener, removePropertyChangeListener+ allow to register or unregister
-     global config change listener instances.
-  ** evaluateValue allows to evaluate a configuration expression based on a given configuration.
-  ** +configure+ performs injection of configured values.
-
-[[TypeConversion]]
-==== Type Conversion
-
-Configuration extend +PropertyProvider+ and add additional support for non String types. This is achieved
-with the help of +PropertyAdapter+ instances:
-
-[source,java]
-.PropertyAdapter
---------------------------------------------
-@FunctionalInterface
-public interface PropertyAdapter<T>{
-    T adapt(String value);
-}
---------------------------------------------
-
-PropertyAdapter instances can be implemented manually or registered and accessed from the
-+PropertyAdapers+ singleton. Hereby the exact mechanism is determined by the API backing up the singleton.
-By default corresponding +PropertyAdapter+ instances can be registered using the Java +ServiceLoader+
-mechanism, or programmatically ba calling the +register(Class, PropertyAdapter)+ method.
-
-[source,java]
---------------------------------------------
-public final class PropertyAdapters{
-    public static <T> PropertyAdapter<T> register(Class<T> targetType, PropertyAdapter<T> adapter);
-    public static boolean isTargetTypeSupported(Class<?> targetType);
-    public static  <T> PropertyAdapter<T> getAdapter(Class<T> targetType);
-    public static  <T> PropertyAdapter<T> getAdapter(Class<T> targetType, WithPropertyAdapter annotation);
-}
---------------------------------------------
-
-Whereas this mechanism per se looks not very useful it's power shows up when combining it with the annotations
-API provided, e.g. look at the following annotated class:
-
-[source,java]
-.Annotated Example Class
---------------------------------------------
-public class ConfiguredClass{
-
-    @ConfiguredProperty
-    private String testProperty;
-
-    @ConfiguredProperty("a.b.c.key1")
-    @DefaultValue("The current \\${JAVA_HOME} env property is ${env:JAVA_HOME}.")
-    String value1;
-
-    @ConfiguredProperty("a.b.c.key2")
-    private int value2;
-
-    @ConfiguredProperty
-    @DefaultValue("http://127.0.0.1:8080/res/api/v1/info.json")
-    private URL accessUrl;
-
-    @ConfiguredProperty
-    @DefaultValue("5")
-    private Integer int1;
-
-    @ConfiguredProperty("a.b.customType")
-    private MyCustomType myCustomType;
-
-    @ConfiguredProperty("BD")
-    private BigDecimal bigNumber;
-
-    ...
-}
---------------------------------------------
-
-The class does not show all the possibilities that are provided, but it shows that arbitrary types can be supported easily.
-This applied similarly to collection types, whereas collections are more advanced and therefore described in a separate section
-later.
-
-Given the class above and the current configuration can provide the values required, configuring an instance of the
-class is simple:
-
-[source,java]
-.Configuring the Example Class
---------------------------------------------
-ConfiguredClass classInstance = new ConfiguredClass();
-Configuration.configure(configuredClass);
---------------------------------------------
-
-Additional types can transparently be supported by implementing and registering corresponding SPI instances. This is explained
-in the SPI documentation of {name}.
-
-==== Extension Points
-
-We are well aware of the fact that this library will not be able to cover all kinds of use cases. Therefore
-we have added similar functional extension mechanisms that were used in other areas of the Java eco-system as well:
-
-* +ConfigOperator+ define unary operations on +Configuration+. They can be used for filtering, implementing
-  configuration views, security interception etc.
-* +ConfigQuery+ defines a function returning any kind of result based on a configuration instance. Typical
-  use cases of queries could be the implementation of configuration SPI instances that are required
-  by other libraries or frameworks.
-
-Both interfaces hereby are defined as functional interfaces:
-
-[source,java]
-.ConfigOperator and ConfigQuery
---------------------------------------------
-@FunctionalInterface
-public interface ConfigOperator{
-    Configuration operate(Configuration config);
-}
-
-@FunctionalInterface
-public interface ConfigQuery<T>{
-    T query(Configuration config);
-}
---------------------------------------------
-
-Both interfaces can be applied on a +Configuration+ instance:
-
-[source,java]
-.Applying Config operators and queries
---------------------------------------------
-Configuration secured = Configuration.of().apply(ConfigSecurity::secure);
-ConfigSecurity securityContext = Configuration.of().query(ConfigSecurity::targetSecurityContext);
---------------------------------------------
-
-NOTE: +ConfigSecurity+ is an arbitrary class.
-
-=== Configuration Injection
-
-The +Configuration+ interface provides static methods that allow to anykind of instances be configured
-ny just passing the instances calling +Configuration.configure(instance);+. The classes passed hereby must
-be annotated with +@ConfiguredProperty+ to define the configured properties. Hereby this annotation can be
-used in multiple ways and combined with other annotations such as +@DefaultValue+,
-+@WithLoadPolicy+, +@WithConfig+, +@WithConfigOperator+, +@WithPropertyAdapter+.
-
-To illustrate the mechanism below the most simple variant of a configured class is given:
-
-[source,java]
-.Most simple configured class
---------------------------------------------
-pubic class ConfiguredItem{
-  @ConfiguredProperty
-  private String aValue;
-}
---------------------------------------------
-
-When this class is configured, e.g. by passing it to +Configuration.configure(Object)+,
-the following is happening:
-
-* The current valid +Configuration+ is evaluated by calling +Configuration cfg = Configuration.of();+
-* The current property value (String) is evaluated by calling +cfg.get("aValue");+
-* if not successful, an error is thrown (+ConfigException+)
-* On success, since no type conversion is involved, the value is injected.
-* The configured bean is registered as a weak change listener in the config system's underlying
-  configuration, so future config changes can be propagated (controllable by applying the
-  +@WithLoadPolicy+ annotation).
-
-In the next example we explicitly define the property value:
-[source,java]
---------------------------------------------
-pubic class ConfiguredItem{
-
-  @ConfiguredProperty
-  @ConfiguredProperty("a.b.value")
-  @configuredProperty("a.b.deprecated.value")
-  @DefaultValue("${env:java.version}")
-  private String aValue;
-}
---------------------------------------------
-
-Within this example we evaluate multiple possible keys. Evaluation is aborted if a key could be successfully
-resolved. Hereby the ordering of the annotations define the ordering of resolution, so in the example above
-resolution equals to +"aValue", "a.b.value", "a.b.deprecated.value"+. If no value could be read
-from the configuration, it uses the value from the +@DefaultValue+ annotation. Interesting here
-is that this value is not static, it is evaluated by calling +Configuration.evaluateValue(Configuration, String)+.
-
-=== Environment
-
-The environment basically is also a kind of property/value provider similar to +System.getProperties()+ and +System
-.getenv()+ in the JDK. Nevertheless it provides additional functionality:
-
-[source,java]
-.Interface Environment
---------------------------------------------
-public interface Environments {
-
-    String getEnvironmentType();
-    String getEnvironmentId();
-    Environment getParentEnvironment();
-
-    Optional<String> get(String key);
-    boolean containsKey(String key);
-    Set<String> keySet();
-    Map<String,String> toMap();
-
-    public static Environment current(){
-    public static Environment getRootEnvironment(){
-    public static List<String> getEnvironmentTypeOrder(){
-    public static List<String> getEnvironmentHierarchy(){
-    public static Optional<Environment> getInstance(String environmentType, String contextId){
-    public static Set<String> getEnvironmentContexts(String environmentType){
-    public static boolean isEnvironmentActive(String environmentType){
---------------------------------------------
-
-* environments are hierarchical. Hereby all environments inherit from the root environment. The root environment
-  hereby must contain
-  ** all JDK's system properties, with same keys, values
-  ** all JDK's environment properties, prefixed with +env:+.
-  ** additional root properties are allowed as well.
-* the root environment is always directly accessible by calling +Environment.getRootEnvironment()+
-* the current environment can be accessed by calling +Environment.of()+.
-* each environment also defines a +Stage+ (implementing +StageSupplier+). Hereby, if not set explicitly the +Stage+ is inherited from the root
-  environment. Consequently the root environment must provide a +Stage+, which by default is +Stage.development()+.
-
-Additionally each environment instance is uniquely identified by the environment type (accessible from
-+getEnvironmentType()+ and the environment id (accessible from +getEnvironmentId()+). So it is possible to access
-an +Environment+ by calling +of(String environmentType, String environmentId)+. Implementations may restrict access
-to environments depending on the current runtime environment (runtime context) active. The API does
-not require further aspects.
-
-The call to +getEnvironmentIds(String)+ returns all context ids of the known +Environment+ instances
-of a given type. E.g. assuming there is an environment type +war+ calling +Environment.getEnvironmentIds("war")+
-may return +"/web/app1", "/web/app2"+ (assuming the war context ids equal the web applications root contexts).
-
-All environments are basically ordered. The ordering can be accessed by calling +getEnvironmentTypeOrder()+. Hereby
-not every environment type in a hierarchy must necessarily present. This is reflected by +getEnvironmentHierarchy()+
-which returns the environment type ids in order, but only containing the types of the environments
-currently present and accessible in the hierarchy. As an example an environment type order in an advanced
-use case could be something like +"root","ear","war","saas","user"+, whereas the concrete environment type hierarchy
-may be +"root","war","saas"+, because the application was not included
-in an additional ear archive and no user is currently active (anonymous). The call to +isEnvironmentActive(String)+
-allows to determine if an environment of the given type is currently active.
-Finally the environment hierarchy is of course similarly reflected by the relationship (+getParentEnvironment()+).
-The following code should illustrate some of these concepts:
-
-[source,java]
-.Interface Environment
---------------------------------------------
-List<String> envHierarchy = Environment.getEnvironmentHierarchy();
-  // -> "root","war","saas"
-Environment env = Environment.of();
-System.out.println(env.getEnvironmentContext()); // saas
-System.out.println(env.getEnvironmentId());      // mysolution_pro
-env = env.getParentEnvironment();
-System.out.println(env.getEnvironmentContext()); // war
-System.out.println(env.getEnvironmentId());      // pro
-env = env.getParentEnvironment();
-System.out.println(env.getEnvironmentContext()); // root
-System.out.println(env.getEnvironmentId());      // system
-env = env.getParentEnvironment();
-// env is null now!
---------------------------------------------
-
-


[4/4] incubator-tamaya git commit: TAMAYA-19: Streamlined API and impl.

Posted by an...@apache.org.
TAMAYA-19:  Streamlined API and impl.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/a60570e8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/a60570e8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/a60570e8

Branch: refs/heads/master
Commit: a60570e8e9e561dd2c02c7d0978e846d4d9dd27e
Parents: 0b5d4fe
Author: anatole <an...@apache.org>
Authored: Fri Dec 26 01:49:55 2014 +0100
Committer: anatole <an...@apache.org>
Committed: Fri Dec 26 01:49:55 2014 +0100

----------------------------------------------------------------------
 .../org/apache/tamaya/AggregationPolicy.java    | 131 ---
 .../java/org/apache/tamaya/Configuration.java   |  37 +-
 .../java/org/apache/tamaya/PropertySource.java  |  45 -
 .../tamaya/annotation/ConfiguredProperty.java   |   2 +-
 .../org/apache/tamaya/annotation/WithCodec.java |  45 -
 .../tamaya/annotation/WithConfigOperator.java   |   2 +-
 .../tamaya/annotation/WithPropertyAdapter.java  |  45 +
 .../java/org/apache/tamaya/spi/CodecSpi.java    |  89 --
 .../tamaya/spi/DefaultServiceComparator.java    |  85 --
 .../spi/DefaultServiceContextProvider.java      |   9 -
 .../java/org/apache/tamaya/spi/Orderable.java   |  34 -
 .../org/apache/tamaya/spi/OrdinalProvider.java  |  37 -
 .../apache/tamaya/spi/PropertyAdapterSpi.java   |  72 ++
 .../tamaya/TestConfigServiceSingletonSpi.java   |  15 -
 .../TestPropertyAdaptersSingletonSpi.java       |  66 +-
 .../services/org.apache.tamaya.spi.CodecSpi     |  19 -
 .../org.apache.tamaya.spi.PropertyAdapterSpi    |  19 +
 .../core/config/FreezedConfiguration.java       |   4 +-
 .../core/internal/config/DefaultCodecSpi.java   | 169 ----
 .../config/DefaultPropertyAdapterSpi.java       | 168 ++++
 .../config/FallbackSimpleConfigProvider.java    |   2 +-
 .../core/internal/config/FileConfiguration.java |   2 -
 .../internal/resources/io/AntPathMatcher.java   |   4 +-
 .../AbstractClasspathAwarePropertySource.java   |   3 -
 .../core/properties/AbstractPropertySource.java |   3 +-
 .../core/properties/AggregationPolicy.java      | 133 +++
 .../properties/BuildablePropertySource.java     |   2 -
 .../properties/EnvironmentPropertySource.java   |   3 -
 .../core/properties/URLBasedPropertySource.java |   1 -
 .../tamaya/core/spi/CodecProviderSpi.java       |  36 -
 .../core/spi/DefaultServiceComparator.java      |  85 ++
 .../core/spi/DefaultServiceContextProvider.java | 112 +++
 .../org/apache/tamaya/core/spi/Orderable.java   |  34 +
 .../apache/tamaya/core/spi/OrdinalProvider.java |  37 +
 .../core/spi/PropertyAdapterProviderSpi.java    |  36 +
 .../services/org.apache.tamaya.spi.CodecSpi     |  19 -
 .../org.apache.tamaya.spi.PropertyAdapterSpi    |  19 +
 .../apache/tamaya/ucs/UC1ReadProperties.java    |   5 +-
 .../apache/tamaya/ucs/UC2CombineProperties.java |   5 +-
 docs/src/main/asciidoc/design/2_API.adoc        | 469 ++++++++++
 .../main/asciidoc/design/2_CoreConcepts.adoc    | 849 -------------------
 docs/src/main/asciidoc/design/3_Core.adoc       | 356 ++++++++
 docs/src/main/asciidoc/design/3_Extensions.adoc | 841 ------------------
 docs/src/main/asciidoc/design/4_Extensions.adoc | 841 ++++++++++++++++++
 .../asciidoc/usecases/se/combine-configs.adoc   |  14 +
 .../se/context-dependent-configuration.adoc     |   7 +
 .../usecases/se/dynamic-provisioning.adoc       |  17 +
 .../usecases/se/external-configuration.adoc     |   6 +
 docs/src/main/asciidoc/usecases/se/formats.adoc |   7 +
 .../main/asciidoc/usecases/se/injection.adoc    |  31 +
 docs/src/main/asciidoc/usecases/se/java8.adoc   |  13 +
 .../main/asciidoc/usecases/se/locations.adoc    |   9 +
 .../main/asciidoc/usecases/se/management.adoc   |   7 +
 .../usecases/se/minimal-propertysource.adoc     |   6 +
 .../usecases/se/multiple-configurations.adoc    |  14 +
 .../usecases/se/scannable-properties.adoc       |   4 +
 .../asciidoc/usecases/se/service-context.adoc   |  14 +
 .../asciidoc/usecases/se/simple-access.adoc     |  18 +
 .../usecases/se/simple-property-access.adoc     |   7 +
 .../main/asciidoc/usecases/se/templates.adoc    |  11 +
 .../usecases/se/type-safe-properties.adoc       |  10 +
 .../usecases/se/value-placeholders.adoc         |   8 +
 docs/src/main/asciidoc/usecases/usecases.adoc   |  19 +
 63 files changed, 2695 insertions(+), 2517 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/AggregationPolicy.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/AggregationPolicy.java b/api/src/main/java/org/apache/tamaya/AggregationPolicy.java
deleted file mode 100644
index c0f7cc0..0000000
--- a/api/src/main/java/org/apache/tamaya/AggregationPolicy.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya;
-
-import java.util.logging.Logger;
-
-/**
- * Policy that defines how the different configurations/property sources should be aggregated.
- * This is done by a mapping function defined as follows:
- * <pre>
- *     function f(key, value1, value2) -> result
- *
- * whereas
- *
- *       key = the fully qualified property key,
- *       value1 = the value from the first configuration/property source (can be null)
- *       value2 = the value from the second configuration/property source (can be null)
- *
- *       result = the value to be used in the aggregation, or null, which removed the
- *       key from the result.
- * </pre>
- *
- * Of course, during this evaluation step additional actions can be taken, e.g. refer to #LOG_ERROR, which
- * ignores duplicate entries, but also logs the conflict on severe/error level.
- */
-public interface AggregationPolicy {
-
-    /**
-     * Method which decides how keys/values are aggregated.
-     * @param key the key current the entry, must not be {@code null}.
-     * @param currentValue the current keys, or {@code null}.
-     * @param newValue the new keys, never {@code null}.
-     * @return the target keys to be used in the resulting property set, or null, to remove the property.
-     */
-    public String aggregate(String key, String currentValue, String newValue);
-
-    /** Ignore overrides, only extend (additive). */
-    public static final AggregationPolicy IGNORE_DUPLICATES = (k, v1, v2) -> v1 == null? v2 : v1;
-
-    /** Combine multiple values into a comma separated list. */
-    public static final AggregationPolicy COMBINE = (k, v1, v2) -> v1 != null && v2 != null ? v1 + ',' + v2: v2;
-
-    /**
-     * Interpret later keys as override (additive and override), replacing
-     * the key loaded earlier/fromMap previous contained
-     * {@link PropertySource}.
-     */
-    public static final AggregationPolicy OVERRIDE = (k, v1, v2) -> v2;
-
-    /**
-     * Throw an exception, when keys are not disjunctive (strictly
-     * additive).
-     */
-    public static final AggregationPolicy EXCEPTION =
-        (String key, String value, String newValue) -> {
-            if(value!=null && newValue!=null && !value.equals(newValue)){
-                throw new ConfigException("Conflicting values encountered key="+key+", keys="+value+", newValue="+newValue);
-            }
-            return newValue;
-        };
-
-    /**
-     * Ignores any duplicates, but logs the conflict encountered to error/severe level.
-     */
-    public static final AggregationPolicy LOG_ERROR =
-            (String key, String value, String newValue) -> {
-                if(value!=null && newValue!=null && !value.equals(newValue)){
-                    Logger.getLogger(AggregationPolicy.class.getName())
-                            .severe(() -> "Conflicting values encountered key=" + key + ", keys=" + value + ", newValue=" + newValue);
-                    return value;
-                }
-                return newValue;
-            };
-
-    /**
-     * Ignores any duplicates, but logs the conflict encountered to info level.
-     */
-    public static final AggregationPolicy LOG_WARNING =
-            (String key, String value, String newValue) -> {
-                if(value!=null && newValue!=null && !value.equals(newValue)){
-                    Logger.getLogger(AggregationPolicy.class.getName())
-                            .warning(() -> "Conflicting values encountered key=" + key + ", keys=" + value + ", newValue=" + newValue);
-                    return value;
-                }
-                return newValue;
-            };
-
-    /**
-     * Ignores any duplicates, but logs the conflict encountered to info level.
-     */
-    public static final AggregationPolicy LOG_INFO =
-        (String key, String value, String newValue) -> {
-            if(value!=null && newValue!=null && !value.equals(newValue)){
-                Logger.getLogger(AggregationPolicy.class.getName())
-                        .info(() -> "Conflicting values encountered key=" + key + ", keys=" + value + ", newValue=" + newValue);
-                return value;
-            }
-            return newValue;
-        };
-
-    /**
-     * Ignores any duplicates, but logs the conflict encountered to debug/finest level.
-     */
-    public static final AggregationPolicy LOG_DEBUG =
-            (String key, String value, String newValue) -> {
-                if(value!=null && newValue!=null && !value.equals(newValue)){
-                    Logger.getLogger(AggregationPolicy.class.getName())
-                            .finest(() -> "Conflicting values encountered key=" + key + ", keys=" + value + ", newValue=" + newValue);
-                    return value;
-                }
-                return newValue;
-            };
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/Configuration.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/Configuration.java b/api/src/main/java/org/apache/tamaya/Configuration.java
index 543a515..8254e3a 100644
--- a/api/src/main/java/org/apache/tamaya/Configuration.java
+++ b/api/src/main/java/org/apache/tamaya/Configuration.java
@@ -22,7 +22,6 @@ import org.apache.tamaya.spi.ConfigurationSpi;
 import org.apache.tamaya.spi.ServiceContext;
 
 import java.util.*;
-import java.util.function.Consumer;
 import java.util.function.UnaryOperator;
 
 /**
@@ -126,10 +125,10 @@ public interface Configuration extends PropertySource {
      * @throws IllegalArgumentException if the keys could not be converted to the required target
      *                                  type, or no such property exists.
      */
-    default <T> Optional<T> getAdapted(String key, Codec<T> adapter){
+    default <T> Optional<T> getAdapted(String key, PropertyAdapter<T> adapter){
         Optional<String> value = get(key);
         if(value.isPresent()) {
-            return Optional.ofNullable(adapter.deserialize(value.get()));
+            return Optional.ofNullable(adapter.adapt(value.get()));
         }
         return Optional.empty();
     }
@@ -137,7 +136,7 @@ public interface Configuration extends PropertySource {
 
     /**
      * Get the property keys as type T. This will implicitly require a corresponding {@link
-     * Codec} to be available that is capable current providing type T
+     * PropertyAdapter} to be available that is capable current providing type T
      * fromMap the given String keys.
      *
      * @param key          the property's absolute, or relative path, e.g. @code
@@ -148,7 +147,7 @@ public interface Configuration extends PropertySource {
      *                                  type.
      */
     default <T> Optional<T> get(String key, Class<T> type){
-        return getAdapted(key, Codec.getInstance(type));
+        return getAdapted(key, PropertyAdapter.getInstance(type));
     }
 
     /**
@@ -227,7 +226,6 @@ public interface Configuration extends PropertySource {
      * @param configurations overriding configurations to be used for evaluating the values for injection into {@code instance}, not null.
      *                       If no such config is passed, the default configurationa provided by the current
      *                       registered providers are used.
-     * @return the corresponding typed Configuration instance, never null.
      * @throws ConfigException if the configuration could not be resolved.
      */
     public static void configure(Object instance, Configuration... configurations){
@@ -247,31 +245,4 @@ public interface Configuration extends PropertySource {
         return ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).evaluateValue(expression, configurations);
     }
 
-    /**
-     * Add a ConfigChangeListener to the given PropertySource instance.
-     * @param l the listener, not null.
-     */
-    public static void addChangeListener(Consumer<ConfigChangeSet> l){
-        ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).addChangeListener(l);
-    }
-
-    /**
-     * Removes a ConfigChangeListener from the given PropertySource instance.
-     * @param l the listener, not null.
-     */
-    public static void removeChangeListener(Consumer<ConfigChangeSet> l){
-        ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).removeChangeListener(l);
-    }
-
-    /**
-     * Method to publish changes on a {@link org.apache.tamaya.PropertySource} to all interested parties.
-     * Basically this method gives an abstraction on the effective event bus design fo listeners. In a CDI context
-     * the CDI enterprise event bus should be used internally to do the work, whereas in a SE only environment
-     * a more puristic approach would be useful.
-     * @param configChange the change to be published, not null.
-     */
-    public static void publishChange(ConfigChangeSet configChange){
-        ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).publishChange(configChange);
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/PropertySource.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/PropertySource.java b/api/src/main/java/org/apache/tamaya/PropertySource.java
index 2cd3af7..d0c5bc1 100644
--- a/api/src/main/java/org/apache/tamaya/PropertySource.java
+++ b/api/src/main/java/org/apache/tamaya/PropertySource.java
@@ -111,36 +111,6 @@ public interface PropertySource {
     }
 
     /**
-     * Reloads the {@link PropertySource}.
-     */
-    default ConfigChangeSet load() {
-        // by default do nothing
-        return ConfigChangeSet.emptyChangeSet(this);
-    }
-
-    /**
-     * Allows to evaluate if the provider is mutable.
-     *
-     * @return true, if the provider is mutable.
-     * @see #applyChanges(ConfigChangeSet)
-     */
-    default boolean isMutable() {
-        return false;
-    }
-
-    /**
-     * Apply a config change to this item. Hereby the change must be related to the same instance.
-     *
-     * @param change the config change
-     * @throws ConfigException               if an unrelated change was passed.
-     * @throws UnsupportedOperationException when the configuration is not writable.
-     * @see #isMutable()
-     */
-    default void applyChanges(ConfigChangeSet change) {
-        throw new UnsupportedOperationException("Config/properties not mutable: " + this);
-    }
-
-    /**
      * Convert the this PropertyProvider instance to a {@link org.apache.tamaya.Configuration}.
      *
      * @return the configuration, never null.
@@ -158,26 +128,11 @@ public interface PropertySource {
             }
 
             @Override
-            public boolean isMutable() {
-                return PropertySource.this.isMutable();
-            }
-
-            @Override
-            public void applyChanges(ConfigChangeSet changes) {
-                PropertySource.this.applyChanges(changes);
-            }
-
-            @Override
             public boolean isEmpty() {
                 return PropertySource.this.isEmpty();
             }
 
             @Override
-            public ConfigChangeSet load() {
-                return PropertySource.this.load();
-            }
-
-            @Override
             public Optional<String> get(String key) {
                 return PropertySource.this.get(key);
             }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/annotation/ConfiguredProperty.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/annotation/ConfiguredProperty.java b/api/src/main/java/org/apache/tamaya/annotation/ConfiguredProperty.java
index a29ef8b..21d4e3a 100644
--- a/api/src/main/java/org/apache/tamaya/annotation/ConfiguredProperty.java
+++ b/api/src/main/java/org/apache/tamaya/annotation/ConfiguredProperty.java
@@ -25,7 +25,7 @@ import java.lang.annotation.*;
  * a configuration template method. Hereby this annotation can be used in multiple ways and combined
  * with other annotations such as {@link org.apache.tamaya.annotation.DefaultValue},
  * {@link org.apache.tamaya.annotation.WithLoadPolicy}, {@link org.apache.tamaya.annotation.WithConfig},
- * {@link org.apache.tamaya.annotation.WithConfigOperator}, {@link WithCodec}.
+ * {@link org.apache.tamaya.annotation.WithConfigOperator}, {@link WithPropertyAdapter}.
  *
  * Below the most simple variant current a configured class is given:
  * {@code

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/annotation/WithCodec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/annotation/WithCodec.java b/api/src/main/java/org/apache/tamaya/annotation/WithCodec.java
deleted file mode 100644
index 465d7b3..0000000
--- a/api/src/main/java/org/apache/tamaya/annotation/WithCodec.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.apache.tamaya.Codec;
-
-/**
- * Annotation to define a type adapter to be used before injecting a configured keys, or for applying changes.
- * This will override any other adapter for performing the type conversion before
- * injecting the field keys.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(value = { ElementType.FIELD, ElementType.METHOD })
-public @interface WithCodec {
-
-    /**
-     * Define a custom adapter or codec that should be used to deserialize the configuration entry injected. This overrides any
-     * general org.apache.tamaya.core.internal registered. If no adapter is defined (default) and no corresponding adapter is
-     * registered, it is handled as a deployment error.
-     */
-    @SuppressWarnings("rawtypes")
-	Class<? extends Codec> value();
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/annotation/WithConfigOperator.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/annotation/WithConfigOperator.java b/api/src/main/java/org/apache/tamaya/annotation/WithConfigOperator.java
index 0ede2c2..9f6c4f5 100644
--- a/api/src/main/java/org/apache/tamaya/annotation/WithConfigOperator.java
+++ b/api/src/main/java/org/apache/tamaya/annotation/WithConfigOperator.java
@@ -36,7 +36,7 @@ import java.util.function.UnaryOperator;
 public @interface WithConfigOperator {
 
     /**
-     * Define a custom adapter that should be used to deserialize the configuration entry injected. This overrides any
+     * Define a custom adapter that should be used to adapt the configuration entry injected. This overrides any
      * general org.apache.tamaya.core.internal registered. If no adapter is defined (default) and no corresponding adapter is
      * registered, it is handled as a deployment error.
      */

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/annotation/WithPropertyAdapter.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/annotation/WithPropertyAdapter.java b/api/src/main/java/org/apache/tamaya/annotation/WithPropertyAdapter.java
new file mode 100644
index 0000000..fa9cfdf
--- /dev/null
+++ b/api/src/main/java/org/apache/tamaya/annotation/WithPropertyAdapter.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.annotation;
+
+import org.apache.tamaya.PropertyAdapter;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to define a type adapter to be used before injecting a configured keys, or for applying changes.
+ * This will override any other adapter for performing the type conversion before
+ * injecting the field keys.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.FIELD, ElementType.METHOD })
+public @interface WithPropertyAdapter {
+
+    /**
+     * Define a custom adapter or codec that should be used to adapt the configuration entry injected. This overrides any
+     * general org.apache.tamaya.core.internal registered. If no adapter is defined (default) and no corresponding adapter is
+     * registered, it is handled as a deployment error.
+     */
+    @SuppressWarnings("rawtypes")
+	Class<? extends PropertyAdapter> value();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/spi/CodecSpi.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/spi/CodecSpi.java b/api/src/main/java/org/apache/tamaya/spi/CodecSpi.java
deleted file mode 100644
index 7a0670b..0000000
--- a/api/src/main/java/org/apache/tamaya/spi/CodecSpi.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.spi;
-
-import org.apache.tamaya.Codec;
-import org.apache.tamaya.annotation.WithCodec;
-
-import java.util.Objects;
-import java.util.function.Function;
-
-/**
- * SPI that is used by the {@link org.apache.tamaya.Codecs} singleton as delegation instance.
- */
-public interface CodecSpi {
-
-    /**
-     * Registers a new PropertyAdapter for the given target type, hereby replacing any existing adapter for
-     * this type.
-     * @param targetType The target class, not null.
-     * @param adapter The adapter, not null.
-     * @param <T> The target type
-     * @return any adapter replaced with the new adapter, or null.
-     */
-    <T> Codec<T> register(Class<T> targetType, Codec<T> adapter);
-
-    default <T> Codec<T> register(Class<T> targetType, Function<String,T> decoder, Function<T, String> encoder){
-        Objects.requireNonNull(targetType);
-        Objects.requireNonNull(decoder);
-        Objects.requireNonNull(encoder);
-        return register(targetType, new Codec<T>(){
-
-            @Override
-            public T deserialize(String value) {
-                return decoder.apply(value);
-            }
-
-            @Override
-            public String serialize(T value) {
-                return encoder.apply(value);
-            }
-
-            @Override
-            public String toString(){
-                return "Codec(decoder="+decoder.getClass().getName()+", encoder="+encoder.getClass().getName()+")";
-            }
-        });
-    }
-
-    /**
-     * Get an adapter converting to the given target type.
-     * @param targetType the target type class
-     * @return true, if the given target type is supported.
-     */
-    default <T> Codec<T> getAdapter(Class<T> targetType){
-        return getCodec(targetType, null);
-    }
-
-    /**
-     * Get an adapter converting to the given target type.
-     * @param targetType the target type class
-     * @param <T> the target type
-     * @return the corresponding adapter, never null.
-     * @throws org.apache.tamaya.ConfigException if the target type is not supported.
-     */
-    <T> Codec<T> getCodec(Class<T> targetType, WithCodec annotation);
-
-    /**
-     * Checks if the given target type is supported, i.e. a adapter is registered and accessible.
-     * @param targetType the target type class
-     * @return true, if the given target type is supported.
-     */
-    boolean isTargetTypeSupported(Class<?> targetType);
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/spi/DefaultServiceComparator.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/spi/DefaultServiceComparator.java b/api/src/main/java/org/apache/tamaya/spi/DefaultServiceComparator.java
deleted file mode 100644
index c53a52d..0000000
--- a/api/src/main/java/org/apache/tamaya/spi/DefaultServiceComparator.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.spi;
-
-import java.util.*;
-
-/**
- * Simple comparator based on a Collection of {@link org.apache.tamaya.spi.OrdinalProvider} instances.
- */
-final class DefaultServiceComparator implements Comparator<Object>{
-
-    /**
-     * List of ordinal providers loaded.
-     */
-    private List<OrdinalProvider> ordinalProviders = new ArrayList<>();
-
-    DefaultServiceComparator(Collection<? extends OrdinalProvider> providers){
-        ordinalProviders.addAll(Objects.requireNonNull(providers));
-        ordinalProviders.sort(this::compare);
-    }
-
-    private int compare(OrdinalProvider provider1, OrdinalProvider provider2){
-        int o1 = getOrdinal(provider1);
-        int o2 = getOrdinal(provider2);
-        int order = o1-o2;
-        if(order < 0){
-            return -1;
-        }
-        else if(order > 0){
-            return 1;
-        }
-        return 0;
-    }
-
-    private int getOrdinal(OrdinalProvider provider){
-        if(provider instanceof Orderable){
-            return ((Orderable)provider).order();
-        }
-        return 0;
-    }
-
-    public int getOrdinal(Object service){
-        for(OrdinalProvider provider: ordinalProviders){
-            OptionalInt ord = provider.getOrdinal(service.getClass());
-            if(ord.isPresent()){
-                return ord.getAsInt();
-            }
-        }
-        if(service instanceof Orderable){
-            return ((Orderable)service).order();
-        }
-        return 0;
-    }
-
-
-    @Override
-    public int compare(Object o1, Object o2) {
-        int ord1 = getOrdinal(o1);
-        int ord2 = getOrdinal(o2);
-        int order = ord1-ord2;
-        if(order < 0){
-            return -1;
-        }
-        else if(order > 0){
-            return 1;
-        }
-        return 0;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/spi/DefaultServiceContextProvider.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/spi/DefaultServiceContextProvider.java b/api/src/main/java/org/apache/tamaya/spi/DefaultServiceContextProvider.java
index 295bab7..e1d1740 100644
--- a/api/src/main/java/org/apache/tamaya/spi/DefaultServiceContextProvider.java
+++ b/api/src/main/java/org/apache/tamaya/spi/DefaultServiceContextProvider.java
@@ -33,12 +33,6 @@ class DefaultServiceContextProvider implements ServiceContext {
 	private final ConcurrentHashMap<Class, List<Object>> servicesLoaded = new ConcurrentHashMap<>();
     /** Singletons. */
     private final ConcurrentHashMap<Class, Optional<?>> singletons = new ConcurrentHashMap<>();
-    /** Comparator for ordering of multiple services found. */
-    private DefaultServiceComparator serviceComparator;
-
-    public DefaultServiceContextProvider(){
-        serviceComparator = new DefaultServiceComparator(getServices(OrdinalProvider.class, Collections.emptyList()));
-    }
 
     @Override
     public <T> Optional<T> getService(Class<T> serviceType) {
@@ -94,9 +88,6 @@ class DefaultServiceContextProvider implements ServiceContext {
             if(services.isEmpty()){
                 services.addAll(defaultList);
             }
-            if(!serviceType.equals(OrdinalProvider.class)) {
-                services.sort(serviceComparator);
-            }
             services = Collections.unmodifiableList(services);
             final List<T> previousServices = (List<T>) servicesLoaded.putIfAbsent(serviceType, (List<Object>)services);
             return previousServices != null ? previousServices : services;

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/spi/Orderable.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/spi/Orderable.java b/api/src/main/java/org/apache/tamaya/spi/Orderable.java
deleted file mode 100644
index 56a99d7..0000000
--- a/api/src/main/java/org/apache/tamaya/spi/Orderable.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.spi;
-
-/**
- * Interface that can be optionally implemented by SPI components to be loaded into
- * the Tamaya's ServiceContext. The ordinal provided will be used to determine
- * priority and precedence, when multiple components implement the same
- * service interface.
- */
-@FunctionalInterface
-public interface Orderable {
-    /**
-     * Get the ordinal keys for the component, by default 0.
-     * @return the ordinal keys
-     */
-    int order();
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/spi/OrdinalProvider.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/spi/OrdinalProvider.java b/api/src/main/java/org/apache/tamaya/spi/OrdinalProvider.java
deleted file mode 100644
index aad8618..0000000
--- a/api/src/main/java/org/apache/tamaya/spi/OrdinalProvider.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.spi;
-
-import java.util.OptionalInt;
-
-/**
- * The ordinal provider is an optional component that provides an abstraction for ordering/prioritizing
- * services loaded. This can be used to determine, which SPI should be used, if multiple instances are
- * available, or for ordering chain of services.
- * @see ServiceContext
- */
-public interface OrdinalProvider {
-    /**
-     * Evaluate the ordinal number for the given type.
-     * @param type the target type, not null.
-     * @return the ordinal, if not defined, 0 should be returned.
-     */
-     OptionalInt getOrdinal(Class<?> type);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/main/java/org/apache/tamaya/spi/PropertyAdapterSpi.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/tamaya/spi/PropertyAdapterSpi.java b/api/src/main/java/org/apache/tamaya/spi/PropertyAdapterSpi.java
new file mode 100644
index 0000000..a1222a4
--- /dev/null
+++ b/api/src/main/java/org/apache/tamaya/spi/PropertyAdapterSpi.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.PropertyAdapter;
+import org.apache.tamaya.annotation.WithPropertyAdapter;
+
+
+/**
+ * Manager for {@link org.apache.tamaya.Configuration} instances. Implementations must register an instance
+ * using the {@link org.apache.tamaya.spi.ServiceContextManager} mechanism in place (by default this is based on the {@link java.util.ServiceLoader}.
+ * The {@link org.apache.tamaya.Configuration} Singleton in the API delegates its corresponding calls to the
+ * instance returned by the current bootstrap service in place.
+ *
+ * @see org.apache.tamaya.Configuration
+ * @see org.apache.tamaya.spi.ServiceContextManager
+ */
+public interface PropertyAdapterSpi {
+
+
+    /**
+     * Registers a new PropertyAdapter for the given target type, hereby replacing any existing adapter for
+     * this type.
+     * @param targetType The target class, not null.
+     * @param adapter The adapter, not null.
+     * @param <T> The target type
+     * @return any adapter replaced with the new adapter, or null.
+     */
+    <T> PropertyAdapter<T> register(Class<T> targetType, PropertyAdapter<T> adapter);
+
+    /**
+     * Get an adapter converting to the given target type.
+     * @param targetType the target type class
+     * @return true, if the given target type is supported.
+     */
+    default <T> PropertyAdapter<T> getAdapter(Class<T> targetType){
+        return getPropertyAdapter(targetType, null);
+    }
+
+    /**
+     * Get an adapter converting to the given target type.
+     * @param targetType the target type class
+     * @param <T> the target type
+     * @return the corresponding adapter, never null.
+     * @throws org.apache.tamaya.ConfigException if the target type is not supported.
+     */
+    <T> PropertyAdapter<T> getPropertyAdapter(Class<T> targetType, WithPropertyAdapter annotation);
+
+    /**
+     * Checks if the given target type is supported, i.e. a adapter is registered and accessible.
+     * @param targetType the target type class
+     * @return true, if the given target type is supported.
+     */
+    boolean isTargetTypeSupported(Class<?> targetType);
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/test/java/org/apache/tamaya/TestConfigServiceSingletonSpi.java
----------------------------------------------------------------------
diff --git a/api/src/test/java/org/apache/tamaya/TestConfigServiceSingletonSpi.java b/api/src/test/java/org/apache/tamaya/TestConfigServiceSingletonSpi.java
index 0ec2aa0..858786d 100644
--- a/api/src/test/java/org/apache/tamaya/TestConfigServiceSingletonSpi.java
+++ b/api/src/test/java/org/apache/tamaya/TestConfigServiceSingletonSpi.java
@@ -87,19 +87,4 @@ public class TestConfigServiceSingletonSpi implements ConfigurationSpi {
         return expression;
     }
 
-    @Override
-    public void addChangeListener(Consumer<ConfigChangeSet> l) {
-        // ignore
-    }
-
-    @Override
-    public void removeChangeListener(Consumer<ConfigChangeSet> l) {
-        // ignore
-    }
-
-    @Override
-    public void publishChange(ConfigChangeSet configChangeSet) {
-        // ignore
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/test/java/org/apache/tamaya/TestPropertyAdaptersSingletonSpi.java
----------------------------------------------------------------------
diff --git a/api/src/test/java/org/apache/tamaya/TestPropertyAdaptersSingletonSpi.java b/api/src/test/java/org/apache/tamaya/TestPropertyAdaptersSingletonSpi.java
index b27164c..65e6c1d 100644
--- a/api/src/test/java/org/apache/tamaya/TestPropertyAdaptersSingletonSpi.java
+++ b/api/src/test/java/org/apache/tamaya/TestPropertyAdaptersSingletonSpi.java
@@ -29,71 +29,71 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.apache.tamaya.annotation.WithCodec;
-import org.apache.tamaya.spi.CodecSpi;
+import org.apache.tamaya.annotation.WithPropertyAdapter;
+import org.apache.tamaya.spi.PropertyAdapterSpi;
 
 /**
- * Test implementation current {@link org.apache.tamaya.spi.CodecSpi}, which provides codecs
+ * Test implementation current {@link org.apache.tamaya.spi.PropertyAdapterSpi}, which provides propertyAdapters
  * for some basic types.
  */
 @SuppressWarnings({"unchecked", "rawtypes"})
-public final class TestPropertyAdaptersSingletonSpi implements CodecSpi {
+public final class TestPropertyAdaptersSingletonSpi implements PropertyAdapterSpi {
 
-	private Map<Class, Codec<?>> codecs = new ConcurrentHashMap<>();
+	private Map<Class, PropertyAdapter<?>> propertyAdapters = new ConcurrentHashMap<>();
 
     private TestPropertyAdaptersSingletonSpi(){
-        register(char.class, (s) -> s.charAt(0), (ch) -> String.valueOf(ch));
-        register(int.class, Integer::parseInt, Object::toString);
-        register(byte.class, Byte::parseByte, Object::toString);
-        register(short.class, Short::parseShort, Object::toString);
-        register(boolean.class, Boolean::parseBoolean, b -> String.valueOf(b));
-        register(float.class, Float::parseFloat, f -> String.valueOf(f));
-        register(double.class, Double::parseDouble, d -> String.valueOf(d));
+        register(char.class, (s) -> s.charAt(0));
+        register(int.class, Integer::parseInt);
+        register(byte.class, Byte::parseByte);
+        register(short.class, Short::parseShort);
+        register(boolean.class, Boolean::parseBoolean);
+        register(float.class, Float::parseFloat);
+        register(double.class, Double::parseDouble);
 
-        register(Character.class, (s) -> s.charAt(0), Object::toString);
-        register(Integer.class, Integer::valueOf, Object::toString);
-        register(Byte.class, Byte::valueOf, Object::toString);
-        register(Short.class, Short::valueOf, String::valueOf);
-        register(Boolean.class, Boolean::valueOf, String::valueOf);
-        register(Float.class, Float::valueOf, String::valueOf);
-        register(Double.class, Double::valueOf, String::valueOf);
-        register(BigDecimal.class, BigDecimal::new, String::valueOf);
-        register(BigInteger.class, BigInteger::new, String::valueOf);
+        register(Character.class, (s) -> s.charAt(0));
+        register(Integer.class, Integer::valueOf);
+        register(Byte.class, Byte::valueOf);
+        register(Short.class, Short::valueOf);
+        register(Boolean.class, Boolean::valueOf);
+        register(Float.class, Float::valueOf);
+        register(Double.class, Double::valueOf);
+        register(BigDecimal.class, BigDecimal::new);
+        register(BigInteger.class, BigInteger::new);
 
-        register(Currency.class, Currency::getInstance, Object::toString);
+        register(Currency.class, Currency::getInstance);
 
-        register(LocalDate.class, LocalDate::parse, Object::toString);
-        register(LocalTime.class, LocalTime::parse, Object::toString);
-        register(LocalDateTime.class, LocalDateTime::parse, Object::toString);
-        register(ZoneId.class, ZoneId::of, ZoneId::getId);
+        register(LocalDate.class, LocalDate::parse);
+        register(LocalTime.class, LocalTime::parse);
+        register(LocalDateTime.class, LocalDateTime::parse);
+        register(ZoneId.class, ZoneId::of);
     }
 
 
 	@Override
-    public <T> Codec<T> register(Class<T> targetType, Codec<T> codec){
+    public <T> PropertyAdapter<T> register(Class<T> targetType, PropertyAdapter<T> codec){
         Objects.requireNonNull(targetType);
         Objects.requireNonNull(codec);
-        return (Codec<T>) codecs.put(targetType, codec);
+        return (PropertyAdapter<T>) propertyAdapters.put(targetType, codec);
     }
 
     @Override
-    public <T> Codec<T> getCodec(Class<T> targetType, WithCodec annotation){
+    public <T> PropertyAdapter<T> getPropertyAdapter(Class<T> targetType, WithPropertyAdapter annotation){
         if(annotation!=null){
             Class<?> adapterType = annotation.value();
-            if(!adapterType.equals(Codec.class)){
+            if(!adapterType.equals(PropertyAdapter.class)){
                 try{
-                    return (Codec<T>)adapterType.newInstance();
+                    return (PropertyAdapter<T>)adapterType.newInstance();
                 }
                 catch(Exception e){
                     throw new ConfigException("Failed to load PropertyAdapter: " + adapterType, e);
                 }
             }
         }
-        return (Codec<T>) codecs.get(targetType);
+        return (PropertyAdapter<T>) propertyAdapters.get(targetType);
     }
 
     @Override
     public boolean isTargetTypeSupported(Class<?> targetType){
-        return codecs.containsKey(targetType);
+        return propertyAdapters.containsKey(targetType);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/test/resources/META-INF/services/org.apache.tamaya.spi.CodecSpi
----------------------------------------------------------------------
diff --git a/api/src/test/resources/META-INF/services/org.apache.tamaya.spi.CodecSpi b/api/src/test/resources/META-INF/services/org.apache.tamaya.spi.CodecSpi
deleted file mode 100644
index e9b04b4..0000000
--- a/api/src/test/resources/META-INF/services/org.apache.tamaya.spi.CodecSpi
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy current the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-org.apache.tamaya.TestPropertyAdaptersSingletonSpi

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/api/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi
----------------------------------------------------------------------
diff --git a/api/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi b/api/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi
new file mode 100644
index 0000000..e9b04b4
--- /dev/null
+++ b/api/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy current the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.tamaya.TestPropertyAdaptersSingletonSpi

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/config/FreezedConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/config/FreezedConfiguration.java b/core/src/main/java/org/apache/tamaya/core/config/FreezedConfiguration.java
index 240ccbe..43d6957 100644
--- a/core/src/main/java/org/apache/tamaya/core/config/FreezedConfiguration.java
+++ b/core/src/main/java/org/apache/tamaya/core/config/FreezedConfiguration.java
@@ -22,9 +22,7 @@ import org.apache.tamaya.*;
 import org.apache.tamaya.core.properties.PropertySourceBuilder;
 
 import java.io.Serializable;
-import java.time.Instant;
 import java.util.Map;
-import java.util.Objects;
 
 /**
  * Configuration implementation that stores all current values current a given (possibly dynamic, contextual and non remote
@@ -41,7 +39,7 @@ final class FreezedConfiguration extends AbstractConfiguration implements Serial
      */
     private FreezedConfiguration(Configuration config){
         super(config.getName());
-        this.properties = PropertySourceBuilder.of(config).buildFreezed();
+        this.properties = PropertySourceBuilder.of(config).buildFrozen();
     }
 
     public static final Configuration of(Configuration config){

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/internal/config/DefaultCodecSpi.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/config/DefaultCodecSpi.java b/core/src/main/java/org/apache/tamaya/core/internal/config/DefaultCodecSpi.java
deleted file mode 100644
index fbbf130..0000000
--- a/core/src/main/java/org/apache/tamaya/core/internal/config/DefaultCodecSpi.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.internal.config;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.util.Currency;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Function;
-
-import org.apache.tamaya.Codec;
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.annotation.WithCodec;
-import org.apache.tamaya.spi.CodecSpi;
-
-/**
- * Default codecs singleton, which provides default codesc for all kind of classes out of the box, which will be
- * instantiatable from configuration, if one of the following is given:
- * <ul>
- *     <li>static factory methods using a String as simgle argument, called {@code of, valueOf, getInstance, instance, parse}</li>
- *     <li>have constructors taking a single String</li>
- * </ul>
- */
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class DefaultCodecSpi implements CodecSpi {
-
-
-	private Map<Class,Codec> adapters = new ConcurrentHashMap<>();
-
-    public DefaultCodecSpi(){
-        // Add default adapters
-        register(char.class, (s) -> s.charAt(0), (ch) -> String.valueOf(ch));
-        register(byte.class, Byte::parseByte, Object::toString);
-        register(short.class, Short::parseShort, Object::toString);
-        register(int.class, Integer::parseInt, Object::toString);
-        register(long.class, Long::parseLong, Object::toString);
-        register(boolean.class, Boolean::parseBoolean, b -> String.valueOf(b));
-        register(float.class, Float::parseFloat, f -> String.valueOf(f));
-        register(double.class, Double::parseDouble, d -> String.valueOf(d));
-
-        register(Character.class, (s) -> s.charAt(0), Object::toString);
-        register(Byte.class, Byte::valueOf, Object::toString);
-        register(Short.class, Short::valueOf, String::valueOf);
-        register(Integer.class, Integer::valueOf, Object::toString);
-        register(Long.class, Long::valueOf, Object::toString);
-        register(Boolean.class, Boolean::valueOf, b -> String.valueOf(b));
-        register(Float.class, Float::valueOf, f -> String.valueOf(f));
-        register(Double.class, Double::valueOf, d -> String.valueOf(d));
-        register(BigDecimal.class, BigDecimal::new, String::valueOf);
-        register(BigInteger.class, BigInteger::new, String::valueOf);
-
-        register(Currency.class, Currency::getInstance, Object::toString);
-
-        register(LocalDate.class, LocalDate::parse, Object::toString);
-        register(LocalTime.class, LocalTime::parse, Object::toString);
-        register(LocalDateTime.class, LocalDateTime::parse, Object::toString);
-        register(ZoneId.class, ZoneId::of, ZoneId::getId);
-    }
-
-	@Override
-    public <T> Codec<T> register(Class<T> targetType, Codec<T> adapter){
-        return adapters.put(targetType, adapter);
-    }
-
-    @Override
-    public <T> Codec<T> getCodec(Class<T> targetType, WithCodec adapterAnnot){
-        Codec codec = null;
-        Class<? extends Codec> configuredCodec = null;
-        if(adapterAnnot != null){
-            configuredCodec = adapterAnnot.value();
-            if(!configuredCodec.equals(Codec.class)){
-                try{
-                    codec = configuredCodec.newInstance();
-                }
-                catch(Exception e){
-                    throw new ConfigException("Invalid codec configured.", e);
-                }
-            }
-        }
-        if(codec == null){
-            codec = adapters.get(targetType);
-        }
-        if(codec == null){
-            codec = getDefaultCodec(targetType);
-        }
-        if(codec == null){
-            throw new ConfigException("No Codec found for " + targetType.getName());
-        }
-        return codec;
-    }
-
-    private <T> Codec getDefaultCodec(Class<T> targetType) {
-        Function<String, T> decoder = null;
-        Method factoryMethod = getFactoryMethod(targetType, "of", "valueOf", "instanceOf", "getInstance", "from", "parse");
-        if(factoryMethod!=null){
-            decoder = (s) -> {
-                try{
-                    factoryMethod.setAccessible(true);
-                    return targetType.cast(factoryMethod.invoke(s));
-                }
-                catch (Exception e){
-                    throw new ConfigException("Failed to decode '"+s+"'", e);
-                }
-            };
-        }
-        if(decoder==null) {
-            try {
-                Constructor<T> constr = targetType.getDeclaredConstructor(String.class);
-                decoder = (s) -> {
-                    try{
-                        constr.setAccessible(true);
-                        return constr.newInstance(s);
-                    }
-                    catch (Exception e){
-                        throw new ConfigException("Failed to decode '"+s+"'", e);
-                    }
-                };
-            } catch (Exception e) {
-                // ignore, TODO log finest
-            }
-        }
-        if(decoder!=null) {
-            return register(targetType, decoder, String::valueOf);
-        }
-        return null;
-    }
-
-    private Method getFactoryMethod(Class<?> type, String... methodNames) {
-        Method m;
-        for(String name:methodNames){
-            try{
-                m  = type.getDeclaredMethod(name, String.class);
-                return m;
-            }
-            catch(Exception e){
-                // ignore, TODO log finest
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public boolean isTargetTypeSupported(Class<?> targetType){
-        return adapters.containsKey(targetType);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/internal/config/DefaultPropertyAdapterSpi.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/config/DefaultPropertyAdapterSpi.java b/core/src/main/java/org/apache/tamaya/core/internal/config/DefaultPropertyAdapterSpi.java
new file mode 100644
index 0000000..f1b14e0
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/config/DefaultPropertyAdapterSpi.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.internal.config;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.util.Currency;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.PropertyAdapter;
+import org.apache.tamaya.annotation.WithPropertyAdapter;
+import org.apache.tamaya.spi.PropertyAdapterSpi;
+
+/**
+ * Default codecs singleton, which provides default codesc for all kind of classes out of the box, which will be
+ * instantiatable from configuration, if one of the following is given:
+ * <ul>
+ *     <li>static factory methods using a String as simgle argument, called {@code of, valueOf, getInstance, instance, parse}</li>
+ *     <li>have constructors taking a single String</li>
+ * </ul>
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class DefaultPropertyAdapterSpi implements PropertyAdapterSpi {
+
+
+	private Map<Class,PropertyAdapter> adapters = new ConcurrentHashMap<>();
+
+    public DefaultPropertyAdapterSpi(){
+        // Add default adapters
+        register(char.class, (s) -> s.charAt(0));
+        register(byte.class, Byte::parseByte);
+        register(short.class, Short::parseShort);
+        register(int.class, Integer::parseInt);
+        register(long.class, Long::parseLong);
+        register(boolean.class, Boolean::parseBoolean);
+        register(float.class, Float::parseFloat);
+        register(double.class, Double::parseDouble);
+
+        register(Character.class, (s) -> s.charAt(0));
+        register(Byte.class, Byte::valueOf);
+        register(Short.class, Short::valueOf);
+        register(Integer.class, Integer::valueOf);
+        register(Long.class, Long::valueOf);
+        register(Boolean.class, Boolean::valueOf);
+        register(Float.class, Float::valueOf);
+        register(Double.class, Double::valueOf);
+        register(BigDecimal.class, BigDecimal::new);
+        register(BigInteger.class, BigInteger::new);
+
+        register(Currency.class, Currency::getInstance);
+
+        register(LocalDate.class, LocalDate::parse);
+        register(LocalTime.class, LocalTime::parse);
+        register(LocalDateTime.class, LocalDateTime::parse);
+        register(ZoneId.class, ZoneId::of);
+    }
+
+	@Override
+    public <T> PropertyAdapter<T> register(Class<T> targetType, PropertyAdapter<T> adapter){
+        return adapters.put(targetType, adapter);
+    }
+
+    @Override
+    public <T> PropertyAdapter<T> getPropertyAdapter(Class<T> targetType, WithPropertyAdapter adapterAnnot){
+        PropertyAdapter codec = null;
+        Class<? extends PropertyAdapter> configuredCodec = null;
+        if(adapterAnnot != null){
+            configuredCodec = adapterAnnot.value();
+            if(!configuredCodec.equals(PropertyAdapter.class)){
+                try{
+                    codec = configuredCodec.newInstance();
+                }
+                catch(Exception e){
+                    throw new ConfigException("Invalid codec configured.", e);
+                }
+            }
+        }
+        if(codec == null){
+            codec = adapters.get(targetType);
+        }
+        if(codec == null){
+            codec = getDefaultPropertyAdapter(targetType);
+        }
+        if(codec == null){
+            throw new ConfigException("No Codec found for " + targetType.getName());
+        }
+        return codec;
+    }
+
+    private <T> PropertyAdapter getDefaultPropertyAdapter(Class<T> targetType) {
+        PropertyAdapter<T> decoder = null;
+        Method factoryMethod = getFactoryMethod(targetType, "of", "valueOf", "instanceOf", "getInstance", "from", "parse");
+        if(factoryMethod!=null){
+            decoder = (s) -> {
+                try{
+                    factoryMethod.setAccessible(true);
+                    return targetType.cast(factoryMethod.invoke(s));
+                }
+                catch (Exception e){
+                    throw new ConfigException("Failed to decode '"+s+"'", e);
+                }
+            };
+        }
+        if(decoder==null) {
+            try {
+                Constructor<T> constr = targetType.getDeclaredConstructor(String.class);
+                decoder = (s) -> {
+                    try{
+                        constr.setAccessible(true);
+                        return constr.newInstance(s);
+                    }
+                    catch (Exception e){
+                        throw new ConfigException("Failed to decode '"+s+"'", e);
+                    }
+                };
+            } catch (Exception e) {
+                // ignore, TODO log finest
+            }
+        }
+        if(decoder!=null) {
+            return register(targetType, decoder);
+        }
+        return null;
+    }
+
+    private Method getFactoryMethod(Class<?> type, String... methodNames) {
+        Method m;
+        for(String name:methodNames){
+            try{
+                m  = type.getDeclaredMethod(name, String.class);
+                return m;
+            }
+            catch(Exception e){
+                // ignore, TODO log finest
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isTargetTypeSupported(Class<?> targetType){
+        return adapters.containsKey(targetType);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/internal/config/FallbackSimpleConfigProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/config/FallbackSimpleConfigProvider.java b/core/src/main/java/org/apache/tamaya/core/internal/config/FallbackSimpleConfigProvider.java
index 42140c7..7f997e5 100644
--- a/core/src/main/java/org/apache/tamaya/core/internal/config/FallbackSimpleConfigProvider.java
+++ b/core/src/main/java/org/apache/tamaya/core/internal/config/FallbackSimpleConfigProvider.java
@@ -1,7 +1,7 @@
 package org.apache.tamaya.core.internal.config;
 
-import org.apache.tamaya.AggregationPolicy;
 import org.apache.tamaya.Configuration;
+import org.apache.tamaya.core.properties.AggregationPolicy;
 import org.apache.tamaya.core.properties.PropertySourceBuilder;
 import org.apache.tamaya.core.spi.ConfigurationProviderSpi;
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/internal/config/FileConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/config/FileConfiguration.java b/core/src/main/java/org/apache/tamaya/core/internal/config/FileConfiguration.java
index 661bf64..8286768 100644
--- a/core/src/main/java/org/apache/tamaya/core/internal/config/FileConfiguration.java
+++ b/core/src/main/java/org/apache/tamaya/core/internal/config/FileConfiguration.java
@@ -3,10 +3,8 @@ package org.apache.tamaya.core.internal.config;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.UUID;
 
 import org.apache.tamaya.Configuration;
-import org.apache.tamaya.MetaInfo;
 
 /**
  * Implementation of Configuration which the information is from xml or properties files.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/internal/resources/io/AntPathMatcher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/resources/io/AntPathMatcher.java b/core/src/main/java/org/apache/tamaya/core/internal/resources/io/AntPathMatcher.java
index 0fd542b..43d2a20 100644
--- a/core/src/main/java/org/apache/tamaya/core/internal/resources/io/AntPathMatcher.java
+++ b/core/src/main/java/org/apache/tamaya/core/internal/resources/io/AntPathMatcher.java
@@ -286,7 +286,7 @@ class AntPathMatcher {
 		if (tokenized == null) {
 			tokenized = tokenizePath(pattern);
 			if (cachePatterns == null && this.tokenizedPatternCache.size() >= CACHE_TURNOFF_THRESHOLD) {
-				// Try to deserialize to the runtime situation that we're encountering:
+				// Try to adapt to the runtime situation that we're encountering:
 				// There are obviously too many different patterns coming in here...
 				// So let's turn off the cache since the patterns are unlikely to be reoccurring.
 				deactivatePatternCache();
@@ -340,7 +340,7 @@ class AntPathMatcher {
 		if (matcher == null) {
 			matcher = new AntPathStringMatcher(pattern);
 			if (cachePatterns == null && this.stringMatcherCache.size() >= CACHE_TURNOFF_THRESHOLD) {
-				// Try to deserialize to the runtime situation that we're encountering:
+				// Try to adapt to the runtime situation that we're encountering:
 				// There are obviously too many different patterns coming in here...
 				// So let's turn off the cache since the patterns are unlikely to be reoccurring.
 				deactivatePatternCache();

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/properties/AbstractClasspathAwarePropertySource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/AbstractClasspathAwarePropertySource.java b/core/src/main/java/org/apache/tamaya/core/properties/AbstractClasspathAwarePropertySource.java
index 58fb301..47eb150 100644
--- a/core/src/main/java/org/apache/tamaya/core/properties/AbstractClasspathAwarePropertySource.java
+++ b/core/src/main/java/org/apache/tamaya/core/properties/AbstractClasspathAwarePropertySource.java
@@ -22,9 +22,6 @@ import org.apache.tamaya.core.resource.Resource;
 import org.apache.tamaya.spi.ServiceContext;
 import org.apache.tamaya.core.resource.ResourceLoader;
 
-import org.apache.tamaya.MetaInfo;
-import org.apache.tamaya.MetaInfoBuilder;
-
 import java.util.*;
 
 public abstract class AbstractClasspathAwarePropertySource extends AbstractPropertySource {

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/properties/AbstractPropertySource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/AbstractPropertySource.java b/core/src/main/java/org/apache/tamaya/core/properties/AbstractPropertySource.java
index 6fe3df0..fbfd6df 100644
--- a/core/src/main/java/org/apache/tamaya/core/properties/AbstractPropertySource.java
+++ b/core/src/main/java/org/apache/tamaya/core/properties/AbstractPropertySource.java
@@ -21,7 +21,6 @@ package org.apache.tamaya.core.properties;
 import java.io.Serializable;
 import java.util.*;
 
-import org.apache.tamaya.MetaInfo;
 import org.apache.tamaya.PropertySource;
 
 /**
@@ -78,7 +77,7 @@ public abstract class AbstractPropertySource implements PropertySource, Serializ
     @Override
     public String toString(){
         StringBuilder b = new StringBuilder(getClass().getSimpleName()).append("{\n");
-        b.append("  ").append("(").append(MetaInfo.NAME).append(" = ").append(getName()).append(")\n");
+        b.append("  ").append("(").append(getName()).append(" = ").append(getName()).append(")\n");
         printContents(b);
         return b.append('}').toString();
     }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/properties/AggregationPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/AggregationPolicy.java b/core/src/main/java/org/apache/tamaya/core/properties/AggregationPolicy.java
new file mode 100644
index 0000000..99be931
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/properties/AggregationPolicy.java
@@ -0,0 +1,133 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+package org.apache.tamaya.core.properties;
+
+import org.apache.tamaya.ConfigException;
+
+import java.util.logging.Logger;
+
+/**
+* Policy that defines how the different configurations/property sources should be aggregated.
+* This is done by a mapping function defined as follows:
+* <pre>
+*     function f(key, value1, value2) -> result
+*
+* whereas
+*
+*       key = the fully qualified property key,
+*       value1 = the value from the first configuration/property source (can be null)
+*       value2 = the value from the second configuration/property source (can be null)
+*
+*       result = the value to be used in the aggregation, or null, which removed the
+*       key from the result.
+* </pre>
+*
+* Of course, during this evaluation step additional actions can be taken, e.g. refer to #LOG_ERROR, which
+* ignores duplicate entries, but also logs the conflict on severe/error level.
+*/
+public interface AggregationPolicy {
+
+    /**
+     * Method which decides how keys/values are aggregated.
+     * @param key the key current the entry, must not be {@code null}.
+     * @param currentValue the current keys, or {@code null}.
+     * @param newValue the new keys, never {@code null}.
+     * @return the target keys to be used in the resulting property set, or null, to remove the property.
+     */
+    public String aggregate(String key, String currentValue, String newValue);
+
+    /** Ignore overrides, only extend (additive). */
+    public static final AggregationPolicy IGNORE_DUPLICATES = (k, v1, v2) -> v1 == null? v2 : v1;
+
+    /** Combine multiple values into a comma separated list. */
+    public static final AggregationPolicy COMBINE = (k, v1, v2) -> v1 != null && v2 != null ? v1 + ',' + v2: v2;
+
+    /**
+     * Interpret later keys as override (additive and override), replacing
+     * the key loaded earlier/fromMap previous contained
+     * {@link org.apache.tamaya.PropertySource}.
+     */
+    public static final AggregationPolicy OVERRIDE = (k, v1, v2) -> v2;
+
+    /**
+     * Throw an exception, when keys are not disjunctive (strictly
+     * additive).
+     */
+    public static final AggregationPolicy EXCEPTION =
+        (String key, String value, String newValue) -> {
+            if(value!=null && newValue!=null && !value.equals(newValue)){
+                throw new ConfigException("Conflicting values encountered key="+key+", keys="+value+", newValue="+newValue);
+            }
+            return newValue;
+        };
+
+    /**
+     * Ignores any duplicates, but logs the conflict encountered to error/severe level.
+     */
+    public static final AggregationPolicy LOG_ERROR =
+            (String key, String value, String newValue) -> {
+                if(value!=null && newValue!=null && !value.equals(newValue)){
+                    Logger.getLogger(AggregationPolicy.class.getName())
+                            .severe(() -> "Conflicting values encountered key=" + key + ", keys=" + value + ", newValue=" + newValue);
+                    return value;
+                }
+                return newValue;
+            };
+
+    /**
+     * Ignores any duplicates, but logs the conflict encountered to info level.
+     */
+    public static final AggregationPolicy LOG_WARNING =
+            (String key, String value, String newValue) -> {
+                if(value!=null && newValue!=null && !value.equals(newValue)){
+                    Logger.getLogger(AggregationPolicy.class.getName())
+                            .warning(() -> "Conflicting values encountered key=" + key + ", keys=" + value + ", newValue=" + newValue);
+                    return value;
+                }
+                return newValue;
+            };
+
+    /**
+     * Ignores any duplicates, but logs the conflict encountered to info level.
+     */
+    public static final AggregationPolicy LOG_INFO =
+        (String key, String value, String newValue) -> {
+            if(value!=null && newValue!=null && !value.equals(newValue)){
+                Logger.getLogger(AggregationPolicy.class.getName())
+                        .info(() -> "Conflicting values encountered key=" + key + ", keys=" + value + ", newValue=" + newValue);
+                return value;
+            }
+            return newValue;
+        };
+
+    /**
+     * Ignores any duplicates, but logs the conflict encountered to debug/finest level.
+     */
+    public static final AggregationPolicy LOG_DEBUG =
+            (String key, String value, String newValue) -> {
+                if(value!=null && newValue!=null && !value.equals(newValue)){
+                    Logger.getLogger(AggregationPolicy.class.getName())
+                            .finest(() -> "Conflicting values encountered key=" + key + ", keys=" + value + ", newValue=" + newValue);
+                    return value;
+                }
+                return newValue;
+            };
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/properties/BuildablePropertySource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/BuildablePropertySource.java b/core/src/main/java/org/apache/tamaya/core/properties/BuildablePropertySource.java
index 33eb2a6..847fbe9 100644
--- a/core/src/main/java/org/apache/tamaya/core/properties/BuildablePropertySource.java
+++ b/core/src/main/java/org/apache/tamaya/core/properties/BuildablePropertySource.java
@@ -17,13 +17,11 @@
  */
 package org.apache.tamaya.core.properties;
 
-import org.apache.tamaya.MetaInfo;
 import org.apache.tamaya.PropertySource;
 
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.UUID;
 
 /**
  * Created by Anatole on 07.12.2014.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/properties/EnvironmentPropertySource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/EnvironmentPropertySource.java b/core/src/main/java/org/apache/tamaya/core/properties/EnvironmentPropertySource.java
index 9958f8d..d0b2172 100644
--- a/core/src/main/java/org/apache/tamaya/core/properties/EnvironmentPropertySource.java
+++ b/core/src/main/java/org/apache/tamaya/core/properties/EnvironmentPropertySource.java
@@ -18,9 +18,6 @@
  */
 package org.apache.tamaya.core.properties;
 
-import org.apache.tamaya.MetaInfoBuilder;
-import org.apache.tamaya.core.properties.AbstractPropertySource;
-
 import java.util.Map;
 
 class EnvironmentPropertySource extends AbstractPropertySource {

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/properties/URLBasedPropertySource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/URLBasedPropertySource.java b/core/src/main/java/org/apache/tamaya/core/properties/URLBasedPropertySource.java
index 8086c23..1d79537 100644
--- a/core/src/main/java/org/apache/tamaya/core/properties/URLBasedPropertySource.java
+++ b/core/src/main/java/org/apache/tamaya/core/properties/URLBasedPropertySource.java
@@ -18,7 +18,6 @@
  */
 package org.apache.tamaya.core.properties;
 
-import org.apache.tamaya.AggregationPolicy;
 import org.apache.tamaya.ConfigException;
 import org.apache.tamaya.core.internal.resources.io.UrlResource;
 import org.apache.tamaya.core.resource.Resource;

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/spi/CodecProviderSpi.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/spi/CodecProviderSpi.java b/core/src/main/java/org/apache/tamaya/core/spi/CodecProviderSpi.java
deleted file mode 100644
index b814037..0000000
--- a/core/src/main/java/org/apache/tamaya/core/spi/CodecProviderSpi.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.spi;
-
-import org.apache.tamaya.Codec;
-
-/**
- * This service provides different {@link org.apache.tamaya.Codec} instances for types.
- */
-public interface CodecProviderSpi {
-
-	/**
-	 * Called, when a given {@link org.apache.tamaya.Configuration} has to be evaluated.
-	 *
-	 * @return the corresponding {@link java.util.function.Function<String, T>}, or {@code null}, if
-	 *         not available for the given target type.
-	 */
-	<T> Codec<T> getCodec(Class<T> type);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/spi/DefaultServiceComparator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/spi/DefaultServiceComparator.java b/core/src/main/java/org/apache/tamaya/core/spi/DefaultServiceComparator.java
new file mode 100644
index 0000000..2fb719c
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/spi/DefaultServiceComparator.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.spi;
+
+import java.util.*;
+
+/**
+ * Simple comparator based on a Collection of {@link OrdinalProvider} instances.
+ */
+final class DefaultServiceComparator implements Comparator<Object>{
+
+    /**
+     * List of ordinal providers loaded.
+     */
+    private List<OrdinalProvider> ordinalProviders = new ArrayList<>();
+
+    DefaultServiceComparator(Collection<? extends OrdinalProvider> providers){
+        ordinalProviders.addAll(Objects.requireNonNull(providers));
+        ordinalProviders.sort(this::compare);
+    }
+
+    private int compare(OrdinalProvider provider1, OrdinalProvider provider2){
+        int o1 = getOrdinal(provider1);
+        int o2 = getOrdinal(provider2);
+        int order = o1-o2;
+        if(order < 0){
+            return -1;
+        }
+        else if(order > 0){
+            return 1;
+        }
+        return 0;
+    }
+
+    private int getOrdinal(OrdinalProvider provider){
+        if(provider instanceof Orderable){
+            return ((Orderable)provider).order();
+        }
+        return 0;
+    }
+
+    public int getOrdinal(Object service){
+        for(OrdinalProvider provider: ordinalProviders){
+            OptionalInt ord = provider.getOrdinal(service.getClass());
+            if(ord.isPresent()){
+                return ord.getAsInt();
+            }
+        }
+        if(service instanceof Orderable){
+            return ((Orderable)service).order();
+        }
+        return 0;
+    }
+
+
+    @Override
+    public int compare(Object o1, Object o2) {
+        int ord1 = getOrdinal(o1);
+        int ord2 = getOrdinal(o2);
+        int order = ord1-ord2;
+        if(order < 0){
+            return -1;
+        }
+        else if(order > 0){
+            return 1;
+        }
+        return 0;
+    }
+}


[3/4] incubator-tamaya git commit: TAMAYA-19: Streamlined API and impl.

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/spi/DefaultServiceContextProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/spi/DefaultServiceContextProvider.java b/core/src/main/java/org/apache/tamaya/core/spi/DefaultServiceContextProvider.java
new file mode 100644
index 0000000..9a2fb1b
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/spi/DefaultServiceContextProvider.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.spi;
+
+import org.apache.tamaya.spi.ServiceContext;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * This class implements the (default) {@link org.apache.tamaya.spi.ServiceContext} interface and hereby uses the JDK
+ * {@link java.util.ServiceLoader} to load the services required.
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+class DefaultServiceContextProvider implements ServiceContext {
+    /** List current services loaded, per class. */
+	private final ConcurrentHashMap<Class, List<Object>> servicesLoaded = new ConcurrentHashMap<>();
+    /** Singletons. */
+    private final ConcurrentHashMap<Class, Optional<?>> singletons = new ConcurrentHashMap<>();
+    /** Comparator for ordering of multiple services found. */
+    private DefaultServiceComparator serviceComparator;
+
+    public DefaultServiceContextProvider(){
+        serviceComparator = new DefaultServiceComparator(getServices(OrdinalProvider.class, Collections.emptyList()));
+    }
+
+    @Override
+    public <T> Optional<T> getService(Class<T> serviceType) {
+		Optional<T> cached = (Optional<T>)singletons.get(serviceType);
+        if(cached==null) {
+            List<? extends T> services = getServices(serviceType, Collections.emptyList());
+            if (services.isEmpty()) {
+                cached = Optional.empty();
+            }
+            else{
+                cached = Optional.of(services.get(0));
+            }
+            singletons.put(serviceType, cached);
+        }
+        return cached;
+    }
+
+    /**
+     * Loads and registers services.
+     *
+     * @param serviceType
+     *            The service type.
+     * @param <T>
+     *            the concrete type.
+     * @param defaultList
+     *            the list current items returned, if no services were found.
+     * @return the items found, never {@code null}.
+     */
+    @Override
+    public <T> List<? extends T> getServices(final Class<T> serviceType, final List<? extends T> defaultList) {
+        List<T> found = (List<T>) servicesLoaded.get(serviceType);
+        if (found != null) {
+            return found;
+        }
+        return loadServices(serviceType, defaultList);
+    }
+
+    /**
+     * Loads and registers services.
+     *
+     * @param   serviceType  The service type.
+     * @param   <T>          the concrete type.
+     * @param   defaultList  the list current items returned, if no services were found.
+     *
+     * @return  the items found, never {@code null}.
+     */
+    private <T> List<? extends T> loadServices(final Class<T> serviceType, final List<? extends T> defaultList) {
+        try {
+            List<T> services = new ArrayList<>();
+            for (T t : ServiceLoader.load(serviceType)) {
+                services.add(t);
+            }
+            if(services.isEmpty()){
+                services.addAll(defaultList);
+            }
+            if(!serviceType.equals(OrdinalProvider.class)) {
+                services.sort(serviceComparator);
+            }
+            services = Collections.unmodifiableList(services);
+            final List<T> previousServices = (List<T>) servicesLoaded.putIfAbsent(serviceType, (List<Object>)services);
+            return previousServices != null ? previousServices : services;
+        } catch (Exception e) {
+            Logger.getLogger(DefaultServiceContextProvider.class.getName()).log(Level.WARNING,
+                                                                         "Error loading services current type " + serviceType, e);
+            return defaultList;
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/spi/Orderable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/spi/Orderable.java b/core/src/main/java/org/apache/tamaya/core/spi/Orderable.java
new file mode 100644
index 0000000..5397776
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/spi/Orderable.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.spi;
+
+/**
+ * Interface that can be optionally implemented by SPI components to be loaded into
+ * the Tamaya's ServiceContext. The ordinal provided will be used to determine
+ * priority and precedence, when multiple components implement the same
+ * service interface.
+ */
+@FunctionalInterface
+public interface Orderable {
+    /**
+     * Get the ordinal keys for the component, by default 0.
+     * @return the ordinal keys
+     */
+    int order();
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/spi/OrdinalProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/spi/OrdinalProvider.java b/core/src/main/java/org/apache/tamaya/core/spi/OrdinalProvider.java
new file mode 100644
index 0000000..2d7f057
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/spi/OrdinalProvider.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.spi;
+
+import java.util.OptionalInt;
+
+/**
+ * The ordinal provider is an optional component that provides an abstraction for ordering/prioritizing
+ * services loaded. This can be used to determine, which SPI should be used, if multiple instances are
+ * available, or for ordering chain of services.
+ * @see org.apache.tamaya.spi.ServiceContext
+ */
+public interface OrdinalProvider {
+    /**
+     * Evaluate the ordinal number for the given type.
+     * @param type the target type, not null.
+     * @return the ordinal, if not defined, 0 should be returned.
+     */
+     OptionalInt getOrdinal(Class<?> type);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/java/org/apache/tamaya/core/spi/PropertyAdapterProviderSpi.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/spi/PropertyAdapterProviderSpi.java b/core/src/main/java/org/apache/tamaya/core/spi/PropertyAdapterProviderSpi.java
new file mode 100644
index 0000000..b8e7122
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/spi/PropertyAdapterProviderSpi.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.spi;
+
+import org.apache.tamaya.PropertyAdapter;
+
+/**
+ * This service provides different {@link org.apache.tamaya.PropertyAdapter} instances for types.
+ */
+public interface PropertyAdapterProviderSpi {
+
+	/**
+	 * Called, when a given {@link org.apache.tamaya.Configuration} has to be evaluated.
+	 *
+	 * @return the corresponding {@link java.util.function.Function<String, T>}, or {@code null}, if
+	 *         not available for the given target type.
+	 */
+	<T> PropertyAdapter<T> getPropertyAdapter(Class<T> type);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.CodecSpi
----------------------------------------------------------------------
diff --git a/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.CodecSpi b/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.CodecSpi
deleted file mode 100644
index c0a61aa..0000000
--- a/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.CodecSpi
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy current the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-org.apache.tamaya.core.internal.config.DefaultCodecSpi

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi
----------------------------------------------------------------------
diff --git a/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi b/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi
new file mode 100644
index 0000000..0554453
--- /dev/null
+++ b/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy current the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.tamaya.core.internal.config.DefaultPropertyAdapterSpi

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/test/java/org/apache/tamaya/ucs/UC1ReadProperties.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/tamaya/ucs/UC1ReadProperties.java b/core/src/test/java/org/apache/tamaya/ucs/UC1ReadProperties.java
index 7571c1e..50e1753 100644
--- a/core/src/test/java/org/apache/tamaya/ucs/UC1ReadProperties.java
+++ b/core/src/test/java/org/apache/tamaya/ucs/UC1ReadProperties.java
@@ -26,11 +26,10 @@ import static org.junit.Assert.assertNotNull;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-import org.apache.tamaya.AggregationPolicy;
 import org.apache.tamaya.Configuration;
-import org.apache.tamaya.MetaInfo;
 import org.apache.tamaya.PropertySource;
 import org.apache.tamaya.core.config.ConfigFunctions;
+import org.apache.tamaya.core.properties.AggregationPolicy;
 import org.apache.tamaya.core.properties.PropertySourceBuilder;
 import org.junit.Test;
 
@@ -88,7 +87,6 @@ public class UC1ReadProperties {
         assertNotNull(config);
         assertTrue(config.isEmpty());
         assertTrue(config.getProperties().isEmpty());
-        assertFalse(config.isMutable());
     }
 
     @Test
@@ -97,7 +95,6 @@ public class UC1ReadProperties {
         assertNotNull(provider);
         assertTrue(provider.isEmpty());
         assertTrue(provider.getProperties().isEmpty());
-        assertFalse(provider.isMutable());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/core/src/test/java/org/apache/tamaya/ucs/UC2CombineProperties.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/tamaya/ucs/UC2CombineProperties.java b/core/src/test/java/org/apache/tamaya/ucs/UC2CombineProperties.java
index 3a6e471..60ab6ea 100644
--- a/core/src/test/java/org/apache/tamaya/ucs/UC2CombineProperties.java
+++ b/core/src/test/java/org/apache/tamaya/ucs/UC2CombineProperties.java
@@ -18,10 +18,9 @@
  */
 package org.apache.tamaya.ucs;
 
-import org.apache.tamaya.AggregationPolicy;
 import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.MetaInfo;
 import org.apache.tamaya.PropertySource;
+import org.apache.tamaya.core.properties.AggregationPolicy;
 import org.apache.tamaya.core.properties.PropertySourceBuilder;
 import org.junit.Test;
 
@@ -34,7 +33,7 @@ import org.junit.Test;
 public class UC2CombineProperties {
 
     /**
-     * The most common use cases is aggregating two property config to new provider, hereby {@link org.apache.tamaya.AggregationPolicy}
+     * The most common use cases is aggregating two property config to new provider, hereby {@link org.apache.tamaya.core.properties.AggregationPolicy}
      * defines the current variants supported.
      */
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/design/2_API.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/design/2_API.adoc b/docs/src/main/asciidoc/design/2_API.adoc
new file mode 100644
index 0000000..69a06c1
--- /dev/null
+++ b/docs/src/main/asciidoc/design/2_API.adoc
@@ -0,0 +1,469 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+<<<
+[[API]]
+== The Tamaya API
+=== Overview
+Though Tamaya is a very powerful and flexible solution there are basically only a few simple core concepts required that build
+the base of all the other mechanisms:
+
+The API provides these artifacts, which are:
+
+* A simple but complete SE API for accessing key/value based _Configuration_.
+* _Configuration_ hereby models configuration and as well provides the static entry point to access configuration.
+  _ Configuration_ provides
+     ** access to literal key/value pairs.
+     ** +PropertyAdapter+ support to convert String values to arbitrary non-String types for type safe configuration access.
+     ** functional extension points (+with,query+) based un +UnaryOperator<Configuration>+ (operator) and +Function<Configuration,T>+ (query).
+     ** provides static access to the current +Configuration+ (default configuration)
+     ** provides static access to the additional named +Configuration+ instances
+     ** a service to inject configuration into beans, including listener and callback support
+     ** a service for creating onfiguration _templates_ based on interfaces.
+* +PropertyAdapter+ defines a functional interface for converting String values into any required target types. It also
+  provides static access to the adapters registered to implement transparent type conversion as needed, if possible.
+* _PropertySource:_ is the the SPI for a source that provides configuration data. A +PropertySource+
+     hereby
+     ** is designed as a minimalistic data interface to be implemented by any kind of data providers (local or remote)
+     ** provides data key/value pairs in raw format as String key/values only
+     ** can optionally support scanning of its provided values
+
+* _Annotations_ a set of annotations allows to configure configuration injection on classes or interface (aka config templates).
+
+The SPI contains the following core concepts/artifacts:
+
+* _ServiceContext_ is the delegate singleton that is used by the framework to resolve components. The effective component
+  loading can be accessed by implementing and registering an instance of +ServiceContextProvider+ using +java.util.ServiceLoader+.
+* All the singleton used explicitly (+Configuration, PropertyAdapter+) are backed up corresponding API interfaces
+  (+ConfigurationSpi, PropertyAdapterSpi+).
+  To override a singleton's behaviour the corresponding SPI has to be implemented and registered, so it can be loaded
+  by the current +ServiceContext+ setup (by default ServiceLoader based).
+
+This is also reflected in the main parts of the API, which is quite small:
+
+* +org.apache.tamaya+ contains the main abstractions +Configuration, ConfigQuery, PropertyAdapter,
+  PropertySource+ and +ConfigException+
+* +org.apache.tamaya.spi+ contains the SPI interfaces to be implemented by implementations and the +ServiceContextManager+
+  mechanism (+ConfigurationSpi, PropertyAdapterSpi, ServiceContext+).
++ +org.apache.tamaya.annot+ contains the annotations defined to control configuration injection.
+
+So basically an implementation has to implement the SPIs provided. The +ServiceContext+ only has to be overridden, when
+a default SE +java.util.ServiceLoader+ mechanism is not sufficient.
+
+[[APIKeyValues]]
+=== Key/Value Pairs
+
+Basically configuration is a very generic concept. Therefore it should be modelled in a generic way. The most simple
+and most commonly used approach are simple literal key/value pairs. So the core building block of {name} are key/value pairs.
+You can think of a common +.properties+ file, e.g.
+
+[source,properties]
+.A simple properties file
+--------------------------------------------
+a.b.c=cVal
+a.b.c.1=cVal1
+a.b.c.2=cVal2
+a=aVal
+a.b=abVal
+a.b2=abVal
+--------------------------------------------
+
+Now you can use +java.util.Properties+ to read this file and access the corresponding properties, e.g.
+
+[source,properties]
+.Accessing some properties
+--------------------------------------------
+Properties props = new Properties();
+props.readProperties(...);
+String val = props.getProperty("a.b.c");
+val = props.getProperty("a.b.c.1");
+...
+--------------------------------------------
+
+This looks familiar to most of you. Nevertheless when looking closer to the above key/value pairs,
+there are more things in place: looking at the keys +a.b.c+, +a.b.c.1+, +a.b.c.2+, +a+, +a.b+ we
+see that the key names build up a flattened tree structure. So we can define the following:
+
+Given a key +p1.p2.p3.k=value+:
+
+* +p1.p2.p3.k+ is called the _qualified key_
+* +p1.p2.p3+ is the key's _area_
+* the child areas +p1.p2", "p1+ are called _areas_ as well
+* +k+ is the _(unqualified) key_
+
+This terminology is used also later ta some locations. Nevertheless given that you can perform some very useful actions:
+
+* you can filter the keys with an area. E.g. in the example before you can query for all keys within the area +a.b.c+
+  and map them to new property set.
+* you can access all child keys of an area
+* you can evaluate the areas present.
+* ...and more.
+
+All this kind of actions (and more) must not be included in the API, because they can be modelled as +ConfigQuery+ instances and
+implemented/provided by implementation code.
+
+
+==== Why Using Strings Only
+
+There are good reason to keep of non String-values as core storage representation of configuration. Mostly
+there are several huge advantages:
+
+* Strings are simple to understand
+* Strings are human readable and therefore easy to prove for correctness
+* Strings can easily be used within different language, different VMs, files or network communications.
+* Strings can easily be compared and manipulated
+* Strings can easily be searched, indexed and cached
+* It is very easy to provide Strings as configuration, which gives much flexibility for providing configuration in
+  production as well in testing.
+* and more...
+
+On the other side there are also disadvantages:
+
+* Strings are inherently not type safe, they do not provide validation out of the box for special types, such as
+numbers, dates etc.
+* In many cases you want to access configuration in a typesafe way avoiding conversion to the target types explicitly
+  throughout your code.
+* Strings are neither hierarchical nor multi-valued, so mapping hierarchical and collection structures requires some
+  extra efforts.
+
+Nevertheless most of these advantages can be mitigated easily, hereby still keeping all the benefits from above:
+
+* Adding type safe adapters on top of String allow to add any type easily, that can be directly mapped out of Strings.
+  This includes all common base types such as numbers, dates, time, but also timezones, formatting patterns and more.
+* Also multi-valued, complex and collection types can be defined as a corresponding +PropertyAdapter+ knows how to
+  parse and create the target instance required.
+* String s also can be used as references pointing to other locations and formats, where configuration is
+  accessible.
+
+
+[API PropertySource]
+=== PropertySource
+==== Basic Model
+
+We have seen that constraining configuration aspects to simple literal key/value pairs provides us with an easy to
+understand, generic, flexible, yet expendable mechanism. Looking at the Java language features a +java.util.Map<String,
+String>+ and +java.util.Properties+ basically model these aspects out of the box.
+
+Though there are advantages in using these types as a model, there are some severe drawbacks, mostly implementation
+of these types is far not trivial or the basic model has sever drawbacks, because of backward compatibility with
+the original collection API.
+
+To make implementation of a custom property source as convinient as possible only the following methods were
+identified to be necessary:
+
+[source,java]
+.Interface PropertySource
+--------------------------------------------
+public interface PropertySource{
+
+      Optional<String> get(String key);
+      boolean isBrowseable();
+      Map<String, String> getProperties();
+
+}
+--------------------------------------------
+
+Hereby
+
+* +get+ looks similar to the methods on +Map+, though +get+ uses the +Optional+ type introduced
+  with Java 8. This avoids returning +null+ or throwing exceptions in case no such entry is available and also
+  reduces the API's footprint, since default values can be easily implemented by calling +Optional.orElse+ and
+  similar methods.
+* +getProperties+ allows to extract mapped data to a +Map+. Other methods like +containsKey, keySet+ as well as
+  streaming operations then can be applied on the returned +Map+ instance.
+* But not in all scenarios a property source may be browseable. This can be evaluated by calling +isBrowseable()+.
+
+This interface can be implemented by any kind of logic. It could be a simple in memory map, a distributed configuration
+provided by a data grid, a database, the JNDI tree or other resources. Or it can be a combination of multiple
+property sources with additional combination/aggregation rules in place.
+
+==== Meta Information
+
+Meta information is not explicitly modelled, since it can be easily added by some key naming schemes. E.g. look at
+the example below, which return a map of all metadata keys for +a.b.c+.:
+
+[source,java]
+.Modelling Meta Data
+--------------------------------------------
+PropertySource src = ...;
+Map<String, String> metaData = src.getArea("a.b.c[meta]");
+--------------------------------------------
+
+The API does not provide any explicit support for meta-data, whereas implementations may provide metadata editors
+or readers.
+
+==== Mutability
+
+In general Property sources can be modeled as mutable. Nevertheless the API does not support out of the box mutability,
+due to the following reasons:
+
+* Mutability is rather complex
+* Mutability is only rarely required
+* Mutability can be implemented in various ways
+
+As a consequence mutability mechanisms may be provided by implementations as needed, but are not part of the API.
+
+
+[[API Configuration]]
+=== Configuration
+==== Basic Model: Extending PropertySource
+
++Configuration+ inherits all basic features from +PropertySource+, but additionally adds functionality for
+type safety and external features of any interacting with configuration:
+
+[source,java]
+.Interface Configuration
+--------------------------------------------
+public interface Configuration extends PropertySource{
+    // type support
+    default Optional<Boolean> getBoolean(String key);
+    default OptionalInt getInteger(String key);
+    default OptionalLong getLong(String key);
+    default OptionalDouble getDouble(String key);
+    default <T> Optional<T> getAdapted(String key, PropertyAdapter<T> adapter);
+    <T> Optional<T> get(String key, Class<T> type);
+
+    // extension points
+    default Configuration with(UnaryOperator<Configuration> operator);
+    default <T> T query(ConfigQuery<T> query);
+}
+--------------------------------------------
+
+Hereby
+
+* +XXX getXXX(String)+ provide type safe accessors for all basic wrapper types of the JDK. Basically all this
+  methods delegate to the +getAdapted+ method, additionally passing the required +PropertyAdapter+.
+* +getAdapted+ allow accessing any type, hereby also passing a +PropertyAdapter+ that converts
+  the configured literal value to the type required.
+* +with, query+ provide the extension points for adding additional functionality.
+
+Additionally +Configuration+ provides several access methods:
+
+[source,java]
+.Interface Configuration
+--------------------------------------------
+public interface Configuration extends PropertySource{
+   ...
+
+    // accessors for configuration
+    public static Configuration current();
+    public static Configuration current(String name);
+    public static boolean isAvailable(String name);
+    // accessors for template and injection
+    public static <T> T createTemplate(Class<T> template, Configuration... configurations);
+    public static void configure(Object instance, Configuration... configurations);
+}
+--------------------------------------------
+
+Hereby
+* +current()+ returns the _default_ +Configuration+
+* +current(String name)+ returns a named +Configuration+ (there may be arbitrary additional +Configuration+ instance
+  additionally to the default +Configuration+ instance.
+* +isAvailable(String name)+ allows to determine if a named +Configuration+ is available.
+* +createTemplate(Class<T> template, Configuration... configurations)+ allows to create a new template instance based
+  on a (optionally) annotated interface. The according getter methods are backed up and implemented by Tamaya based
+  on the configuration values available. The +configurations+ parameter allows parts of +Configuration+ instances to be
+  passed that override any instances available through +current(name), current()+.
+* +configure+ performs injection of configured values on a (optionally) annotated non abstract type.
+  The +configurations+ parameter allows parts of +Configuration+ instances to be
+  passed that override any instances available through +current(name), current()+.
+
+
+[[TypeConversion]]
+==== Type Conversion
+
+Configuration extend +PropertySource+ and adds additional support for non String types. This is achieved
+with the help of +PropertyAdapter+ instances:
+
+[source,java]
+.PropertyAdapter
+--------------------------------------------
+@FunctionalInterface
+public interface PropertyAdapter<T>{
+    T adapt(String value);
+}
+--------------------------------------------
+
++PropertyAdapter+ instances can be implemented manually or registered and accessed from the
++PropertyAdaper+ using static methods. Hereby the exact mechanism is determined by the implementation
+of +PropertyAdapterSpi+ backing up the static methods.
+By default corresponding +PropertyAdapter+ instances can be registered using the Java +ServiceLoader+
+mechanism, or programmatically ba calling the +register(Class, PropertyAdapter)+.
+
+[source,java]
+.PropertyAdapter
+--------------------------------------------
+@FunctionalInterface
+public interface PropertyAdapter<T>{
+    T adapt(String value);
+
+    public static <T> PropertyAdapter<T> register(Class<T> targetType, PropertyAdapter<T> adapter);
+    public static boolean isTargetTypeSupported(Class<?> targetType);
+    public static  <T> PropertyAdapter<T> getAdapter(Class<T> targetType);
+    public static  <T> PropertyAdapter<T> getAdapter(Class<T> targetType, WithPropertyAdapter annotation);
+}
+--------------------------------------------
+
+The now a typed instance of a +Configuration+ is required, by default the +Configuration+ implementation acquires
+a matching +PropertyAdapter+. If one is found it can easily pass the String value from its String property store
+for converting it to the required target type. In the normal case for the mostly needed types this is completely
+transparent to the user.
+But basically this mechanism can also be used for adaptive filtering of values accessed. As an example lets assume
+we want to decode an encryped password on the fly, so we can achieve this with as less code as follows:
+
+[source,java]
+.Simple Filtering Adapter Use Case
+--------------------------------------------
+Configuration config = Configuration.cuirrent();
+String decryptedPassword = config.getAdapted(String.class, "user.password", p -> PKI.decrypt(p));
+--------------------------------------------
+
+[[Injection]]
+=== Inversion of Control
+==== Overview
+
+Inversion of Control (aka IoC/the Hollywood Principle) has proven to be very handy and effective in avoiding boilerplate
+code. In Java there are different frameworks available that all provide IoC mechanisms. Unfortunately IoC is not a
+built-in language feature. So for a portable solution OOTB that works also in Java SE Tamaya itself has to provide the
+according injection services. As an example refer to the following example:
+
+[source,java]
+.Annotated Example Class
+--------------------------------------------
+public class ConfiguredClass{
+
+    // resolved by default, using property name, class and package name
+    private String testProperty;
+
+    @ConfiguredProperty(config="pluginConfig", keys={"a.b.c.key1","a.b.legacyKey"})
+    @ConfiguredProperty(config="productConfig", keys="area1.key2")
+    @DefaultValue("The current \\${JAVA_HOME} env property is ${env:JAVA_HOME}.")
+    String value1;
+
+    @ConfiguredProperty(keys="a.b.c.key2")
+    private int value2;
+
+    // resolved by default
+    @DefaultValue("http://127.0.0.1:8080/res/api/v1/info.json")
+    private URL accessUrl;
+
+    // Config injection disabled for this property
+    @NoConfig
+    private Integer int1;
+
+    @ConfiguredProperty("BD")
+    @WithAdapter(MyBigDecimalRoundingAdapter.class)
+    private BigDecimal bigNumber;
+
+    ...
+}
+--------------------------------------------
+
+The class does not show all (but most all) the possibilities that are provided. Configuring an instance of the
+class using Tamaya is very simple:
+
+[source,java]
+.Configuring the +ConfiguredClass+ Instance
+--------------------------------------------
+ConfiguredClass classInstance = new ConfiguredClass();
+Configuration.configure(configuredClass);
+--------------------------------------------
+
+==== The Annotations in detail
+
+tbd
+
+The +Configuration+ interface provides static methods that allow to any kind of instances be configured
+ny just passing the instances calling +Configuration.configure(instance);+. The classes passed hereby must
+be annotated with +@ConfiguredProperty+ to define the configured properties. Hereby this annotation can be
+used in multiple ways and combined with other annotations such as +@DefaultValue+,
++@WithLoadPolicy+, +@WithConfig+, +@WithConfigOperator+, +@WithPropertyAdapter+.
+
+To illustrate the mechanism below the most simple variant of a configured class is given:
+
+[source,java]
+.Most simple configured class
+--------------------------------------------
+pubic class ConfiguredItem{
+  @ConfiguredProperty
+  private String aValue;
+}
+--------------------------------------------
+
+When this class is configured, e.g. by passing it to +Configuration.configure(Object)+,
+the following is happening:
+
+* The current valid +Configuration+ is evaluated by calling +Configuration cfg = Configuration.of();+
+* The current property value (String) is evaluated by calling +cfg.get("aValue");+
+* if not successful, an error is thrown (+ConfigException+)
+* On success, since no type conversion is involved, the value is injected.
+* The configured bean is registered as a weak change listener in the config system's underlying
+  configuration, so future config changes can be propagated (controllable by applying the
+  +@WithLoadPolicy+ annotation).
+
+In the next example we explicitly define the property value:
+[source,java]
+--------------------------------------------
+pubic class ConfiguredItem{
+
+  @ConfiguredProperty
+  @ConfiguredProperty("a.b.value")
+  @configuredProperty("a.b.deprecated.value")
+  @DefaultValue("${env:java.version}")
+  private String aValue;
+}
+--------------------------------------------
+
+Within this example we evaluate multiple possible keys. Evaluation is aborted if a key could be successfully
+resolved. Hereby the ordering of the annotations define the ordering of resolution, so in the example above
+resolution equals to +"aValue", "a.b.value", "a.b.deprecated.value"+. If no value could be read
+from the configuration, it uses the value from the +@DefaultValue+ annotation. Interesting here
+is that this value is not static, it is evaluated by calling +Configuration.evaluateValue(Configuration, String)+.
+
+
+=== Extension Points
+
+We are well aware of the fact that this library will not be able to cover all kinds of use cases. Therefore
+we have added functional extension mechanisms to +Configuration+ that were used in other areas of the Java eco-system as well:
+
+* +with(UnaryOperator<Configuration> operator)+ allows to pass arbitrary functions that take adn return instances of +Configuration+.
+  They can be used to cover use cases such as filtering, configuration views, security interception and more.
+* +query(Function<Configuration,T> query)+ ConfigQuery+ defines a function returning any kind of result based on a
+  configuration instance. Queries are used for accessing/deriving any kind of data of a +Configuration+ instance,
+  e.g. accessing a +Set<String>+ of area keys present.
+
+Both interfaces hereby are functional interfaces, defined in +java.util.function+ and can be applied using Lambdas or
+method references:
+
+[source,java]
+.Applying a Configuration Query
+--------------------------------------------
+ConfigSecurity securityContext = Configuration.current().query(ConfigSecurity::targetSecurityContext);
+--------------------------------------------
+
+NOTE: +ConfigSecurity+ is an arbitrary class.
+
+Or an operator calls looks as follows:
+
+[source,java]
+.Applying a Configuration Operators
+--------------------------------------------
+Configuration secured = Configuration.current().with(ConfigSecurity::secure);
+--------------------------------------------
+
+
+== SPI
+

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a60570e8/docs/src/main/asciidoc/design/2_CoreConcepts.adoc
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/design/2_CoreConcepts.adoc b/docs/src/main/asciidoc/design/2_CoreConcepts.adoc
deleted file mode 100644
index 831a71f..0000000
--- a/docs/src/main/asciidoc/design/2_CoreConcepts.adoc
+++ /dev/null
@@ -1,849 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-<<<
-[[CoreConcepts]]
-== {name} Core Concepts
-Though {name} is a very powerful and flexible solution there are basically only a few simple core concepts required that build
-the base of all the other mechanisms:
-
-The API contains the following core concepts/artifacts:
-
-* Literal Key/Value Pairs
-* _PropertySource:_ is the the SPI for a source that provides configuration data. A +PropertySource+
-     hereby defines
-     ** a minimalistic SPI to be implemented by the config data source
-     ** provides data key/value pairs in raw format as String key/values only
-     ** providers should not have any dependencies other than to the datasource
-     ** providers may read context dependent data, but basically providers themselves are not contextual.
-        Context management should be done by the ConfigurationProvider implementation that also is responsible
-        for combining a set of property providers to a Configuration.
-  _Configuration_ is the API that users of Tamaya will see, when they access configuration in raw format. Hereby +Configuration+
-     ** adds type support for non String types
-     ** provides functional extension points (+with,query+)
-     ** allows registering/deregistering of change listeners
-     ** is the entry point for evaluating the current +Configuration+
-     ** each +PropertySource+ can be easily converted into a +Configuration+
-     ** allows configuration entries to be injected
-     ** to access configuration _templates_ (annotated interfaces).
-     ** Configuration may support mutability by allowing instances of +ConfigChangeSet+ to be passed.
-* _PropertySourceBuilder_ allows to aggregate different property sources. Hereby property sources are
-  seen as sets, which can be combined to new sources using set styled operations (aggregation, intersection, subtraction).
-  This allows to model and create composite sources, to build up more complex configuration models
-  step by step.
-* _MetaInfo_ is provided by each +Configuration, PropertySource+ and describes the configuration/provider and its entries.
-* _Environment_ is the base model for modelling the environment and the accessor for getting the current +Environment+ instance.
-* _Annotations_ a set of annotations allows to configure configuration injection on classes or interface (aka config templates).
-
-The SPI contains the following core concepts/artifacts:
-
-* _ServiceContext_ is the delegate singleton that is used by the framework to resolve components. The effective component
-  loading can be accessed by implementing and registering an instance of +ServiceContextProvider+ using +java.util.ServiceLoader+.
-* All the singleton used explicitly (+Environment,Configuration+ are backed up corresponding API interfaces.
-  To override a singleton's behaviour the corresponding SPI has to be implemented and registered, so it can be loaded
-  by the current +ServiceContext+ setup (by default ServiceLoader based).
-* Also the singleton used implicitly by +Configuration, Environment+ are backed up corresponding SPI interfaces.
-  To override a singleton's behaviour the corresponding SPI has to be implemented and registered, so it can be loaded
-  by the current +ServiceContext+ setup (by default ServiceLoader based).
-
-This is also reflected in the main parts of the API, which is quite small:
-
-* +org.apache.tamaya+ contains the main abstractions +Configuration, ConfigQuery, PropertyAdapter,
-  Environment, PropertySource, MetaInfo+
-* +org.apache.tamaya.spi+ contains the SPI interfaces to be implemented by implementations and the +ServiceContext+ mechanism.
-+ +org.apache.tamaya.annot+ contains the annotations defined.
-
-In the implementation are there are additional projects:
-
-* +org.apache.tamaya.core+ contains the core implementation of the API. Deploying it together with the API results in a
-  flexible framework that can be easily used for configuration of different complexity. But out of the box this framework
-  will not do much more than exposing system and environment properties, its power comes when an additional meta-model
-  is defined and deployed. Hereby you can write your own, or use on e of the provided ones (see later).
-* the core part is extended by multiple additional modules
-  ** CDI integration
-  ** Default configuration meta-models and providers for the most common usage scenarios
-    *** standalone applications
-    *** Java EE
-    *** ...
-
-These parts are explained in the following sections. It is recommended that user's of the API read through this part.
-All subsequent parts are building upon this concepts and may be more difficult to understand without having read
-this section.
-
-
-[[APIKeyValues]]
-=== Key/Value Pairs
-
-Basically configuration is a very generic concept. Therefore it should be modelled in a generic way. The most simple
-and similarly most commonly used are simple literal key/value pairs. So the core building block of {name} are key/value pairs.
-You can think of a common +.properties+ file, e.g.
-
-[source,properties]
-.A simple properties file
---------------------------------------------
-a.b.c=cVal
-a.b.c.1=cVal1
-a.b.c.2=cVal2
-a=aVal
-a.b=abVal
-a.b2=abVal
---------------------------------------------
-
-Now you can use +java.util.Properties+ to read this file and access the corresponding properties, e.g.
-
-[source,properties]
-.Accessing some properties
---------------------------------------------
-Properties props = new Properties();
-props.readProperties(...);
-String val = props.getProperty("a.b.c");
-val = props.getProperty("a.b.c.1");
-...
---------------------------------------------
-
-This looks familiar to most of you. Nevertheless when looking closer to the above key/value pairs,
-there are more concepts in place: looking at the keys +a.b.c+, +a.b.c.1+, +a.b.c.2+, +a+, +a.b+ we
-see that the key names build up a flattened tree structure. So we can define the following:
-
-Given a key +p1.p2.p3.k=value+:
-
-* +p1.p2.p3.k+ is called the _qualified key_
-* +p1.p2.p3+ is the key's _area_
-* the child areas +p1.p2", "p1+ are called _areas_ as well
-* +k+ is the _(unqualified) key_
-
-Given that you can perform some very useful actions:
-
-* you can filter the keys with an area. E.g. in the example before you can query for all keys within the area +a.b.c+
-  and map them to new properties set as follows:
-
-[source,properties]
-.Accessing an area
---------------------------------------------
-1=cVal1
-2=cVal2
---------------------------------------------
-
-Similarly accessing the area +a+ results in the following properties:
-
-[source,properties]
-.Accessing the area +a+
---------------------------------------------
-b=abVal
-b2=abVal
---------------------------------------------
-
-Additionally you can access all values of an area recursively, so accessing +a+ recursively results in
-the following properties:
-
-[source,properties]
-.Accessing area +a+ recursively
---------------------------------------------
-b.c=cVal
-b.c.1=cVal1
-b.c.2=cVal2
-b=abVal
-b2=abVal
---------------------------------------------
-
-Why this is useful? Well there are different use cases:
-
-* you can segregate your configuration properties, e.g. a module can access its module configuration by
-  querying all properties under the area +config.modules.myModule+ (or whatever would be appropriate).
-* you can use this mechanism to configure maps (or more generally: collections).
-* you can easily filter parts of configuration
-* ...and more.
-
-==== Why Using Strings Only
-
-Using Strings as base representation of configuration comes with several huge advantages:
-
-* Strings are simple to understand
-* Strings are human readable and therefore easy to prove for correctness
-* Strings can easily be used within different language, different VMs, files or network communications.
-* Strings can easily be compared and manipulated
-* Strings can easily be searched, indexed and cached
-* It is very easy to provide Strings as configuration, which gives much flexibility for providing configuration in
-  production as well in testing.
-* and more
-
-On the other side there are also disadvantages:
-
-* Strings are inherently not type safe, they do not provide validation out of the box for special types, such as
-numbers,
-  dates etc.
-* Often you want not to work with Strings, but with according types.
-* Strings are not hierarchical, so mapping hierarchical structures requires some extra efforts.
-
-Nevertheless most of these advantages can be mitigated easily, hereby still keeping all the benefits from above:
-
-* Adding type safe converters on top of String allow to add any type easily, that can be directly mapped out of Strings.
-  This includes all common base types such as numbers, dates, time, but also timezones, formatting patterns and more.
-* Even more complex mappings can be easily realized, by using String not as a direct representation of configuration,
-  but a reference that defines where the more complex configuration artifact is available. This mechanism is similarly
-  easy to understand as parsing Strings to numbers, but is powerful enough to provide e.g. all kind of deployment
-  descriptors in Java EE.
-* Hierarchical and collection types can be mapped in different ways:
-** The keys of configuration can have additional syntax/semantics. E.g. when adding dor-separating path semantics
-*** trees/maps can also simply be mapped.
-
-[API PropertySource]
-=== PropertySource
-==== Basic Model
-
-We have seen that constrain configuration aspects to simple literal key/value pairs provides us with an easy to
-understand, generic, flexible, yet expendable mechanism. Looking at the Java language features a +java.util.Map<String,
-String>+ and +java.util.Properties+ basically model these quite well out of the box.
-So it would make sense to build configuration on top of the JDK's +Map+ interface. This creates immediately additional
-benefits:
-
-* we inherit full Lambda and collection support
-* Maps are widely known and well understood
-
-Nevertheless there are some severe drawbacks:
-
-* +Configuration+ also requires meta-data, such as
-** the origin of a certain configuration entry and how it was derived from other values
-** the sensitivity of some data
-** the provider that have read the data
-** the time, when the data was read
-** the timestamp, when some data may be outdated
-** ...
-
-Basically the same is also the not related to some single configuration key, but also to a whole map.
-The +PropertySource+ interface models exact these aspects and looks as illustrated below:
-
-[source,java]
-.Interface PropertySource
---------------------------------------------
-public interface PropertySource{
-
-      Optional<String> get(String key);
-      boolean containsKey(String key);
-      Map<String, String> toMap();
-      MetaInfo getMetaInfo();
-
-      default Set<String> keySet();
-      default ConfigChangeSet load();
-      default boolean isMutable();
-      default void apply(ConfigChangeSet change);
-}
---------------------------------------------
-
-Hereby
-
-* +getMetaInfo()+ return the meta information for the property provider, as well as for individual property key/value pairs.
-* +get+ look similar to the methods on +Map+, though +get+ uses the +Optional+ type introduced
-  with Java 8. This avoids returning +null+ or throwing exceptions in case no such entry is available and also
-  reduced the API's footprint, since default values can be easily implemented by calling +Optional.orElse+.
-* +containsKey, keySet+ are as well methods similar to +java.util.Map+ though implementations may only returns
-  limited data, especially when the underlying map storage does not support iteration.
-* +isMutable()+ allows to easy check, if a property provider is mutable, which is more elegant than catching
-  +NonSupportedOperation+ exception thrown on the according methods of +Map+.
-* +load()+ finally allows to (re)load a property map. It depends on the implementing source, if this operation
-  has any effect. If the map changes an according +ConfigChange+ must be returned, describing the
-  changes applied.
-* +toMap+ allows to extract thing to a +Map+. Similar to +containsKey, keySet+ implementations may only return
-  a limited data map, especially when the underlying map storage does not support iteration.
-
-This simple model will be used within the spi, where configuration can be injected/provided from external resources.
-But we have seen, that we have to consider additional aspects, such as extendability and type safety. Therefore we
-extend +PropertySource+ and hereby also apply the 'composite pattern', which results in the following key abstraction.
-
-==== Meta Information
-
-Each instance also provides an instance of +MetaInfo+, which provides meta information for the providers and its properties:
-
-[source,java]
-.Accessing Meta Information
---------------------------------------------
-PropertySource prov = ...;
-MetaInfo metaInfo = prov.getMetaInfo();
-Set<String> keys = metaInfo.keySet();  // returns the attribute keys, for which meta-information is accessible.
-String metaData = metaInfo.get("a.b.c.value"); // access meta information
-String itemName = metaInfo.getName(); // access meta information for the provider
---------------------------------------------
-
-As we have seen above there is as well a +MetaInfoBuilder+, which must be used to create instances of
-+MetaInfo+.
-
-==== Mutability
-
-Property sources optionally may be mutable. This can be checked by calling +boolean isMutable()+. If a source
-is mutable a +ConfigChangeSet+ can be passed. This change set can then be applied by the source. On creation
-of the +ConfigChangeSetBuilder+ a source can pass version information, so _optimistic locking_ can be implemented
-easily:
-
-[source,java]
-.Creating and applying a +ConfigChangeSet+ to a PropertySource
---------------------------------------------
-PropertySource source = ...;
-ConfigChangeSet changeSet = ConfigChangeSetBuilder.of(provider)  // creating a default version
-   .remove("key1ToBeRemoved", +key2ToBeRemoved")
-   .put("key2", "key2Value")
-   .put("key3", 12345)
-   .put("key4", 123.45)
-   .build();
-source.apply(changeSet);
---------------------------------------------
-
-
-[[API Configuration]]
-=== Configuration
-==== Basic Model
-
-Configuration inherits all basic features from +PropertySource+, but additionally adds functionality for
-type safety and extension mechanisms:
-
-[source,java]
-.Interface Configuration
---------------------------------------------
-public interface Configuration extends PropertySource{
-
-    default Optional<Boolean> getBoolean(String key);
-    default OptionalInt getInteger(String key);
-    default OptionalLong getLong(String key);
-    default OptionalDouble getDouble(String key);
-    default <T> Optional<T> getAdapted(String key, PropertyAdapter<T> adapter);
-    <T> Optional<T> get(String key, Class<T> type);
-
-    // accessing areas
-    default Set<String> getAreas();
-    default Set<String> getTransitiveAreas();
-    default Set<String> getAreas(final Predicate<String> predicate);
-    default Set<String> getTransitiveAreas(Predicate<String> predicate);
-    default boolean containsArea(String key);
-
-    // extension points
-    default Configuration with(UnaryOperator<Configuration> operator);
-    default <T> T query(ConfigQuery<T> query);
-
-    // versioning
-    default String getVersion(){return "N/A";}
-
-    // singleton accessors
-    public static boolean isDefined(String name);
-    public static <T> T current(String name, Class<T> template);
-    public static Configuration current(String name);
-    public static Configuration current();
-    public static <T> T current(Class<T> type){
-    public static void configure(Object instance);
-    public static String evaluateValue(String expression);
-    public static String evaluateValue(Configuration config, String expression);
-    public static void addChangeListener(ConfigChangeListener listener);
-    public static void removeChangeListener(ConfigChangeListener listener);
-}
---------------------------------------------
-
-Hereby
-
-* +XXX getXXX(String)+ provide type safe accessors for all basic wrapper types of the JDK.
-* +getAdapted+ allow accessing any type, hereby also passing a +PropertyAdapter+ that converts
-  the configured literal value to the type required.
-* +getAreas()+, +getTransitiveAreas()+ allow to examine the hierarchical tree modeled by the configuration tree.
-  Optionally also predicates can be passed to select only part of the tree to be returned.
-* +containsArea+ allows to check, if an area is defined.
-* +with, query+ provide the extension points for adding additional functionality.
-
-* the static accessor methods define:
-  ** +current(), current(Class), current(String), current(String, Class)+ return the configuration valid for the current runtime environment.
-  ** +addChangeListener, removeChangeListener+ allow to register or unregister
-     global config change listener instances.
-  ** evaluateValue allows to evaluate a configuration expression based on a given configuration.
-  ** +configure+ performs injection of configured values.
-
-[[TypeConversion]]
-==== Type Conversion
-
-Configuration extend +PropertySource+ and add additional support for non String types. This is achieved
-with the help of +PropertyAdapter+ instances:
-
-[source,java]
-.PropertyAdapter
---------------------------------------------
-@FunctionalInterface
-public interface PropertyAdapter<T>{
-    T adapt(String value);
-}
---------------------------------------------
-
-PropertyAdapter instances can be implemented manually or registered and accessed from the
-+PropertyAdapers+ singleton. Hereby the exact mechanism is determined by the API backing up the singleton.
-By default corresponding +PropertyAdapter+ instances can be registered using the Java +ServiceLoader+
-mechanism, or programmatically ba calling the +register(Class, PropertyAdapter)+ method.
-
-[source,java]
---------------------------------------------
-public final class PropertyAdapters{
-    public static <T> PropertyAdapter<T> register(Class<T> targetType, PropertyAdapter<T> adapter);
-    public static boolean isTargetTypeSupported(Class<?> targetType);
-    public static  <T> PropertyAdapter<T> getAdapter(Class<T> targetType);
-    public static  <T> PropertyAdapter<T> getAdapter(Class<T> targetType, WithPropertyAdapter annotation);
-}
---------------------------------------------
-
-Whereas this mechanism per se looks not very useful it's power shows up when combining it with the annotations
-API provided, e.g. look at the following annotated class:
-
-[source,java]
-.Annotated Example Class
---------------------------------------------
-public class ConfiguredClass{
-
-    @ConfiguredProperty
-    private String testProperty;
-
-    @ConfiguredProperty("a.b.c.key1")
-    @DefaultValue("The current \\${JAVA_HOME} env property is ${env:JAVA_HOME}.")
-    String value1;
-
-    @ConfiguredProperty("a.b.c.key2")
-    private int value2;
-
-    @ConfiguredProperty
-    @DefaultValue("http://127.0.0.1:8080/res/api/v1/info.json")
-    private URL accessUrl;
-
-    @ConfiguredProperty
-    @DefaultValue("5")
-    private Integer int1;
-
-    @ConfiguredProperty("a.b.customType")
-    private MyCustomType myCustomType;
-
-    @ConfiguredProperty("BD")
-    private BigDecimal bigNumber;
-
-    ...
-}
---------------------------------------------
-
-The class does not show all the possibilities that are provided, but it shows that arbitrary types can be supported easily.
-This applied similarly to collection types, whereas collections are more advanced and therefore described in a separate section
-later.
-
-Given the class above and the current configuration can provide the values required, configuring an instance of the
-class is simple:
-
-[source,java]
-.Configuring the Example Class
---------------------------------------------
-ConfiguredClass classInstance = new ConfiguredClass();
-Configuration.configure(configuredClass);
---------------------------------------------
-
-Additional types can transparently be supported by implementing and registering corresponding SPI instances. This is explained
-in the SPI documentation of {name}.
-
-==== Extension Points
-
-We are well aware of the fact that this library will not be able to cover all kinds of use cases. Therefore
-we have added similar functional extension mechanisms that were used in other areas of the Java eco-system as well:
-
-* +ConfigOperator+ define unary operations on +Configuration+. They can be used for filtering, implementing
-  configuration views, security interception etc.
-* +ConfigQuery+ defines a function returning any kind of result based on a configuration instance. Typical
-  use cases of queries could be the implementation of configuration SPI instances that are required
-  by other libraries or frameworks.
-
-Both interfaces hereby are defined as functional interfaces:
-
-[source,java]
-.ConfigQuery
---------------------------------------------
-@FunctionalInterface
-public interface ConfigQuery<T>{
-    T query(Configuration config);
-}
---------------------------------------------
-
-Instances of this interface can be applied on a +Configuration+ instance:
-
-[source,java]
-.Applying Config operators and queries
---------------------------------------------
-ConfigSecurity securityContext = Configuration.current().query(ConfigSecurity::targetSecurityContext);
---------------------------------------------
-
-NOTE: +ConfigSecurity+ is an arbitrary class.
-
-Similarly an instance of +UnaryOpertor<Configuration>+ can be applied as well to decorate an existing +Configuration+
-instance:
-
-[source,java]
-.Applying Config operators
---------------------------------------------
-Configuration secured = Configuration.current().with(ConfigSecurity::secure);
---------------------------------------------
-
-=== Configuration Injection
-
-The +Configuration+ interface provides static methods that allow to anykind of instances be configured
-ny just passing the instances calling +Configuration.configure(instance);+. The classes passed hereby must
-be annotated with +@ConfiguredProperty+ to define the configured properties. Hereby this annotation can be
-used in multiple ways and combined with other annotations such as +@DefaultValue+,
-+@WithLoadPolicy+, +@WithConfig+, +@WithConfigOperator+, +@WithPropertyAdapter+.
-
-To illustrate the mechanism below the most simple variant of a configured class is given:
-
-[source,java]
-.Most simple configured class
---------------------------------------------
-pubic class ConfiguredItem{
-  @ConfiguredProperty
-  private String aValue;
-}
---------------------------------------------
-
-When this class is configured, e.g. by passing it to +Configuration.configure(Object)+,
-the following is happening:
-
-* The current valid +Configuration+ is evaluated by calling +Configuration cfg = Configuration.of();+
-* The current property value (String) is evaluated by calling +cfg.get("aValue");+
-* if not successful, an error is thrown (+ConfigException+)
-* On success, since no type conversion is involved, the value is injected.
-* The configured bean is registered as a weak change listener in the config system's underlying
-  configuration, so future config changes can be propagated (controllable by applying the
-  +@WithLoadPolicy+ annotation).
-
-In the next example we explicitly define the property value:
-[source,java]
---------------------------------------------
-pubic class ConfiguredItem{
-
-  @ConfiguredProperty
-  @ConfiguredProperty("a.b.value")
-  @configuredProperty("a.b.deprecated.value")
-  @DefaultValue("${env:java.version}")
-  private String aValue;
-}
---------------------------------------------
-
-Within this example we evaluate multiple possible keys. Evaluation is aborted if a key could be successfully
-resolved. Hereby the ordering of the annotations define the ordering of resolution, so in the example above
-resolution equals to +"aValue", "a.b.value", "a.b.deprecated.value"+. If no value could be read
-from the configuration, it uses the value from the +@DefaultValue+ annotation. Interesting here
-is that this value is not static, it is evaluated by calling +Configuration.evaluateValue(Configuration, String)+.
-
-[[API ConfigurationBuilder]]
-==== Building Simple Configuration
-
-Looking at the structures of configuration system used by large companies we typically encounter some kind of configuration
-hierarchies that are combined in arbitrary ways. Users of the systems are typically not aware of the complexities in this
-area, since they simply know the possible locations, formats and the overriding policies. Framework providers on the other
-side must face the complexities and it would be very useful if Tamaya can support here by providing prebuilt functionality
-that helps implementing these aspects. All this leads to the feature set of combining property sources. Hereby the following
-strategies are useful:
-
-* aggregating configurations, hereby later configurations added
-  ** override any existing entries from earlier configurations
-  ** combine conflicting entries from earlier configurations, e.g. into a comma-separated structure.
-  ** may throw a ConfigException ig entries are conflicting
-  ** may only add entries not yet defined by former providers, preventing entries that are already present to be overwrite
-  ** any custom aggregation strategy, which may be a mix of above
-* intersecting configurations
-* subtracting configurations
-* filtering configurations
-
-These common functionality is provided by +ConfigurationBuilder+ instances. Additionally to the base strategies above a
-+MetaInfo+ instance can be passed optionally as well to define the meta information for the newly created configuration.
-Let's assume we have two configurations with the following data:
-
-[source,properties]
-.Configuration 1
---------------------------------------------
-a=a
-b=b
-c=c
-g=g
-h=h
-i=i
---------------------------------------------
-
-[source,properties]
-.Configuration 2
---------------------------------------------
-a=A
-b=B
-c=C
-d=D
-e=E
-f=F
---------------------------------------------
-
-Looking in detail you see that the entries +a,b,c+ are present in both configurations, whereas +d,e,f+ are only present in Configuration 1,
-and +g,h,i+ only in Configuration 2.
-
-[source,java]
-.Example Combining Configurations
---------------------------------------------
-Configuration cfg1 = ...
-Configuration cfg2 = ...
-
-// aggregate, hereby values from Configuration 2 override values from Configuration 1
-Configuration unionOverriding = ConfigurationBuilder.of().aggregate(cfg1, cfg2).build();
-System.out.println("unionOverriding: " + unionOverriding);
-
-// ignore duplicates, values present in Configuration 1 are not overriden by Configuration 2
-Configuration unionIgnoringDuplicates = ConfigurationBuilder.of()
-                       .withAggregationPolicy(AggregationPolicy.IGNORE_DUPLICATES).aggregate(cfg1, cfg2).build();
-System.out.println("unionIgnoringDuplicates: " + unionIgnoringDuplicates);
-
-// this variant combines/maps duplicate values into a new value
-Configuration unionCombined = ConfigurationBuilder.of().withAggregationPolicy(AggregationPolicy.COMBINE)
-                       .aggregate(cfg1, cfg2);
-System.out.println("unionCombined: " + unionCombined);
-
-// This variant throws an exception since there are key/value paris in both providers, but with different values
-try{
-    ConfigurationBuilder.of().withAggregationPolicy(AggregationPolicy.EXCEPTION).aggregate(provider1, provider2)
-                       .build();
-}
-catch(ConfigException e){
-    // expected!
-}
---------------------------------------------
-
-The example above produces the following outpout:
-
-[source,listing]
-.Example Combining Configurations
---------------------------------------------
-AggregatedConfiguration{
-  (name = dynamicAggregationTests)
-  a = "[a][A]"
-  b = "[b][B]"
-  c = "[c][C]"
-  d = "[D]"
-  e = "[E]"
-  f = "[F]"
-  g = "[g]"
-  h = "[h]"
-  i = "[i]"
-}
-unionOverriding: AggregatedConfigurations{
-  (name = <noname>)
-  a = "A"
-  b = "B"
-  c = "C"
-  d = "D"
-  e = "E"
-  f = "F"
-  g = "g"
-  h = "h"
-  i = "i"
-}
-unionIgnoringDuplicates: AggregatedConfigurations{
-  (name = <noname>)
-  a = "a"
-  b = "b"
-  c = "c"
-  d = "D"
-  e = "E"
-  f = "F"
-  g = "g"
-  h = "h"
-  i = "i"
-}
-unionCombined: AggregatedConfigurations{
-  (name = <noname>)
-  a = "a,A"
-  b = "b,B"
-  c = "c,C"
-  d = "D"
-  e = "E"
-  f = "F"
-  g = "g"
-  h = "h"
-  i = "i"
-}
---------------------------------------------
-
-No +AggregationPolicy+ is also a functional interface that can be implemented:
-
-[source,java]
-.AggregationPolicy Interface
---------------------------------------------
-@FunctionalInterface
-public interface AggregationPolicy {
-    String aggregate(String key, String value1, String value2);
-}
---------------------------------------------
-
-So we can also define our own aggregation strategy using a Lambda expression:
-
-[source,java]
-.Use a Custom AggregationPolicy
---------------------------------------------
-Configuration cfg1 = ...;
-Configuration cfg2 = ...;
-Configuration config = ConfigurationBuilder.of("dynamicAggregationTests")
-      .withAggregationPolicy((k, v1, v2) -> (v1 != null ? v1 : "") + '[' + v2 + "]")
-      .aggregate(cfg1, cfg2).build();
-System.out.println(config);
---------------------------------------------
-
-Additionally we also create here an instance of +MetaInfo+. The output of this code snippet is as follows:
-
-[source,listing]
-.Listing of dynamic aggregation policy
---------------------------------------------
-AggregatedConfiguration{
-  (name = dynamicAggregationTests)
-  a = "[a][A]"
-  b = "[b][B]"
-  c = "[c][C]"
-  d = "[D]"
-  e = "[E]"
-  f = "[F]"
-  g = "[g]"
-  h = "[h]"
-  i = "[i]"
-}
---------------------------------------------
-
-Summarizing the +ConfigurationBuilder+ allows to combine providers in various forms:
-
-[source,listing]
-.Methods provided on PropertySources
---------------------------------------------
-public final class ConfigurationBuilder {
-
-    private ConfigurationBuilder() {}
-
-    public static ConfigurationBuilder of();
-    public static ConfigurationBuilder of(PropertySource config);
-    public static ConfigurationBuilder of(MetaInfo metaInfo);
-    public static ConfigurationBuilder of(String name);
-
-    public ConfigurationBuilder withMetaInfo(MetaInfo metaInfo);
-    public ConfigurationBuilder withAggregationPolicy(AggregationPolicy aggregationPolicy);
-
-    public ConfigurationBuilder addArgs(String... args);
-    public ConfigurationBuilder addPaths(List<String> paths);
-    public ConfigurationBuilder addUrls(URL... urls);
-    public ConfigurationBuilder addUrls(List<URL> urls);
-    public ConfigurationBuilder addMap(Map<String, String> map);
-
-    public ConfigurationBuilder empty();
-    public ConfigurationBuilder empty(MetaInfo metaInfo);
-    public ConfigurationBuilder emptyMutable(MetaInfo metaInfo);
-    public ConfigurationBuilder addEnvironmentProperties();
-    public ConfigurationBuilder addSystemProperties();
-    public ConfigurationBuilder aggregate(Configuration... configs){
-    public ConfigurationBuilder aggregate(List<Configuration> configs) {
-    public ConfigurationBuilder mutable(Configuration config) {
-    public ConfigurationBuilder intersected(Configuration... providers) {
-    public ConfigurationBuilder subtracted(Configuration target, Configuration... providers) {
-    public ConfigurationBuilder filtered(Predicate<String> filter, Configuration config) {
-    public ConfigurationBuilder contextual(Supplier<Configuration> mapSupplier,
-                                              Supplier<String> isolationKeySupplier) {
-    public ConfigurationBuilder delegating(Configuration mainMap, Map<String, String> parentMap) {
-    public ConfigurationBuilder replacing(Configuration mainMap, Map<String, String> replacementMap);
-
-    public Configuration build();
-    public Configuration buildFrozen();
-}
---------------------------------------------
-
-
-
-=== Environment
-
-The environment basically is also a kind of property/value provider similar to +System
-.getenv()+ in the JDK. Nevertheless it provides additional functionality:
-
-[source,java]
-.Interface Environment
---------------------------------------------
-public interface Environment {
-
-    Optional<String> get(String key);
-    boolean containsKey(String key);
-    Set<String> keySet();
-    Map<String,String> toMap();
-
-    public static Environment current();
-    public static Environment root();
---------------------------------------------
-
-* Basically an environment can contain any properties. The root environment
-  hereby must contain at least
-  ** all JDK's environment properties.
-  ** additional root properties are allowed as well.
-* the root environment is always directly accessible by calling +Environment.root()+
-* the current environment can be accessed by calling +Environment.current()+.
-
-Summarizing the Environment can be seen as a runtime context. This also implies, that this context changes
-depending on the current runtime context. Developers implementing an environment mechanism should be aware that
-an environment can be accessed very frequently, so evaluation and access of an +Environment+ must be fast. For
-further details we recommend the SPI details section of the core implementation.
-
-
-== SPI
-
-[[API PropertySourceBuilder]]
-==== Building Property Sources
-
-In [[PropertSource]] we have outlines that the essence of a property key store for configuration can be modelled by
-the +PropertySource+ interface. Similarly to the +ConfigurationBuilder+ you can also combine several +PropertySource+
-instances to assemble more complex configuration scenarios. Typically assembling is done within a +ConfigProvider+,
-which is responsible for providing correct Configuration corresponding to the current environment.
-
-Summarizing you can
-* aggregate providers, hereby later providers added
-  ** override any existing entries from earlier providers
-  ** combine conflicting entries from earlier providers, e.g. into a comma-separated structure.
-  ** may throw a ConfigException ig entries are conflicting
-  ** may only add entries not yet defined by former providers, preventing entries that are already present to be overwritten
-  ** any custom aggregation strategy, which may be a mix of above
-* intersecting providers
-* subtracting providers
-* filtering providers
-
-The following code snippet gives a couple of examples:
-
-[source,java]
-.Example Combining PropertySources
---------------------------------------------
-PropertySource provider1 = ...
-PropertySource provider2 = ...
-
-// aggregate, hereby values from provider 2 override values from provider 1
-PropertySource unionOverriding = PropertySourceBuilder.of()
-             .aggregate(provider1, provider2).build(); // OVERRIDE policy is default
-System.out.println("unionOverriding: " + unionOverriding);
-
-// ignore duplicates, values present in provider 1 are not overriden by provider 2
-PropertySource unionIgnoringDuplicates = PropertySources
-             .aggregate(AggregationPolicy.IGNORE_DUPLICATES(), provider1, provider2).build();
-System.out.println("unionIgnoringDuplicates: " + unionIgnoringDuplicates);
-
-// this variant combines/maps duplicate values into a new value
-PropertySource unionCombined = PropertySourceBuilder.of().withAggregationPolicy(AggregationPolicy.COMBINE))
-            .aggregate(provider1, provider2).build();
-System.out.println("unionCombined: " + unionCombined);
-
-// This variant throws an exception since there are key/value paris in both providers, but with different values
-try{
-    PropertySourceBuilder.of().withAggregationPolicy(AggregationPolicy.EXCEPTION).aggregate(provider1, provider2);
-}
-catch(ConfigException e){
-    // expected!
-}
---------------------------------------------
-
-