Merge pull request #55 from peculater/TAMAYA-386-move-example-to-extensions

TAMAYA-386 move distributed example to extensions, fix deprecation warnings
diff --git a/.travis.yml b/.travis.yml
index 0a9639a..0a66eb0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,15 +6,12 @@
   sonarcloud:
     organization: "apache"
 
-script:
-  - sonar-scanner
-
 jobs:
     include:
         - name: "Java 8"
           jdk: openjdk8
-          # script: mvn clean install sonar:sonar -Dsonar.organization=apache -Dsonar.projectKey=apache_incubator-tamaya -Dsonar.host.url="https://sonarcloud.io" -Dsonar.login="$SONAR_TOKEN"
-          script: mvn clean install 
+          script: mvn clean install
+          after_success: mvn sonar:sonar -Dsonar.organization=apache -Dsonar.projectKey=apache_incubator-tamaya
 
         - name: "Java 9"
           jdk: openjdk9
@@ -28,4 +25,6 @@
           jdk: openjdk11
           script: mvn clean install
 
-
+        - name: "Java 12"
+          jdk: openjdk12
+          script: mvn clean install
diff --git a/code/api/src/main/java/org/apache/tamaya/Configuration.java b/code/api/src/main/java/org/apache/tamaya/Configuration.java
index 9d62652..083f494 100644
--- a/code/api/src/main/java/org/apache/tamaya/Configuration.java
+++ b/code/api/src/main/java/org/apache/tamaya/Configuration.java
@@ -29,7 +29,7 @@
 
 
 /**
- * <p>A configuration models an aggregated set of current properties, identified by
+ * <p>A configuration models an aggregated setPropertyValue of current properties, identified by
  * a unique key, but adds higher level access functions to
  * a {@link org.apache.tamaya.spi.PropertySource}. Hereby in most
  * cases a configuration is a wrapper around a composite
@@ -46,7 +46,7 @@
  * </ul>
  *
  * <p>It is not recommended that implementations also are serializable, since the any configuration can be <i>frozen</i>
- * by reading out its complete configuration map into a serializable and remotable structure. This helps significantly
+ * by reading out its complete configuration mapProperties into a serializable and remotable structure. This helps significantly
  * by simplifying the development of this interface, e.g. for being backed up by systems and stores that are not part of
  * this library at all.</p>
  */
@@ -461,7 +461,7 @@
      * @return the builder, never null.
      */
     static ConfigurationBuilder createConfigurationBuilder(){
-        return ServiceContextManager.getServiceContext(Configuration.class.getClassLoader())
+        return ServiceContextManager.getServiceContext(ServiceContextManager.getDefaultClassLoader())
                 .getService(ConfigurationProviderSpi.class).getConfigurationBuilder();
     }
 
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java
index ac19542..ccc6244 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java
@@ -94,7 +94,7 @@
      * lowest priority  regardless of its current ordinal value. To sort the property
      * sources based on their ordinals call {@link #sortPropertySources}.
      *
-     * @param propertySources the {@link PropertySource}s to add
+     * @param propertySources the {@link PropertySource}s to addPropertyValue
      * @return this builder, for chaining, never null.
      * @throws IllegalArgumentException If a property source with a given name already
      * exists.
@@ -127,7 +127,7 @@
      * lowest priority regardless of its current ordinal value. To sort the property
      * sources based on their ordinals call {@link #sortPropertySources}.
      *
-     * @param propertySources the {@link PropertySource}s to add
+     * @param propertySources the {@link PropertySource}s to addPropertyValue
      * @return this builder, for chaining, never null.
      * @throws IllegalArgumentException If a property source with a given name already
      * exists.
@@ -241,7 +241,7 @@
      * property filters remains unchanged. To sort the property
      * filters call {@link #sortPropertyFilter}.
      *
-     * @param filters the filters to add
+     * @param filters the filters to addPropertyValue
      * @return this builder, for chaining, never null.
      */
     default ConfigurationBuilder addPropertyFilters(PropertyFilter... filters){
@@ -254,7 +254,7 @@
      * property filters remains unchanged. To sort the property
      * filters call {@link #sortPropertyFilter}.
      *
-     * @param filters the filters to add
+     * @param filters the filters to addPropertyValue
      * @return this builder, for chaining, never null.
      */
     ConfigurationBuilder addPropertyFilters(Collection<PropertyFilter> filters);
@@ -292,7 +292,7 @@
      * method has no effect.
      *
      * @param typeToConvert     the type for which the converter is used
-     * @param propertyConverters the {@link PropertyConverter}s to add for this type
+     * @param propertyConverters the {@link PropertyConverter}s to addPropertyValue for this type
      * @param <T> the target type.
      * @return this builder, for chaining, never null.
      */
@@ -309,7 +309,7 @@
      * method has no effect.
      *
      * @param typeToConvert the type for which the converter is used
-     * @param propertyConverters the PropertyConverters to add for this type
+     * @param propertyConverters the PropertyConverters to addPropertyValue for this type
      * @param <T> the target type.
      * @return this builder, for chaining, never null.
      */
@@ -378,6 +378,16 @@
     ConfigurationBuilder sortPropertyFilter(Comparator<PropertyFilter> comparator);
 
     /**
+     * Sorts the current registered property converters using the given comparator.
+     *
+     * <p>NOTE: property converters at the beginning have minimal significance.
+     *
+     * @param comparator the comparator to be used, not {@code null}.
+     * @return this instance for chaining.
+     */
+    ConfigurationBuilder sortPropertyConverter(Comparator<PropertyConverter> comparator);
+
+    /**
      * Builds a new {@link Configuration} based on the data in this builder. The ordering of property
      * sources and property filters is not changed, regardless of their ordinals. For ensure a certain
      * ordering/significance use {@link #sortPropertyFilter(Comparator)} and/or {@link #sortPropertySources(Comparator)}
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java
index e762576..a23b035 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java
@@ -83,7 +83,7 @@
      *  }
      * </pre>
      *
-     * @return map with sorted createList of registered {@link PropertySource}s per type.
+     * @return mapProperties with sorted createList of registered {@link PropertySource}s per type.
      */
     Map<TypeLiteral<?>, List<PropertyConverter<?>>> getPropertyConverters();
 
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java b/code/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java
index cb4ae32..c7156fb 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java
@@ -100,7 +100,7 @@
 
     /**
      * Evaluate the metadata for the current target key from the given values. Later values hereby are more significant.
-     * @return the evaluated meta data map.
+     * @return the evaluated meta data mapProperties.
      */
     public Map<String, String> getMeta() {
         Map<String, String> metaMap = new HashMap<>();
@@ -116,7 +116,7 @@
     }
 
     /**
-     * Allows to add information on the supported/tried formats, which can be shown to the user, especially when
+     * Allows to addPropertyValue information on the supported/tried formats, which can be shown to the user, especially when
      * conversion failed. Adding of formats is synchronized, all formats are added in order to the overall createList.
      * This means formats should be passed in order of precedence.
      * @param converterType the converters, which implements the formats provided.
@@ -141,6 +141,20 @@
         }
     }
 
+    /**
+     * Creates a builder based on this instance.
+     */
+    public Builder toBuilder(){
+        Builder builder = new Builder(key, targetType)
+                .setConfiguration(this.configuration)
+                .setValues(this.values);
+        if(annotatedElement!=null) {
+            builder.setAnnotatedElement(annotatedElement);
+        }
+        builder.supportedFormats.addAll(this.supportedFormats);
+        return builder;
+    }
+
     @Override
     public String toString() {
         return "ConversionContext{" +
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/FilterContext.java b/code/api/src/main/java/org/apache/tamaya/spi/FilterContext.java
index db4fd73..8a1642f 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/FilterContext.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/FilterContext.java
@@ -48,15 +48,11 @@
      * @param configurationContext the current configurationContext, not {@code null}.
      */
     public FilterContext(PropertyValue value, Map<String,PropertyValue> configEntries, ConfigurationContext configurationContext) {
-        Objects.requireNonNull(value, "Value must not be null.");
-        Objects.requireNonNull(configEntries, "Initial configuration entries must be not null.");
-        Objects.requireNonNull(configurationContext, "Context must be not null.");
-
-        this.singlePropertyScoped = false;
-        this.values = Collections.singletonList(Objects.requireNonNull(value));
-        this.configurationContext = Objects.requireNonNull(configurationContext);
-        this.configEntries.putAll(configEntries);
+        this.values = Collections.singletonList(Objects.requireNonNull(value, "Value must not be null."));
+        this.configurationContext = Objects.requireNonNull(configurationContext, "Context must be non null");
+        this.configEntries.putAll(Objects.requireNonNull(configEntries, "Initial configuration entries must be not null."));
         this.configEntries = Collections.unmodifiableMap(this.configEntries);
+        this.singlePropertyScoped = false;
     }
 
     /**
@@ -66,13 +62,7 @@
      * @param configurationContext the current configurationContext, not {@code null}.
      */
     public FilterContext(PropertyValue value, ConfigurationContext configurationContext) {
-        Objects.requireNonNull(value, "Value must not be null.");
-        Objects.requireNonNull(configurationContext, "Context must be not null.");
-
-        this.singlePropertyScoped = true;
-        this.configurationContext = Objects.requireNonNull(configurationContext);
-        this.values = Collections.singletonList(Objects.requireNonNull(value));
-        this.configEntries = Collections.unmodifiableMap(this.configEntries);
+        this(Collections.singletonList(Objects.requireNonNull(value)), configurationContext);
     }
 
     /**
@@ -82,13 +72,10 @@
      * @param configurationContext the current configurationContext, not {@code null}.
      */
     public FilterContext(List<PropertyValue> values, ConfigurationContext configurationContext) {
-        Objects.requireNonNull(values, "Value must not be null.");
-        Objects.requireNonNull(configurationContext, "Context must be not null.");
-
-        this.singlePropertyScoped = true;
-        this.configurationContext = Objects.requireNonNull(configurationContext);
-        this.values = Collections.unmodifiableList(new ArrayList<>(values));
+        this.configurationContext = Objects.requireNonNull(configurationContext, "Context must not be null.");
+        this.values = Collections.unmodifiableList(new ArrayList<>(Objects.requireNonNull(values, "Value must not be null.")));
         this.configEntries = Collections.unmodifiableMap(this.configEntries);
+        this.singlePropertyScoped = true;
     }
 
     /**
@@ -132,18 +119,18 @@
     }
 
     /**
-     * This map contains the following keys:
+     * This mapProperties contains the following keys:
      * <ul>
      * <li>the original createValue <b>before</b> any filters were applied on it.</li>
      * <li>all values starting with an {@code _<key>.}, for example {@code a.createValue}
-     * may have a map setCurrent with {@code a.createValue} (oringinal createValue), {@code _a.createValue.origin,
+     * may have a mapProperties setCurrent with {@code a.createValue} (oringinal createValue), {@code _a.createValue.origin,
      * _a.createValue.type, etc}. The exact contents is determine by the {@link PropertySource}s
      * active.</li>
      * </ul>
-     * Also important to know is that this map given contains all the evaluated raw entries, regardless
+     * Also important to know is that this mapProperties given contains all the evaluated raw entries, regardless
      * of the filters that are later applied. This ensures that met-information required by one filter is
      * not hidden by another filter, because of an invalid filter ordering. In other words filters may remove
-     * key/createValue pairs, e.g. fir security reasons, by returning {@code null}, but the values in the raw map
+     * key/createValue pairs, e.g. fir security reasons, by returning {@code null}, but the values in the raw mapProperties
      * passed as input to the filter process will not be affected by any such removal (but the final properties
      * returned are affected, of course).
      * 
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ListValue.java b/code/api/src/main/java/org/apache/tamaya/spi/ListValue.java
index c59a7b1..e70988c 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ListValue.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ListValue.java
@@ -19,7 +19,6 @@
 package org.apache.tamaya.spi;
 
 import java.util.*;
-import java.util.function.Predicate;
 
 /**
  * Class modelling the result of a request for a property createValue. A property createValue is basically identified by its key.
@@ -41,16 +40,16 @@
     /**
      * Creates a new instance
      * @param key the key, not {@code null}.
-     * @param parent the parent.
      */
-    ListValue(PropertyValue parent, String key){
-        super(parent, key);
+    ListValue(String key){
+        super(key);
     }
 
     /**
      * Get the item's current createValue type.
      * @return the createValue type, never null.
      */
+    @Override
     public ValueType getValueType() {
         return ValueType.ARRAY;
     }
@@ -81,30 +80,18 @@
     /**
      * Adds a createValue to the array.
      * @param value the createValue, not null
-     * @param <T> the instance type.
      * @return this instance, for chaining.
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public <T extends PropertyValue> T add(T value) {
+    public ListValue addPropertyValue(PropertyValue value) {
         checkImmutable();
-        value.setParent(this);
         if(!this.list.stream().filter(p -> p==value).findAny().isPresent()){
+            value.setKey(generateListKey());
+            value.setParent(this);
             this.list.add(value);
         }
-        return value;
-    }
-
-    /**
-     * Adds an named text value to the array.
-     * @param key the child's key, not null.
-     * @param value the child's value, not null.
-     * @return the created value, not null.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public PropertyValue addValue(String key, String value) {
-        return add(new PropertyValue(this,key, value));
+        return this;
     }
 
     /**
@@ -114,8 +101,8 @@
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public PropertyValue addValue(String value) {
-        return add(new PropertyValue(this,"", value));
+    public ListValue addValue(String value) {
+        return addPropertyValue(new PropertyValue(generateListKey(), value));
     }
 
     /**
@@ -125,12 +112,12 @@
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public List<PropertyValue> addValues(String... values) {
+    public ListValue addValues(String... values) {
         List<PropertyValue> result = new ArrayList<>();
         for(String val:values) {
-            result.add(add(new PropertyValue(this, "", val)));
+            result.add(addPropertyValue(new PropertyValue(generateListKey(), val)));
         }
-        return result;
+        return this;
     }
 
     /**
@@ -140,18 +127,9 @@
      * @see #isImmutable()
      */
     public ObjectValue addObject() {
-        return add(new ObjectValue(this, ""));
-    }
-
-    /**
-     * Adds a child createObject to the array.
-     * @param name the child's name, not null.
-     * @return the created createObject, not null.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public ObjectValue addObject(String name) {
-        return add(new ObjectValue(this,name));
+        ObjectValue ov = new ObjectValue(generateListKey());
+        addPropertyValue(ov);
+        return ov;
     }
 
     /**
@@ -161,39 +139,26 @@
      * @see #isImmutable()
      */
     public ListValue addList() {
-        return add(new ListValue(this, ""));
+        ListValue lv = new ListValue(generateListKey());
+        addPropertyValue(lv);
+        return lv;
     }
 
     /**
-     * Adds a named array.
-     * @param name the child's name, not null.
-     * @return this instance, for chaining.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
+     * Get a String value with the given key, if possible. If a node is present, but no value is setPropertyValue, then the
+     * node's {@code toString()} method is used as a result.
+     * @param index the target index.
+     * @return the value found, or null.
      */
-    public ListValue addList(String name) {
-        return add(new ListValue(this,name));
-    }
-
-    /**
-     * Get the array elements, filtered by the given predicate.
-     * @param filter the filter predicate, null selects all elements.
-     * @return this values matching, never null.
-     */
-    public List<PropertyValue> getValues(Predicate<PropertyValue> filter) {
-        List<PropertyValue> result = new ArrayList<>();
-        this.list.stream().filter(filter::test).forEach(result::add);
-        return result;
-    }
-
-    /**
-     * Get the array elements.
-     * @return this values matching, never null.
-     */
-    public List<PropertyValue> getValues() {
-        List<PropertyValue> result = new ArrayList<>();
-        result.addAll(this.list);
-        return result;
+    public String getValue(int index) {
+        PropertyValue value = getPropertyValue(index);
+        if(value!=null){
+            if(value.getValueType()==ValueType.VALUE) {
+                return value.getValue();
+            }
+            return value.toString();
+        }
+        return null;
     }
 
     /**
@@ -202,8 +167,8 @@
      * @return the element found
      * @throws NoSuchElementException if no such element exists.
      */
-    public PropertyValue get(int n) {
-        return this.getValues().get(n);
+    public PropertyValue getPropertyValue(int n) {
+        return this.list.get(n);
     }
 
 
@@ -256,7 +221,7 @@
      * @param name the name of the objects, null selects all.
      * @return this values matching, never null.
      */
-    public List<PropertyValue> getValues(String name) {
+    public List<PropertyValue> getPropertyValues(String name) {
         List<PropertyValue> result = new ArrayList<>();
         if (name == null) {
             result.addAll(this.list);
@@ -271,22 +236,14 @@
     }
 
     @Override
-    public PropertyValue toPropertyValue(){
-        PropertyValue value = new PropertyValue(getParent(), getKey(), getValue());
-        value.setMeta(getMeta());
-        value.setVersion(getVersion());
-        return value;
-    }
-
-    @Override
     public ObjectValue toObjectValue(){
-        ObjectValue object = new ObjectValue(getParent(), getKey());
+        ObjectValue object = new ObjectValue(getKey());
+        object.setParent(getParent());
         object.setMeta(getMeta());
         object.setVersion(getVersion());
-        object.setValue(getValue());
         int index = 0;
         for(PropertyValue val: list){
-            object.set(val.deepClone().setKey(val.getKey()+"["+index+"]"));
+            object.setPropertyValue(val.deepClone().setKey(val.getKey()));
             index++;
         }
         return object;
@@ -298,6 +255,19 @@
     }
 
     /**
+     * Get the node's createValue.
+     * @return the createValue, or null.
+     */
+    public String getValue() {
+        return "List: " + this.list;
+    }
+
+    @Override
+    public PropertyValue setValue(String value) {
+        throw new UnsupportedOperationException("Cannot set value on list value.");
+    }
+
+    /**
      * Clones this instance and all it's children, marking as mutable value.
      * @return the new value clone.
      */
@@ -308,11 +278,11 @@
 
     @Override
     protected ListValue deepClone(){
-        ListValue newProp = new ListValue(getParent(), getKey());
+        ListValue newProp = new ListValue(getKey());
+        newProp.setParent(getParent());
         newProp.setMeta(getMeta());
-        list.forEach(c -> newProp.add(c.deepClone().mutable()));
+        list.forEach(c -> newProp.addPropertyValue(c.deepClone().mutable()));
         newProp.setVersion(getVersion());
-        newProp.setValue(getValue());
         return newProp;
     }
 
@@ -331,6 +301,10 @@
                 Objects.equals(getMeta(), dataNode.getMeta());
     }
 
+    private String generateListKey(){
+        return "["+this.list.size()+"]";
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(getKey(), list, getValue(), getMeta());
@@ -339,12 +313,24 @@
 
     @Override
     public String toString() {
-        return "PropertyValue[ARRAY]{" +
-                '\'' +getQualifiedKey() + '\'' +
-                (getValue()!=null?", value='" + getValue() + '\'':"") +
+        return "List{" +
                 ", size='" + getSize() + '\'' +
+                ", values=" + list +
                 (getMeta().isEmpty()?"":", metaData=" + getMeta()) +
                 '}';
     }
 
+    /**
+     * Merges multiple values into one single node.
+     * @param values the values to merge, not null.
+     * @return the merged instance, or null.
+     */
+    public static ListValue from(Collection<PropertyValue> values) {
+        ListValue merged = PropertyValue.createList();
+        for(PropertyValue val:values){
+            merged.addPropertyValue(val);
+        }
+        return merged;
+    }
+
 }
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ObjectValue.java b/code/api/src/main/java/org/apache/tamaya/spi/ObjectValue.java
index 286fbe5..ea244ef 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ObjectValue.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ObjectValue.java
@@ -19,10 +19,7 @@
 package org.apache.tamaya.spi;
 
 import java.util.*;
-import java.util.function.Predicate;
 import java.util.function.Supplier;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
 
 /**
  * Class modelling the result of a request for a property value. A property value is basically identified by its key.
@@ -38,8 +35,6 @@
 
     private static final long serialVersionUID = 1L;
 
-    private static final Logger LOG = Logger.getLogger(ObjectValue.class.getName());
-
     /** List of child properties. */
     private Map<String, PropertyValue> fields = new HashMap<>();
 
@@ -47,16 +42,16 @@
     /**
      * Creates a new instance
      * @param key the key, not {@code null}.
-     * @param parent the parent.
      */
-    ObjectValue(PropertyValue parent, String key){
-        super(parent, key);
+    ObjectValue( String key){
+        super(key);
     }
 
     /**
      * Get the item's current value type.
      * @return the value type, never null.
      */
+    @Override
     public ValueType getValueType() {
         return ValueType.MAP;
     }
@@ -70,32 +65,60 @@
     }
 
     /**
-     * Get the fields of this instance, filtered with the given predicate.
-     * @param predicate the predicate, not null.
-     * @return the current fields, never null.
+     * Access the current present field names/keys.
+     * @return the keys present, never null.
      */
-    public Collection<PropertyValue> getValues(Predicate<PropertyValue> predicate){
-        return Collections.unmodifiableCollection(this.fields.values().stream()
-        .filter(predicate).collect(Collectors.toList()));
+    public Set<String> getKeys() {
+        return Collections.unmodifiableSet(this.fields.keySet());
     }
 
     /**
      * Get a single child getValue by name.
      * @param name the child's name, not null.
      * @return the child found, or null.
-     * @throws IllegalArgumentException if multiple getValues with the given name are existing (ambigous).
+     * @throws IllegalArgumentException if multiple getPropertyValues with the given name are existing (ambigous).
      */
-    public PropertyValue getValue(String name){
+    public PropertyValue getPropertyValue(String name){
         return this.fields.get(name);
     }
 
     /**
+     * Get the node's createValue.
+     * @return the createValue, or null.
+     */
+    public String getValue() {
+        return "Map: " + this.fields;
+    }
+
+    @Override
+    public PropertyValue setValue(String value) {
+        throw new UnsupportedOperationException("Cannot set value on object value.");
+    }
+
+    /**
+     * Get a String value with the given key, if possible. If a node is present, but no value is setPropertyValue, then the
+     * node's {@code toString()} method is used as a result.
+     * @param key the key, not null.
+     * @return the value found, or null.
+     */
+    public String getValue(String key) {
+        String result = null;
+        PropertyValue value = getPropertyValue(key);
+        if(value!=null){
+            result = value.getValue();
+            if(result==null){
+                result = value.toString();
+            }
+        }
+        return result;
+    }
+
+    /**
      * Get a single child getValue with the given name, creates it if not existing.
      * @param name the child's name, not null.
      * @param valueSupplier the supplier to create a new instance, if no value is present, not null.
      * @param <T> the target type.
      * @return the child found or created, never null.
-     * @throws IllegalArgumentException if multiple getValues with the given name are existing (ambigous).
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
@@ -119,12 +142,38 @@
         return this.fields.size();
     }
 
-    @Override
-    public PropertyValue toPropertyValue(){
-        PropertyValue value = new PropertyValue(getParent(), getKey(), getValue());
-        value.setMeta(getMeta());
-        value.setVersion(getVersion());
-        return value;
+    /**
+     * Applies a mapProperties of {@code Map<String,String>} to this instance as values.
+     * @param config the String based mapProperties, not {@code null}.
+     * @return the corresponding createValue based mapProperties.
+     */
+    public ObjectValue setValues(Map<String, String> config) {
+        return setValues(config, null, true);
+    }
+
+    /**
+     * Applies a mapProperties of {@code Map<String,String>} to this instance as values.
+     * @param config the String based mapProperties, not {@code null}.
+     * @param source the source name, optional.
+     * @param overwriteExisting if true, existing values will be overridden.
+     * @return the corresponding createValue based mapProperties.
+     */
+    public ObjectValue setValues(Map<String, String> config, String source, boolean overwriteExisting) {
+        checkImmutable();
+        Map<String, PropertyValue> result = PropertyValue.mapProperties(config, source);
+        for(Map.Entry<String,String> en:config.entrySet()){
+            PropertyValue value = new PropertyValue( en.getKey(), en.getValue());
+            value.setParent(this);
+            if(source!=null) {
+                value.setMeta("source", source);
+            }
+            if(overwriteExisting){
+                this.fields.put(en.getKey(), value);
+            }else{
+                this.fields.putIfAbsent(en.getKey(), value);
+            }
+        }
+        return this;
     }
 
     @Override
@@ -134,13 +183,12 @@
 
     @Override
     public ListValue toListValue(){
-        ListValue array = new ListValue(getParent(), getKey());
-        array.setValue(getValue());
+        ListValue array = new ListValue(getKey());
+        array.setParent(getParent());
         array.setMeta(getMeta());
         array.setVersion(getVersion());
-        int index = 0;
         for(PropertyValue val:fields.values()){
-            array.add(val.deepClone());
+            array.addPropertyValue(val.deepClone());
         }
         return array;
     }
@@ -151,36 +199,19 @@
         return Collections.unmodifiableCollection(this.fields.values()).iterator();
     }
 
-    /**
-     * Adds text values to the createObject.
-     * @param values the child's values, not null.
-     * @return the created values, not null.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public Collection<PropertyValue> setValues(Map<String, String> values) {
-        checkImmutable();
-        List<PropertyValue> result = new ArrayList<>();
-        for(Map.Entry<String, String> en:values.entrySet()) {
-            PropertyValue val = setValue(en.getKey(), en.getValue());
-            result.add(val);
-        }
-        return result;
-    }
 
     /**
      * Adds another existing node, hereby setting the corresponding parent node.
      * @param value the value, not null
-     * @param <T> the value type.
      * @return the value added, not null.
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public <T extends PropertyValue> T set(T value) {
+    protected ObjectValue setPropertyValue(PropertyValue value) {
         checkImmutable();
         value.setParent(this);
         this.fields.put(value.getKey(), value);
-        return value;
+        return this;
     }
 
     /**
@@ -189,8 +220,8 @@
      * @param v the value, not null.
      * @return the value added, not null.
      */
-    public PropertyValue setValue(String k, String v) {
-        return set(PropertyValue.createValue(k,v));
+    public ObjectValue setValue(String k, String v) {
+        return setPropertyValue(new PropertyValue(k,v));
     }
 
     /**
@@ -198,8 +229,10 @@
      * @param key the key, not null.
      * @return the value added, not null.
      */
-    public ListValue setList(String key) {
-        return set(PropertyValue.createList(key));
+    public ListValue addList(String key) {
+        ListValue lv = PropertyValue.createList(key);
+        setPropertyValue(lv);
+        return lv;
     }
 
     /**
@@ -207,8 +240,10 @@
      * @param key the key, not null.
      * @return the value added, not null.
      */
-    public ObjectValue setObject(String key) {
-        return set(PropertyValue.createObject(key));
+    public ObjectValue addObject(String key) {
+        ObjectValue ov = PropertyValue.createObject(key);
+        setPropertyValue(ov);
+        return ov;
     }
 
     /**
@@ -229,7 +264,7 @@
             if(tokenizer.hasMoreTokens()) {
                 node = node.getOrSetValue(token, () -> PropertyValue.createObject(token));
             }else{
-                return node.set(PropertyValue.createValue(token, value));
+                return node.setPropertyValue(new PropertyValue(token, value));
             }
         }
         return null;
@@ -253,20 +288,40 @@
     }
 
     /**
-     * Convert the getValue tree to a property map.
+     * Convert the value tree to a property map.
      * @return the corresponding property map, not null.
      */
     @Override
     public Map<String,String> toMap(){
         Map<String, String> map = new TreeMap<>();
         for (PropertyValue n : fields.values()) {
+            if (ValueType.VALUE.equals(n.getValueType())) {
+                map.put(n.getQualifiedKey(), n.getValue());
+            } else {
+                for(PropertyValue val:n) {
+                    map.putAll(val.toMap());
+                }
+            }
+        }
+        return map;
+    }
+
+    /**
+     * Convert the value tree to a local property map.
+     * @return the corresponding local map, not null.
+     */
+    @Override
+    public Map<String,String> toLocalMap(){
+        Map<String, String> map = new TreeMap<>();
+        for (PropertyValue n : fields.values()) {
             switch(n.getValueType()){
                 case VALUE:
-                    map.put(n.getQualifiedKey(), n.getValue());
+                    map.put(n.getKey(), n.getValue());
                     break;
                 default:
                     for(PropertyValue val:n) {
-                        map.putAll(val.toMap());
+                        Map<String,String> valueMap = val.toLocalMap();
+                        map.putAll(valueMap);
                     }
             }
         }
@@ -285,11 +340,11 @@
 
     @Override
     protected ObjectValue deepClone(){
-        ObjectValue newProp = new ObjectValue(getParent(), getKey());
+        ObjectValue newProp = new ObjectValue(getKey());
+        newProp.setParent(getParent());
         newProp.setMeta(getMeta());
-        fields.values().forEach(c -> newProp.set(c.deepClone().mutable()));
+        fields.values().forEach(c -> newProp.setPropertyValue(c.deepClone().mutable()));
         newProp.setVersion(getVersion());
-        newProp.setValue(getValue());
         return newProp;
     }
 
@@ -315,12 +370,27 @@
 
     @Override
     public String toString() {
-        return "PropertyValue[MAP]{" +
-                '\'' +getQualifiedKey() + '\'' +
-                (getValue()!=null?", value='" + getValue() + '\'':"") +
-                ", size='" + getSize() + '\'' +
+        return "Object{" +
+                "size='" + getSize() + '\'' +
+                ", values='" + toLocalMap() +
                 (getMeta().isEmpty()?"":", metaData=" + getMeta()) +
                 '}';
     }
 
+    /**
+     * Merges multiple values into one single node.
+     * @param values the values to merge, not null.
+     * @return the merged instance, or null.
+     */
+    public static ObjectValue from(Collection<PropertyValue> values) {
+        if(values.size()==1){
+            return values.iterator().next().toObjectValue();
+        }
+        ObjectValue merged = PropertyValue.createObject();
+        for(PropertyValue val:values){
+            merged.setPropertyValue(val);
+        }
+        return merged;
+    }
+
 }
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertyConverter.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertyConverter.java
index 986e17e..4d08a55 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyConverter.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertyConverter.java
@@ -30,7 +30,7 @@
 
     /**
      * Convert the given configuration keys from its String representation into the required target type.
-     * Additional data can be obtained from {@link ConversionContext}, which also allows to add a list
+     * Additional data can be obtained from {@link ConversionContext}, which also allows to addPropertyValue a list
      * of supported formats, which is very handy in case a
      * value could not be converted. This list of supported formats can then shown to the user to give some hints
      * how a value could be configured.
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertyFilter.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertyFilter.java
index 376f686..bea080f 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyFilter.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertyFilter.java
@@ -20,7 +20,7 @@
 
 
 /**
- * <p>Interface for filtering the current map of properties during the evaluation of the chain of PropertySources.
+ * <p>Interface for filtering the current mapProperties of properties during the evaluation of the chain of PropertySources.
  * Filters can be registered using the {@link org.apache.tamaya.spi.ServiceContext}. The ordinal
  * hereby is defined by the corresponding {@code @Priority} annotation.</p>
  * <p>Filters </p>
@@ -31,7 +31,7 @@
     /**
      * <p>Maps the current {@code value} to a new value. The resulting value will be used as the result
      * passed to the user.</p>
-     * <p>If a filter is currently not available, it should just pass the input map to the method's
+     * <p>If a filter is currently not available, it should just pass the input mapProperties to the method's
      * output.</p>
      * <p>Returning {@code null} will remove the entry.</p>
      * <h3>Implementation specification</h3>
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertySource.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertySource.java
index 8ea4801..0bf4b4b 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/PropertySource.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertySource.java
@@ -112,7 +112,7 @@
      *
      * <p>Reordering of the default order of the config-sources:</p>
      * <p>Example: If the properties file/s should be used <b>before</b> the other implementations,
-     * you have to configure an ordinal &gt; 1000. That means, you have to add e.g. tamaya.ordinal=401 to
+     * you have to configure an ordinal &gt; 1000. That means, you have to addPropertyValue e.g. tamaya.ordinal=401 to
      * /META-INF/javaconfiguration.properties . Hint: In case of property files every file is handled as independent
      * config-source, but all of them have ordinal 400 by default (and can be reordered in a fine-grained manner.</p>
      *
@@ -152,7 +152,7 @@
      * Access a property.
      *
      * @param key the property's key, not {@code null}.
-     * @return the property value map, where {@code map.current(key) == value}, including also any metadata. In case a
+     * @return the property value mapProperties, where {@code mapProperties.current(key) == value}, including also any metadata. In case a
      * value is null, simply return {@code null}.
      */
     PropertyValue get(String key);
@@ -161,7 +161,7 @@
      * Access the current properties as Set. The resulting Map may not return all items accessible, e.g.
      * when the underlying storage does not support iteration of its entries.
      {@code null}
-     * @return the corresponding map, never null.
+     * @return the corresponding mapProperties, never null.
      */
     Map<String, PropertyValue> getProperties();
 
@@ -197,7 +197,7 @@
     /**
      * Get the current version. A new version signals that it is known that properties have changed for this property
      * source. This is especially useful, when {@link #getChangeSupport()} is {@link ChangeSupport#SUPPORTED}.
-     * The content and format of the version String is imeplemtation specific. We recommend to add information
+     * The content and format of the version String is imeplemtation specific. We recommend to addPropertyValue information
      * such as the loading timestamp, the source systems read or whatever is appropriate. By default this
      * method returns {@code "N/A"}.
      * @return the version this property source, never null.
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
index 5ea569c..32e119e 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
@@ -35,6 +35,8 @@
 public class PropertyValue implements Serializable, Iterable<PropertyValue>{
 
     private static final long serialVersionUID = 2L;
+    private static final int EMPTY = 0;
+    private static final String SOURCE = "source";
     /** The requested key. */
     private String key;
     /** The createValue. */
@@ -62,27 +64,11 @@
 
 
     /**
-     * Creates a new builder instance.
-     * @param key the key, not {@code null}.
-     * @param source the source, typically the name of the {@link PropertySource}
-     *               providing the createValue, not {@code null}.
-     * @return a new builder instance.
-     * @deprecated Will be removed, use {@link PropertyValue} directly.
-     */
-    @Deprecated
-    public static PropertyValueBuilder builder(String key, String source){
-        Objects.requireNonNull(key, "Key must be given.");
-        Objects.requireNonNull(source, "Source must be given");
-
-        return new PropertyValueBuilder(key, null).setSource(source);
-    }
-
-    /**
      * Creates a new (invisible) root, which is a node with an empty name.
      * @return a new empty root, never null.
      */
     public static ObjectValue createObject(){
-        return new ObjectValue(null, "");
+        return new ObjectValue("");
     }
 
     /**
@@ -90,7 +76,7 @@
      * @return a new empty root, never null.
      */
     public static ListValue createList(){
-        return new ListValue(null, "");
+        return new ListValue("");
     }
 
     /**
@@ -100,7 +86,7 @@
      * @return a new createValue instance.
      */
     public static PropertyValue createValue(String key, String value){
-        return new PropertyValue(null, key, value);
+        return new PropertyValue(key, value);
     }
 
     /**
@@ -109,7 +95,7 @@
      * @return a new createValue instance.
      */
     public static ListValue createList(String key){
-        return new ListValue(null, key);
+        return new ListValue(key);
     }
 
     /**
@@ -118,62 +104,60 @@
      * @return a new createValue instance.
      */
     public static ObjectValue createObject(String key){
-        return new ObjectValue(null, key);
+        return new ObjectValue(key);
     }
 
     /**
-     * Creates a new builder instance.
-     * @param key the key, not {@code null}.
-     * @param value the property createValue, not {@code null}.
-     * @param source the source, typically the name of the {@link PropertySource}
-     *               providing the createValue, not {@code null}.
-     * @return a new builder instance.
+     * Maps a mapProperties of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}.
+     * @param config the String based mapProperties, not {@code null}.
+     * @param source the source name, not {@code null}.
+     * @return the corresponding createValue based mapProperties.
      */
-    @Deprecated
-    public static PropertyValue of(String key, String value, String source) {
-        Objects.requireNonNull(key);
-        if(source!=null) {
-            return new PropertyValue(null, key, value).setMeta("source", source);
-        }
-        return new PropertyValue(null, key, value);
+    public static Map<String, PropertyValue> mapProperties(Map<String, String> config, String source) {
+        return mapProperties(config, source, null);
     }
 
     /**
-      * Maps a map of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}.
-      * @param config the String based map, not {@code null}.
-      * @param source the source name, not {@code null}.
-      * @return the corresponding createValue based map.
-      */
-    public static Map<String, PropertyValue> map(Map<String, String> config, String source) {
-        Map<String, PropertyValue> result = new HashMap<>(config.size());
-        for(Map.Entry<String,String> en:config.entrySet()){
-            result.put(en.getKey(), createValue(en.getKey(), en.getValue()).setMeta("source", source));
-        }
-        return result;
-    }
-
-    /**
-     * Maps a map of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}.
+     * Maps a mapProperties of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}.
      *
-     * @param config the String based map, not {@code null}.
+     * @param config the String based mapProperties, not {@code null}.
      * @param source the source name, not {@code null}.
      * @param metaData additional metadata, not {@code null}.
-     * @return the corresponding createValue based map.
+     * @return the corresponding createValue based mapProperties.
      */
-    public static Map<String, PropertyValue> map(Map<String, String> config, String source,
-                                                 Map<String,String> metaData) {
+    public static Map<String, PropertyValue> mapProperties(Map<String, String> config, String source,
+                                                           Map<String,String> metaData) {
+        return mapProperties(config, source, metaData, null);
+    }
+
+    /**
+     * Maps a mapProperties of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}.
+     *
+     * @param config the String based mapProperties, not {@code null}.
+     * @param source the source name, not {@code null}.
+     * @param metaData additional metadata, not {@code null}.
+     * @param prefix the prefix to add (optional).
+     * @return the corresponding createValue based mapProperties.
+     */
+    public static Map<String, PropertyValue> mapProperties(Map<String, String> config, String source,
+                                                           Map<String,String> metaData, String prefix) {
         Objects.requireNonNull(config, "Config must be given.");
-        Objects.requireNonNull(metaData, "Meta data must be given.");
 
         Map<String, PropertyValue> result = new HashMap<>(config.size());
 
         for(Map.Entry<String,String> en:config.entrySet()){
-            PropertyValue pv = createValue(en.getKey(), en.getValue())
-                    .setMeta(metaData);
-            if(source!=null){
-                pv.setMeta("source", source);
+            PropertyValue pv = createValue(en.getKey(), en.getValue());
+            if(metaData!=null) {
+                pv.setMeta(metaData);
             }
-            result.put(en.getKey(), pv);
+            if(source!=null){
+                pv.setMeta(SOURCE, source);
+            }
+            if(prefix==null) {
+                result.put(en.getKey(), pv);
+            }else{
+                result.put(prefix + en.getKey(), pv.setKey(prefix=en.getKey()));
+            }
         }
         return result;
     }
@@ -181,20 +165,17 @@
     /**
      * Creates a new instance
      * @param key the key, not {@code null}.
-     * @param parent the parent.
      */
-    protected PropertyValue(PropertyValue parent, String key){
-        this(parent, key, null);
+    public PropertyValue(String key){
+        this(key, null);
     }
 
     /**
      * Creates a new instance
      * @param key the key, not {@code null}.
-     * @param parent the parent.
      * @param value the initial text createValue.
      */
-    protected PropertyValue(PropertyValue parent, String key, String value){
-        this.parent = parent;
+    protected PropertyValue(String key, String value){
         this.key = Objects.requireNonNull(key);
         this.value = value;
     }
@@ -259,7 +240,7 @@
      */
     @Deprecated
     public String getSource() {
-        return this.metaEntries.get("source");
+        return this.metaEntries.get(SOURCE);
     }
 
 
@@ -363,7 +344,7 @@
      */
     @Deprecated
     public String getMetaEntry(String key) {
-        return (String)this.metaEntries.get(Objects.requireNonNull(key));
+        return this.metaEntries.get(Objects.requireNonNull(key));
     }
 
     /**
@@ -381,7 +362,7 @@
      * @return the getNumChilds of this multi createValue.
      */
     public int getSize() {
-        return 0;
+        return EMPTY;
     }
 
     @Override
@@ -391,23 +372,6 @@
 
 
     /**
-     * Changes the entry's key, mapping also corresponding context entries.
-     * @param key the new key, not {@code null}.
-     * @return the builder for chaining.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public PropertyValue setKey(String key) {
-        checkImmutable();
-        if(!Objects.equals(this.key, key)) {
-            this.key = Objects.requireNonNull(key);
-            version.incrementAndGet();
-        }
-        return this;
-    }
-
-
-    /**
      * Replaces/sets the context data.
      * @param metaEntries the context data to be applied, not {@code null}.
      * @return the builder for chaining.
@@ -474,37 +438,25 @@
     }
 
     /**
+     * Convert the value tree to a property mapProperties using local keys.
+     * @return the corresponding property mapProperties, not null.
+     */
+    public Map<String,String> toLocalMap(){
+        Map<String, String> map = new TreeMap<>();
+        if(value!=null) {
+            map.put(getKey(), value);
+        }
+        return map;
+    }
+
+
+    /**
      * Create a String representation of the tree.
      * @return the corresponding String representation, not null.
      */
-    public String asString() {
-        Map<String, String> map = toMap();
-        StringBuilder b = new StringBuilder();
-        map.entrySet().forEach(en -> b.append(en.getKey()).append(" = ").append(en.getValue()).append('\n'));
-        if(b.length()==0){
-            return "<nodata>";
-        }
-        return b.toString();
-    }
-
-    /**
-     * Creates a new builder instance based on this item.
-     * @return a new builder, never null.
-     * @deprecated Use {@link PropertyValue} directly.
-     */
-    @Deprecated
-    public PropertyValueBuilder toBuilder() {
-        return new PropertyValueBuilder(this.getKey(), this.getValue())
-                .setMeta(this.metaEntries);
-    }
-
-    /**
-     * Convert an instance to a simple PropertyValue. Note, that in case
-     * of object/list values, data loss can occur.
-     * @return the simple value, never null.
-     */
-    public PropertyValue toPropertyValue(){
-        return this;
+    @Override
+    public String toString() {
+        return String.valueOf(value);
     }
 
     /**
@@ -512,8 +464,9 @@
      * @return the list value, never null.
      */
     public ObjectValue toObjectValue(){
-        ObjectValue ov = new ObjectValue(getParent(),getKey());
-        ov.setValue("createValue", value);
+        ObjectValue ov = new ObjectValue(getKey());
+        ov.setParent(getParent());
+        ov.setValue("value", value);
         return ov;
     }
 
@@ -522,8 +475,9 @@
      * @return the list value, never null.
      */
     public ListValue toListValue(){
-        ListValue lv = new ListValue(getParent(),getKey());
-        lv.addValue("createValue", value);
+        ListValue lv = new ListValue(getKey());
+        lv.setParent(getParent());
+        lv.addValue(value);
         return lv;
     }
 
@@ -533,7 +487,8 @@
      * @return a clone, never null.
      */
     protected PropertyValue deepClone() {
-        PropertyValue newProp = new PropertyValue(getParent(), getKey(), this.value);
+        PropertyValue newProp = new PropertyValue(getKey(), this.value);
+        newProp.setParent(getParent());
         newProp.setMeta(getMeta());
         newProp.setVersion(getVersion());
         newProp.setValue(getValue());
@@ -567,6 +522,23 @@
     }
 
     /**
+     * Changes the entry's key, mapping also corresponding context entries.
+     *
+     * @param key the new key, not {@code null}.
+     * @return the builder for chaining.
+     * @throws IllegalStateException if the instance is immutable.
+     * @see #isImmutable()
+     */
+    public PropertyValue setKey(String key) {
+        checkImmutable();
+        if(!Objects.equals(this.key, key)) {
+            this.key = Objects.requireNonNull(key);
+            version.incrementAndGet();
+        }
+        return this;
+    }
+
+    /**
      * Sets the new parent, used iternally when converting between value types.
      * @param parent the parent value.
      * @return the simple value, never null.
@@ -587,8 +559,7 @@
         }
         PropertyValue dataNode = (PropertyValue) o;
         return Objects.equals(getKey(), dataNode.getKey()) &&
-                Objects.equals(value, dataNode.value) &&
-                Objects.equals(getMeta(), dataNode.getMeta());
+                Objects.equals(value, dataNode.value);
     }
 
     @Override
@@ -596,14 +567,4 @@
         return Objects.hash(getParent(), getKey(), value, getMeta());
     }
 
-
-    @Override
-    public String toString() {
-        return "PropertyValue{" +
-                '\'' +getQualifiedKey() + '\'' +
-                (value!=null?", value='" + value + '\'':"") +
-                (getMeta().isEmpty()?"":", metaData=" + getMeta()) +
-                '}';
-    }
-
 }
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
deleted file mode 100644
index 6f6ca9a..0000000
--- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
+++ /dev/null
@@ -1,205 +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.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Builder to createObject a {@link org.apache.tamaya.spi.PropertyValue} instance.
- * @deprecated Use {@link PropertyValue} directly.
- */
-@Deprecated
-public class PropertyValueBuilder {
-    /** The key accessed. */
-    protected String key;
-    /** The property value. */
-    protected String value;
-    /** The property value. */
-    protected String source;
-    /** additional metadata entries (optional). */
-    protected Map<String,String> metaEntries = new HashMap<>();
-    /** The parent value, null if it's a root value. */
-    protected PropertyValue parent;
-    /** The value's getIndex, if the value is participating in a createList structure. */
-    protected int index = -1;
-    /** Helper structure used for indexing new createList values. */
-    protected Map<String, AtomicInteger> indices = new HashMap<>();
-
-    /**
-     * Create a new builder instance, for a given setCurrent of parameters.
-     * Before calling build at least a {@link #value}
-     * must be setCurrent.
-     */
-    PropertyValueBuilder(String key, String value){
-        this.key = Objects.requireNonNull(key);
-        this.value = value;
-    }
-
-    /**
-     * Replaces/sets the context data.
-     * @param metaEntries the context data to be applied, not {@code null}.
-     * @return the builder for chaining.
-     */
-    public PropertyValueBuilder setMeta(Map<String, String> metaEntries) {
-        this.metaEntries.clear();
-        this.metaEntries.putAll(metaEntries);
-        return this;
-    }
-
-    /**
-     * Add an additional context data information.
-     * @param key the context data key, not {@code null}.
-     * @param value the context value, not {@code null} (will be converted to String).
-     * @return the builder for chaining.
-     */
-    public PropertyValueBuilder addMetaEntry(String key, String value) {
-        Objects.requireNonNull(key, "Meta key must be given.");
-        Objects.requireNonNull(value, "Meta value must be given.");
-
-        this.metaEntries.put(key, value);
-        return this;
-    }
-
-    /**
-     * Adds the context data given.
-     * @param metaEntries the context data to be applied, not {@code null}.
-     * @return the builder for chaining.
-     */
-    public PropertyValueBuilder setMetaEntries(Map<String, String> metaEntries) {
-        this.metaEntries.putAll(metaEntries);
-        return this;
-    }
-
-    /**
-     * Removes a getMeta entry.
-     * @param key the entry's key, not {@code null}.
-     * @return the builder for chaining.
-     */
-    public PropertyValueBuilder removeMetaEntry(String key) {
-        Objects.requireNonNull(key, "Key must be given.");
-
-        this.metaEntries.remove(key);
-        return this;
-    }
-
-    /**
-     * Get the value's context data.
-     * @return the context data, not {@code null}.
-     */
-    public Map<String,String> getMetaEntries() {
-        return Collections.unmodifiableMap(this.metaEntries);
-    }
-
-    /**
-     * Get the value's context data.
-     * @param key the key, not null.
-     * @return the context data, not {@code null}.
-     */
-    public String getMeta(String key) {
-        return this.metaEntries.get(key);
-    }
-
-    /**
-     * Get the value's context data.
-     * @param <T> the type of the class modeled by the type parameter
-     * @param type the target type, not null.
-     * @return the context data, not {@code null}.
-     */
-    public <T> T getMeta(Class<T> type) {
-        return (T)this.metaEntries.get(type.toString());
-    }
-
-    /**
-     * Changes the entry's key, mapping also corresponding context entries.
-     * @param key the new key, not {@code null}.
-     * @return the builder for chaining.
-     */
-    public PropertyValueBuilder mapKey(String key) {
-        // todo obf if (1==1) throw new RuntimeException("No tests written.");
-        Map<String,String> newContext = new HashMap<>();
-        for(Map.Entry<String,String> en:this.metaEntries.entrySet()){
-            if(en.getKey().startsWith("_"+this.key)){
-                newContext.put("_"+key+'.'+ en.getKey().substring(this.key.length()+1), en.getValue());
-            }else{
-                newContext.put(en.getKey(), en.getValue());
-            }
-        }
-        this.metaEntries = newContext;
-        this.key = key;
-        return this;
-    }
-
-    /**
-     * Sets a new key.
-     * @param key the new key, not {@code null}.
-     * @return the builder for chaining.
-     */
-    public PropertyValueBuilder setKey(String key) {
-        this.key = Objects.requireNonNull(key);
-        return this;
-    }
-
-    /**
-     * Sets a new value.
-     * @param value the new value, not {@code null}.
-     * @return the builder for chaining.
-     */
-    public PropertyValueBuilder setValue(String value) {
-        this.value = Objects.requireNonNull(value, "Value must be given.");
-
-        return this;
-    }
-
-    /**
-     * Sets a new source.
-     * @param source the new source, not {@code null}.
-     * @return the builder for chaining.
-     * @deprecated Use {@link #addMetaEntry(String, String)}
-     */
-    @Deprecated
-    public PropertyValueBuilder setSource(String source) {
-        if(source!=null) {
-            this.source = source;
-        }
-        return this;
-    }
-
-    /**
-     * Creates a new immutable {@link org.apache.tamaya.spi.PropertyValue}.
-     * @return a new immutable {@link org.apache.tamaya.spi.PropertyValue}, never {@code null}.
-     */
-    public PropertyValue build(){
-        return PropertyValue.of(key, value, source).setMeta(metaEntries);
-    }
-
-    @Override
-    public String toString() {
-        return "PropertyValueBuilder{" +
-                "key='" + key + '\'' +
-                ", value='" + value + '\'' +
-                ", source='" + source + '\'' +
-                ", metaEntries=" + metaEntries +
-                '}';
-    }
-
-}
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
index 3d97e93..cf3b2ea 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
@@ -19,10 +19,11 @@
 package org.apache.tamaya.spi;
 
 import javax.annotation.Priority;
-import java.io.IOException;
 import java.net.URL;
 import java.util.*;
 import java.util.function.Supplier;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 
 /**
@@ -32,6 +33,24 @@
 public interface ServiceContext extends ClassloaderAware{
 
     /**
+     * True if the {@link Priority} annotation class is available on the classpath.
+     */
+    boolean PRIORITY_ANNOTATION_AVAILABLE = checkPriorityAnnotation(ServiceContextManager.getDefaultClassLoader());
+
+    /**
+     * Checks if the {@link Priority} annotation class is on the classpath.
+     * @param classLoader the target classloader, not null.
+     * @return true, if the annotation is loaded.
+     */
+    static boolean checkPriorityAnnotation(ClassLoader classLoader) {
+        try{
+            Class.forName("javax.annotation.Priority", true, classLoader);
+            return true;
+        }catch(Exception e){
+            return false;
+        }
+    }
+    /**
      * Get the ordinal of the ServiceContext.
      * @return ordinal of the ServiceContext. The one with the highest ordinal will be taken.
      */
@@ -46,10 +65,12 @@
      * @return a priority, by default 1.
      */
     static int getPriority(Object o){
-        int prio = 1; //X TODO discuss default priority
-        Priority priority = o.getClass().getAnnotation(Priority.class);
-        if (priority != null) {
-            prio = priority.value();
+        int prio = 1;
+        if(PRIORITY_ANNOTATION_AVAILABLE) {
+            Priority priority = o.getClass().getAnnotation(Priority.class);
+            if (priority != null) {
+                prio = priority.value();
+            }
         }
         return prio;
     }
@@ -147,10 +168,19 @@
      * specific code to load resources, e.g. within OSGI environments.
      * @param resource the resource, not {@code null}.
      * @return the resources found
-     * @throws IOException if load fails.
      */
-    default Enumeration<URL> getResources(String resource) throws IOException{
-        return getClassLoader().getResources(resource);
+    default Collection<URL> getResources(String resource){
+        List<URL> urls = new ArrayList<>();
+        try {
+            Enumeration<URL> found = getClassLoader().getResources(resource);
+            while (found.hasMoreElements()) {
+                urls.add(found.nextElement());
+            }
+        }catch(Exception e){
+            Logger.getLogger(ServiceContext.class.getName())
+                    .log(Level.FINEST, e, () -> "Failed to lookup resources: " + resource);
+        }
+        return urls;
     }
 
     /**
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java
index 4a5de3a..7d81fe1 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java
@@ -41,7 +41,7 @@
     /**
      * The ServiceProvider used.
      */
-    private static volatile Map<ClassLoader, ServiceContext> serviceContexts = new ConcurrentHashMap<>();
+    private static final Map<ClassLoader, ServiceContext> SERVICE_CONTEXTS = new ConcurrentHashMap<>();
 
     /**
      * Private singletons constructor.
@@ -104,7 +104,7 @@
 
         ServiceContext previousContext;
         synchronized (ServiceContextManager.class) {
-            previousContext = ServiceContextManager.serviceContexts
+            previousContext = ServiceContextManager.SERVICE_CONTEXTS
                     .put(cl, serviceContext);
         }
         if(previousContext!=null) {
@@ -127,7 +127,7 @@
      */
     public static ServiceContext getServiceContext(ClassLoader classLoader) {
         Objects.requireNonNull(classLoader, "Classloader required.");
-        return serviceContexts.computeIfAbsent(classLoader, ServiceContextManager::loadDefaultServiceProvider);
+        return SERVICE_CONTEXTS.computeIfAbsent(classLoader, ServiceContextManager::loadDefaultServiceProvider);
     }
 
     /**
@@ -140,10 +140,15 @@
     }
 
     /**
-     * Evaluate the default classloader: This class's classloader.
+     * Evaluate the default classloader: This return the current thread context classloader, or this
+     * class's classloader as fallback.
      * @return the classloder, not null.
      */
     public static ClassLoader getDefaultClassLoader() {
-        return ServiceContextManager.class.getClassLoader();
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if(cl==null) {
+            cl = ServiceContextManager.class.getClassLoader();
+        }
+        return cl;
     }
 }
diff --git a/code/api/src/test/java/org/apache/tamaya/ConfigurationTest.java b/code/api/src/test/java/org/apache/tamaya/ConfigurationTest.java
index 1c4f071..f4e438c 100644
--- a/code/api/src/test/java/org/apache/tamaya/ConfigurationTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/ConfigurationTest.java
@@ -266,7 +266,7 @@
     public void testMap() throws Exception {
         UnaryOperator<Configuration> noop = (Configuration config) -> config;
         assertThat(Configuration.current().map(noop)).isNotNull();
-        assertThat(Configuration.current().map(noop)== Configuration.current());
+        assertThat(Configuration.current().map(noop)).isEqualTo(Configuration.current());
     }
 
     @Test
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationBuilderTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationBuilderTest.java
index cdd3414..3fde90e 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationBuilderTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationBuilderTest.java
@@ -231,6 +231,11 @@
         }
 
         @Override
+        public ConfigurationBuilder sortPropertyConverter(Comparator<PropertyConverter> comparator) {
+            return null;
+        }
+
+        @Override
         public Configuration build() {
             return null;
         }
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java
index c269013..33a9929 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java
@@ -104,7 +104,7 @@
     public void testGetSetValues_Ellipse(){
         ConversionContext ctx = new ConversionContext.Builder("toString", TypeLiteral.of(List.class))
                 .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn", "x.x.x.x/yyy")
-                .setValues(PropertyValue.createValue("test", "value")).build();
+                .setValues(new PropertyValue("test", "value")).build();
         assertThat(ctx.getValues()).isNotNull().hasSize(1);
         assertThat("value").isEqualTo(ctx.getValues().get(0).getValue());
         assertThat("test").isEqualTo(ctx.getValues().get(0).getKey());
@@ -114,7 +114,7 @@
     public void testGetSetValues_List(){
         ConversionContext ctx = new ConversionContext.Builder("toString", TypeLiteral.of(List.class))
                 .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn", "x.x.x.x/yyy")
-                .setValues(Collections.singletonList(PropertyValue.createValue("test", "value"))).build();
+                .setValues(Collections.singletonList(new PropertyValue("test", "value"))).build();
         assertThat(ctx.getValues()).isNotNull().hasSize(1);
         assertThat("value").isEqualTo(ctx.getValues().get(0).getValue());
         assertThat("test").isEqualTo(ctx.getValues().get(0).getKey());
@@ -124,7 +124,7 @@
     public void testGetConfigurationContext(){
         ConversionContext ctx = new ConversionContext.Builder("toString", TypeLiteral.of(List.class))
                 .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn", "x.x.x.x/yyy")
-                .setValues(PropertyValue.createValue("test", "value")).build();
+                .setValues(PropertyValue.createObject().setValue("test", "value")).build();
         assertThat(ctx.getConfigurationContext()).isNotNull();
     }
 
@@ -132,7 +132,7 @@
     public void testGetMeta(){
         ConversionContext ctx = new ConversionContext.Builder("test", TypeLiteral.of(List.class))
                 .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn", "x.x.x.x/yyy")
-                .setValues(PropertyValue.createValue("test", "value")
+                .setValues(new PropertyValue("test", "value")
                 .setMeta("meta1", "val1").setMeta("meta2", "val2")).build();
         assertThat(ctx.getMeta()).isNotNull().isNotEmpty().hasSize(2);
     }
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java b/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
index 1602f57..361ded7 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
@@ -34,7 +34,7 @@
 
     @Test
     public void constructorWithContext() {
-        PropertyValue val = new PropertyValue(null, "");
+        PropertyValue val = new PropertyValue( "");
         FilterContext ctx = new FilterContext(val, ConfigurationContext.EMPTY);
         assertThat(val).isEqualTo(ctx.getProperty());
         assertThat(ConfigurationContext.EMPTY).isEqualTo(ctx.getConfigurationContext());
@@ -44,27 +44,27 @@
 
 //    @Test
 //    public void setNullContext() {
-//        FilterContext.set(null);
+//        FilterContext.setPropertyValue(null);
 //    }
 //
 //    @Test
 //    public void setGetContext() {
-//        PropertyValue val = PropertyValue.of("getKey", "v", "");
+//        PropertyValue val = new PropertyValue( "getKey", "v", "");
 //        FilterContext ctx = new FilterContext(val,
 //                new HashMap<String,PropertyValue>(), ConfigurationContext.EMPTY);
-//        FilterContext.set(ctx);
-//        assertEquals(ctx, FilterContext.get());
+//        FilterContext.setPropertyValue(ctx);
+//        assertEquals(ctx, FilterContext.getPropertyValue());
 //    }
 //
 //    @Test
 //    public void resetContext() {
-//        PropertyValue val = PropertyValue.of("getKey", "v", "");
+//        PropertyValue val = new PropertyValue( "getKey", "v", "");
 //        FilterContext ctx = new FilterContext(val,
 //                new HashMap<String,PropertyValue>(), ConfigurationContext.EMPTY);
-//        FilterContext.set(ctx);
-//        assertNotNull(FilterContext.get());
+//        FilterContext.setPropertyValue(ctx);
+//        assertNotNull(FilterContext.getPropertyValue());
 //        FilterContext.reset();
-//        assertNull(FilterContext.get());
+//        assertNull(FilterContext.getPropertyValue());
 //    }
 
     @Test(expected = NullPointerException.class)
@@ -79,7 +79,7 @@
 
     @Test(expected = NullPointerException.class)
     public void constructorRequiresNonNullConfigurationContextTwoParameterVariant() {
-        new FilterContext(Collections.singletonList(PropertyValue.of("a", "b", "s")), null);
+        new FilterContext(Collections.singletonList(new PropertyValue( "a", "b")), null);
     }
 
     @SuppressWarnings("unchecked")
@@ -91,17 +91,17 @@
     @SuppressWarnings("unchecked")
     @Test(expected = NullPointerException.class)
     public void constructorRequiresNonNullConfigurationContextThreeParameterVariant() {
-        new FilterContext(PropertyValue.of("a", "b", "s"), Collections.EMPTY_MAP, null);
+        new FilterContext(new PropertyValue( "a", "b"), Collections.EMPTY_MAP, null);
     }
 
     @Test(expected = NullPointerException.class)
     public void constructorRequiresNonNullMapForConfigEntriesThreeParameterVariant() {
-        new FilterContext(PropertyValue.of("a", "b", "s"), null, ConfigurationContext.EMPTY);
+        new FilterContext(new PropertyValue("a", "b"), null, ConfigurationContext.EMPTY);
     }
 
     @Test
     public void getKey() throws Exception {
-        PropertyValue val = PropertyValue.of("getKey", "v", "");
+        PropertyValue val = new PropertyValue( "getKey", "v");
         FilterContext ctx = new FilterContext(val,
                 new HashMap<String,PropertyValue>(), ConfigurationContext.EMPTY);
         assertThat(ctx.getProperty()).isEqualTo(val);
@@ -109,7 +109,7 @@
 
     @Test
     public void isSinglePropertyScoped() throws Exception {
-        PropertyValue val = PropertyValue.of("isSinglePropertyScoped", "v", "");
+        PropertyValue val = new PropertyValue( "isSinglePropertyScoped", "v");
         FilterContext ctx = new FilterContext(val, new HashMap<String,PropertyValue>(), ConfigurationContext.EMPTY);
         assertThat(ctx.isSinglePropertyScoped()).isEqualTo(false);
         ctx = new FilterContext(Collections.singletonList(val), ConfigurationContext.EMPTY);
@@ -120,9 +120,9 @@
     public void getConfigEntries() throws Exception {
         Map<String,PropertyValue> config = new HashMap<>();
         for(int i=0;i<10;i++) {
-            config.put("key-"+i, PropertyValue.of("key-"+i, "value-"+i, "test"));
+            config.put("key-"+i, new PropertyValue( "key-"+i, "value-"+i));
         }
-        PropertyValue val = PropertyValue.of("getConfigEntries", "v", "");
+        PropertyValue val = new PropertyValue( "getConfigEntries", "v");
         FilterContext ctx = new FilterContext(val, config, ConfigurationContext.EMPTY);
         assertThat(ctx.getConfigEntries()).isEqualTo(config);
         assertThat(config != ctx.getConfigEntries()).isTrue();
@@ -130,18 +130,18 @@
 
     @Test
     public void testToString() throws Exception {
-        Map<String,PropertyValue> config = new HashMap<>();
-        for(int i=0;i<2;i++) {
-            config.put("key-"+i, PropertyValue.of("key-"+i, "value-"+i, "test"));
+        Map<String, PropertyValue> config = new HashMap<>();
+        for (int i = 0; i < 2; i++) {
+            config.put("key-" + i, new PropertyValue("key-" + i, "value-" + i));
         }
-        PropertyValue val = PropertyValue.of("testToString", "val", "mySource");
+        PropertyValue val = new PropertyValue("testToString", "val");
         FilterContext ctx = new FilterContext(val, config, ConfigurationContext.EMPTY);
         String toString = ctx.toString();
 
         assertThat(toString).isNotNull();
         System.out.println(toString);
-        assertThat(toString).contains("FilterContext{value='[PropertyValue{'testToString', value='val'," +
-                " metaData={source=mySource}}]', configEntries=[", "key-0", "key-1").endsWith("}");
+        assertThat(toString).contains("FilterContext{value='[val]', configEntries=[",
+                "key-0", "key-1").endsWith("}");
     }
 
 }
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ListValueTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ListValueTest.java
index c432366..5d97f26 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/ListValueTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/ListValueTest.java
@@ -21,7 +21,6 @@
 import org.junit.Test;
 
 import java.util.Iterator;
-import java.util.List;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -47,65 +46,82 @@
     @Test
     public void getIndex() {
         ListValue lv = PropertyValue.createList();
-        PropertyValue val = PropertyValue.createValue("k", "v");
-        lv.add(val);
-        PropertyValue val2 = PropertyValue.createValue("k2", "v2");
-        lv.add(val2);
+        PropertyValue val = new PropertyValue(  "k", "v");
+        lv.addPropertyValue(val);
+        PropertyValue val2 = new PropertyValue(  "k2", "v2");
+        lv.addPropertyValue(val2);
         assertThat(0).isEqualTo(lv.getIndex(val));
         assertThat(1).isEqualTo(lv.getIndex(val2));
-        PropertyValue val3 = PropertyValue.createValue("k3", "v");
+        PropertyValue val3 = new PropertyValue(  "k3", "v");
         assertThat(-1).isEqualTo(lv.getIndex(val3));
     }
 
     @Test
+    public void getLists() {
+        ListValue lv = PropertyValue.createList();
+        PropertyValue val = PropertyValue.createList("k");
+        lv.addPropertyValue(val);
+        PropertyValue val2 = PropertyValue.createObject("k2");
+        lv.addPropertyValue(val2);
+        assertThat(lv.getLists()).isNotEmpty().hasSize(1);
+    }
+
+    @Test
+    public void getObjects() {
+        ListValue lv = PropertyValue.createList();
+        PropertyValue val = PropertyValue.createObject("k");
+        lv.addPropertyValue(val);
+        PropertyValue val2 = PropertyValue.createObject("k2");
+        lv.addPropertyValue(val2);
+        assertThat(lv.getObjects("[0]")).isNotEmpty().hasSize(1);
+        assertThat(lv.getObjects("[1]")).isNotEmpty().hasSize(1);
+        assertThat(lv.getObjects("foo")).isEmpty();
+    }
+
+    @Test
+    public void getStringValue() {
+        ListValue lv = PropertyValue.createList();
+        PropertyValue val = PropertyValue.createObject("k").setValue("k1", "v1");
+        lv.addPropertyValue(val);
+        assertThat(lv.getValue(0)).isNotNull();
+        assertThat(lv.getPropertyValue(0).toObjectValue().getValue("k1")).isEqualTo("v1");
+    }
+
+    @Test
     public void getSize() {
         ListValue lv = PropertyValue.createList();
         assertThat(0).isEqualTo(lv.getSize());
-        PropertyValue val = PropertyValue.createValue("k", "v");
-        lv.add(val);
+        PropertyValue val = new PropertyValue(  "k", "v");
+        lv.addPropertyValue(val);
         assertThat(1).isEqualTo(lv.getSize());
-        PropertyValue val2 = PropertyValue.createValue("k", "v");
-        lv.add(val2);
+        PropertyValue val2 = new PropertyValue(  "k", "v");
+        lv.addPropertyValue(val2);
         assertThat(2).isEqualTo(lv.getSize());
     }
 
     @Test
     public void getList() {
         ListValue lv = PropertyValue.createList();
-        PropertyValue val = PropertyValue.createValue("k", "v");
-        lv.add(val);
-        PropertyValue val2 = PropertyValue.createValue("k", "v");
-        lv.add(val2);
-        assertThat(lv.getValues()).isNotNull().hasSize(2);
-        assertThat(val).isEqualTo(lv.getValues().get(0));
-        assertThat(val2).isEqualTo(lv.getValues().get(1));
-        lv.add(val2);
-        assertThat(lv.getValues()).isNotNull().hasSize(2);
-        assertThat(val).isEqualTo(lv.getValues().get(0));
-        assertThat(val2).isEqualTo(lv.getValues().get(1));
-    }
-
-    @Test
-    public void getList_WithPredicate() {
-        ListValue lv = PropertyValue.createList();
-        PropertyValue val = PropertyValue.createValue("k1", "v");
-        lv.add(val);
-        PropertyValue val2 = PropertyValue.createValue("k2", "v");
-        lv.add(val2);
-        List<PropertyValue> result = lv.getValues(
-                pv -> "k1".equals(pv.getKey())
-        );
-        assertThat(result).isNotNull().hasSize(1);
-        assertThat(val).isEqualTo(result.get(0));
+        PropertyValue val = new PropertyValue(  "k", "v");
+        lv.addPropertyValue(val);
+        PropertyValue val2 = new PropertyValue(  "k", "v");
+        lv.addPropertyValue(val2);
+        assertThat(lv.getSize()).isEqualTo(2);
+        assertThat(val).isEqualTo(lv.getPropertyValue(0));
+        assertThat(val2).isEqualTo(lv.getPropertyValue(1));
+        lv.addPropertyValue(val2);
+        assertThat(lv.getSize()).isEqualTo(2);
+        assertThat(val).isEqualTo(lv.getPropertyValue(0));
+        assertThat(val2).isEqualTo(lv.getPropertyValue(1));
     }
 
     @Test
     public void iterator() {
         ListValue lv = PropertyValue.createList();
-        PropertyValue val = PropertyValue.createValue("k", "v");
-        PropertyValue val2 = PropertyValue.createValue("k", "v");
-        lv.add(val);
-        lv.add(val2);
+        PropertyValue val = new PropertyValue(  "k", "v");
+        PropertyValue val2 = new PropertyValue(  "k", "v");
+        lv.addPropertyValue(val);
+        lv.addPropertyValue(val2);
         Iterator iter = lv.iterator();
         assertThat(iter).isNotNull();
         assertThat(iter.hasNext()).isTrue();
@@ -118,12 +134,12 @@
     @Test
     public void add() {
         ListValue lv = PropertyValue.createList();
-        PropertyValue val = PropertyValue.createValue("k", "v");
-        lv.add(val);
-        lv.add(val);
-        lv.add(val);
+        PropertyValue val = new PropertyValue(  "k", "v");
+        lv.addPropertyValue(val);
+        lv.addPropertyValue(val);
+        lv.addPropertyValue(val);
         assertThat(1).isEqualTo(lv.getSize());
-        assertThat(val).isEqualTo(lv.get(0));
+        assertThat(val).isEqualTo(lv.getPropertyValue(0));
 
     }
 
@@ -132,30 +148,30 @@
         ListValue lv = PropertyValue.createList();
         lv.addValue("v");
         assertThat(1).isEqualTo(lv.getSize());
-        assertThat("v").isEqualTo(lv.get(0).getValue());
+        assertThat("v").isEqualTo(lv.getPropertyValue(0).getValue());
         lv.addValue("v2");
         assertThat(2).isEqualTo(lv.getSize());
-        assertThat("v2").isEqualTo(lv.get(1).getValue());
+        assertThat("v2").isEqualTo(lv.getPropertyValue(1).getValue());
         lv.addValue("v");
         assertThat(3).isEqualTo(lv.getSize());
-        assertThat("v").isEqualTo(lv.get(2).getValue());
+        assertThat("v").isEqualTo(lv.getPropertyValue(2).getValue());
     }
 
     @Test
     public void addValue_KeyValue() {
         ListValue lv = PropertyValue.createList();
-        lv.addValue("k", "v");
+        lv.addValue("v");
         assertThat(1).isEqualTo(lv.getSize());
-        assertThat("v").isEqualTo(lv.get(0).getValue());
-        assertThat("k").isEqualTo(lv.get(0).getKey());
-        lv.addValue("k2", "v2");
+        assertThat("v").isEqualTo(lv.getPropertyValue(0).getValue());
+        assertThat("[0]").isEqualTo(lv.getPropertyValue(0).getKey());
+        lv.addValue("v2");
         assertThat(2).isEqualTo(lv.getSize());
-        assertThat("v2").isEqualTo(lv.get(1).getValue());
-        assertThat("k2").isEqualTo(lv.get(1).getKey());
-        lv.addValue("k", "v");
+        assertThat("v2").isEqualTo(lv.getPropertyValue(1).getValue());
+        assertThat("[1]").isEqualTo(lv.getPropertyValue(1).getKey());
+        lv.addValue("v");
         assertThat(3).isEqualTo(lv.getSize());
-        assertThat("v").isEqualTo(lv.get(2).getValue());
-        assertThat("k").isEqualTo(lv.get(2).getKey());
+        assertThat("v").isEqualTo(lv.getPropertyValue(2).getValue());
+        assertThat("[2]").isEqualTo(lv.getPropertyValue(2).getKey());
     }
 
     @Test
@@ -163,9 +179,9 @@
         ListValue lv = PropertyValue.createList();
         lv.addValues("v", "v1", "v");
         assertThat(3).isEqualTo(lv.getSize());
-        assertThat("v").isEqualTo(lv.get(0).getValue());
-        assertThat("v1").isEqualTo(lv.get(1).getValue());
-        assertThat("v").isEqualTo(lv.get(2).getValue());
+        assertThat("v").isEqualTo(lv.getPropertyValue(0).getValue());
+        assertThat("v1").isEqualTo(lv.getPropertyValue(1).getValue());
+        assertThat("v").isEqualTo(lv.getPropertyValue(2).getValue());
     }
 
     @Test
@@ -173,16 +189,7 @@
         ListValue lv = PropertyValue.createList();
         lv.addObject();
         assertThat(1).isEqualTo(lv.getSize());
-        ObjectValue ov = (ObjectValue)lv.get(0);
-    }
-
-    @Test
-    public void addObject_Key() {
-        ListValue lv = PropertyValue.createList();
-        lv.addObject("key");
-        assertThat(1).isEqualTo(lv.getSize());
-        ObjectValue ov = (ObjectValue)lv.get(0);
-        assertThat("key").isEqualTo(ov.getKey());
+        ObjectValue ov = (ObjectValue)lv.getPropertyValue(0);
     }
 
     @Test
@@ -190,53 +197,35 @@
         ListValue lv = PropertyValue.createList();
         lv.addList();
         assertThat(1).isEqualTo(lv.getSize());
-        ListValue ov = (ListValue)lv.get(0);
-        assertThat("").isEqualTo(ov.getKey());
-    }
-
-    @Test
-    public void addList_Key() {
-        ListValue lv = PropertyValue.createList();
-        lv.addList("key");
-        assertThat(1).isEqualTo(lv.getSize());
-        ListValue ov = (ListValue)lv.get(0);
-        assertThat("key").isEqualTo(ov.getKey());
+        ListValue ov = (ListValue)lv.getPropertyValue(0);
+        assertThat("[0]").isEqualTo(ov.getKey());
     }
 
     @Test
     public void getValues() {
         ListValue lv = PropertyValue.createList();
-        lv.addList("list");
-        lv.addObject("object");
-        assertThat(lv.getValues("")).isNotNull().hasSize(0);
-        assertThat(lv.getValues("list")).hasSize(1);
-        assertThat(lv.getValues("object")).hasSize(1);
-    }
-
-    @Test
-    public void toPropertyValue() {
-        ListValue lv = PropertyValue.createList("foo");
-        lv.addList("list");
-        PropertyValue pv = lv.toPropertyValue();
-        assertThat(pv).isNotNull();
-        assertThat(pv.getKey()).isEqualTo(lv.getKey());
+        lv.addList();
+        lv.addObject();
+        assertThat(lv.getPropertyValues("")).isNotNull().hasSize(0);
+        assertThat(lv.getPropertyValues("[0]")).hasSize(1);
+        assertThat(lv.getPropertyValues("[1]")).hasSize(1);
     }
 
     @Test
     public void toObjectValue() {
         ListValue lv = PropertyValue.createList("foo");
-        lv.addList("list").setValue("a");
+        lv.addList().addValue("a");
         ObjectValue ov = lv.toObjectValue();
         assertThat(ov).isNotNull();
         assertThat(ov.getKey()).isEqualTo(lv.getKey());
-        assertThat(ov.getValue("list[0]")).isNotNull();
-        assertThat(lv.getLists("list").get(0).getValue()).isEqualTo(ov.getValue("list[0]").getValue());
+        assertThat(ov.getValue("[0]")).isNotNull();
+        assertThat(ov.getValue("[0]")).isEqualTo("List: [a]");
     }
 
     @Test
     public void toListValue() {
         ListValue lv = PropertyValue.createList("foo");
-        lv.addList("list");
+        lv.addList();
         ListValue lv2 = lv.toListValue();
         assertThat(lv == lv2).isTrue();
     }
@@ -244,7 +233,7 @@
     @Test
     public void mutable() {
         ListValue lv = PropertyValue.createList("foo");
-        lv.addList("list");
+        lv.addList();
         assertThat(lv.isImmutable()).isFalse();
         ListValue lv2 = lv.mutable();
         assertThat(lv2.isImmutable()).isFalse();
@@ -254,9 +243,8 @@
     @Test
     public void deepClone() {
         ListValue lv1 = PropertyValue.createList("foo");
-        lv1.addList("list");
+        lv1.addList();
         ListValue lv2 = lv1.deepClone();
-        assertThat(lv1.getValues()!=lv2.getValues()).isTrue();
         assertThat(lv1.getMeta()!=lv2.getMeta()).isTrue();
         assertThat(lv1.equals(lv2)).isTrue();
         assertThat(lv1.iterator().next()!=lv2.iterator().next()).isTrue();
@@ -265,18 +253,18 @@
     @Test
     public void equals() {
         ListValue lv1 = PropertyValue.createList("foo");
-        lv1.addList("list");
+        lv1.addList();
         ListValue lv2 = PropertyValue.createList("foo");
-        lv2.addList("list");
+        lv2.addList();
         assertThat(lv1.equals(lv2)).isTrue();
     }
 
     @Test
     public void testHashCode() {
         ListValue lv1 = PropertyValue.createList("foo");
-        lv1.addList("list");
+        lv1.addList();
         ListValue lv2 = PropertyValue.createList("foo");
-        lv2.addList("list");
+        lv2.addList();
         assertThat(lv1.hashCode() == lv2.hashCode()).isTrue();
     }
 
@@ -285,15 +273,16 @@
         ListValue lv1 = PropertyValue.createList("foo");
         String toString = lv1.toString();
         assertThat(toString).isNotNull();
-        lv1.addList("list");
+        lv1.addList();
         toString = lv1.toString();
         assertThat(toString).isNotNull();
-        lv1.addObject("object");
+        lv1.addObject();
         toString = lv1.toString();
         assertThat(toString).isNotNull();
         lv1.addValue("valueKey");
         toString = lv1.toString();
         assertThat(toString).isNotNull();
-        assertThat("PropertyValue[ARRAY]{'foo', size='3'}").isEqualTo(toString);
+        assertThat("List{, size='3', values=[List{, size='0', values=[]}, Object{size='0', values='{}}, " +
+                "valueKey]}").isEqualTo(toString);
     }
 }
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ObjectValueTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ObjectValueTest.java
index 8e1fcb1..67ca968 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/ObjectValueTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/ObjectValueTest.java
@@ -49,59 +49,94 @@
     @Test
     public void getIndex() {
         ObjectValue ov = PropertyValue.createObject();
-        PropertyValue val = PropertyValue.createValue("k", "v");
-        ov.set(val);
-        PropertyValue val2 = PropertyValue.createValue("k2", "v2");
-        ov.set(val2);
-        assertThat(val).isEqualTo(ov.getValue(val.getKey()));
-        assertThat(val2).isEqualTo(ov.getValue(val2.getKey()));
-        assertThat(ov.getValue("foo")).isNull();
+        PropertyValue val = new PropertyValue("k", "v");
+        ov.setPropertyValue(val);
+        PropertyValue val2 = new PropertyValue("k2", "v2");
+        ov.setPropertyValue(val2);
+        assertThat(val).isEqualTo(ov.getPropertyValue(val.getKey()));
+        assertThat(val2).isEqualTo(ov.getPropertyValue(val2.getKey()));
+        assertThat(ov.getPropertyValue("foo")).isNull();
+    }
+
+    @Test
+    public void getKeys() {
+        ObjectValue ov = PropertyValue.createObject();
+        PropertyValue val = new PropertyValue("k", "v");
+        ov.setPropertyValue(val);
+        PropertyValue val2 = new PropertyValue("k2", "v2");
+        ov.setPropertyValue(val2);
+        assertThat(ov.getKeys()).contains("k", "k2");
     }
 
     @Test
     public void getSize() {
         ObjectValue ov = PropertyValue.createObject();
         assertThat(0).isEqualTo(ov.getSize());
-        PropertyValue val = PropertyValue.createValue("k", "v");
-        ov.set(val);
+        PropertyValue val = new PropertyValue("k", "v");
+        ov.setPropertyValue(val);
         assertThat(1).isEqualTo(ov.getSize());
-        PropertyValue val2 = PropertyValue.createValue("k2", "v");
-        ov.set(val2);
+        PropertyValue val2 = new PropertyValue("k2", "v");
+        ov.setPropertyValue(val2);
         assertThat(2).isEqualTo(ov.getSize());
-        PropertyValue val3 = PropertyValue.createValue("k2", "v");
-        ov.set(val3);
+        PropertyValue val3 = new PropertyValue("k2", "v");
+        ov.setPropertyValue(val3);
         assertThat(2).isEqualTo(ov.getSize());
     }
 
     @Test
     public void getValue() {
         ObjectValue ov = PropertyValue.createObject();
-        PropertyValue val = PropertyValue.createValue("k1", "v");
-        ov.set(val);
-        PropertyValue val2 = PropertyValue.createValue("k2", "v");
-        ov.set(val2);
+        PropertyValue val = new PropertyValue("k1", "v");
+        ov.setPropertyValue(val);
+        PropertyValue val2 = new PropertyValue("k2", "v");
+        ov.setPropertyValue(val2);
         assertThat(ov.getValues()).isNotNull().hasSize(2);
-        assertThat(val).isEqualTo(ov.getValue("k1"));
-        assertThat(val2).isEqualTo(ov.getValue("k2"));
-        ov.set(val2);
+        assertThat(val).isEqualTo(ov.getPropertyValue("k1"));
+        assertThat(val2).isEqualTo(ov.getPropertyValue("k2"));
+        ov.setPropertyValue(val2);
         assertThat(ov.getValues()).isNotNull().hasSize(2);
-        assertThat(val).isEqualTo(ov.getValue("k1"));
-        assertThat(val2).isEqualTo(ov.getValue("k2"));
+        assertThat(val).isEqualTo(ov.getPropertyValue("k1"));
+        assertThat(val2).isEqualTo(ov.getPropertyValue("k2"));
+    }
+
+    @Test
+    public void setValueWithCompositeKeys_KeyValue() {
+        ObjectValue ov = PropertyValue.createObject();
+        ov.setValueWithCompositeKey("a.b", "val");
+        assertThat(ov.toLocalMap()).containsKeys("b");
+    }
+
+    @Test
+    public void setValueWithCompositeKeys_Map() {
+        ObjectValue ov = PropertyValue.createObject();
+        Map<String,String> data = new HashMap<>();
+        data.put("a.b", "val");
+        ov.setValueWithCompositeKey(data);
+        assertThat(ov.toLocalMap()).containsKeys("b");
+    }
+
+    @Test
+    public void getStringValue() {
+        ObjectValue ov = PropertyValue.createObject();
+        PropertyValue val = new PropertyValue("k1", "v");
+        ov.setPropertyValue(val);
+        assertThat(ov.getValue("k1")).isEqualTo("v");
+        assertThat(ov.getValue("foo")).isNull();
     }
 
     @Test
     public void getOrSetValue() {
         ObjectValue ov = PropertyValue.createObject();
-        PropertyValue val = PropertyValue.createValue("k1", "v");
-        ov.set(val);
+        PropertyValue val = new PropertyValue("k1", "v");
+        ov.setPropertyValue(val);
         PropertyValue val2 = ov.getOrSetValue("k2",
-                () -> PropertyValue.createValue("foo", "bar"));
-        PropertyValue pv = ov.getOrSetValue("foo",  () -> PropertyValue.createValue("foo", "bar"));
+                () -> new PropertyValue("foo", "bar"));
+        PropertyValue pv = ov.getOrSetValue("foo",  () -> new PropertyValue("foo", "bar"));
         assertThat(pv).isNotNull();
         assertThat(ov.getValues()).hasSize(3);
-        assertThat(val).isEqualTo(ov.getValue("k1"));
-        assertThat(val2).isEqualTo(ov.getValue("k2"));
-        assertThat(pv).isEqualTo(ov.getValue("foo"));
+        assertThat(val).isEqualTo(ov.getPropertyValue("k1"));
+        assertThat(val2).isEqualTo(ov.getPropertyValue("k2"));
+        assertThat(pv).isEqualTo(ov.getPropertyValue("foo"));
     }
 
     @Test
@@ -112,7 +147,7 @@
         map.put("k2.k3", "v2");
         map.put("foo", "bar");
         ov.setValues(map);
-        PropertyValue pv = ov.getValue("foo");
+        PropertyValue pv = ov.getPropertyValue("foo");
         assertThat(pv).isNotNull();
         assertThat("foo").isEqualTo(pv.getKey());
         assertThat("bar").isEqualTo(pv.getValue());
@@ -121,10 +156,10 @@
     @Test
     public void iterator() {
         ObjectValue ov = PropertyValue.createObject();
-        PropertyValue val = PropertyValue.createValue("k1", "v");
-        PropertyValue val2 = PropertyValue.createValue("k2", "v");
-        ov.set(val);
-        ov.set(val2);
+        PropertyValue val = new PropertyValue("k1", "v");
+        PropertyValue val2 = new PropertyValue("k2", "v");
+        ov.setPropertyValue(val);
+        ov.setPropertyValue(val2);
         Iterator iter = ov.iterator();
         assertThat(iter).isNotNull();
         assertThat(iter.hasNext()).isTrue();
@@ -137,21 +172,20 @@
     @Test
     public void set() {
         ObjectValue ov = PropertyValue.createObject();
-        PropertyValue val = PropertyValue.createValue("k", "v");
-        ov.set(val);
-        ov.set(val);
-        ov.set(val);
+        PropertyValue val = new PropertyValue("k", "v");
+        ov.setPropertyValue(val);
+        ov.setPropertyValue(val);
+        ov.setPropertyValue(val);
         assertThat(1).isEqualTo(ov.getSize());
-        assertThat(val).isEqualTo(ov.getValue("k"));
+        assertThat(val).isEqualTo(ov.getPropertyValue("k"));
 
     }
 
     @Test
     public void getSet_Value() {
         ObjectValue ov = PropertyValue.createObject();
-        ov.setValue("v");
         assertThat(0).isEqualTo(ov.getSize());
-        assertThat("v").isEqualTo(ov.getValue());
+        assertThat(ov.getValue()).isNotNull();
     }
 
     @Test
@@ -159,16 +193,16 @@
         ObjectValue ov = PropertyValue.createObject();
         ov.setValue("k", "v");
         assertThat(1).isEqualTo(ov.getSize());
-        assertThat("v").isEqualTo(ov.getValue("k").getValue());
-        assertThat("k").isEqualTo(ov.getValue("k").getKey());
+        assertThat("v").isEqualTo(ov.getValue("k"));
+        assertThat("k").isEqualTo(ov.getPropertyValue("k").getKey());
         ov.setValue("k2", "v2");
         assertThat(2).isEqualTo(ov.getSize());
-        assertThat("v2").isEqualTo(ov.getValue("k2").getValue());
-        assertThat("k2").isEqualTo(ov.getValue("k2").getKey());
+        assertThat("v2").isEqualTo(ov.getValue("k2"));
+        assertThat("k2").isEqualTo(ov.getPropertyValue("k2").getKey());
         ov.setValue("k", "v");
         assertThat(2).isEqualTo(ov.getSize());
-        assertThat("v").isEqualTo(ov.getValue("k").getValue());
-        assertThat("k").isEqualTo(ov.getValue("k").getKey());
+        assertThat("v").isEqualTo(ov.getPropertyValue("k").getValue());
+        assertThat("k").isEqualTo(ov.getPropertyValue("k").getKey());
     }
 
     @Test
@@ -176,11 +210,11 @@
         ObjectValue ov = PropertyValue.createObject();
         ov.setValueWithCompositeKey("k1.k2.k3", "v");
         assertThat(1).isEqualTo(ov.getSize());
-        ObjectValue treeNode = (ObjectValue)ov.getValue("k1");
+        ObjectValue treeNode = (ObjectValue)ov.getPropertyValue("k1");
         assertThat(treeNode).isNotNull();
-        treeNode = (ObjectValue)treeNode.getValue("k2");
+        treeNode = (ObjectValue)treeNode.getPropertyValue("k2");
         assertThat(treeNode).isNotNull();
-        PropertyValue finalValue = treeNode.getValue("k3");
+        PropertyValue finalValue = treeNode.getPropertyValue("k3");
         assertThat(finalValue).isNotNull();
         assertThat("v").isEqualTo(finalValue.getValue());
     }
@@ -189,9 +223,9 @@
     @Test
     public void setObject() {
         ObjectValue ov = PropertyValue.createObject();
-        ov.setObject("k");
+        ov.addObject("k");
         assertThat(1).isEqualTo(ov.getSize());
-        ObjectValue ov2 = (ObjectValue)ov.getValue("k");
+        ObjectValue ov2 = (ObjectValue)ov.getPropertyValue("k");
         assertThat(ov2).isNotNull();
         assertThat("k").isEqualTo(ov2.getKey());
     }
@@ -199,72 +233,49 @@
     @Test
     public void setList() {
         ObjectValue ov = PropertyValue.createObject();
-        ov.setList("k");
+        ov.addList("k");
         assertThat(1).isEqualTo(ov.getSize());
-        ListValue lv = (ListValue)ov.getValue("k");
+        ListValue lv = (ListValue)ov.getPropertyValue("k");
         assertThat("k").isEqualTo(lv.getKey());
     }
 
     @Test
     public void getValue_WithName() {
         ObjectValue ov = PropertyValue.createObject();
-        ov.setList("k1");
-        ov.setList("k2");
-        ov.setObject("k3");
+        ov.addList("k1");
+        ov.addList("k2");
+        ov.addObject("k3");
         ov.setValue("k4", "v");
         Collection<PropertyValue> values = ov.getValues();
         assertThat(values).isNotNull().hasSize(4);
     }
 
     @Test
-    public void getValues_WithPredicate() {
-        ObjectValue ov = PropertyValue.createObject();
-        ov.setList("k1");
-        ov.setList("k2");
-        ov.setObject("k3");
-        ov.setValue("k4", "v");
-        Collection<PropertyValue> values = ov.getValues(
-                pv -> "k1".equals(pv.getKey())
-        );
-        assertThat(values).isNotNull().hasSize(1);
-        assertThat("k1").isEqualTo(values.iterator().next().getKey());
-    }
-
-    @Test
     public void getValues() {
         ObjectValue ov = PropertyValue.createObject();
-        ov.setList("k1");
-        ov.setList("k2");
-        ov.setObject("k3");
+        ov.addList("k1");
+        ov.addList("k2");
+        ov.addObject("k3");
         ov.setValue("k4", "v");
         Collection<PropertyValue> values = ov.getValues();
         assertThat(values).isNotNull().hasSize(4);
     }
 
     @Test
-    public void toPropertyValue() {
-        ObjectValue ov = PropertyValue.createObject("foo");
-        ov.setList("list");
-        PropertyValue pv = ov.toPropertyValue();
-        assertThat(pv).isNotNull();
-        assertThat(pv.getKey()).isEqualTo(ov.getKey());
-    }
-
-    @Test
     public void toListValue() {
         ObjectValue ov = PropertyValue.createObject("foo");
-        ov.setList("list").setValue("a");
+        ov.addList("list").addValue("a");
         ListValue lv = ov.toListValue();
         assertThat(lv).isNotNull();
         assertThat(lv.getKey()).isEqualTo(ov.getKey());
-        assertThat(lv.get(0)).isNotNull();
-        assertThat(ov.getValue("list").getValue()).isEqualTo(lv.get(0).getValue());
+        assertThat(lv.getPropertyValue(0)).isNotNull();
+        assertThat(ov.getValue("list")).isEqualTo(lv.getPropertyValue(0).getValue());
     }
 
     @Test
     public void toObjectValue() {
         ObjectValue ov = PropertyValue.createObject("foo");
-        ov.setList("list");
+        ov.addList("list");
         ObjectValue ov2 = ov.toObjectValue();
         assertThat(ov == ov2).isTrue();
     }
@@ -272,7 +283,7 @@
     @Test
     public void mutable() {
         ObjectValue ov = PropertyValue.createObject("foo");
-        ov.setList("list");
+        ov.addList("list");
         assertThat(ov.isImmutable()).isFalse();
         ObjectValue ov2 = ov.mutable();
         assertThat(ov2.isImmutable()).isFalse();
@@ -280,9 +291,37 @@
     }
 
     @Test
+    public void testSetValues_WithSource() throws Exception {
+        Map<String, String> map = new HashMap<>();
+        map.put("a", "b");
+        map.put("b", "c");
+        ObjectValue ov = PropertyValue.createObject();
+        ov.setValues(map, "source", true);
+        assertThat(ov.getSize()).isEqualTo(map.size());
+        for(PropertyValue pv:ov){
+            assertThat("source").isEqualTo(pv.getMeta("source"));
+        }
+        assertThat("b").isEqualTo(ov.getValue("a"));
+        assertThat("c").isEqualTo(ov.getValue("b"));
+    }
+
+    @Test
+    public void testSetValues() {
+        Map<String, String> map = new HashMap<>();
+        map.put("a", "b");
+        map.put("b", "c");
+        ObjectValue ov = PropertyValue.createObject();
+        ov.setValues(map);
+        assertThat(ov.getSize()).isEqualTo(map.size());
+        assertThat(ov.getSize()).isEqualTo(map.size());
+        assertThat("b").isEqualTo(ov.getValue("a"));
+        assertThat("c").isEqualTo(ov.getValue("b"));
+    }
+
+    @Test
     public void deepClone() {
         ObjectValue ov1 = PropertyValue.createObject("foo");
-        ov1.setList("list");
+        ov1.addList("list");
         ObjectValue ov2 = ov1.deepClone();
         assertThat(ov1.getValues()!=ov2.getValues()).isTrue();
         assertThat(ov1.getMeta()!=ov2.getMeta()).isTrue();
@@ -293,18 +332,18 @@
     @Test
     public void equals() {
         ObjectValue ov1 = PropertyValue.createObject("foo");
-        ov1.setList("list");
+        ov1.addList("list");
         ObjectValue ov2 = PropertyValue.createObject("foo");
-        ov2.setList("list");
+        ov2.addList("list");
         assertThat(ov1.equals(ov2)).isTrue();
     }
 
     @Test
     public void testHashCode() {
         ObjectValue ov1 = PropertyValue.createObject("foo");
-        ov1.setList("list");
+        ov1.addList("list");
         ObjectValue ov2 = PropertyValue.createObject("foo");
-        ov2.setList("list");
+        ov2.addList("list");
         assertThat(ov1.hashCode() == ov2.hashCode()).isTrue();
     }
 
@@ -313,15 +352,15 @@
         ObjectValue ov1 = PropertyValue.createObject("foo");
         String toString = ov1.toString();
         assertThat(toString).isNotNull();
-        ov1.setList("list");
+        ov1.addList("list");
         toString = ov1.toString();
         assertThat(toString).isNotNull();
-        ov1.setObject("object");
+        ov1.addObject("object");
         toString = ov1.toString();
         assertThat(toString).isNotNull();
         ov1.setValue("valueKey", "value");
         toString = ov1.toString();
         assertThat(toString).isNotNull();
-        assertThat("PropertyValue[MAP]{'foo', size='3'}").isEqualTo(toString);
+        assertThat("Object{size='3', values='{valueKey=value}}").isEqualTo(toString);
     }
 }
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/PropertySourceTest.java b/code/api/src/test/java/org/apache/tamaya/spi/PropertySourceTest.java
index 139e85b..3614d93 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/PropertySourceTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/PropertySourceTest.java
@@ -26,6 +26,7 @@
 import org.junit.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.mockito.Mockito.mock;
 
 public class PropertySourceTest {
@@ -49,9 +50,9 @@
     public void getOrdinal(){
         assertThat(0).isEqualTo(new PropertySourceImpl().getOrdinal());
         PropertySourceImpl ps = new PropertySourceImpl();
-        ps.value = PropertyValue.createValue(PropertySource.TAMAYA_ORDINAL, "123");
+        ps.value = new PropertyValue(PropertySource.TAMAYA_ORDINAL, "123");
         assertThat(123).isEqualTo(ps.getOrdinal());
-        ps.value = PropertyValue.createValue(PropertySource.TAMAYA_ORDINAL, "abc");
+        ps.value = new PropertyValue(PropertySource.TAMAYA_ORDINAL, "abc");
         assertThat(0).isEqualTo(ps.getOrdinal());
     }
 
@@ -63,18 +64,18 @@
     @Test
     public void addChangeListener(){
         BiConsumer<Set<String>,PropertySource> l = mock(BiConsumer.class);
-        new PropertySourceImpl().addChangeListener(l);
+        assertThatCode(() -> new PropertySourceImpl().addChangeListener(l)).doesNotThrowAnyException();
     }
 
     @Test
     public void removeChangeListener(){
         BiConsumer<Set<String>,PropertySource> l = mock(BiConsumer.class);
-        new PropertySourceImpl().removeChangeListener(l);
+        assertThatCode(() -> new PropertySourceImpl().removeChangeListener(l)).doesNotThrowAnyException();
     }
 
     @Test
     public void removeAllChangeListeners(){
-        new PropertySourceImpl().removeAllChangeListeners();
+        assertThatCode(() -> new PropertySourceImpl().removeAllChangeListeners()).doesNotThrowAnyException();
     }
 
     @Test
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java
index 3af9775..c718aa1 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java
@@ -199,17 +199,17 @@
 //
 //    @Test(expected = NullPointerException.class)
 //    public void mapThreeParameterVariantRequiresNonNullValueForConfigParameter() {
-//        PropertyValueBuilder.map(null, "a", Collections.EMPTY_MAP);
+//        PropertyValueBuilder.mapProperties(null, "a", Collections.EMPTY_MAP);
 //    }
 //
 //    @Test
 //    public void mapThreeParameterVariantRequiresNonNullValueForSource() {
-//        PropertyValueBuilder.map(Collections.EMPTY_MAP, null, Collections.EMPTY_MAP);
+//        PropertyValueBuilder.mapProperties(Collections.EMPTY_MAP, null, Collections.EMPTY_MAP);
 //    }
 //
 //    @Test(expected = NullPointerException.class)
 //    public void mapThreeParameterVariantRequiresNonNullValueForMetaData() {
-//        PropertyValueBuilder.map(Collections.EMPTY_MAP, "s", null);
+//        PropertyValueBuilder.mapProperties(Collections.EMPTY_MAP, "s", null);
 //    }
 //
 //}
\ No newline at end of file
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java
index 2a5f946..694ef50 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java
@@ -20,40 +20,39 @@
 
 import org.junit.Test;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 
 @SuppressWarnings("unchecked")
 public class PropertyValueTest {
 
-    @Test(expected = NullPointerException.class)
-    public void ofDoesNotAcceptNullAsKey() throws Exception {
-        PropertyValue.of(null, "b", "source");
-    }
-
     @Test
-    public void ofDoesAcceptNullAsSource() throws Exception {
-        PropertyValue.of("a", "b", null);
-    }
+    public void from(){
 
-    @Test
-    public void builder() throws Exception {
-        PropertyValueBuilder b = PropertyValue.builder("a", "b");
-        assertThat(b).isNotNull();
-        assertThat("a").isEqualTo(b.key);
-        assertThat("b").isEqualTo(b.source);
-    }
-
-    @Test
-    public void testOf(){
-        assertThat(PropertyValue.of("k", "v", "testGetKey")).isNotNull();
-    }
-
-    @Test(expected = NullPointerException.class)
-    public void getMetaEntryRequiresNonNullValueForKey() {
-        PropertyValue.of("a", "b", "s").getMeta(null);
+        ObjectValue val = ObjectValue.from(Arrays.asList());
+        assertThat(val).isNotNull();
+        val = ObjectValue.from(Arrays.asList(
+                PropertyValue.createObject("o1").setValue("key", "value"),
+                PropertyValue.createObject("o2").setValue("key2", "value2"))
+        );
+        assertThat(val).isNotNull();
+        assertThat(val.getValue("o1")).isNotNull();
+        assertThat(val.getValue("o2")).isNotNull();
+        assertThat(val.getPropertyValue("o1").toObjectValue().getValue("key")).isEqualTo("value");
+        assertThat(val.getPropertyValue("o2").toObjectValue().getValue("key2")).isEqualTo("value2");
+        val = ObjectValue.from(Arrays.asList(
+                PropertyValue.createList("o1").addValue("value"),
+                new PropertyValue( "o2", "value2"))
+        );
+        assertThat(val).isNotNull();
+        assertThat(val.getValue("o1")).isNotNull();
+        assertThat(val.getValue("o2")).isNotNull();
+        assertThat(val.getPropertyValue("o1").toListValue().getValue(0)).isEqualTo("value");
+        assertThat(val.getPropertyValue("o2").getValue()).isEqualTo("value2");
     }
 
     @Test(expected = NullPointerException.class)
@@ -113,80 +112,39 @@
 
     @Test
     public void testGetMetaEntries2() throws Exception {
-        PropertyValue pv = PropertyValue.of("k", "v", null);
+        PropertyValue pv = new PropertyValue( "k", "v");
         assertThat(pv.getMeta()).isNotNull().isEmpty();
     }
 
     @Test
-    public void testMap() throws Exception {
-        Map<String, String> map = new HashMap<>();
-        map.put("a", "b");
-        map.put("b", "c");
-        Map<String, PropertyValue> result = PropertyValue.map(map, "source");
-        assertThat(result).isNotNull().hasSize(map.size());
-       for(PropertyValue pv:result.values()){
-           assertThat("source").isEqualTo(pv.getMetaEntry("source"));
-       }
-        assertThat("b").isEqualTo(map.get("a"));
-        assertThat("c").isEqualTo(map.get("b"));
-    }
-
-    @Test
-    public void testMap_WithMeta() throws Exception {
-        Map<String, String> map = new HashMap<>();
-        map.put("a", "b");
-        map.put("b", "c");
-        Map<String, String> meta = new HashMap<>();
-        meta.put("m1", "m1v");
-        meta.put("m2", "m2v");
-        Map<String, PropertyValue> result = PropertyValue.map(map, "source", meta);
-        assertThat(result).isNotNull().hasSize(map.size());
-        for(PropertyValue pv:result.values()){
-            assertThat("source").isEqualTo(pv.getMetaEntry("source"));
-            assertThat("m1v").isEqualTo(pv.getMeta("m1"));
-            assertThat("m2v").isEqualTo(pv.getMeta("m2"));
-        }
-        assertThat("b").isEqualTo(map.get("a"));
-        assertThat("c").isEqualTo(map.get("b"));
-    }
-
-    @Test
     public void testHashCode(){
-        assertThat(PropertyValue.of("k", "v", "testGetKey").hashCode()).isEqualTo(PropertyValue.of("k", "v", "testGetKey").hashCode());
-        assertThat(PropertyValue.of("k", "v", "testGetKey").hashCode()).isNotSameAs(PropertyValue.of("k1", "v", "testGetKey").hashCode());
-        assertThat(PropertyValue.of("k", "v", "testGetKey").hashCode()).isNotSameAs(PropertyValue.of("k", "v1", "testGetKey").hashCode());
-        assertThat(PropertyValue.of("k", "v", "1").hashCode()).isNotSameAs(PropertyValue.of("k", "v", "2").hashCode());
+        assertThat(new PropertyValue( "k", "v").hashCode()).isEqualTo(new PropertyValue( "k", "v").hashCode());
+        assertThat(new PropertyValue( "k", "v").hashCode()).isNotSameAs(new PropertyValue( "k1", "v").hashCode());
+        assertThat(new PropertyValue( "k", "v").hashCode()).isNotSameAs(new PropertyValue( "k", "v1").hashCode());
+        assertThat(new PropertyValue( "k", "v").hashCode()).isNotSameAs(new PropertyValue( "k", "v").hashCode());
     }
 
     @Test
     public void testEquals(){
-        assertThat(PropertyValue.of("k", "v", "testEquals")).isEqualTo(PropertyValue.of("k", "v", "testEquals"));
-        assertThat(PropertyValue.of("k2", "v", "testEquals")).isNotSameAs(PropertyValue.of("k", "v", "testEquals"));
-        assertThat(PropertyValue.of("k", "v", "testEquals")).isNotSameAs(PropertyValue.of("k", "v2", "testEquals"));
-        assertThat(PropertyValue.of("k", "v", "testEquals")).isNotSameAs(PropertyValue.of("k", "v", "testEquals2"));
+        assertThat(new PropertyValue( "k", "v")).isEqualTo(new PropertyValue( "k", "v"));
+        assertThat(new PropertyValue( "k2", "v")).isNotSameAs(new PropertyValue( "k", "v"));
+        assertThat(new PropertyValue( "k", "v")).isNotSameAs(new PropertyValue( "k", "v2"));
+        assertThat(new PropertyValue( "k", "v")).isNotSameAs(new PropertyValue( "k", "v"));
     }
         
     @Test
     public void testGetKey() throws Exception {
-        PropertyValue pv = PropertyValue.of("k", "v", "testGetKey");
+        PropertyValue pv = new PropertyValue( "k", "v");
         assertThat(pv.getKey()).isEqualTo("k");
     }
 
     @Test
     public void testGetValue() throws Exception {
-        PropertyValue pv = PropertyValue.of("k", "v", "testGetValue");
+        PropertyValue pv = new PropertyValue("k", "v");
         assertThat(pv.getValue()).isEqualTo("v");
     }
 
     @Test
-    public void testGetSource() throws Exception {
-        PropertyValue pv = PropertyValue.of("k", "v", "testGetSource");
-        assertThat(pv.getSource()).isEqualTo("testGetSource");
-        pv = PropertyValue.of("k", "v", "testGetSource");
-        assertThat(pv.getSource()).isEqualTo("testGetSource");
-    }
-
-    @Test
     public void testGetMetaEntry() throws Exception {
         PropertyValue pv = PropertyValue.createObject("k")
                 .setMeta("k", "v2");
@@ -202,17 +160,17 @@
 
     @Test(expected = NullPointerException.class)
     public void testInstantiateNoKey2() throws Exception {
-        PropertyValue.createValue(null, "v");
+        new PropertyValue( null, "v");
     }
 
     @Test
     public void testInstantiateNoValue2() throws Exception {
-        PropertyValue.createValue("k", null);
+        assertThatCode(() -> PropertyValue.createValue("k", null)).doesNotThrowAnyException();
     }
 
     @Test
     public void testInstantiateNoSource2() throws Exception {
-        PropertyValue.createValue("k", "v");
+        assertThatCode(() -> PropertyValue.createValue("k", "v")).doesNotThrowAnyException();
     }
 
     @Test(expected = NullPointerException.class)
@@ -227,7 +185,7 @@
 
     @Test
     public void newXXX() {
-        assertThat(PropertyValue.createValue("", null)).isNotNull();
+        assertThat(new PropertyValue("", null)).isNotNull();
         assertThat(PropertyValue.createObject()).isNotNull();
         assertThat(PropertyValue.createObject("")).isNotNull();
         assertThat(PropertyValue.createList()).isNotNull();
@@ -236,7 +194,7 @@
 
     @Test
     public void valueOf() {
-        PropertyValue foo = PropertyValue.createValue("foo", "bar");
+        PropertyValue foo = new PropertyValue("foo", "bar");
         assertThat(foo).isNotNull();
         assertThat("foo").isEqualTo(foo.getKey());
         assertThat("bar").isEqualTo(foo.getValue());
@@ -255,10 +213,10 @@
         assertThat(root.getSize() == 0).isTrue();
         assertThat(root.setValue("foo", null)).isNotNull();
         assertThat(root.getSize()==0).isFalse();
-        assertThat(root.getValue("foo")).isNotNull();
-        assertThat(root.getValue("foo").getValue()).isNull();
+        assertThat(root.getPropertyValue("foo")).isNotNull();
+        assertThat(root.getValue("foo")).isEqualTo("null");
         assertThat(root.setValue("foo", "bar")).isNotNull();
-        assertThat(root.getValue("foo").getValue()).isEqualTo("bar");
+        assertThat(root.getValue("foo")).isEqualTo("bar");
         assertThat(root.getSize()==1).isTrue();
     }
 
@@ -280,15 +238,16 @@
         ObjectValue root = PropertyValue.createObject("a");
         assertThat("a").isEqualTo(root.getQualifiedKey());
         ObjectValue child = PropertyValue.createObject("b");
-        ObjectValue n = root.set(child);
+        ObjectValue n = root.setPropertyValue(child);
         assertThat("a.b").isEqualTo(child.getQualifiedKey());
-        PropertyValue added = child.setValue("c", null);
-        assertThat("a.b.c").isEqualTo(added.getQualifiedKey());
+        child.setValue("c", null);
+        PropertyValue val = child.getPropertyValue("c");
+        assertThat("a.b.c").isEqualTo(val.getQualifiedKey());
     }
 
     @Test
     public void isLeaf() {
-        PropertyValue n = PropertyValue.createValue("", "");
+        PropertyValue n = new PropertyValue("", "");
         assertThat(n.isLeaf()).isTrue();
         n = PropertyValue.createList("");
         assertThat(n.isLeaf()).isFalse();
@@ -296,7 +255,7 @@
 
     @Test
     public void isImmutable() {
-        PropertyValue n = PropertyValue.createValue("", "");
+        PropertyValue n = new PropertyValue("", "");
         assertThat(n.isImmutable()).isFalse();
         n.immutable();
         assertThat(n.isImmutable()).isTrue();
@@ -305,22 +264,22 @@
 
     @Test
     public void isRoot() {
-        PropertyValue n = PropertyValue.createValue("", "");
+        PropertyValue n = new PropertyValue("", "");
         assertThat(n.isRoot()).isTrue();
-        n = PropertyValue.createValue("", "").setParent(n);
+        n = new PropertyValue("", "").setParent(n);
         assertThat(n.isRoot()).isFalse();
     }
 
     @Test(expected=IllegalStateException.class)
     public void checkImmutableChangeThrowsExceotion() {
-        PropertyValue n = PropertyValue.createValue("", "");
+        PropertyValue n = new PropertyValue("", "");
         n.immutable();
         n.setValue("jhgjg");
     }
 
     @Test
     public void checkMutable() {
-        PropertyValue n = PropertyValue.createValue("", "");
+        PropertyValue n = new PropertyValue("", "");
         n.immutable();
         n = n.mutable();
         n.setValue("jhgjg");
@@ -331,22 +290,22 @@
     public void getParent() {
         ObjectValue n = PropertyValue.createObject("");
         assertThat(n.getParent()).isNull();
-        PropertyValue val = n.setObject("b");
+        PropertyValue val = n.addObject("b");
         assertThat(n.getValue("b")).isNotNull();
-        assertThat(val).isEqualTo(n.getValue("b"));
-        assertThat(n.getValue("b").getParent()).isNotNull();
+        assertThat(val).isEqualTo(n.getPropertyValue("b"));
+        assertThat(n.getPropertyValue("b").getParent()).isNotNull();
     }
 
     @Test
     public void size(){
-        PropertyValue n = PropertyValue.createValue("key", "");
+        PropertyValue n = new PropertyValue("key", "");
         assertThat(0).isEqualTo(n.getSize());
         assertThat(n.iterator().hasNext()).isFalse();
     }
 
     @Test
     public void setValue() {
-        PropertyValue n = PropertyValue.createValue("key", "");
+        PropertyValue n = new PropertyValue("key", "");
         assertThat("").isEqualTo(n.getValue());
         n.setValue("jhgjg");
         assertThat("jhgjg").isEqualTo(n.getValue());
@@ -354,33 +313,21 @@
 
     @Test
     public void setKey() {
-        PropertyValue n = PropertyValue.createValue("key", "");
+        PropertyValue n = new PropertyValue("key", "");
         assertThat("key").isEqualTo(n.getKey());
         n.setKey("jhgjg");
         assertThat("jhgjg").isEqualTo(n.getKey());
     }
 
     @Test
-    public void toBuilder() {
-        PropertyValue n = PropertyValue.createValue("key", "");
-        assertThat(n.toBuilder()).isNotNull();
-    }
-
-    @Test
-    public void toPropertyValue() {
-        PropertyValue n = PropertyValue.createValue("key", "");
-        assertThat(n == n.toPropertyValue()).isTrue();
-    }
-
-    @Test
     public void toObjectValue() {
-        PropertyValue n = PropertyValue.createValue("key", "");
+        PropertyValue n = new PropertyValue("key", "");
         assertThat(n.toObjectValue()).isNotNull();
     }
 
     @Test
     public void toListValue() {
-        PropertyValue n = PropertyValue.createValue("key", "");
+        PropertyValue n = new PropertyValue("key", "");
         assertThat(n.toListValue()).isNotNull();
     }
 
@@ -391,25 +338,25 @@
 //        n.setField("b");
 //        n.setField("c");
 //        n.setField("c");
-//        List<PropertyValue> nodes = n.getValues("a");
+//        List<PropertyValue> nodes = n.getPropertyValues("a");
 //        assertNotNull(nodes);
 //        assertEquals(1, nodes.size());
 //        assertEquals("a", nodes.getValue(0).getKey());
 //
-//        nodes = n.getValues("c");
+//        nodes = n.getPropertyValues("c");
 //        assertEquals(2, nodes.size());
 //        assertEquals("c", nodes.getValue(0).getKey());
 //        assertEquals("c", nodes.getValue(1).getKey());
 //    }
 //
 //    @Test
-//    public void getValues() {
+//    public void getPropertyValues() {
 //        PropertyValue n = PropertyValue.createObject();
 //        n.setField("a");
 //        n.setField("b");
 //        n.setField("c");
 //        n.setField("c");
-//        List<PropertyValue> nodes = n.getValues();
+//        List<PropertyValue> nodes = n.getPropertyValues();
 //        assertNotNull(nodes);
 //        assertEquals(4, nodes.size());
 //        assertEquals("a", nodes.getValue(0).getKey());
@@ -419,11 +366,28 @@
 //    }
 
     @Test
-    public void asMap() {
+    public void toMap() {
         ObjectValue n = PropertyValue.createObject("");
         n.setValue("a", "aVal");
-        n.setObject("b").setObject("b2").setValue("b3", "b3Val");
-        ListValue array = n.setList("c");
+        n.addObject("b").addObject("b2").setValue("b3", "b3Val");
+        ListValue array = n.addList("c");
+        array.addValue("cVal1");
+        array.addValue("cVal2");
+        Map<String,String> map = n.toMap();
+        System.out.println(map);
+        assertThat(map).hasSize(4);
+        assertThat("aVal").isEqualTo(map.get("a"));
+        assertThat("b3Val").isEqualTo(map.get("b.b2.b3"));
+        assertThat("cVal1").isEqualTo(map.get("c[0]"));
+        assertThat("cVal2").isEqualTo(map.get("c[1]"));
+    }
+
+    @Test
+    public void toLocalMap() {
+        ObjectValue n = PropertyValue.createObject("");
+        n.setValue("a", "aVal");
+        n.addObject("b").addObject("b2").setValue("b3", "b3Val");
+        ListValue array = n.addList("c");
         array.addValue("cVal1");
         array.addValue("cVal2");
         Map<String,String> map = n.toMap();
@@ -441,9 +405,7 @@
         n.setValue("a", "aVal");
         n.setValue("b.b2.b3", "b3Val");
         n.setValue("c", "cVal2");
-        assertThat("a = aVal\n" +
-                "b.b2.b3 = b3Val\n" +
-                "c = cVal2\n").isEqualTo(n.asString());
+        assertThat("Object{size='3', values='{a=aVal, b.b2.b3=b3Val, c=cVal2}}").isEqualTo(n.toString());
     }
 
     @Test
@@ -461,7 +423,7 @@
         n.setValue("a", "aVal");
         n.setValue("b.b2.b3", "b3Val");
         n.setValue("c", "cVal1");
-        assertThat("PropertyValue[MAP]{'', size='3'}").isEqualTo(n.toString());
+        assertThat("Object{size='3', values='{a=aVal, b.b2.b3=b3Val, c=cVal1}}").isEqualTo(n.toString());
     }
 
 }
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
index a72ea2b..dd6bd73 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
@@ -20,10 +20,9 @@
 
 import org.junit.Test;
 
-import java.io.IOException;
 import java.net.URL;
+import java.util.Collection;
 import java.util.Collections;
-import java.util.Enumeration;
 import java.util.List;
 import java.util.function.Supplier;
 
@@ -88,8 +87,8 @@
         }
 
         @Override
-        public Enumeration<URL> getResources(String resource) throws IOException {
-            return null;
+        public Collection<URL> getResources(String resource) {
+            return Collections.emptySet();
         }
 
         @Override
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java b/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java
index 6c5beb4..ac926d9 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java
@@ -18,7 +18,6 @@
  */
 package org.apache.tamaya.spi;
 
-import java.io.IOException;
 import java.net.URL;
 import java.util.*;
 import java.util.function.Supplier;
@@ -77,7 +76,7 @@
     }
 
     @Override
-    public Enumeration<URL> getResources(String resource) throws IOException {
+    public Collection<URL> getResources(String resource) {
         throw ex;
     }
 
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java b/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
index b00a7a0..9dddd41 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
@@ -18,7 +18,6 @@
  */
 package org.apache.tamaya.spi;
 
-import java.io.IOException;
 import java.net.URL;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
@@ -113,8 +112,18 @@
     }
 
     @Override
-    public Enumeration<URL> getResources(String resource) throws IOException {
-        return classLoader.getResources(resource);
+    public Collection<URL> getResources(String resource) {
+        List<URL> urls = new ArrayList<>();
+        try {
+            Enumeration<URL> found = getClassLoader().getResources(resource);
+            while (found.hasMoreElements()) {
+                urls.add(found.nextElement());
+            }
+        }catch(Exception e){
+            Logger.getLogger(ServiceContext.class.getName())
+                    .log(Level.FINEST, e, () -> "Failed to lookup resources: " + resource);
+        }
+        return urls;
     }
 
     @Override
diff --git a/code/core/pom.xml b/code/core/pom.xml
index 51397cf..8220e62 100644
--- a/code/core/pom.xml
+++ b/code/core/pom.xml
@@ -98,7 +98,7 @@
                     <!--
                      ! Add -Djava.security.debug=all for debugging if needed
                      !-->
-                    <argLine>-Djava.security.policy=${project.basedir}/src/test/resources/java-security.policy ${argLine}</argLine>
+                    <argLine>-Djava.security.policy=${project.basedir}/src/test/resources/java-security.policy</argLine>
                 </configuration>
             </plugin>
         </plugins>
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/BannerManager.java b/code/core/src/main/java/org/apache/tamaya/core/internal/BannerManager.java
index 5ec3bfe..2481ecf 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/BannerManager.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/BannerManager.java
@@ -61,7 +61,7 @@
     /**
      * The resouce path to the file containing the banner of Tamaya.
      */
-    protected final static String BANNER_RESOURCE_PATH = "/tamaya-banner.txt";
+    protected static final String BANNER_RESOURCE_PATH = "/tamaya-banner.txt";
 
     /**
      * The target for the Tamaya banner output.
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/CoreConfigurationBuilder.java b/code/core/src/main/java/org/apache/tamaya/core/internal/CoreConfigurationBuilder.java
index 3aeac8c..ae76062 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/CoreConfigurationBuilder.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/CoreConfigurationBuilder.java
@@ -79,6 +79,7 @@
     }
 
     @SuppressWarnings("unchecked")
+    @Override
     protected void addCorePropertyConverters() {
         addPropertyConverters(TypeLiteral.<BigDecimal>of(BigDecimal.class), new BigDecimalConverter());
         addPropertyConverters(TypeLiteral.<BigInteger>of(BigInteger.class), new BigIntegerConverter());
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/CoreConfigurationProvider.java b/code/core/src/main/java/org/apache/tamaya/core/internal/CoreConfigurationProvider.java
index bbfecf6..989821b 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/CoreConfigurationProvider.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/CoreConfigurationProvider.java
@@ -82,7 +82,7 @@
         Objects.requireNonNull(config.getContext());
         Configuration old = this.configurations.put(classLoader, Objects.requireNonNull(config));
         if(old != null){
-            LOG.warning(String.format("Replaced config %S with %S for classloader %S", old, config, classLoader));
+            LOG.warning(String.format("Replaced config %s with %s for classloader %s", old, config, classLoader));
         }
     }
 
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java
index f039d27..6cd16e9 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tamaya.core.internal;
 
+import org.apache.tamaya.spi.ServiceContext;
 import org.osgi.framework.ServiceReference;
 
 import javax.annotation.Priority;
@@ -61,9 +62,11 @@
      */
     public static int getPriority(Class<? extends Object> type) {
         int prio = 1;
-        Priority priority = type.getAnnotation(Priority.class);
-        if (priority != null) {
-            prio = priority.value();
+        if(ServiceContext.PRIORITY_ANNOTATION_AVAILABLE) {
+            Priority priority = type.getAnnotation(Priority.class);
+            if (priority != null) {
+                prio = priority.value();
+            }
         }
         return prio;
     }
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
index 2d67dc8..4cb820f 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
@@ -25,7 +25,6 @@
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 
-import java.io.IOException;
 import java.net.URL;
 import java.util.*;
 import java.util.function.Supplier;
@@ -167,7 +166,7 @@
     }
 
     @Override
-    public Enumeration<URL> getResources(String resource) throws IOException{
+    public Collection<URL> getResources(String resource){
         LOG.finest("TAMAYA  Loading resources: " + resource);
         List<URL> result = new ArrayList<>();
         URL url = osgiServiceLoader.getBundleContext().getBundle()
@@ -191,7 +190,7 @@
                 result.add(url);
             }
         }
-        return Collections.enumeration(result);
+        return result;
     }
 
     @Override
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
index 0efe5b0..b97c7bf 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
@@ -22,6 +22,7 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -48,9 +49,9 @@
     private static final Logger LOG = Logger.getLogger(OSGIServiceLoader.class.getName());
     private static final String META_INF_SERVICES = "META-INF/services/";
 
-    private BundleContext context;
+    private final BundleContext context;
 
-    private Set<Bundle> resourceBundles = Collections.synchronizedSet(new HashSet<Bundle>());
+    private final Set<Bundle> resourceBundles = Collections.synchronizedSet(new HashSet<>());
 
     public OSGIServiceLoader(BundleContext context) {
         this.context = Objects.requireNonNull(context);
@@ -75,11 +76,10 @@
     @Override
     public void bundleChanged(BundleEvent bundleEvent) {
         // Parse and createObject metadata when installed
+        Bundle bundle = bundleEvent.getBundle();
         if (bundleEvent.getType() == BundleEvent.STARTED) {
-            Bundle bundle = bundleEvent.getBundle();
             checkAndLoadBundle(bundle);
         } else if (bundleEvent.getType() == BundleEvent.STOPPED) {
-            Bundle bundle = bundleEvent.getBundle();
             checkAndUnloadBundle(bundle);
         }
     }
@@ -129,16 +129,10 @@
             URL child = bundle.getEntry(entryPath);
             InputStream inStream = child.openStream();
             LOG.info("Loading Services " + serviceClass.getName() + " from bundle...: " + bundle.getSymbolicName());
-            try (BufferedReader br = new BufferedReader(new InputStreamReader(inStream, "UTF-8"))) {
-                String implClassName = br.readLine();
-                while (implClassName != null) {
-                    int hashIndex = implClassName.indexOf("#");
-                    if (hashIndex > 0) {
-                        implClassName = implClassName.substring(0, hashIndex - 1);
-                    } else if (hashIndex == 0) {
-                        implClassName = "";
-                    }
-                    implClassName = implClassName.trim();
+            try (BufferedReader br = new BufferedReader(new InputStreamReader(inStream, StandardCharsets.UTF_8))) {
+                String line = br.readLine();
+                while (line != null) {
+                    String implClassName = getImplClassName(line);
                     if (implClassName.length() > 0) {
                         try {
                             // Load the service class
@@ -164,13 +158,11 @@
                             BundleContext bundleContext = bundle.getBundleContext();
                             bundleContext.registerService(serviceName, factory, props);
                             LOG.info("Registered Tamaya service class: " + implClassName + "(" + serviceName + ")");
-                        } catch (Exception e) {
-                            LOG.log(Level.SEVERE, "Failed to load service: " + implClassName, e);
-                        } catch (NoClassDefFoundError err) {
+                        } catch (NoClassDefFoundError | Exception err) {
                             LOG.log(Level.SEVERE, "Failed to load service: " + implClassName, err);
                         }
                     }
-                    implClassName = br.readLine();
+                    line = br.readLine();
                 }
             }
         } catch (RuntimeException rte) {
@@ -192,39 +184,31 @@
             URL child = bundle.getEntry(entryPath);
             InputStream inStream = child.openStream();
 
-            BufferedReader br = new BufferedReader(new InputStreamReader(inStream, "UTF-8"));
-            String implClassName = br.readLine();
-            while (implClassName != null) {
-                int hashIndex = implClassName.indexOf("#");
-                if (hashIndex > 0) {
-                    implClassName = implClassName.substring(0, hashIndex - 1);
-                } else if (hashIndex == 0) {
-                    implClassName = "";
-                }
-                implClassName = implClassName.trim();
-                if (implClassName.length() > 0) {
-                    LOG.fine("Unloading Service (" + serviceName + "): " + implClassName);
-                    try {
-                        // Load the service class
-                        Class<?> implClass = bundle.loadClass(implClassName);
-                        if (!serviceClass.isAssignableFrom(implClass)) {
-                            LOG.warning("Configured service: " + implClassName + " is not assignable to "
-                                    + serviceClass.getName());
-                            continue;
+            try (BufferedReader br = new BufferedReader(new InputStreamReader(inStream, StandardCharsets.UTF_8))) {
+                String line = br.readLine();
+                while (line != null) {
+                    String implClassName = getImplClassName(line);
+                    if (implClassName.length() > 0) {
+                        LOG.fine("Unloading Service (" + serviceName + "): " + implClassName);
+                        try {
+                            // Load the service class
+                            Class<?> implClass = bundle.loadClass(implClassName);
+                            if (!serviceClass.isAssignableFrom(implClass)) {
+                                LOG.warning("Configured service: " + implClassName + " is not assignable to "
+                                        + serviceClass.getName());
+                                continue;
+                            }
+                            ServiceReference<?> ref = bundle.getBundleContext().getServiceReference(implClass);
+                            if (ref != null) {
+                                bundle.getBundleContext().ungetService(ref);
+                            }
+                        } catch (NoClassDefFoundError | Exception err) {
+                            LOG.log(Level.SEVERE, "Failed to unload service: " + implClassName, err);
                         }
-                        ServiceReference<?> ref = bundle.getBundleContext().getServiceReference(implClass);
-                        if (ref != null) {
-                            bundle.getBundleContext().ungetService(ref);
-                        }
-                    } catch (Exception e) {
-                        LOG.log(Level.SEVERE, "Failed to unload service: " + implClassName, e);
-                    } catch (NoClassDefFoundError err) {
-                        LOG.log(Level.SEVERE, "Failed to unload service: " + implClassName, err);
                     }
+                    line = br.readLine();
                 }
-                implClassName = br.readLine();
             }
-            br.close();
         } catch (RuntimeException rte) {
             throw rte;
         } catch (Exception e) {
@@ -232,13 +216,24 @@
         }
     }
 
+    private String getImplClassName(String line) {
+        int hashIndex = line.indexOf('#');
+        if (hashIndex > 0) {
+            return line.substring(0, hashIndex - 1).trim();
+        } else if (hashIndex == 0) {
+            return "";
+        } else {
+            return line.trim();
+        }
+    }
+
     /**
      * Service factory simply instantiating the configured service.
      */
     static class JDKUtilServiceFactory implements ServiceFactory {
         private final Class<?> serviceClass;
 
-        public JDKUtilServiceFactory(Class<?> serviceClass) {
+        JDKUtilServiceFactory(Class<?> serviceClass) {
             this.serviceClass = serviceClass;
         }
 
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java
index 989e4da..77d954f 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java
@@ -32,7 +32,7 @@
 @Component(service = PropertyConverter.class)
 public class BooleanConverter implements PropertyConverter<Boolean> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(BooleanConverter.class.getName());
 
     @Override
     public Boolean convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java
index a07015f..8b43738 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java
@@ -47,7 +47,7 @@
 @Component(service = PropertyConverter.class)
 public class ByteConverter implements PropertyConverter<Byte>{
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(ByteConverter.class.getName());
 
     @Override
     public Byte convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ClassConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ClassConverter.java
index d3dc31f..4c3b4ee 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ClassConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ClassConverter.java
@@ -36,7 +36,7 @@
 @Component(service = PropertyConverter.class)
 public class ClassConverter implements PropertyConverter<Class<?>>{
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(ClassConverter.class.getName());
 
     @Override
     public Class<?> convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/DurationConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/DurationConverter.java
index c58e0af..f8239ce 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/DurationConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/DurationConverter.java
@@ -34,7 +34,7 @@
 @Component(service = PropertyConverter.class)
 public class DurationConverter implements PropertyConverter<Duration> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(DurationConverter.class.getName());
 
     @Override
     public Duration convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/FileConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/FileConverter.java
index b911e31..e9b21a9 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/FileConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/FileConverter.java
@@ -33,7 +33,7 @@
 @Component(service = PropertyConverter.class)
 public class FileConverter implements PropertyConverter<File> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(FileConverter.class.getName());
 
     @Override
     public File convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/InstantConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/InstantConverter.java
index 4a0994f..5c3b6ec 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/InstantConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/InstantConverter.java
@@ -33,7 +33,7 @@
 @Component(service = PropertyConverter.class)
 public class InstantConverter implements PropertyConverter<Instant> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(InstantConverter.class.getName());
 
     @Override
     public Instant convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalDateConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalDateConverter.java
index 5f09ec4..ced145e 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalDateConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalDateConverter.java
@@ -33,7 +33,7 @@
 @Component(service = PropertyConverter.class)
 public class LocalDateConverter implements PropertyConverter<LocalDate> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(LocalDateConverter.class.getName());
 
     @Override
     public LocalDate convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalDateTimeConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalDateTimeConverter.java
index ea92f6c..9983291 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalDateTimeConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalDateTimeConverter.java
@@ -33,7 +33,8 @@
 @Component(service = PropertyConverter.class)
 public class LocalDateTimeConverter implements PropertyConverter<LocalDateTime> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(LocalDateTimeConverter.class.getName());
+
 
     @Override
     public LocalDateTime convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalTimeConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalTimeConverter.java
index 5fbaa47..2507b37 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalTimeConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LocalTimeConverter.java
@@ -33,7 +33,7 @@
 @Component(service = PropertyConverter.class)
 public class LocalTimeConverter implements PropertyConverter<LocalTime> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(LocalTimeConverter.class.getName());
 
     @Override
     public LocalTime convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/MonthDayConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/MonthDayConverter.java
new file mode 100644
index 0000000..f6331b7
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/MonthDayConverter.java
@@ -0,0 +1,61 @@
+/*
+ * 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.converters;
+
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.osgi.service.component.annotations.Component;
+
+import java.time.MonthDay;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Year.
+ */
+@Component(service = PropertyConverter.class)
+public class MonthDayConverter implements PropertyConverter<MonthDay> {
+
+    private static final Logger LOG = Logger.getLogger(MonthDayConverter.class.getName());
+
+    @Override
+    public MonthDay convert(String value, ConversionContext ctx) {
+        ctx.addSupportedFormats(getClass(), MonthDay.now().toString());
+        if(value==null){
+            return null;
+        }
+        try{
+            return MonthDay.parse(value);
+        }catch(Exception e){
+            LOG.log(Level.FINEST, e, () -> "Cannot parse MonthDay: " + value);
+            return null;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return Objects.nonNull(o) && getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+}
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/OffsetDateTimeConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/OffsetDateTimeConverter.java
index 3ef70db..f266ceb 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/OffsetDateTimeConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/OffsetDateTimeConverter.java
@@ -33,7 +33,7 @@
 @Component(service = PropertyConverter.class)
 public class OffsetDateTimeConverter implements PropertyConverter<OffsetDateTime> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(OffsetDateTimeConverter.class.getName());
 
     @Override
     public OffsetDateTime convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/OffsetTimeConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/OffsetTimeConverter.java
index 9eb7b0a..a51b99a 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/OffsetTimeConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/OffsetTimeConverter.java
@@ -33,7 +33,7 @@
 @Component(service = PropertyConverter.class)
 public class OffsetTimeConverter implements PropertyConverter<OffsetTime> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(OffsetTimeConverter.class.getName());
 
     @Override
     public OffsetTime convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/PathConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/PathConverter.java
index 57e739b..2a36d3b 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/PathConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/PathConverter.java
@@ -34,7 +34,7 @@
 @Component(service = PropertyConverter.class)
 public class PathConverter implements PropertyConverter<Path> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(PathConverter.class.getName());
 
     @Override
     public Path convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URIConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URIConverter.java
index 19aa341..41c5ca4 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URIConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URIConverter.java
@@ -33,7 +33,7 @@
 @Component(service = PropertyConverter.class)
 public class URIConverter implements PropertyConverter<URI> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(URIConverter.class.getName());
 
     @Override
     public URI convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URLConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URLConverter.java
index 2939e85..f7c90e6 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URLConverter.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URLConverter.java
@@ -33,7 +33,7 @@
 @Component(service = PropertyConverter.class)
 public class URLConverter implements PropertyConverter<URL> {
 
-    private final Logger LOG = Logger.getLogger(getClass().getName());
+    private static final Logger LOG = Logger.getLogger(URLConverter.class.getName());
 
     @Override
     public URL convert(String value, ConversionContext ctx) {
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/YearConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/YearConverter.java
new file mode 100644
index 0000000..414d891
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/YearConverter.java
@@ -0,0 +1,61 @@
+/*
+ * 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.converters;
+
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.osgi.service.component.annotations.Component;
+
+import java.time.Year;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Year.
+ */
+@Component(service = PropertyConverter.class)
+public class YearConverter implements PropertyConverter<Year> {
+
+    private static final Logger LOG = Logger.getLogger(YearConverter.class.getName());
+
+    @Override
+    public Year convert(String value, ConversionContext ctx) {
+        ctx.addSupportedFormats(getClass(), Year.now().toString());
+        if(value==null){
+            return null;
+        }
+        try{
+            return Year.parse(value);
+        }catch(Exception e){
+            LOG.log(Level.FINEST, e, () -> "Cannot parse Year: " + value);
+            return null;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return Objects.nonNull(o) && getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+}
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/YearMonthConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/YearMonthConverter.java
new file mode 100644
index 0000000..0bcf52d
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/YearMonthConverter.java
@@ -0,0 +1,61 @@
+/*
+ * 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.converters;
+
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.osgi.service.component.annotations.Component;
+
+import java.time.YearMonth;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to YearMonth.
+ */
+@Component(service = PropertyConverter.class)
+public class YearMonthConverter implements PropertyConverter<YearMonth> {
+
+    private static final Logger LOG = Logger.getLogger(YearMonthConverter.class.getName());
+
+    @Override
+    public YearMonth convert(String value, ConversionContext ctx) {
+        ctx.addSupportedFormats(getClass(), YearMonth.now().toString());
+        if(value==null){
+            return null;
+        }
+        try{
+            return YearMonth.parse(value);
+        }catch(Exception e){
+            LOG.log(Level.FINEST, e, () -> "Cannot parse YearMonth: " + value);
+            return null;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o){
+        return Objects.nonNull(o) && getClass().equals(o.getClass());
+    }
+
+    @Override
+    public int hashCode(){
+        return getClass().hashCode();
+    }
+}
diff --git a/code/core/src/main/java/org/apache/tamaya/core/propertysource/BasePropertySource.java b/code/core/src/main/java/org/apache/tamaya/core/propertysource/BasePropertySource.java
index 0a3bc1b..0f74b09 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/propertysource/BasePropertySource.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/propertysource/BasePropertySource.java
@@ -36,7 +36,7 @@
     /** default ordinal that will be used, if no ordinal is provided with the config. */
     private int defaultOrdinal;
     /** Used if the ordinal has been setCurrent explicitly. */
-    private volatile Integer ordinal;
+    private Integer ordinal;
     /** The name of the property source. */
     private String name;
 
diff --git a/code/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyConverter b/code/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyConverter
index 396aef1..1320a98 100644
--- a/code/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyConverter
+++ b/code/core/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyConverter
@@ -28,6 +28,7 @@
 org.apache.tamaya.core.internal.converters.BigDecimalConverter
 org.apache.tamaya.core.internal.converters.BigIntegerConverter
 org.apache.tamaya.core.internal.converters.CurrencyConverter
+org.apache.tamaya.core.internal.converters.MonthDayConverter
 org.apache.tamaya.core.internal.converters.NumberConverter
 org.apache.tamaya.core.internal.converters.URIConverter
 org.apache.tamaya.core.internal.converters.URLConverter
@@ -42,3 +43,5 @@
 org.apache.tamaya.core.internal.converters.InstantConverter
 org.apache.tamaya.core.internal.converters.OptionalConverter
 org.apache.tamaya.core.internal.converters.SupplierConverter
+org.apache.tamaya.core.internal.converters.YearConverter
+org.apache.tamaya.core.internal.converters.YearMonthConverter
diff --git a/code/core/src/test/java/org/apache/tamaya/core/ConfigurationBuilderTest.java b/code/core/src/test/java/org/apache/tamaya/core/ConfigurationBuilderTest.java
index 82a9aea..f8bc6c5 100644
--- a/code/core/src/test/java/org/apache/tamaya/core/ConfigurationBuilderTest.java
+++ b/code/core/src/test/java/org/apache/tamaya/core/ConfigurationBuilderTest.java
@@ -55,7 +55,7 @@
                 .addPropertySources(testPropertySource, testPS2);
         Configuration cfg = b.build();
         assertThat(cfg.getContext().getPropertySources()).hasSize(2).contains(testPropertySource, testPS2);
-        // Ensure no sorting happens during add, so switch ordinals!
+        // Ensure no sorting happens during addPropertyValue, so switch ordinals!
         testPS2 = new TestPropertySource("addPropertySources_Array", 1);
         b = Configuration.createConfigurationBuilder()
                 .addPropertySources(testPS2, testPropertySource);
@@ -74,7 +74,7 @@
         assertThat(cfg.getContext().getPropertySources()).hasSize(2).contains(testPropertySource, testPS2);
         assertThat("TestPropertySource").isEqualTo(cfg.getContext().getPropertySources().get(0).getName());
         assertThat("addPropertySources_Collection").isEqualTo(cfg.getContext().getPropertySources().get(1).getName());
-        // Ensure no sorting happens during add, so switch ordinals!
+        // Ensure no sorting happens during addPropertyValue, so switch ordinals!
         testPS2 = new TestPropertySource("addPropertySources_Collection", 1);
         b = Configuration.createConfigurationBuilder()
                 .addPropertySources(Arrays.asList(new PropertySource[]{testPS2, testPropertySource}));
diff --git a/code/core/src/test/java/org/apache/tamaya/core/internal/CoreConfigurationProviderTest.java b/code/core/src/test/java/org/apache/tamaya/core/internal/CoreConfigurationProviderTest.java
index d3f8174..e9d1cfb 100644
--- a/code/core/src/test/java/org/apache/tamaya/core/internal/CoreConfigurationProviderTest.java
+++ b/code/core/src/test/java/org/apache/tamaya/core/internal/CoreConfigurationProviderTest.java
@@ -22,6 +22,7 @@
 import org.junit.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 
 /**
  * Created by atsticks on 11.09.16.
@@ -30,7 +31,7 @@
 
     @Test
     public void testInstantiation() throws Exception {
-        new CoreConfigurationProvider();
+        assertThatCode(() -> new CoreConfigurationProvider()).doesNotThrowAnyException();
     }
 
     @Test
@@ -53,11 +54,11 @@
     @SuppressWarnings("deprecation")
     @Test
     public void setConfiguration() throws Exception {
-        new CoreConfigurationProvider()
+        assertThatCode(() -> new CoreConfigurationProvider()
                 .setConfiguration(new CoreConfigurationProvider().getConfiguration(
                         getClass().getClassLoader()),
                         getClass().getClassLoader()
-                );
+                )).doesNotThrowAnyException();
     }
 
     @SuppressWarnings("deprecation")
diff --git a/code/core/src/test/java/org/apache/tamaya/core/internal/CoreConfigurationTest.java b/code/core/src/test/java/org/apache/tamaya/core/internal/CoreConfigurationTest.java
index 0075784..3d707eb 100644
--- a/code/core/src/test/java/org/apache/tamaya/core/internal/CoreConfigurationTest.java
+++ b/code/core/src/test/java/org/apache/tamaya/core/internal/CoreConfigurationTest.java
@@ -48,6 +48,7 @@
     @Test
     public void testToString() throws Exception {
         String toString = Configuration.current().getContext().toString();
+        assertThat(toString).contains("Property Filters").contains("Property Converters");
     }
 
     @Test
diff --git a/code/core/src/test/java/org/apache/tamaya/core/internal/OSGIServiceContextTest.java b/code/core/src/test/java/org/apache/tamaya/core/internal/OSGIServiceContextTest.java
index e3227cc..0f079a9 100644
--- a/code/core/src/test/java/org/apache/tamaya/core/internal/OSGIServiceContextTest.java
+++ b/code/core/src/test/java/org/apache/tamaya/core/internal/OSGIServiceContextTest.java
@@ -20,7 +20,7 @@
 
 import java.io.IOException;
 import java.net.URL;
-import java.util.Enumeration;
+import java.util.Collection;
 import java.util.List;
 
 import org.junit.Test;
@@ -98,11 +98,11 @@
         mockBundleContext.installBundle(startedBundle);
         OSGIServiceContext instance = new OSGIServiceContext(loader);
 
-        Enumeration<URL> resources = instance.getResources("dummy");
+        Collection<URL> resources = instance.getResources("dummy");
         assertThat(resources).isNotNull();
-        URL resource = (URL)resources.nextElement();
+        URL resource = (URL)resources.iterator().next();
         assertThat(resource.toString()).contains("mockbundle.service");
-        assertThat(resources.hasMoreElements()).isFalse();
+        assertThat(resources.size()).isEqualTo(1);
     }
 
     /**
diff --git a/code/core/src/test/java/org/apache/tamaya/core/propertysource/BasePropertySourceTest.java b/code/core/src/test/java/org/apache/tamaya/core/propertysource/BasePropertySourceTest.java
index 5ac28be..1074b41 100644
--- a/code/core/src/test/java/org/apache/tamaya/core/propertysource/BasePropertySourceTest.java
+++ b/code/core/src/test/java/org/apache/tamaya/core/propertysource/BasePropertySourceTest.java
@@ -125,7 +125,7 @@
         @Override
         public Map<String, PropertyValue> getProperties() {
             Map<String, PropertyValue> result = new HashMap<>(1);
-            result.put(PropertySource.TAMAYA_ORDINAL, PropertyValue.of(PropertySource.TAMAYA_ORDINAL, "1000", getName()));
+            result.put(PropertySource.TAMAYA_ORDINAL, PropertyValue.createValue(PropertySource.TAMAYA_ORDINAL, "1000"));
             return result;
         }
     }
@@ -144,7 +144,8 @@
         @Override
         public Map<String, PropertyValue> getProperties() {
             Map<String, PropertyValue> result = new HashMap<>(1);
-            result.put(PropertySource.TAMAYA_ORDINAL, PropertyValue.of(PropertySource.TAMAYA_ORDINAL, "invalid", getName()));
+            result.put(PropertySource.TAMAYA_ORDINAL, PropertyValue.createValue(PropertySource.TAMAYA_ORDINAL, "invalid")
+                    .setMeta("source", getName()));
             return result;
         }
     }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
index a5cf45b..a41c068 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
@@ -29,6 +29,10 @@
 import org.apache.tamaya.spi.PropertyConverter;
 import org.apache.tamaya.spi.PropertyValue;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.util.*;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -38,7 +42,7 @@
  * chain of {@link org.apache.tamaya.spi.PropertySource} and {@link org.apache.tamaya.spi.PropertyFilter}
  * instances to evaluate the current Configuration.
  */
-public class DefaultConfiguration implements Configuration {
+public class DefaultConfiguration implements Configuration, Serializable {
     /**
      * The logger.
      */
@@ -47,12 +51,12 @@
     /**
      * The current {@link ConfigurationContext} of the current instance.
      */
-    private final ConfigurationContext configurationContext;
+    private ConfigurationContext configurationContext;
 
     /**
      * EvaluationStrategy
      */
-    private ConfigValueEvaluator configEvaluator;
+    private transient ConfigValueEvaluator configEvaluator;
 
 
     private ConfigValueEvaluator loadConfigValueEvaluator() {
@@ -301,4 +305,23 @@
                 configurationContext +
                 '}';
     }
+
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        configurationContext = (ConfigurationContext)ois.readObject();
+        configEvaluator = loadConfigValueEvaluator();
+    }
+
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        if(configurationContext instanceof Serializable){
+            oos.writeObject(configurationContext);
+        }else{
+            oos.writeObject(new DefaultConfigurationContext(
+                    this.configurationContext.getServiceContext(),
+                    this.configurationContext.getPropertyFilters(),
+                    this.configurationContext.getPropertySources(),
+                    this.configurationContext.getPropertyConverters(),
+                    this.configurationContext.getServiceContext().getService(MetadataProvider.class,
+                            () -> new DefaultMetaDataProvider())));
+        }
+    }
 }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java
index 3cd459d..d050638 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java
@@ -61,6 +61,7 @@
      * Creates a new builder instance.
      */
     public DefaultConfigurationBuilder() {
+
     }
 
 
@@ -87,6 +88,7 @@
     @Override
     public ConfigurationBuilder setClassLoader(ClassLoader classLoader) {
         setServiceContext(ServiceContextManager.getServiceContext(classLoader));
+        serviceContext.reset();
         return this;
     }
 
@@ -142,16 +144,21 @@
     /**
      * Adds the given sources as property sources.
      *
-     * @param sources property sources to add.
+     * @param sources property sources to addPropertyValue.
      * @return the current configuration builder.
      */
     @Override
     public ConfigurationBuilder addPropertySources(Collection<PropertySource> sources){
         checkBuilderState();
         for(PropertySource source:sources) {
-            if (!this.propertySources.contains(source)) {
-                this.propertySources.add(source);
+            if(this.propertySources.stream()
+                    .filter(ex -> Objects.equals(ex.getName(), source.getName()))
+                    .findAny()
+                    .isPresent()){
+                LOG.finest(() -> "Omitting already present property source: " + source.getName());
+                continue;
             }
+            this.propertySources.add(source);
         }
         return this;
     }
@@ -308,7 +315,7 @@
             if (!converters.contains(propertyConverter)) {
                 converters.add(propertyConverter);
             } else {
-                LOG.warning("Converter ignored, already registered: " + propertyConverter);
+                LOG.finest("Converter ignored, already registered: " + propertyConverter);
             }
         }
         return this;
@@ -346,6 +353,14 @@
     }
 
     @Override
+    public ConfigurationBuilder sortPropertyConverter(Comparator<PropertyConverter> comparator) {
+        for(List<PropertyConverter<?>> converters:this.propertyConverters.values()) {
+            Collections.sort(converters, comparator);
+        }
+        return this;
+    }
+
+    @Override
     public List<PropertyFilter> getPropertyFilters() {
         return this.propertyFilters;
     }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
index 0645edc..d5ad696 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
@@ -25,19 +25,26 @@
 import org.apache.tamaya.spi.PropertySource;
 import org.apache.tamaya.spi.PropertyValue;
 import org.apache.tamaya.spi.ServiceContext;
+import org.apache.tamaya.spi.ServiceContextManager;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.util.*;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.logging.Logger;
+import java.util.stream.Collectors;
 
 /**
  * Default implementation of a simple {@link ConfigurationContext}.
  */
-public class DefaultConfigurationContext implements ConfigurationContext {
+public class DefaultConfigurationContext implements ConfigurationContext, Serializable {
 
     /** The logger used. */
     private final static Logger LOG = Logger.getLogger(DefaultConfigurationContext.class.getName());
-    private final MetadataProvider metaDataProvider;
+
+    private MetadataProvider metaDataProvider;
 
     /**
      * Subcomponent handling {@link PropertyConverter} instances.
@@ -61,7 +68,7 @@
     /**
      * Lock for internal synchronization.
      */
-    private final ReentrantReadWriteLock propertySourceLock = new ReentrantReadWriteLock();
+    private ReentrantReadWriteLock propertySourceLock = new ReentrantReadWriteLock();
 
     @SuppressWarnings("unchecked")
     protected DefaultConfigurationContext(DefaultConfigurationBuilder builder) {
@@ -79,7 +86,7 @@
         List<PropertyFilter> propertyFilters = new ArrayList<>(builder.getPropertyFilters());
         immutablePropertyFilters = Collections.unmodifiableList(propertyFilters);
 
-        // Finally add the converters
+        // Finally addPropertyValue the converters
         for(Map.Entry<TypeLiteral<?>, List<PropertyConverter<?>>> en:builder.getPropertyConverter().entrySet()) {
             for (@SuppressWarnings("rawtypes") PropertyConverter converter : en.getValue()) {
                 this.propertyConverterManager.register(en.getKey(), converter);
@@ -268,4 +275,42 @@
         return immutablePropertyFilters;
     }
 
+    /**
+     * Evaluates all present keys from the property sources loaded.
+     * @return the keys found, never null.
+     */
+    private Set<String> getKeys() {
+        Set<String> keys = new HashSet<>();
+        for(PropertySource ps:immutablePropertySources){
+            keys.addAll(ps.getProperties().keySet());
+        }
+        return keys;
+    }
+
+    /**
+     * Deserialization only reads the property source snapshots from the stream. Converters, filters,
+     * meta data provider and the service context are reinitialized based on the current environment.
+     * @param ois the input stream
+     * @throws IOException if the stream is corrupted
+     * @throws ClassNotFoundException if s property source class cannot be serialized.
+     */
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        this.serviceContext = ServiceContextManager.getServiceContext();
+        this.propertyConverterManager = new PropertyConverterManager(
+                this.serviceContext, true);
+        this.immutablePropertySources = Collections.unmodifiableList(
+                (List<PropertySource>)ois.readObject());
+        this.immutablePropertyFilters = Collections.unmodifiableList(
+                this.serviceContext.getServices(PropertyFilter.class));
+        this.metaDataProvider = this.serviceContext.getService(MetadataProvider.class);
+        propertySourceLock = new ReentrantReadWriteLock();
+    }
+
+    private void writeObject(ObjectOutputStream oos)throws IOException{
+        // omit converters, they will be reloaded from scratch.
+        oos.writeObject(this.immutablePropertySources.stream()
+                .map(ps -> DefaultPropertySourceSnapshot.of(ps, getKeys())).collect(Collectors.toList()));
+        // omit filters, they will be reloaded from scratch
+    }
+
 }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationSnapshot.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationSnapshot.java
index ac4fe8b..9d2d9cb 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationSnapshot.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationSnapshot.java
@@ -40,10 +40,10 @@
     /**
      * The properties frozen.
      */
-    private Configuration snapshot;
+    private DefaultConfiguration snapshot;
     private long frozenAt = System.nanoTime();
     private UUID id = UUID.randomUUID();
-    private transient ConfigurationContext context;
+    private DefaultConfigurationContext context;
     private Set<String> keys = new HashSet<>();
 
     /**
@@ -101,6 +101,7 @@
      * Get the evaluated keys of this frozen coinfiguration.
      * @return the keys, not null.
      */
+    @Override
     public Set<String> getKeys() {
         return keys;
     }
@@ -209,4 +210,5 @@
     public UUID getId() {
         return id;
     }
+
 }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultMetaDataProvider.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultMetaDataProvider.java
index e1337bd..fa27237 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultMetaDataProvider.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultMetaDataProvider.java
@@ -30,7 +30,7 @@
 /**
  * Default metadata provider implementation, which searches for all kind of entries
  * formatted as {@code [(META)key].metaKey=metaValue}. All matching key/values are added to the
- * meta data map for the given key as {@code metaKey=metaValue} meta entries.
+ * meta data mapProperties for the given key as {@code metaKey=metaValue} meta entries.
  */
 public class DefaultMetaDataProvider implements MetadataProvider {
 
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultPropertySourceSnapshot.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultPropertySourceSnapshot.java
index 6c37543..ee76418 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultPropertySourceSnapshot.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultPropertySourceSnapshot.java
@@ -79,7 +79,7 @@
         this.name = propertySource.getName();
         if(propertySource.getChangeSupport().equals(ChangeSupport.UNSUPPORTED) ||
             propertySource.getChangeSupport().equals(ChangeSupport.IMMUTABLE)){
-            // simply get the keys and we are done. We cant do more...
+            // simply getPropertyValue the keys and we are done. We cant do more...
             this.properties = initProperties(propertySource, false);
         }else{
             this.properties = initProperties(propertySource, true);
@@ -120,8 +120,8 @@
     }
 
     /**
-     * Creates a new FrozenPropertySource instance based on a PropertySource and the target key set given. This method
-     * uses all keys available in the property map.
+     * Creates a new FrozenPropertySource instance based on a PropertySource and the target key setPropertyValue given. This method
+     * uses all keys available in the property mapProperties.
      *
      * @param propertySource the property source to be frozen, not null.
      * @return the frozen property source.
@@ -132,7 +132,7 @@
     }
 
     /**
-     * Creates a new FrozenPropertySource instance based on a PropertySource and the target key set given.
+     * Creates a new FrozenPropertySource instance based on a PropertySource and the target key setPropertyValue given.
      *
      * @param propertySource the property source to be frozen, not null.
      * @param keys the keys to be evaluated for the snapshot. Only these keys will be contained in the resulting
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultServiceContext.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultServiceContext.java
index 9b63a99..9bd1040 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultServiceContext.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultServiceContext.java
@@ -22,7 +22,6 @@
 import org.apache.tamaya.spi.ClassloaderAware;
 import org.apache.tamaya.spi.ServiceContext;
 
-import javax.annotation.Priority;
 import java.text.MessageFormat;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/MetadataProvider.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/MetadataProvider.java
index d4a0abe..0253f94 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/MetadataProvider.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/MetadataProvider.java
@@ -63,7 +63,7 @@
      * from alternate sources.
      *
      * @param property the property key, not null.
-     * @param metaData the metadata to set/replace.
+     * @param metaData the metadata to setPropertyValue/replace.
      * @return this instance, for chaining.
      */
     MetadataProvider setMeta(String property, Map<String, String> metaData);
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
index ef68eed..25bdbc3 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
@@ -18,6 +18,8 @@
  */
 package org.apache.tamaya.spisupport;
 
+import org.apache.tamaya.spi.ServiceContext;
+
 import javax.annotation.Priority;
 import java.io.Serializable;
 import java.util.Comparator;
@@ -75,9 +77,11 @@
     @SuppressWarnings({ "rawtypes", "unchecked" })
     public static int getPriority(Class type) {
         int prio = 1;
-        Priority priority = (Priority)type.getAnnotation(Priority.class);
-        if (priority != null) {
-            prio = priority.value();
+        if(ServiceContext.PRIORITY_ANNOTATION_AVAILABLE) {
+            Priority priority = (Priority) type.getAnnotation(Priority.class);
+            if (priority != null) {
+                prio = priority.value();
+            }
         }
         return prio;
     }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java
index ce718b7..a9ea77b 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java
@@ -185,11 +185,11 @@
     }
 
     /**
-     * Get a map of all property converters currently registered. This will not contain the converters that
+     * Get a mapProperties of all property converters currently registered. This will not contain the converters that
      * may be created, when an instance is adapted, which provides a String constructor or compatible
      * factory methods taking a single String instance.
      *
-     * @return the current map of instantiated and registered converters.
+     * @return the current mapProperties of instantiated and registered converters.
      * @see #createDefaultPropertyConverter(org.apache.tamaya.TypeLiteral)
      */
     public Map<TypeLiteral<?>, List<PropertyConverter<?>>> getPropertyConverters() {
@@ -254,6 +254,15 @@
                 readLock.unlock();
             }
         }
+        if(converterList.isEmpty() && targetType.getRawType().isArray() &&
+            !targetType.getRawType().getComponentType().isPrimitive()){
+            try {
+                readLock.lock();
+                addConvertersToList(List.class.cast(this.converters.get(TypeLiteral.of(Object[].class))), converterList);
+            } finally {
+                readLock.unlock();
+            }
+        }
         if (converterList.isEmpty() && !TypeLiteral.of(String.class).equals(targetType)) {
             // adding any converters created on the fly, e.g. for enum types.
             PropertyConverter<T> defaultConverter = createDefaultPropertyConverter(targetType);
@@ -364,36 +373,38 @@
             return new EnumConverter<>(targetType.getRawType());
         }
         PropertyConverter<T> converter = null;
-        final Method factoryMethod = getFactoryMethod(targetType.getRawType(), "of", "createValue", "instanceOf", "getInstance", "from", "fromString", "parse");
+        final Method factoryMethod = getFactoryMethod(targetType.getRawType(), "of", "valueOf", "createValue", "instanceOf", "getInstance", "from", "fromString", "parse");
         if (factoryMethod != null) {
             converter = new DefaultPropertyConverter<>(factoryMethod, targetType.getRawType());
         }
         if (converter == null) {
-            final Constructor<T> constr;
+            Constructor<T> constr;
             try {
                 constr = targetType.getRawType().getDeclaredConstructor(String.class);
             } catch (NoSuchMethodException e) {
-                LOG.log(Level.FINEST, "No matching constructor for " + targetType, e);
-                return null;
+                try {
+                    constr = targetType.getRawType().getDeclaredConstructor(CharSequence.class);
+                } catch (NoSuchMethodException e2) {
+                    LOG.log(Level.FINEST, "No matching constructor found for " + targetType);
+                    return null;
+                }
             }
+            Constructor<T> finalConstr = constr;
             converter = new PropertyConverter<T>() {
                     @Override
                     public T convert(String value, ConversionContext context) {
                         AccessController.doPrivileged(new PrivilegedAction<Object>() {
                             @Override
                             public Object run() {
-                                AccessController.doPrivileged(new PrivilegedAction<Object>() {
-                                    @Override
-                                    public Object run() {
-                                        constr.setAccessible(true);
-                                        return null;
-                                    }
+                                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
+                                    finalConstr.setAccessible(true);
+                                    return null;
                                 });
                                 return null;
                             }
                         });
                         try {
-                            return constr.newInstance(value);
+                            return finalConstr.newInstance(value);
                         } catch (Exception e) {
                             LOG.log(Level.SEVERE, "Error creating new PropertyConverter instance " + targetType, e);
                         }
@@ -418,6 +429,12 @@
                 m = type.getDeclaredMethod(name, String.class);
                 return m;
             } catch (NoSuchMethodException | RuntimeException e) {
+                // continue, try also with CharSequence
+            }
+            try {
+                m = type.getDeclaredMethod(name, CharSequence.class);
+                return m;
+            } catch (NoSuchMethodException | RuntimeException e) {
                 LOG.finest("No such factory method found on type: " + type.getName() + ", methodName: " + name);
             }
         }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
index c1d5520..3d0d501 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
@@ -19,6 +19,7 @@
 package org.apache.tamaya.spisupport;
 
 import org.apache.tamaya.spi.PropertyFilter;
+import org.apache.tamaya.spi.ServiceContext;
 
 import javax.annotation.Priority;
 import java.io.Serializable;
@@ -51,11 +52,19 @@
      * @return the comparison result
      */
     private int comparePropertyFilters(PropertyFilter filter1, PropertyFilter filter2) {
-        Priority prio1 = filter1.getClass().getAnnotation(Priority.class);
-        Priority prio2 = filter2.getClass().getAnnotation(Priority.class);
-        int ord1 = prio1 != null ? prio1.value() : 0;
-        int ord2 = prio2 != null ? prio2.value() : 0;
+        int ord1 = 0;
+        int ord2 = 0;
 
+        if(ServiceContext.PRIORITY_ANNOTATION_AVAILABLE) {
+            Priority prio1 = filter1.getClass().getAnnotation(Priority.class);
+            Priority prio2 = filter2.getClass().getAnnotation(Priority.class);
+            if(prio1!=null) {
+                ord1 = prio1.value();
+            }
+            if(prio2!=null) {
+                ord2 = prio2.value();
+            }
+        }
         if (ord1 < ord2) {
             return -1;
         } else if (ord1 > ord2) {
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
index 3222635..3a35c37 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
@@ -21,7 +21,6 @@
 import org.apache.tamaya.spi.PropertySource;
 import org.apache.tamaya.spi.PropertyValue;
 
-import javax.annotation.Priority;
 import java.io.Serializable;
 import java.util.Comparator;
 import java.util.logging.Logger;
@@ -76,7 +75,7 @@
      *     to convert it to an {@code int} createValue, using {@link Integer#parseInt(String)}.</li>
      *     <li>It tries to find and evaluate a method {@code int getOrdinal()}.</li>
      *     <li>It tries to find and evaluate a static field {@code int ORDINAL}.</li>
-     *     <li>It tries to find and evaluate a class level {@link Priority} annotation.</li>
+     *     <li>It tries to find and evaluate a class level {@link javax.annotation.Priority} annotation.</li>
      *     <li>It uses the default priority ({@code 0}.</li>
      * </ol>
      * @param propertySource the property source, not {@code null}.
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java
index 51a0a24..68be9d1 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java
@@ -18,7 +18,6 @@
  */
 package org.apache.tamaya.spisupport.propertysource;
 
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 import java.util.logging.Level;
@@ -36,11 +35,10 @@
     /** default ordinal that will be used, if no ordinal is provided with the config. */
     private int defaultOrdinal;
     /** Used if the ordinal has been setCurrent explicitly. */
-    private volatile Integer ordinal;
+    private Integer ordinal;
     /** The name of the property source. */
     private String name;
-    /** The optional prefix. */
-    private String prefix;
+
     /**
      * If true, this property source does not return any properties. This is useful since this
      * property source is applied by default, but can be switched off by setting the
@@ -155,14 +153,6 @@
         return val;
     }
 
-    public String getPrefix() {
-        return prefix;
-    }
-
-    public void setPrefix(String prefix) {
-        this.prefix = prefix;
-    }
-
     public boolean isDisabled() {
         return disabled;
     }
@@ -200,32 +190,10 @@
     protected String toStringValues() {
         return  "  defaultOrdinal=" + defaultOrdinal + '\n' +
                 "  ordinal=" + ordinal  + '\n' +
-                "  prefix=" + prefix + '\n' +
                 "  disabled=" + disabled + '\n' +
                 "  name='" + name + '\''  + '\n';
     }
 
-    protected Map<String,PropertyValue> mapProperties(Map<String, String> props, long timestamp) {
-        Map<String,PropertyValue> result = new HashMap<>();
-        String timestampVal = String.valueOf(timestamp);
-        if (prefix == null) {
-            for (Map.Entry<String, String> en : props.entrySet()) {
-                result.put(en.getKey(),
-                        PropertyValue.createValue(en.getKey(), en.getValue())
-                                .setMeta("source", getName())
-                                .setMeta("timestamp", timestampVal));
-            }
-        } else {
-            for (Map.Entry<String, String> en : props.entrySet()) {
-                result.put(prefix + en.getKey(),
-                        PropertyValue.createValue(prefix + en.getKey(), en.getValue())
-                                .setMeta("source", getName())
-                                .setMeta("timestamp", timestampVal));
-            }
-        }
-        return result;
-    }
-
     @Override
     public ChangeSupport getChangeSupport() {
         return changeSupport;
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java
index e9a7f70..7568cb0 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java
@@ -149,7 +149,7 @@
          * @return the builder
          */
         public Builder withSimpleProperty(String key, String value) {
-            return withProperties(PropertyValue.of(key, value, this.source));
+            return withProperties(PropertyValue.createValue(key, value).setMeta("source", this.source));
         }
 
         /**
@@ -161,7 +161,7 @@
          * @return the builder
          */
         public Builder withSimpleProperty(String key, String value, String source) {
-            return withProperties(PropertyValue.of(key, value, source));
+            return withProperties(PropertyValue.createValue(key, value).setMeta("source", source));
         }
 
         /**
@@ -196,7 +196,7 @@
          * @return the builder
          */
         public Builder withProperties(Map<String, String> properties, String source) {
-            this.properties.putAll(PropertyValue.map(properties, source));
+            this.properties.putAll(PropertyValue.mapProperties(properties, source));
             return this;
         }
 
@@ -207,7 +207,7 @@
          * @return the builder
          */
         public Builder withSimpleProperties(Map<String, String> properties) {
-            this.properties.putAll(PropertyValue.map(properties, this.source));
+            this.properties.putAll(PropertyValue.mapProperties(properties, this.source));
             return this;
         }
 
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/CLIPropertySource.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/CLIPropertySource.java
index 502af4b..62968ac 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/CLIPropertySource.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/CLIPropertySource.java
@@ -32,7 +32,7 @@
     /** The original main arguments. */
     private static String[] args = new String[0];
 
-    /** The map of parsed main arguments. */
+    /** The mapProperties of parsed main arguments. */
     private static Map<String,PropertyValue> mainArgs;
 
     /** Initializes the initial state. */
@@ -120,7 +120,7 @@
         Map<String,PropertyValue> finalProps = new HashMap<>();
         for(Map.Entry<String,String> en:result.entrySet()) {
             finalProps.put(en.getKey(),
-                    PropertyValue.of(en.getKey(), en.getValue(), "main-args"));
+                    PropertyValue.createValue(en.getKey(), en.getValue()).setMeta("source", "main-args"));
         }
         CLIPropertySource.mainArgs = Collections.unmodifiableMap(finalProps);
     }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/EnvironmentPropertySource.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/EnvironmentPropertySource.java
index 0308b76..ae156f5 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/EnvironmentPropertySource.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/EnvironmentPropertySource.java
@@ -198,6 +198,13 @@
         return "environment-properties";
     }
 
+    /*
+    Exact match (i.e. com.ACME.size)
+
+Replace the character that is neither alphanumeric nor _ with _ (i.e. com_ACME_size)
+
+Replace the character that is neither alphanumeric nor _ with _ and convert to upper case (i.e. COM_ACME_SIZE)
+     */
     @Override
     public PropertyValue get(String key) {
         if (isDisabled()) {
@@ -209,19 +216,21 @@
         String value = getPropertiesProvider().getenv(effectiveKey);
         // Replace all . by _ (i.e. com_ACME_size)
         if(value==null){
-            value = getPropertiesProvider().getenv(effectiveKey.replaceAll("\\.", "_"));
+            effectiveKey = effectiveKey.replaceAll("\\W", "_");
+            value = getPropertiesProvider().getenv(effectiveKey);
         }
         // Replace all . by _ and convert to upper case (i.e. COM_ACME_SIZE)
         if(value==null){
-            value = getPropertiesProvider().getenv(effectiveKey.replaceAll("\\.", "_")
-                    .toUpperCase());
+            effectiveKey = effectiveKey.toUpperCase();
+            value = getPropertiesProvider().getenv(effectiveKey);
         }
         if(value==null){
             return null;
         }
-        return PropertyValue.of(key, value, getName());
+        return PropertyValue.createValue(key, value).setMeta("source", getName());
     }
 
+
     private boolean hasPrefix() {
         return null != prefix && prefix.isEmpty();
     }
@@ -235,13 +244,15 @@
         if(prefix==null) {
             Map<String, PropertyValue> entries = new HashMap<>(System.getenv().size());
             for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
-                entries.put(entry.getKey(), PropertyValue.of(entry.getKey(), entry.getValue(), getName()));
+                entries.put(entry.getKey(), PropertyValue.createValue(entry.getKey(), entry.getValue())
+                        .setMeta("source", getName()));
             }
             return entries;
         }else{
             Map<String, PropertyValue> entries = new HashMap<>(System.getenv().size());
             for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
-                entries.put(prefix + entry.getKey(), PropertyValue.of(prefix + entry.getKey(), entry.getValue(), getName()));
+                entries.put(prefix + entry.getKey(), PropertyValue.createValue(prefix + entry.getKey(), entry.getValue())
+                        .setMeta("source", getName()));
             }
             return entries;
         }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/JavaConfigurationPropertySource.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/JavaConfigurationPropertySource.java
index 598808d..ca65c97 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/JavaConfigurationPropertySource.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/JavaConfigurationPropertySource.java
@@ -18,7 +18,6 @@
  */
 package org.apache.tamaya.spisupport.propertysource;
 
-import org.apache.tamaya.ConfigException;
 import org.apache.tamaya.spi.ChangeSupport;
 import org.apache.tamaya.spi.ClassloaderAware;
 import org.apache.tamaya.spi.PropertySource;
@@ -26,12 +25,9 @@
 import org.apache.tamaya.spi.ServiceContextManager;
 import org.apache.tamaya.spisupport.PropertySourceComparator;
 
-import java.io.IOException;
 import java.net.URL;
 import java.util.*;
 
-import static java.lang.String.format;
-
 /**
  * Provider which reads all {@value DEFAULT_SIMPLE_PROPERTIES_FILE_NAME} and
  * {@value DEFAULT_XML_PROPERTIES_FILE_NAME} files found in the
@@ -86,23 +82,12 @@
 
     private Collection<? extends PropertySource> loadPropertySourcesByName(String filename, ClassLoader classLoader) {
         List<PropertySource> propertySources = new ArrayList<>();
-        Enumeration<URL> propertyLocations;
-        try {
-            propertyLocations = ServiceContextManager.getServiceContext(classLoader)
+        Collection<URL> propertyLocations = ServiceContextManager.getServiceContext(classLoader)
                     .getResources(filename);
-        } catch (IOException e) {
-            String msg = format("Error while searching for %s", filename);
 
-            throw new ConfigException(msg, e);
+        for (URL currentUrl:propertyLocations) {
+            propertySources.add(new SimplePropertySource(currentUrl));
         }
-
-        while (propertyLocations.hasMoreElements()) {
-            URL currentUrl = propertyLocations.nextElement();
-            SimplePropertySource sps = new SimplePropertySource(currentUrl);
-
-            propertySources.add(sps);
-        }
-
         return propertySources;
     }
 
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/MapPropertySource.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/MapPropertySource.java
index e93e79f..3817d5f 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/MapPropertySource.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/MapPropertySource.java
@@ -30,6 +30,9 @@
  */
 public class MapPropertySource extends BasePropertySource {
 
+    /** The optional prefix. */
+    private String prefix;
+
     /**
      * The current properties.
      */
@@ -95,4 +98,41 @@
         return ChangeSupport.IMMUTABLE;
     }
 
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+    }
+
+    protected Map<String,PropertyValue> mapProperties(Map<String, String> props, long timestamp) {
+        Map<String,PropertyValue> result = new HashMap<>();
+        String timestampVal = String.valueOf(timestamp);
+        if (prefix == null) {
+            for (Map.Entry<String, String> en : props.entrySet()) {
+                result.put(en.getKey(),
+                        PropertyValue.createValue(en.getKey(), en.getValue())
+                                .setMeta("source", getName())
+                                .setMeta("timestamp", timestampVal));
+            }
+        } else {
+            for (Map.Entry<String, String> en : props.entrySet()) {
+                result.put(prefix + en.getKey(),
+                        PropertyValue.createValue(prefix + en.getKey(), en.getValue())
+                                .setMeta("source", getName())
+                                .setMeta("timestamp", timestampVal));
+            }
+        }
+        return result;
+    }
+
+    protected String toStringValues() {
+        return  "  defaultOrdinal=" + getDefaultOrdinal() + '\n' +
+                "  ordinal=" + getOrdinal()  + '\n' +
+                "  prefix=" + prefix + '\n' +
+                "  disabled=" + isDisabled() + '\n' +
+                "  name='" + getName() + '\''  + '\n';
+    }
+
 }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySource.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySource.java
index 3ddc74f..6f084aa 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySource.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySource.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tamaya.spisupport.propertysource;
 
+import org.apache.tamaya.ConfigException;
 import org.apache.tamaya.spi.ChangeSupport;
 import org.apache.tamaya.spi.PropertySource;
 import org.apache.tamaya.spi.PropertyValue;
@@ -39,7 +40,7 @@
     /** The logger used. */
     private static final Logger LOGGER = Logger.getLogger(PropertiesResourcePropertySource.class.getName());
 
-    private volatile PropertySourceChangeSupport cachedProperties = new PropertySourceChangeSupport(
+    private final PropertySourceChangeSupport cachedProperties = new PropertySourceChangeSupport(
             ChangeSupport.SUPPORTED, this);
 
     /**
@@ -57,7 +58,6 @@
      */
     public PropertiesResourcePropertySource(URL url, String prefix){
         super(url.toExternalForm());
-        setPrefix(prefix);
         this.cachedProperties.load(loadProps(url));
         this.cachedProperties.scheduleChangeMonitor(() -> loadProps(url),
                 120, TimeUnit.SECONDS);
@@ -65,22 +65,19 @@
 
     /**
      * Creates a new instance.
-     * @param prefix the (optional) prefix context for mapping (prefixing) the properties loaded.
      * @param path the resource path, not null.
      */
-    public PropertiesResourcePropertySource(String path, String prefix){
-        this(path, prefix, ServiceContextManager.getDefaultClassLoader());
+    public PropertiesResourcePropertySource(String path){
+        this(path, ServiceContextManager.getDefaultClassLoader());
     }
 
     /**
      * Creates a new instance.
-     * @param prefix the (optional) prefix context for mapping (prefixing) the properties loaded.
      * @param path the resource path, not null.
      * @param cl the class loader.
      */
-    public PropertiesResourcePropertySource(String path, String prefix, ClassLoader cl){
+    public PropertiesResourcePropertySource(String path, ClassLoader cl){
         super(path);
-        setPrefix(prefix);
         this.cachedProperties.load(loadProps(path, cl));
         this.cachedProperties.scheduleChangeMonitor(() -> loadProps(path, cl),
                 120, TimeUnit.SECONDS);
@@ -92,8 +89,12 @@
      * @return the loaded properties.
      */
     private Map<String, PropertyValue> loadProps(String path, ClassLoader cl) {
-        URL url = ServiceContextManager.getServiceContext(cl).getResource(path);
-        return loadProps(url);
+        try {
+            URL url = ServiceContextManager.getServiceContext(cl).getResource(path);
+            return loadProps(url);
+        }catch(Exception e){
+            throw new ConfigException("Failed to load properties from " + path, e);
+        }
     }
 
     /**
@@ -106,7 +107,7 @@
             try (InputStream is = url.openStream()) {
                 Properties props = new Properties();
                 props.load(is);
-                return mapProperties(MapPropertySource.getMap(props), System.currentTimeMillis());
+                return PropertyValue.mapProperties(MapPropertySource.getMap(props), getName());
             } catch (Exception e) {
                 LOGGER.log(Level.WARNING, "Failed to read properties from " + url, e);
             }
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySource.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySource.java
index 8a7567b..b5b68f8 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySource.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySource.java
@@ -78,12 +78,13 @@
     public SimplePropertySource(String name, Map<String, String> properties, int defaultOrdinal){
         super(name, defaultOrdinal);
         for(Map.Entry<String,String> en: properties.entrySet()) {
-            this.properties.put(en.getKey(), PropertyValue.of(en.getKey(), en.getValue(), name));
+            this.properties.put(en.getKey(), PropertyValue.createValue(en.getKey(), en.getValue())
+                    .setMeta("source", name));
         }
     }
 
     /**
-     * Creates a new Properties based PropertySource based on the given properties map.
+     * Creates a new Properties based PropertySource based on the given properties mapProperties.
      *
      * @param name       the name, not null.
      * @param properties the properties, not null.
@@ -150,7 +151,8 @@
             }
             String source = propertiesFile.toString();
             for (String key : props.stringPropertyNames()) {
-                properties.put(key, PropertyValue.of(key, props.getProperty(key), source));
+                properties.put(key, PropertyValue.createValue(key, props.getProperty(key))
+                        .setMeta("source", source));
             }
         } catch (IOException e) {
             throw new ConfigException("Error loading properties from " + propertiesFile, e);
@@ -259,7 +261,8 @@
          */
         public Builder withProperties(Map<String, String> val) {
             for(Map.Entry<String,String> en: val.entrySet()) {
-                this.properties.put(en.getKey(), PropertyValue.of(en.getKey(), en.getValue(), name));
+                this.properties.put(en.getKey(), PropertyValue.createValue(en.getKey(), en.getValue())
+                        .setMeta("source", name));
             }
             return this;
         }
@@ -272,7 +275,7 @@
          * @return a reference to this Builder
          */
         public Builder withProperty(String key, String val) {
-            this.properties.put(key, PropertyValue.of(key, val, name));
+            this.properties.put(key, PropertyValue.createValue(key, val).setMeta("source", name));
             return this;
         }
 
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySource.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySource.java
index 72c8af9..73df268 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySource.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySource.java
@@ -37,9 +37,9 @@
      */
     public static final int DEFAULT_ORDINAL = 1000;
 
-    private AtomicInteger savedHashcode = new AtomicInteger();
+    private final AtomicInteger savedHashcode = new AtomicInteger();
 
-    private volatile PropertySourceChangeSupport cachedProperties = new PropertySourceChangeSupport(
+    private final PropertySourceChangeSupport cachedProperties = new PropertySourceChangeSupport(
             ChangeSupport.SUPPORTED, this);
 
     /**
@@ -51,7 +51,8 @@
      * </pre>
      */
     public SystemPropertySource(){
-        super("system-properties", DEFAULT_ORDINAL);
+        super("system-properties");
+        setDefaultOrdinal(DEFAULT_ORDINAL);
         initFromSystemProperties();
         if(!isDisabled()){
             reload();
@@ -71,7 +72,6 @@
         if(value==null){
             value = System.getenv("tamaya.sysprops.prefix");
         }
-        setPrefix(value);
         value = System.getProperty("tamaya.sysprops.disable");
         if(value==null){
             value = System.getenv("tamaya.sysprops.disable");
@@ -92,31 +92,12 @@
      * @param ordinal the ordinal number.
      */
     public SystemPropertySource(int ordinal){
-        this(null, ordinal);
-    }
-
-    /**
-     * Creates a new instance.
-     * @param prefix the prefix to be used, or null.
-     * @param ordinal the ordinal to be used.
-     */
-    public SystemPropertySource(String prefix, int ordinal){
-        setPrefix(prefix);
         setOrdinal(ordinal);
     }
 
-    /**
-     * Creates a new instance.
-     * @param prefix the prefix to be used, or null.
-     */
-    public SystemPropertySource(String prefix){
-        setPrefix(prefix);
-    }
-
-
     private Map<String, PropertyValue> loadProperties() {
         Map<String, String> props = MapPropertySource.getMap(System.getProperties());
-        return mapProperties(props, System.currentTimeMillis());
+        return PropertyValue.mapProperties(props, getName());
     }
 
     @Override
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/BuildablePropertySourceTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/BuildablePropertySourceTest.java
index 1df89fc..f60373b 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/BuildablePropertySourceTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/BuildablePropertySourceTest.java
@@ -87,7 +87,7 @@
         propertySecond.put("secondKey", "secondValue");
         
         Map<String, PropertyValue> propertyThird = new HashMap<>();
-        propertyThird.put("thirdKey", PropertyValue.of("thirdPVKey", "thirdValue", "thirdSource"));
+        propertyThird.put("thirdKey", PropertyValue.createValue("thirdPVKey", "thirdValue").setMeta("source", "thirdSource"));
         
         //This seems wrong
         BuildablePropertySource bps = BuildablePropertySource.builder()
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilderTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilderTest.java
index 9289bff..7c53001 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilderTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilderTest.java
@@ -32,6 +32,7 @@
 import org.junit.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 
 /**
  * Tests for {@link  DefaultConfigurationBuilder} by atsticks on 06.09.16.
@@ -358,7 +359,7 @@
     @Test
     public void bla() throws Exception {
         ConfigurationBuilder builder = ConfigurationProvider.getConfigurationBuilder();
-        builder.addDefaultPropertyConverters();
+        assertThatCode(() -> builder.addDefaultPropertyConverters()).doesNotThrowAnyException();
     }
 
     private static class TestPropertySource implements PropertySource {
@@ -385,7 +386,7 @@
 
         @Override
         public PropertyValue get(String key) {
-            return PropertyValue.of(key, key + "Value", getName());
+            return PropertyValue.createValue(key, key + "Value").setMeta("source", getName());
         }
 
         @Override
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationSnapshotTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationSnapshotTest.java
index 1538d44..4169b4a 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationSnapshotTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationSnapshotTest.java
@@ -45,6 +45,7 @@
         Configuration config = Configuration.current();
         DefaultConfigurationSnapshot snapshot = new DefaultConfigurationSnapshot(config,
                 Arrays.asList("confkey1", "confkey2", "confkey3"));
+        assertThat(snapshot).isNotNull();
     }
 
     @Test
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationTest.java
index 2964fd6..b80f118 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultConfigurationTest.java
@@ -206,7 +206,7 @@
     public void testConvertValue() {
         DefaultConfiguration c = new DefaultConfiguration(new MockedConfigurationContext());
         assertThat(100 == (Integer) c.convertValue("aHundred",
-                Collections.singletonList(PropertyValue.of("aHundred", "100", null)),
+                Collections.singletonList(PropertyValue.createValue("aHundred", "100")),
                 TypeLiteral.of(Integer.class))).isTrue();
     }
 
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultMetaDataProviderTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultMetaDataProviderTest.java
index a3a9846..c6aca71 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultMetaDataProviderTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/DefaultMetaDataProviderTest.java
@@ -25,6 +25,7 @@
 import java.util.Map;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 
 /**
  * Tests for {@link DefaultMetaDataProvider}.
@@ -33,7 +34,7 @@
 
     @Test
     public void cretion() {
-        new DefaultMetaDataProvider();
+        assertThatCode(() -> new DefaultMetaDataProvider()).doesNotThrowAnyException();
     }
 
     @Test
@@ -85,8 +86,10 @@
         assertThat(provider.getMetaData("foo")).isNotNull().isEmpty();
     }
 
-
     @Test
     public void testToString() {
+        DefaultMetaDataProvider provider = new DefaultMetaDataProvider();
+        assertThat(provider.init(ConfigurationContext.EMPTY).toString())
+            .isEqualTo("DefaultMetaDataProvider[additionalProperties = {}, context = ConfigurationContext.EMPTY]");
     }
 }
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/MockedPropertySource.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/MockedPropertySource.java
index 7b61103..af9ecde 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/MockedPropertySource.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/MockedPropertySource.java
@@ -62,7 +62,7 @@
         } else if (key.contains("missing")){
             return null;
         }
-        return PropertyValue.of(key, "valueFromMockedPropertySource", "MockedPropertySource");
+        return PropertyValue.createValue(key, "valueFromMockedPropertySource");
     }
 
     @Override
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/PropertySourceChangeSupportTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/PropertySourceChangeSupportTest.java
index c6ce987..ddbe8a1 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/PropertySourceChangeSupportTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/PropertySourceChangeSupportTest.java
@@ -30,6 +30,7 @@
 import java.util.function.BiConsumer;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -115,7 +116,7 @@
     public void update() {
         PropertySource ps = BuildablePropertySource.builder().withName("test").build();
         PropertySourceChangeSupport support = new PropertySourceChangeSupport(ChangeSupport.IMMUTABLE, ps);
-        support.load(Collections.emptyMap());
+        assertThatCode(() -> support.load(Collections.emptyMap())).doesNotThrowAnyException();
     }
 
     @Test
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/RegexPropertyFilterTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/RegexPropertyFilterTest.java
index 37417cd..9092fc5 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/RegexPropertyFilterTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/RegexPropertyFilterTest.java
@@ -32,9 +32,9 @@
  */
 public class RegexPropertyFilterTest {
 
-    private static PropertyValue prop1 = PropertyValue.of("test1", "test1", "test");
-    private static PropertyValue prop2 = PropertyValue.of("test2", "test2", "test");
-    private static PropertyValue prop3 = PropertyValue.of("test1.test3", "test.test3", "test");
+    private static PropertyValue prop1 = PropertyValue.createValue("test1", "test1");
+    private static PropertyValue prop2 = PropertyValue.createValue("test2", "test2");
+    private static PropertyValue prop3 = PropertyValue.createValue("test1.test3", "test.test3");
     private static ConfigurationContext configContext = ConfigurationContext.EMPTY;
 
     @org.junit.Test
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/BasePropertySourceTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/BasePropertySourceTest.java
index 089f5ea..62f616d 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/BasePropertySourceTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/BasePropertySourceTest.java
@@ -124,7 +124,8 @@
         @Override
         public Map<String, PropertyValue> getProperties() {
             Map<String, PropertyValue> result = new HashMap<>(1);
-            result.put(PropertySource.TAMAYA_ORDINAL, PropertyValue.of(PropertySource.TAMAYA_ORDINAL, "1000", getName()));
+            result.put(PropertySource.TAMAYA_ORDINAL, PropertyValue.createValue(PropertySource.TAMAYA_ORDINAL, "1000")
+                    .setMeta("source", getName()));
             return result;
         }
     }
@@ -143,7 +144,8 @@
         @Override
         public Map<String, PropertyValue> getProperties() {
             Map<String, PropertyValue> result = new HashMap<>(1);
-            result.put(PropertySource.TAMAYA_ORDINAL, PropertyValue.of(PropertySource.TAMAYA_ORDINAL, "invalid", getName()));
+            result.put(PropertySource.TAMAYA_ORDINAL, PropertyValue.createValue(PropertySource.TAMAYA_ORDINAL, "invalid")
+                    .setMeta("source", getName()));
             return result;
         }
     }
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySourceTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySourceTest.java
index 5b227ad..b29beae 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySourceTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/PropertiesResourcePropertySourceTest.java
@@ -40,22 +40,6 @@
     }
 
     @Test
-    public void testPrefixedConstructor() {
-        PropertiesResourcePropertySource source = new PropertiesResourcePropertySource(resource, "somePrefix");
-        assertThat(source).isNotNull();
-        assertThat(source.getProperties()).hasSize(5).containsKey("somePrefixkey1");
-    }
-
-    @Test
-    public void testPrefixedPathConstructor() {
-        //File path must be relative to classloader, not the class
-        System.out.println(resource.getPath());
-        PropertiesResourcePropertySource source = new PropertiesResourcePropertySource(testFileName, "somePrefix");
-        assertThat(source).isNotNull();
-        assertThat(source.getProperties()).hasSize(5).containsKey("somePrefixkey1");
-    }
-    
-    @Test
     public void testPrefixedPathBadClassloaderConstructor() {
         ClassLoader badLoader = new ClassLoader() {
             @Override
@@ -63,17 +47,9 @@
                 return null;
             }
         };
-        PropertiesResourcePropertySource source = new PropertiesResourcePropertySource(testFileName, "somePrefix", badLoader);
+        PropertiesResourcePropertySource source = new PropertiesResourcePropertySource(testFileName, badLoader);
         assertThat(source).isNotNull();
         assertThat(source.getProperties()).isEmpty();
     }
     
-    @Test
-    public void testPrefixedPathClassloaderConstructor() {
-        PropertiesResourcePropertySource source = new PropertiesResourcePropertySource(testFileName, "somePrefix",
-                getClass().getClassLoader());
-        assertThat(source).isNotNull();
-        assertThat(source.getProperties()).hasSize(5).containsKey("somePrefixkey1");
-    }
-
 }
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySourceTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySourceTest.java
index bacc7de..f497e86 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySourceTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/SimplePropertySourceTest.java
@@ -44,8 +44,8 @@
 
         assertThat(source).isNotNull();
         assertThat(source.getProperties()).hasSize(2); // double the getNumChilds for .source values.
-        assertThat(source.getProperties()).contains(entry("a", PropertyValue.of("a", "b", resource.toString())));
-        assertThat(source.getProperties()).contains(entry("b", PropertyValue.of("b", "1", resource.toString())));
+        assertThat(source.getProperties()).contains(entry("a", PropertyValue.createValue("a", "b")));
+        assertThat(source.getProperties()).contains(entry("b", PropertyValue.createValue("b", "1")));
     }
 
     @Test(expected=ConfigException.class)
@@ -61,8 +61,8 @@
 
         assertThat(source).isNotNull();
         assertThat(source.getProperties()).hasSize(2); // double the getNumChilds for .source values.
-        assertThat(source.getProperties()).contains(entry("a", PropertyValue.of("a", "b", resource.toString())));
-        assertThat(source.getProperties()).contains(entry("b", PropertyValue.of("b", "1", resource.toString())));
+        assertThat(source.getProperties()).contains(entry("a", PropertyValue.createValue("a", "b")));
+        assertThat(source.getProperties()).contains(entry("b", PropertyValue.createValue("b", "1")));
     }
 
     @Test
@@ -73,8 +73,8 @@
 
         assertThat(source).isNotNull();
         assertThat(source.getProperties()).hasSize(2); // double the getNumChilds for .source values.
-        assertThat(source.getProperties()).contains(entry("a", PropertyValue.of("a", "b", resource.toString())));
-        assertThat(source.getProperties()).contains(entry("b", PropertyValue.of("b", "1", resource.toString())));
+        assertThat(source.getProperties()).contains(entry("a", PropertyValue.createValue("a", "b")));
+        assertThat(source.getProperties()).contains(entry("b", PropertyValue.createValue("b", "1")));
     }
 
     @Test
@@ -87,8 +87,8 @@
 
         assertThat(source).isNotNull();
         assertThat(source.getProperties()).hasSize(2); // double the getNumChilds for .source values.
-        assertThat(source.getProperties()).contains(entry("a", PropertyValue.of("a", "b", "test")));
-        assertThat(source.getProperties()).contains(entry("b", PropertyValue.of("b", "1", "test")));
+        assertThat(source.getProperties()).contains(entry("a", PropertyValue.createValue("a", "b").setMeta("source", "test")));
+        assertThat(source.getProperties()).contains(entry("b", PropertyValue.createValue("b", "1").setMeta("source", "test")));
     }
 
     @Test
@@ -221,8 +221,8 @@
                 .build();
 
         assertThat(sps.get("firstKey").getValue()).isEqualTo("firstValue");
-        assertThat(sps.getProperties()).contains(entry("a", PropertyValue.of("a", "b", resource.toString())));
-        assertThat(sps.getProperties()).contains(entry("b", PropertyValue.of("b", "1", resource.toString())));
+        assertThat(sps.getProperties()).contains(entry("a", PropertyValue.createValue("a", "b")));
+        assertThat(sps.getProperties()).contains(entry("b", PropertyValue.createValue("b", "1")));
 
         sps = SimplePropertySource.newBuilder()
                 .withUuidName()
@@ -231,8 +231,8 @@
                 .build();
 
         assertThat(sps.get("firstKey").getValue()).isEqualTo("firstValue");
-        assertThat(sps.getProperties()).contains(entry("a", PropertyValue.of("a", "b", resource.toString())));
-        assertThat(sps.getProperties()).contains(entry("b", PropertyValue.of("b", "1", resource.toString())));
+        assertThat(sps.getProperties()).contains(entry("a", PropertyValue.createValue("a", "b")));
+        assertThat(sps.getProperties()).contains(entry("b", PropertyValue.createValue("b", "1")));
     }
 
     @Test
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySourceTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySourceTest.java
index 09c4e90..4155e05 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySourceTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/SystemPropertySourceTest.java
@@ -33,15 +33,15 @@
 
     private final SystemPropertySource testPropertySource = new SystemPropertySource();
 
-    @Test
-    public void testConstrcutorWithPrefix() throws Exception {
-        SystemPropertySource testPropertySource = new SystemPropertySource("PRE::");
-        assertThat(testPropertySource.getProperties()).isNotNull();
-        for(Map.Entry en:System.getProperties().entrySet()){
-            assertThat(System.getProperty(en.getKey().toString()))
-                .isEqualTo(testPropertySource.get("PRE::"+en.getKey()).getValue());
-        }
-    }
+//    @Test
+//    public void testConstrcutorWithPrefix() throws Exception {
+//        SystemPropertySource testPropertySource = new SystemPropertySource("PRE::");
+//        assertThat(testPropertySource.getProperties()).isNotNull();
+//        for(Map.Entry en:System.getProperties().entrySet()){
+//            assertThat(System.getProperty(en.getKey().toString()))
+//                .isEqualTo(testPropertySource.get("PRE::"+en.getKey()).getValue());
+//        }
+//    }
 
     @Test
     public void testConstructionPropertiesAndDisabledBehavior() throws IOException {
@@ -104,7 +104,7 @@
         SystemPropertySource constructorSetOrdinal22 = new SystemPropertySource(22);
         assertThat(constructorSetOrdinal22.getOrdinal()).isEqualTo(22);
 
-        SystemPropertySource constructorSetOrdinal16 = new SystemPropertySource("sixteenprefix", 16);
+        SystemPropertySource constructorSetOrdinal16 = new SystemPropertySource( 16);
         assertThat(constructorSetOrdinal16.getOrdinal()).isEqualTo(16);
     }
 
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/TestPropertyDefaultSource.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/TestPropertyDefaultSource.java
index b9b9dd0..3d4cf3b 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/TestPropertyDefaultSource.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/TestPropertyDefaultSource.java
@@ -33,8 +33,8 @@
 
     public TestPropertyDefaultSource() {
         super(100);
-        properties.put("name", PropertyValue.of("name", "Anatole", "Test"));
-        properties.put("name2",PropertyValue.of("name2", "Sabine", "Test"));
+        properties.put("name", PropertyValue.createValue("name", "Anatole"));
+        properties.put("name2",PropertyValue.createValue("name2", "Sabine"));
         properties = Collections.unmodifiableMap(properties);
     }
 
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/WrappedPropertySourceTest.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/WrappedPropertySourceTest.java
index 925176e..55877c1 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/WrappedPropertySourceTest.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/propertysource/WrappedPropertySourceTest.java
@@ -149,7 +149,7 @@
 
         @Override
         public PropertyValue get(String key) {
-            return PropertyValue.of(key, "valueFromMockedWrappablePropertySource", "MockedWrappablePropertySource");
+            return PropertyValue.createValue(key, "valueFromMockedWrappablePropertySource");
         }
 
         @Override
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/services/DefaultServiceContext.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/services/DefaultServiceContext.java
index 257baab..2686cdb 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/services/DefaultServiceContext.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/services/DefaultServiceContext.java
@@ -24,7 +24,6 @@
 import org.apache.tamaya.spisupport.PriorityServiceComparator;
 
 import javax.annotation.Priority;
-import java.io.IOException;
 import java.net.URL;
 import java.text.MessageFormat;
 import java.util.*;
@@ -150,10 +149,12 @@
      * @return a priority, by default 1.
      */
     public static int getPriority(Object o){
-        int prio = 1; //X TODO discuss default priority
-        Priority priority = o.getClass().getAnnotation(Priority.class);
-        if (priority != null) {
-            prio = priority.value();
+        int prio = 1;
+        if(ServiceContext.PRIORITY_ANNOTATION_AVAILABLE) {
+            Priority priority = o.getClass().getAnnotation(Priority.class);
+            if (priority != null) {
+                prio = priority.value();
+            }
         }
         return prio;
     }
@@ -213,8 +214,18 @@
     }
 
     @Override
-    public Enumeration<URL> getResources(String resource) throws IOException {
-        return classLoader.getResources(resource);
+    public Collection<URL> getResources(String resource) {
+        List<URL> urls = new ArrayList<>();
+        try {
+            Enumeration<URL> found = getClassLoader().getResources(resource);
+            while (found.hasMoreElements()) {
+                urls.add(found.nextElement());
+            }
+        }catch(Exception e){
+            Logger.getLogger(ServiceContext.class.getName())
+                    .log(Level.FINEST, e, () -> "Failed to lookup resources: " + resource);
+        }
+        return urls;
     }
 
     @Override
diff --git a/examples/01-minimal/pom.xml b/examples/01-minimal/pom.xml
index eac821c..f0e4db3 100644
--- a/examples/01-minimal/pom.xml
+++ b/examples/01-minimal/pom.xml
@@ -28,7 +28,9 @@
         <version>0.4-incubating-SNAPSHOT</version>
     </parent>
 
+    <groupId>org.apache.tamaya.examples</groupId>
     <artifactId>01-minimal</artifactId>
+    <version>0.4-incubating-SNAPSHOT</version>
 
     <name>Apache Tamaya Minimal Example</name>
 
diff --git a/pom.xml b/pom.xml
index 3bc8ee1..7d8209d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -654,7 +654,7 @@
                 							apache-rat-plugin
                 						</artifactId>
                 						<versionRange>
-                							[0.12,)
+                							[0.13,)
                 						</versionRange>
                 						<goals>
                 							<goal>check</goal>
@@ -690,7 +690,7 @@
             <plugin>
                 <groupId>org.jacoco</groupId>
                 <artifactId>jacoco-maven-plugin</artifactId>
-                <version>0.8.2</version>
+                <version>0.8.4</version>
                 <executions>
                   <execution>
                     <goals>