You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2018/11/18 21:21:14 UTC

[10/22] incubator-tamaya git commit: TAMAYA-274 Reduced API footprint by using Java 8 features. Added some lambdas. TAMAYA-355 Enable mapping of lists and arrays into internal datastructures. TAMAYA-353 Adding support for different classloaders.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
----------------------------------------------------------------------
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 5b61055..9f66b24 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
@@ -21,47 +21,53 @@ package org.apache.tamaya.spi;
 import java.io.Serializable;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
-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.
- * There might be reasons, where one want to further analyze, which PropertySources provided a value and which not, so
- * it is possible to create a PropertyValue with a null value.
+ * Class modelling the result of a request for a property createValue. A property createValue is basically identified by its key.
+ * There might be reasons, where one want to further analyze, which PropertySources provided a createValue and which not, so
+ * it is possible to createObject a PropertyValue with a null createValue.
  *
  *  A PropertyValue represents an abstract data point in a configuration structure read. PropertyValues actually
  *  represent a tree, with additional functionality for representing data lists/arrays using indexed children
  *  names. This allows to support a full mapping of common document based configuration formats, such as JSON, YAML,
  *  XML and more.
  */
-public final class PropertyValue implements Serializable, Iterable<PropertyValue>{
+public class PropertyValue implements Serializable, Iterable<PropertyValue>{
 
     private static final long serialVersionUID = 1L;
+    /** The type of node. */
+    private ValueType valueType;
     /** The requested key. */
     private String key;
-    /** The value. */
+    /** The createValue. */
     private String value;
-    /** Additional metadata provided by the provider. */
-    private final transient Map<String,Object> metaData = new HashMap<>();
-    /** List of child properties. */
-    private final List<PropertyValue> children = new ArrayList<>();
-    /** The getParent getChild, null if it's a root getChild. */
+    /** The getParent getField, null if it's a root getField. */
     private PropertyValue parent;
-    /** The getChild's getIndex, if the getChild is participating in a list structure. */
-    private int index = -1;
-    /** The value version, used for determining config changes. */
+    /** The createValue version, used for determining config changes. */
     private AtomicInteger version = new AtomicInteger();
-    /** Helper structure used for indexing new list getChildren. */
-    private Map<String, AtomicInteger> indices = new HashMap<>();
-    /** Flag to mark a value as immutable. */
+    /** Flag to mark a createValue as immutable. */
     private boolean immutable;
+    /** Additional metadata provided by the provider. */
+    private final transient Map<String,Object> metaData = new HashMap<>();
 
+    /**
+     * Enum of the different supported value types.
+     */
+    public enum ValueType{
+        /** A multi valued property value, which contains named child properties. */
+        OBJECT,
+        /** A multi valued property value, which contains unnamed child properties. */
+        ARRAY,
+        /** A simple value property. */
+        VALUE
+    }
 
 
     /**
      * 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 value, not {@code null}.
+     *               providing the createValue, not {@code null}.
      * @return a new builder instance.
      * @deprecated Will be removed, use {@link PropertyValue} directly.
      */
@@ -74,78 +80,76 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
     }
 
     /**
-     * Creates a new builder instance.
-     * @param key the key, not {@code null}.
-     * @param source the source.
-     * @return a new builder instance.
-     * @deprecated Use {@link #create(String)}
+     * Creates a new (invisible) root, which is a node with an empty name.
+     * @return a new empty root, never null.
      */
-    @Deprecated
-    public static PropertyValue of(String key, String source){
-        Objects.requireNonNull(key, "Key must be given.");
+    public static ObjectValue createObject(){
+        return new ObjectValue(null, "");
+    }
 
-        return new PropertyValue(null, key).setMeta("source", source);
+    /**
+     * Creates a new (invisible) root, which is a node with an empty name.
+     * @return a new empty root, never null.
+     */
+    public static ListValue createList(){
+        return new ListValue(null, "");
     }
 
     /**
-     * Creates a new builder instance.
+     * Creates a new createValue of type {@link ValueType#VALUE}.
      * @param key the key, not {@code null}.
-     * @param value the property value, not {@code null}.
-     * @param source the source, typically the name of the {@link PropertySource}
-     *               providing the value, not {@code null}.
-     * @return a new builder instance.
+     * @param value the createValue, not null.
+     * @return a new createValue instance.
      */
-    @Deprecated
-    public static PropertyValue of(String key, String value, String source) {
-        Objects.requireNonNull(key, "Key must be given.");
-        if(source!=null) {
-            return new PropertyValue(null, key).setValue(value).setMeta("source", source);
-        }
-        return new PropertyValue(null, key).setValue(value);
+    public static PropertyValue createValue(String key, String value){
+        return new PropertyValue(null, key, ValueType.VALUE, value);
     }
 
     /**
-     * Creates a new builder instance.
+     * Creates a new createValue of type {@link ValueType#ARRAY}.
      * @param key the key, not {@code null}.
-     * @param value the new value.
-     * @return a new builder instance.
+     * @return a new createValue instance.
      */
-    public static PropertyValue create(String key, String value){
-        Objects.requireNonNull(key, "Key must be given.");
-
-        return new PropertyValue(null, key).setValue(value);
+    public static ListValue createList(String key){
+        return new ListValue(null, key);
     }
 
-
     /**
-     * Creates a new (invisible) root getChild, which is a getChild with an empty name.
-     * @return a new empty root getChild, never null.
+     * Creates a new createValue of type {@link ValueType#OBJECT}.
+     * @param key the key, not {@code null}.
+     * @return a new createValue instance.
      */
-    public static PropertyValue create(){
-        return new PropertyValue(null, "");
+    public static ObjectValue createObject(String key){
+        return new ObjectValue(null, key);
     }
 
     /**
-     * Creates a new named root getChild.
-     * @param name the name, not null.
-     * @return a new named root getChild, never null.
+     * 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.
      */
-    public static PropertyValue create(String name){
-        return new PropertyValue(null, name);
+    @Deprecated
+    public static PropertyValue of(String key, String value, String source) {
+        Objects.requireNonNull(key);
+        if(source!=null) {
+            return new PropertyValue(null, key, ValueType.VALUE, value).setMeta("source", source);
+        }
+        return new PropertyValue(null, key, ValueType.VALUE, value);
     }
 
-
-
     /**
       * 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 value based map.
+      * @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(), PropertyValue.of(en.getKey(), en.getValue(), source));
+            result.put(en.getKey(), createValue(en.getKey(), en.getValue()).setMeta("source", source));
         }
         return result;
     }
@@ -156,7 +160,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
      * @param config the String based map, not {@code null}.
      * @param source the source name, not {@code null}.
      * @param metaData additional metadata, not {@code null}.
-     * @return the corresponding value based map.
+     * @return the corresponding createValue based map.
      */
     public static Map<String, PropertyValue> map(Map<String, String> config, String source,
                                                  Map<String,String> metaData) {
@@ -166,7 +170,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
         Map<String, PropertyValue> result = new HashMap<>(config.size());
 
         for(Map.Entry<String,String> en:config.entrySet()){
-            PropertyValue pv = PropertyValue.create(en.getKey(), en.getValue())
+            PropertyValue pv = createValue(en.getKey(), en.getValue())
                     .setMeta(metaData);
             if(source!=null){
                 pv.setMeta("source", source);
@@ -179,17 +183,32 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
     /**
      * Creates a new instance
      * @param key the key, not {@code null}.
+     * @param parent the parent.
+     * @param valueType the createValue type, not null.
      */
-    private PropertyValue(PropertyValue parent, String key){
+    protected PropertyValue(PropertyValue parent, String key, ValueType valueType){
+        this(parent, key, valueType, null);
+    }
+
+    /**
+     * Creates a new instance
+     * @param key the key, not {@code null}.
+     * @param parent the parent.
+     * @param valueType the createValue type, not null.
+     * @param value the initial text createValue.
+     */
+    protected PropertyValue(PropertyValue parent, String key, ValueType valueType, String value){
         this.parent = parent;
-        this.key = Objects.requireNonNull(key, "Key is required.");
+        this.valueType = Objects.requireNonNull(valueType, "ValueType is required.");
+        this.key = Objects.requireNonNull(key);
+        this.value = value;
     }
 
     /**
      * Checks if the instance is immutable.
      * @return true, if the instance is immutable.
      */
-    public boolean isImmutable(){
+    public final boolean isImmutable(){
         return immutable;
     }
 
@@ -198,28 +217,70 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
      * an {@link IllegalStateException}.
      * @return this instance for chaining.
      */
-    public PropertyValue setImmutable(){
+    public PropertyValue immutable(){
         this.immutable = true;
-        children.forEach(PropertyValue::setImmutable);
         return this;
     }
 
     /**
+     * Clones this instance and all it's children, marking as mutable createValue.
+     * @return the new createValue clone.
+     */
+    public PropertyValue mutable(){
+        if(!immutable){
+            return this;
+        }
+        return deepClone();
+    }
+
+    /**
+     * Get the item's current createValue type.
+     * @return the createValue type, never null.
+     */
+    public final ValueType getValueType() {
+        return valueType;
+    }
+
+    /**
      * The requested key.
      * @return the, key never {@code null}.
      */
-    public String getKey() {
+    public final String getKey() {
         return key;
     }
 
     /**
-     * Get a qualified name of a getChild in property format using '.' as separator, e.g.
+     * Get the node's createValue.
+     * @return the createValue, or null.
+     */
+    public String getValue() {
+        return this.value;
+    }
+
+    /**
+     * Sets the createValue.
+     * @param value the createValue
+     * @return this getField for chaining.
+     * @throws IllegalStateException if the instance is immutable.
+     * @see #isImmutable()
+     */
+    public PropertyValue setValue(String value) {
+        checkImmutable();
+        if(!Objects.equals(this.value, value)) {
+            this.value = value;
+            incrementVersion();
+        }
+        return this;
+    }
+
+    /**
+     * Get a qualified name of a getField in property format using '.' as separator, e.g.
      * {@code a.b.c} or {@code a.b.c[0]} for indexed entries. Entries hereby also can have multiple
      * levels of indexing, e.g. {@code a[1].b.c[14].d} is a valid option.
      *
      * The qualified key is defined by {@link #getQualifiedKey()} of it's parent concatenated with the key
      * of this node. If there is no parent, or the parent's qualified key is empty only {@link #getKey()}
-     * is returned. Additionally if the current values is an indeyed value the key is extended by the
+     * is returned. Additionally if the current values is an indeyed createValue the key is extended by the
      * index in brackets, e.g. {@code [0], [1], ...}. All the subsequent keys are valid qualified keys:
      * <pre>
      *     a
@@ -236,29 +297,21 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
             return key;
         }
         String parentName =  parent.getQualifiedKey();
-        if(!parentName.isEmpty()){
-            parentName+=".";
-        }
-        if(isIndexed()){
-            return parentName+key+"["+index+"]";
+        if(parent instanceof ListValue){
+            return parentName+"["+((ListValue)parent).getIndex(this)+"]";
+        }else{
+            if(!parentName.isEmpty()){
+                parentName+=".";
+            }
+            return parentName+key;
         }
-        return parentName+key;
     }
 
     /**
-     * The value.
-     * @return the value, in case a value is null it is valid to return {#code null} as result for
-     * {@link PropertySource#get(String)}.
-     */
-    public String getValue() {
-        return this.value;
-    }
-
-    /**
-     * Get the getChild's getParent.
+     * Get the getField's getParent.
      * @return the getParent, or null.
      */
-    public PropertyValue getParent(){
+    public final PropertyValue getParent(){
         return parent;
     }
 
@@ -266,83 +319,64 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
      * Get the values version, the version is updated with each change written.
      * @return the version.
      */
-    public int getVersion(){
+    public final int getVersion(){
         return version.get();
     }
 
     /**
-     * Get a getChild's getIndex.
-     * @return the getIndex, or -1, if the getChild does not participate in an array.
-     */
-    public int getIndex(){
-        return index;
-    }
-
-    /**
      * Get the source.
      * @return the source, or null.
      * @deprecated Use {@code getMeta("source")}.
      */
     @Deprecated
-    public String getSource() {
+    public final String getSource() {
         return (String)this.metaData.get("source");
     }
 
 
     /**
-     * Checks if the getChild is a root getChild.
-     * @return true, if the current getChild is a root getChild.
+     * Checks if the getField is a root getField.
+     * @return true, if the current getField is a root getField.
      */
-    public boolean isRoot() {
+    public final boolean isRoot() {
         return parent == null;
     }
 
     /**
-     * Checks if the getChild is a leaf getChild (has no getChildren).
-     * @return true, if the current getChild is a leaf getChild.
-     */
-    public boolean isLeaf(){
-        return children.isEmpty();
-    }
-
-    /**
-     * Allows to check if a getChild is indexed.
-     * @return true, if the getChild participates in an array.
+     * Checks if the getField is a leaf getField (has no getList).
+     * @return true, if the current getField is a leaf getField.
      */
-    public boolean isIndexed(){
-        if(parent==null){
-            return false;
-        }
-        return index>=0;
+    public final boolean isLeaf(){
+        return getValueType()==ValueType.VALUE;
     }
 
     /**
-     * Creates a full configuration map for this key, value pair and all its getMeta context data. This map
-     * is also used for subsequent processing, like value filtering.
-     * @return the property value entry map.
+     * Creates a full configuration map for this key, createValue pair and all its getMeta context data. This map
+     * is also used for subsequent processing, like createValue filtering.
+     * @return the property createValue entry map.
      */
-    public Map<String, Object> getMeta() {
+    public final Map<String, Object> getMeta() {
         return Collections.unmodifiableMap(metaData);
     }
 
     /**
-     * Access the given key from this value. Valid keys are the key or any getMeta-context key.
+     * Access the given key from this createValue. Valid keys are the key or any getMeta-context key.
      * @param key the key, not {@code null}.
-     * @return the value found, or {@code null}.
+     * @return the createValue found, or {@code null}.
      * @deprecated Use {@link #getMeta(String)} instead of.
      */
     @Deprecated
-    public String getMetaEntry(String key) {
+    public final String getMetaEntry(String key) {
         return (String)this.metaData.get(Objects.requireNonNull(key));
     }
 
     /**
-     * Access the given key from this value. Valid keys are the key or any getMeta-context key.
+     * Access the given key from this createValue. Valid keys are the key or any getMeta-context key.
      * @param key the key, not {@code null}.
      * @param <T> the target type.
-     * @return the value found, or {@code null}.
+     * @return the createValue found, or {@code null}.
      */
-    public <T> T getMeta(String key) {
+    public final <T> T getMeta(String key) {
         return (T)this.metaData.get(Objects.requireNonNull(key));
     }
 
@@ -350,216 +384,26 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
      * Access the given metadata.
      * @param type the type, not {@code null}.
      * @param <T> the target type.
-     * @return the value found, or {@code null}.
+     * @return the createValue found, or {@code null}.
      */
-    public <T> T getMeta(Class<T> type) {
+    public final <T> T getMeta(Class<T> type) {
         return (T)this.metaData.get(type.getName());
     }
 
-    /**
-     * Get a single child getChild by name.
-     * @param name the child's name, not null.
-     * @return the child found, or null.
-     * @throws IllegalArgumentException if multiple getChildren with the given name are existing (ambigous).
-     */
-    public PropertyValue getChild(String name){
-        List<PropertyValue> nodes = this.getChildren(name);
-        if(nodes.isEmpty()){
-            return null;
-        }
-        if(nodes.size()>1){
-            throw new IllegalArgumentException("Multiple getChildren existing: " + name);
-        }
-        return nodes.get(0);
-    }
-
-    /**
-     * Get a sub value.
-     * @param index the target getIndex.
-     * @return the value found.
-     * @throws java.util.NoSuchElementException if no such element is existing.
-     */
-    public PropertyValue getChild(int index) {
-        return this.children.get(index);
-    }
-
-    /**
-     * Get a single child getChild with the given name, creates it if not existing.
-     * @param name the child's name, not null.
-     * @return the child found or created, never null.
-     * @throws IllegalArgumentException if multiple getChildren with the given name are existing (ambigous).
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public PropertyValue getOrCreateChild(String name){
-        List<PropertyValue> nodes = this.getChildren(name);
-        if(nodes.isEmpty()){
-            checkImmutable();
-            PropertyValue n = new PropertyValue(this, name);
-            this.children.add(n);
-            version.incrementAndGet();
-            return n;
-        }
-        if(nodes.size()>1){
-            throw new IllegalArgumentException("Multiple getChildren existing: " + name);
-        }
-        return nodes.get(0);
-    }
-
-    /**
-     * Get's the n-th getChild of an indexed getChild setCurrent.
-     * @param name the child's name, not null.
-     * @param index the target getChild getIndex.
-     * @return the getChild found, or null.
-     */
-    public PropertyValue getChildWithIndex(String name, int index){
-        List<PropertyValue> nodes = this.getChildren(name);
-        if(nodes.isEmpty() || nodes.size()<=index){
-            return null;
-        }
-        return nodes.get(index);
-    }
 
     /**
-     * Get all child getChildren with a given name.
-     * @param name the target name, not null.
-     * @return the list of matching getChildren, could be none, one or multiple in case of arrays.
+     * Get the createValue's number of elements.
+     * @return the getNumChilds of this multi createValue.
      */
-    public List<PropertyValue> getChildren(String name){
-        return children.stream().filter(n -> n.key.equals(name)).collect(Collectors.toList());
-    }
-
-    /**
-     * Get the value's number of elements.
-     * @return the getNumChilds of this multi value.
-     */
-    public int getNumChilds() {
-        return this.children.size();
-    }
-
-    /**
-     * The value.
-     * @return the value, in case a value is null it is valid to return {#code null} as result for
-     * {@link PropertySource#get(String)}.
-     */
-    public List<PropertyValue> getChildren() {
-        return Collections.unmodifiableList(this.children);
+    public int getSize() {
+        return 0;
     }
 
     @Override
     public Iterator<PropertyValue> iterator() {
-        return Collections.unmodifiableList(this.children).iterator();
-    }
-
-    /**
-     * Adds a new non-indexed child getChild.
-     * @param name the child's name, not null.
-     * @return the new child, never null.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public PropertyValue createChild(String name){
-        return createChild(name, false);
-    }
-
-    /**
-     * Adds a new non-indexed child.
-     * @param name the child's name, not null.
-     * @param value the child's value, not null.
-     * @return the new child, not null.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public PropertyValue createChild(String name, String value){
-        return createChild(name, false).setValue(value);
-    }
-
-    /**
-     * Adds another existing node, hereby setting the corresponding parent node.
-     * @param value the value, not null
-     * @return this instance, for chaining.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public PropertyValue addChild(PropertyValue value) {
-        checkImmutable();
-        value.parent = this;
-        this.children.add(value);
-        return this;
-    }
-
-    /**
-     * Adds a new child getChild.
-     * @param name the child's name, not null.
-     * @param indexed if true, the getChild will be participate in an array of the given name.
-     * @return the new getChild, not null.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public PropertyValue createChild(String name, boolean indexed){
-        checkImmutable();
-        PropertyValue n = new PropertyValue(this, name);
-        this.children.add(n);
-        version.incrementAndGet();
-        if(indexed) {
-            AtomicInteger index = indices.computeIfAbsent(name, s -> new AtomicInteger(0));
-            n.index = index.getAndIncrement();
-        }else{
-            List<PropertyValue> nodes = this.getChildren(name);
-            if(nodes.size()>1){
-                AtomicInteger index = indices.get(name);
-                if(index!=null){
-                    n.index = index.getAndIncrement();
-                }else{
-                    index = new AtomicInteger(0);
-                    indices.put(name, index);
-                    for(PropertyValue node:nodes){
-                        node.index = index.getAndIncrement();
-                    }
-                }
-            }
-        }
-        return n;
-    }
-
-    /**
-     * Adds a new child getChild, where the getChild is given in '.'-separated property notation,
-     * e.g. {@code a.b.c}.
-     * @param key the property key, e.g. {@code a.b.c}
-     * @param value the property value
-     * @return the new leaf-getChild created.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public PropertyValue addProperty(String key, String value) {
-        checkImmutable();
-        PropertyValue node = this;
-        StringTokenizer tokenizer = new StringTokenizer(key, "\\.", false);
-        while(tokenizer.hasMoreTokens()){
-            String token = tokenizer.nextToken().trim();
-            node = node.getOrCreateChild(token);
-            if(!tokenizer.hasMoreTokens()){
-                // Its the last or single token
-                node.setValue(value);
-            }
-        }
-        return node;
+        return Collections.emptyIterator();
     }
 
-    /**
-     * Adds multiple child getChildren, where the getChildren are defined in '.'-separated property notation,
-     *      * e.g. {@code a.b.c}.
-     * @param props the properties
-     * @return the collection of added leaf-child getChildren.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public Collection<PropertyValue> addProperties(Map<String,String> props) {
-        checkImmutable();
-        List<PropertyValue> result = new ArrayList<>();
-        props.entrySet().forEach(en -> result.add(addProperty(en.getKey(), en.getValue())));
-        return result;
-    }
 
     /**
      * Changes the entry's key, mapping also corresponding context entries.
@@ -577,21 +421,6 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
         return this;
     }
 
-    /**
-     * Sets the value.
-     * @param value the value
-     * @return this getChild for chaining.
-     * @throws IllegalStateException if the instance is immutable.
-     * @see #isImmutable()
-     */
-    public PropertyValue setValue(String value) {
-        checkImmutable();
-        if(!Objects.equals(this.value, value)) {
-            this.value = value;
-            version.incrementAndGet();
-        }
-        return this;
-    }
 
     /**
      * Replaces/sets the context data.
@@ -600,7 +429,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public PropertyValue setMeta(Map<String, Object> metaEntries) {
+    public final PropertyValue setMeta(Map<String, Object> metaEntries) {
         checkImmutable();
         if(!Objects.equals(this.metaData, metaEntries)) {
             this.metaData.clear();
@@ -613,15 +442,15 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
     /**
      * 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).
+     * @param value the context createValue, not {@code null} (will be converted to String).
      * @return the builder for chaining.
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public PropertyValue setMeta(String key, Object value) {
+    public final PropertyValue setMeta(String key, Object value) {
         checkImmutable();
         Objects.requireNonNull(key, "Meta key must be given.");
-        Objects.requireNonNull(value, "Meta value must be given.");
+        Objects.requireNonNull(value, "Meta createValue must be given.");
         if(!Objects.equals(this.metaData.get(key), value)) {
             this.metaData.put(key, value);
             version.incrementAndGet();
@@ -632,16 +461,16 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
     /**
      * Add an additional context data information.
      * @param type the context data type, used as key, not {@code null}.
-     * @param value the context value, not {@code null}.
+     * @param value the context createValue, not {@code null}.
      * @param <T> the target type.
      * @return the builder for chaining.
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public <T> PropertyValue setMeta(Class<T> type, T value) {
+    public final <T> PropertyValue setMeta(Class<T> type, T value) {
         checkImmutable();
         Objects.requireNonNull(type, "Meta key must be given.");
-        Objects.requireNonNull(value, "Meta value must be given.");
+        Objects.requireNonNull(value, "Meta createValue must be given.");
         if(!Objects.equals(this.metaData.get(type.toString()), value)) {
             this.metaData.put(type.toString(), value);
             version.incrementAndGet();
@@ -651,15 +480,15 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
 
     /**
      * Add an additional context data information, using the data's class name as key.
-     * @param value the context value, not {@code null}.
+     * @param value the context createValue, not {@code null}.
      * @param <T> the target type.
      * @return the builder for chaining.
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public <T> PropertyValue setMeta(T value) {
+    public final <T> PropertyValue setMeta(T value) {
         checkImmutable();
-        Objects.requireNonNull(value, "Meta value must be given.");
+        Objects.requireNonNull(value, "Meta createValue must be given.");
         if(!Objects.equals(this.metaData.get(value.getClass().toString()), value)) {
             this.metaData.put(value.getClass().toString(), value);
             version.incrementAndGet();
@@ -674,7 +503,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public PropertyValue removeMeta(String key) {
+    public final PropertyValue removeMeta(String key) {
         checkImmutable();
         Objects.requireNonNull(key, "Key must be given.");
         if(this.metaData.containsKey(key)) {
@@ -691,7 +520,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
      * @throws IllegalStateException if the instance is immutable.
      * @see #isImmutable()
      */
-    public PropertyValue removeMeta(Class type) {
+    public final PropertyValue removeMeta(Class type) {
         checkImmutable();
         Objects.requireNonNull(key, "Key must be given.");
         if(this.metaData.containsKey(type.getName())) {
@@ -702,17 +531,14 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
     }
 
     /**
-     * Convert the getChild tree to a property map.
+     * Convert the getField tree to a property map.
      * @return the corresponding property map, not null.
      */
-    public Map<String,String> asMap(){
+    public Map<String,String> toMap(){
         Map<String, String> map = new TreeMap<>();
-        if(isLeaf()){
+        if(value!=null) {
             map.put(getQualifiedKey(), value);
         }
-        for(PropertyValue n: children){
-            map.putAll(n.asMap());
-        }
         return map;
     }
 
@@ -721,7 +547,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
      * @return the corresponding String representation, not null.
      */
     public String asString() {
-        Map<String, String> map = asMap();
+        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){
@@ -741,36 +567,45 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
                 .setMeta(this.metaData);
     }
 
-    /**
-     * Clones this instance and all it's children, marking as mutable value.
-     * @return the new value clone.
-     */
-    public PropertyValue mutable(){
-        if(!immutable){
-            return this;
-        }
-        PropertyValue newProp = new PropertyValue(this.parent, key);
-        newProp.setValue(this.value);
-        newProp.setMeta(metaData);
-        children.forEach(c -> newProp.children.add(c.mutable()));
-        newProp.version = new AtomicInteger(version.intValue());
+    public PropertyValue toPropertyValue(){
+        return this;
+    }
+
+    public ObjectValue toObjectValue(){
+        ObjectValue ov = new ObjectValue(getParent(),getKey());
+        ov.setField("createValue", value);
+        return ov;
+    }
+
+    public ListValue toListValue(){
+        ListValue lv = new ListValue(getParent(),getKey());
+        lv.addValue("createValue", value);
+        return lv;
+    }
+
+
+    protected PropertyValue deepClone() {
+        PropertyValue newProp = new PropertyValue(getParent(), getKey(), ValueType.VALUE, this.value);
+        newProp.setMeta(getMeta());
+        newProp.setVersion(getVersion());
         return newProp;
     }
 
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (!(o instanceof PropertyValue)) return false;
         PropertyValue dataNode = (PropertyValue) o;
-        return Objects.equals(parent, dataNode.parent) &&
-                Objects.equals(key, dataNode.key) &&
+        return getParent() == dataNode.getParent() &&
+                Objects.equals(getKey(), dataNode.getKey()) &&
                 Objects.equals(value, dataNode.value) &&
-                Objects.equals(metaData, dataNode.metaData);
+                Objects.equals(getMeta(), dataNode.getMeta());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(parent, key, value, metaData);
+        return Objects.hash(getParent(), getKey(), value, getMeta());
     }
 
 
@@ -778,16 +613,29 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue
     public String toString() {
         return "PropertyValue{" +
                 '\'' +getQualifiedKey() + '\'' +
-                (value!=null?", value='" + value + '\'':"") +
-                ", children='" + children.size() + '\'' +
-                (metaData.isEmpty()?"":", metaData=" + metaData) +
+                (value!=null?", createValue='" + value + '\'':"") +
+                (getMeta().isEmpty()?"":", metaData=" + getMeta()) +
                 '}';
     }
 
-    private void checkImmutable(){
+    protected final void checkImmutable(){
         if(immutable){
             throw new IllegalStateException("Instance is immutable.");
         }
     }
 
+    protected final int incrementVersion(){
+        checkImmutable();
+        return version.incrementAndGet();
+    }
+
+    protected final void setVersion(int version) {
+        this.version.set(version);
+    }
+
+    protected final void setParent(PropertyValue parent){
+        this.parent = parent;
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
----------------------------------------------------------------------
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
index 20f49a0..57bd058 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
@@ -22,24 +22,24 @@ import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
- * Builder to create a {@link org.apache.tamaya.spi.PropertyValue} instance.
+ * Builder to createObject a {@link org.apache.tamaya.spi.PropertyValue} instance.
  * @deprecated Use {@link PropertyValue} directly.
  */
 @Deprecated
 public final class PropertyValueBuilder {
     /** The key accessed. */
     protected String key;
-    /** The property value. */
+    /** The property createValue. */
     protected String value;
-    /** The property value. */
+    /** The property createValue. */
     protected String source;
     /** additional metadata entries (optional). */
     protected Map<String,Object> metaEntries = new HashMap<>();
-    /** The getParent getChild, null if it's a root getChild. */
+    /** The getParent getField, null if it's a root getField. */
     protected PropertyValue parent;
-    /** The getChild's getIndex, if the getChild is participating in a list structure. */
+    /** The getField's getIndex, if the getField is participating in a createList structure. */
     protected int index = -1;
-    /** Helper structure used for indexing new list getChildren. */
+    /** Helper structure used for indexing new createList getList. */
     protected Map<String, AtomicInteger> indices = new HashMap<>();
 
     /**
@@ -66,12 +66,12 @@ public final class PropertyValueBuilder {
     /**
      * 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).
+     * @param value the context createValue, not {@code null} (will be converted to String).
      * @return the builder for chaining.
      */
     public PropertyValueBuilder addMetaEntry(String key, Object value) {
         Objects.requireNonNull(key, "Meta key must be given.");
-        Objects.requireNonNull(value, "Meta value must be given.");
+        Objects.requireNonNull(value, "Meta createValue must be given.");
 
         this.metaEntries.put(key, value);
         return this;
@@ -80,13 +80,13 @@ public final class PropertyValueBuilder {
     /**
      * Add an additional context data information.
      * @param type the context data type, used as key, not {@code null}.
-     * @param value the context value, not {@code null}.
+     * @param value the context createValue, not {@code null}.
      * @param <T> the type of the class modeled by the type parameter
      * @return the builder for chaining.
      */
     public <T> PropertyValueBuilder addMetaEntry(Class<T> type, T value) {
         Objects.requireNonNull(type, "Meta key must be given.");
-        Objects.requireNonNull(value, "Meta value must be given.");
+        Objects.requireNonNull(value, "Meta createValue must be given.");
 
         this.metaEntries.put(type.toString(), value);
         return this;
@@ -94,12 +94,12 @@ public final class PropertyValueBuilder {
 
     /**
      * Add an additional context data information, using the data's class name as key.
-     * @param value the context value, not {@code null}.
+     * @param value the context createValue, not {@code null}.
      * @param <T> the type of the class modeled by the type parameter
      * @return the builder for chaining.
      */
     public <T> PropertyValueBuilder addMetaEntry(T value) {
-        Objects.requireNonNull(value, "Meta value must be given.");
+        Objects.requireNonNull(value, "Meta createValue must be given.");
 
         this.metaEntries.put(value.getClass().toString(), value);
         return this;
@@ -128,7 +128,7 @@ public final class PropertyValueBuilder {
     }
 
     /**
-     * Get the value's context data.
+     * Get the createValue's context data.
      * @return the context data, not {@code null}.
      */
     public Map<String,Object> getMetaEntries() {
@@ -136,7 +136,7 @@ public final class PropertyValueBuilder {
     }
 
     /**
-     * Get the value's context data.
+     * Get the createValue's context data.
      * @param <T> the type of the class modeled by the type parameter
      * @return the context data, not {@code null}.
      */
@@ -145,7 +145,7 @@ public final class PropertyValueBuilder {
     }
 
     /**
-     * Get the value's context data.
+     * Get the createValue'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}.
@@ -185,8 +185,8 @@ public final class PropertyValueBuilder {
     }
 
     /**
-     * Sets a new value.
-     * @param value the new value, not {@code null}.
+     * Sets a new createValue.
+     * @param value the new createValue, not {@code null}.
      * @return the builder for chaining.
      */
     public PropertyValueBuilder setValue(String value) {
@@ -221,7 +221,7 @@ public final class PropertyValueBuilder {
     public String toString() {
         return "PropertyValueBuilder{" +
                 "key='" + key + '\'' +
-                ", value='" + value + '\'' +
+                ", createValue='" + value + '\'' +
                 ", source='" + source + '\'' +
                 ", metaEntries=" + metaEntries +
                 '}';

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
----------------------------------------------------------------------
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
index 10a3200..59f0f7a 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
@@ -21,7 +21,7 @@ package org.apache.tamaya.spi;
 
 
 /**
- * Policy that determines how the final value of a configuration entry is evaluated. An instances of this
+ * Policy that determines how the final createValue of a configuration entry is evaluated. An instances of this
  * interface can be registered to current control how multiple PropertySources are combined. This is useful in cases
  * where the default overriding policy as implemented in {@link #DEFAULT_OVERRIDING_POLICY} is not matching
  * the need of the current application, e.g. then entries containing multiple values should be combined to new
@@ -52,22 +52,22 @@ public interface PropertyValueCombinationPolicy {
 
 
      /**
-     * Method that is called for each value evaluated by a PropertySource for the given key. This method is called
+     * Method that is called for each createValue evaluated by a PropertySource for the given key. This method is called
      * either when a single key is accessed, e.g. by calling {@code org.apache.tamaya.Configuration.getXXX}, but also
      * when the full configuration property map is accessed by calling
      * {@link org.apache.tamaya.Configuration#getProperties()}.
      *
-     * @param currentValue the current value, including metadata entries. If no such key is present the current value
+     * @param currentValue the current createValue, including metadata entries. If no such key is present the current createValue
      *                     is null.
-     *                     The collector should either combine the existing value with value from {@code currentValue}
-     *                     or replace the value in {@code currentValue} with {@code valueRead}, hereby returning the
+     *                     The collector should either combine the existing createValue with createValue from {@code currentValue}
+     *                     or replace the createValue in {@code currentValue} with {@code valueRead}, hereby returning the
      *                     result to be used as new {@code currentValue}.
      * @param key The current key to be evaluated.
-     * @param propertySource The PropertySource that may return an value for the given key. The PropertySource given
+     * @param propertySource The PropertySource that may return an createValue for the given key. The PropertySource given
      *                       may be evaluated for additional getMeta-data, how the given values are to be combined.
-     *                       Note that the value returned by a PropertySource can be null. In that case
+     *                       Note that the createValue returned by a PropertySource can be null. In that case
      *                       {@code currentValue} should be returned in almost all cases.
-     * @return the value to be used for future evaluation, including metadata entries.
+     * @return the createValue to be used for future evaluation, including metadata entries.
      */
      PropertyValue collect(PropertyValue currentValue, String key, PropertySource propertySource);
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
----------------------------------------------------------------------
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 c9a521f..0576196 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
@@ -25,6 +25,7 @@ import java.io.IOException;
 import java.net.URL;
 import java.text.MessageFormat;
 import java.util.*;
+import java.util.function.Supplier;
 import java.util.logging.Level;
 
 
@@ -43,7 +44,7 @@ public interface ServiceContext extends ClassloaderAware{
     }
 
     /**
-     * Checks the given instance for a @Priority annotation. If present the annotation's value is evaluated. If no such
+     * Checks the given instance for a @Priority annotation. If present the annotation's createValue is evaluated. If no such
      * annotation is present, a default priority of {@code 1} is returned.
      * @param o the instance, not {@code null}.
      * @return a priority, by default 1.
@@ -68,11 +69,26 @@ public interface ServiceContext extends ClassloaderAware{
      * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
      */
     default <T> T getService(Class<T> serviceType){
-         return create(serviceType);
+        return getService(serviceType, null);
     }
 
     /**
-     * Factory method to create a type, hereby a new instance is created on each access.
+     * Access a service singleton via its type.
+     * If multiple implementations for the very serviceType exist then
+     * the one with the highest {@link javax.annotation.Priority} will be used.
+     *
+     * @param <T> the type of the service type.
+     * @param serviceType the service type.
+     * @param supplier the supplier to be used, if no services could be evaluated. If null,
+     *                 an empty collection is returned, when no services
+     *                 could be located.
+     * @return The instance to be used, or {@code null}
+     * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
+     */
+    <T> T getService(Class<T> serviceType, Supplier<T> supplier);
+
+    /**
+     * Factory method to createObject a type, hereby a new instance is created on each access.
      * If multiple implementations for the very serviceType exist then
      * the one with the highest {@link javax.annotation.Priority} will be used as the base
      * for creating subsequent instances.
@@ -82,29 +98,53 @@ public interface ServiceContext extends ClassloaderAware{
      * @return The new instance to be used, or {@code null}
      * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
      */
-   default <T> T create(Class<T> serviceType){
-        @SuppressWarnings("unchecked")
-        Class<? extends T> implType = null;
-        Collection<T> services = getServices(serviceType);
-        if (services.isEmpty()) {
-            return null;
-        } else {
-            return ((List<T>) services).get(0);
-        }
+    default <T> T create(Class<T> serviceType){
+        return create(serviceType, null);
     }
 
+    /**
+     * Factory method to createObject a type, hereby a new instance is created on each access.
+     * If multiple implementations for the very serviceType exist then
+     * the one with the highest {@link javax.annotation.Priority} will be used as the base
+     * for creating subsequent instances.
+     *
+     * @param <T> the type of the service type.
+     * @param serviceType the service type.
+     * @return The new instance to be used, or {@code null}
+     * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
+     */
+   <T> T create(Class<T> serviceType, Supplier<T> supplier);
 
     /**
-     * Access a list current services, given its type. The bootstrap mechanism should
+     * Access a createList current services, given its type. The bootstrap mechanism should
      * order the instance for precedence, hereby the most significant should be
      * first in order.
      *
      * @param serviceType
      *            the service type.
-     * @param <T> the type of the list element returned by this method
+     * @param <T> the type of the createList element returned by this method
      * @return The instance to be used, never {@code null}
      */
-     <T> List<T> getServices(Class<T> serviceType);
+    default <T> List<T> getServices(Class<T> serviceType){
+        return getServices(serviceType, null);
+    }
+
+    /**
+     * Access a createList current services, given its type. The bootstrap mechanism should
+     * order the instance for precedence, hereby the most significant should be
+     * first in order. If no instances could be found, the instances supplied by the
+     * supplier given are registered and used.
+     *
+     * @param serviceType
+     *            the service type.
+     * @param <T> the type of the createList element returned by this method
+     * @param supplier the supplier to be used, if no services could be evaluated. If null,
+     *                 an empty collection is returned, when no services
+     *                 could be located.
+     * @return The instance to be used, never {@code null}
+     */
+     <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier);
+
     /**
      * Loads resources from the current runtime context. This method allows to use runtime
      * specific code to load resources, e.g. within OSGI environments.
@@ -126,4 +166,26 @@ public interface ServiceContext extends ClassloaderAware{
         return getClassLoader().getResource(resource);
     }
 
+    /**
+     * Registers the given instance as a singleton service for the given instance, if no
+     * instance already has been registered.
+     *
+     * @param type the type to register, not null.
+     * @param instance the instance, not null.
+     * @param <T> thy type.
+     * @param force if true, any existing instance will be replaced.
+     * @return the instance registered or already present.
+     */
+    <T> T register(Class<T> type, T instance, boolean force);
+
+    /**
+     * Registers the given instancea as servicea for the given instance, if no
+     *      * instance already has been registered.
+     * @param type the type to register, not null.
+     * @param instances the instancea, not null.
+     * @param <T> thy type.
+     * @param force if true, any existing instances will be replaced.
+     * @return the instances registered or already present.
+     */
+    <T> List<T> register(Class<T> type, List<T> instances, boolean force);
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java
----------------------------------------------------------------------
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 3c008d1..9909a40 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
@@ -109,6 +109,7 @@ public final class ServiceContextManager {
      * @return the {@link ServiceContext} used.
      */
     public static ServiceContext getServiceContext(ClassLoader classLoader) {
+        Objects.requireNonNull(classLoader, "Classloader required.");
         return serviceContexts.computeIfAbsent(classLoader, ServiceContextManager::loadDefaultServiceProvider);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java
----------------------------------------------------------------------
diff --git a/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java b/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java
index 521c7cd..787e04f 100644
--- a/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java
@@ -29,7 +29,7 @@ import org.mockito.Mockito;
  *
  * Test the {@link ConfigurationProivder} class. The tests end up being tests of
  * the default methods in the {@link ConfigurationProivder} interface as they
- * pass through to the {@link TestConfigurationProvider} mocked object.
+ * pass through to the {@link TestConfigurationProvider} mocked createObject.
  */
 public class ConfigurationProviderTest {
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java
----------------------------------------------------------------------
diff --git a/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java b/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java
index 94923ff..bb68697 100644
--- a/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java
+++ b/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java
@@ -100,7 +100,7 @@ public class TestConfiguration implements Configuration {
 
     @Override
     public Map<String, String> getProperties() {
-        // run toString on each value of the (key, value) setCurrent in VALUES
+        // run toString on each createValue of the (key, createValue) setCurrent in VALUES
         return VALUES.entrySet().stream().collect(
                 Collectors.toMap(
                         Map.Entry::getKey,

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java
----------------------------------------------------------------------
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java
index fb8e7b3..067a18a 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java
@@ -49,7 +49,7 @@ TestConfigurationProvider configProvider = new TestConfigurationProvider();
         try{
             configProvider.setConfigurationContext(newContext);
             //The mocked TestConfigurationProvider doesn't setCurrent the context on the
-            // inner Configuration object, as that's deprecated.
+            // inner Configuration createObject, as that's deprecated.
             assertThat(configProvider.getConfigurationContext()).isEqualTo(newContext);
         }finally{
             configProvider.setConfigurationContext(currentContext);

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
----------------------------------------------------------------------
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 35842ca..3ed57f3 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
@@ -115,7 +115,7 @@ public class FilterContextTest {
     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, PropertyValue.of("key-"+i, "createValue-"+i, "test"));
         }
         PropertyValue val = PropertyValue.of("getConfigEntries", "v", "");
         FilterContext ctx = new FilterContext(val, config, ConfigurationContext.EMPTY);
@@ -127,7 +127,7 @@ public class FilterContextTest {
     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"));
+            config.put("key-"+i, PropertyValue.of("key-"+i, "createValue-"+i, "test"));
         }
         PropertyValue val = PropertyValue.of("testToString", "val", "mySource");
         FilterContext ctx = new FilterContext(val, config, ConfigurationContext.EMPTY);
@@ -135,8 +135,8 @@ public class FilterContextTest {
 
         assertThat(toString).isNotNull();
         System.out.println(toString);
-        assertThat(toString.contains("FilterContext{value='[PropertyValue{'testToString', value='val', children='0', " +
-                "metaData={source=mySource}}]', configEntries=[")).isTrue();
+        assertThat(toString.contains("FilterContext{createValue='[PropertyValue{'testToString', createValue='val'," +
+                " metaData={source=mySource}}]', configEntries=[")).isTrue();
         assertThat(toString.contains("key-0")).isTrue();
         assertThat(toString.contains("key-1")).isTrue();
         assertThat(toString.endsWith("}")).isTrue();

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java
----------------------------------------------------------------------
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 d0d8874..fef0712 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
@@ -150,7 +150,7 @@
 //        PropertyValueBuilder b = new PropertyValueBuilder("k", "v").setSource("testSetContextData");
 //        Map<String,String> context = new HashMap<>();
 //        context.put("source", "testSetContextData");
-//        context.put("ts", String.valueOf(System.currentTimeMillis()));
+//        context.put("ts", String.createValue(System.currentTimeMillis()));
 //        context.put("y", "yValue");
 //        b.setMeta(new HashMap<String, String>());
 //        b.setMeta(context);
@@ -177,13 +177,13 @@
 //
 //    @Test
 //    public void testMapKey() {
-//        PropertyValueBuilder b = new PropertyValueBuilder("key", "value")
+//        PropertyValueBuilder b = new PropertyValueBuilder("key", "createValue")
 //                .setMeta("_keyAndThenSome", "mappedvalue")
 //                .setMeta("somethingelse", "othervalue")
 //                .mapKey("mappedkey");
 //        PropertyValue pv = b.build();
 //        Assertions.assertThat(pv.getKey()).isEqualTo("mappedkey");
-//        Assertions.assertThat(pv.getValue()).isEqualTo("value");
+//        Assertions.assertThat(pv.getValue()).isEqualTo("createValue");
 //        Assertions.assertThat(pv.getMeta()).hasSize(2);
 //        assertThat(pv.getMeta("_mappedkey.AndThenSome")).isEqualTo("mappedvalue");
 //        assertThat(pv.getMeta("somethingelse")).isEqualTo("othervalue");
@@ -194,7 +194,7 @@
 //        PropertyValueBuilder b = new PropertyValueBuilder("k", "v")
 //                .setMeta("metak", "metav");
 //        System.out.println(b.toString());
-//        assertThat(b.toString()).isEqualTo("PropertyValueBuilder{key='k'value='v'listValue='[]', metaEntries={metak=metav}}");
+//        assertThat(b.toString()).isEqualTo("PropertyValueBuilder{key='k'createValue='v'listValue='[]', metaEntries={metak=metav}}");
 //    }
 //
 //    @Test(expected = NullPointerException.class)

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java
----------------------------------------------------------------------
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 3a9d3ef..0ebfbcc 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
@@ -22,7 +22,6 @@ import org.assertj.core.api.Assertions;
 import org.junit.Test;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 import static org.assertj.core.api.Assertions.*;
@@ -60,7 +59,7 @@ public class PropertyValueTest {
 
     @Test(expected = NullPointerException.class)
     public void testSetMetaEntriesRequiresNonNullParameter() {
-        PropertyValue.create().setMeta(null);
+        PropertyValue.createObject().setMeta(null);
     }
 
     @Test
@@ -68,7 +67,7 @@ public class PropertyValueTest {
         Map<String,Object> meta = new HashMap<>();
         meta.put("1","2");
         meta.put("a", "b");
-        PropertyValue pv = PropertyValue.create()
+        PropertyValue pv = PropertyValue.createObject()
                 .setMeta("k", "v2")
                 .setMeta(meta);
         assertThat(pv.getMeta().get("k")).isNull();
@@ -79,18 +78,18 @@ public class PropertyValueTest {
 
     @Test(expected = NullPointerException.class)
     public void removeMetaEntryRequiresNonNullParameter() {
-        PropertyValue.create().removeMeta((String)null);
+        PropertyValue.createObject().removeMeta((String)null);
     }
 
     @Test(expected = NullPointerException.class)
     public void removeMetaEntryRequiresNonNullParameterClass() {
-        PropertyValue.create().removeMeta((Class)null);
+        PropertyValue.createObject().removeMeta((Class)null);
     }
 
 
     @Test
     public void testRemoveMetaEntry() throws Exception {
-        PropertyValue pv = PropertyValue.create("k")
+        PropertyValue pv = PropertyValue.createObject("k")
                 .setMeta("k", "v2")
                 .setMeta("k2", "v22")
                 .removeMeta("k");
@@ -100,7 +99,7 @@ public class PropertyValueTest {
 
     @Test
     public void testRemoveMetaEntryClass() throws Exception {
-        PropertyValue pv = PropertyValue.create("k")
+        PropertyValue pv = PropertyValue.createObject("k")
                 .setMeta(String.class, "v2")
                 .setMeta("k2", "v22")
                 .removeMeta(String.class);
@@ -113,7 +112,7 @@ public class PropertyValueTest {
         Map<String,Object> meta = new HashMap<>();
         meta.put("1","2");
         meta.put("a", "b");
-        PropertyValue pv = PropertyValue.create("k")
+        PropertyValue pv = PropertyValue.createObject("k")
                 .setMeta(meta);
         assertThat(pv.getMeta()).isEqualTo(meta);
         Assertions.assertThat(pv.getMeta()).isEqualTo(meta);
@@ -164,110 +163,88 @@ public class PropertyValueTest {
 
     @Test
     public void testGetMetaEntry() throws Exception {
-        PropertyValue pv = PropertyValue.create("k")
-                .setValue("v")
+        PropertyValue pv = PropertyValue.createObject("k")
                 .setMeta("k", "v2");
-        Assertions.assertThat(pv.getValue()).isEqualTo("v");
         Assertions.assertThat(pv.getKey()).isEqualTo("k");
         assertThat(pv.getMeta().get("k")).isEqualTo("v2");
-        assertThat((String)pv.getMeta("k")).isEqualTo("v2");
     }
 
 
     @Test(expected = NullPointerException.class)
     public void testInstantiateNoKey1() throws Exception {
-        PropertyValue.create((String)null);
+        PropertyValue.createObject((String)null);
     }
 
     @Test(expected = NullPointerException.class)
     public void testInstantiateNoKey2() throws Exception {
-        PropertyValue.of(null, "v", "testGetKey");
+        PropertyValue.createValue(null, "v");
     }
 
     @Test
     public void testInstantiateNoValue2() throws Exception {
-        PropertyValue.of("k", null, "testGetKey");
+        PropertyValue.createValue("k", null);
     }
 
     @Test
     public void testInstantiateNoSource2() throws Exception {
-        PropertyValue.of("k", "v", null);
+        PropertyValue.createValue("k", "v");
     }
 
     @Test(expected = NullPointerException.class)
     public void addMetaEntryRequiresNonNullParameterForKey() {
-        PropertyValue.create("k").setMeta((String)null, "a");
+        PropertyValue.createObject("k").setMeta((String)null, "a");
     }
 
     @Test(expected = NullPointerException.class)
     public void addMetaEntryRequiresNonNullParameterForKeyClass() {
-        PropertyValue.create("k").setMeta((Class)null, "a");
+        PropertyValue.createValue("k", null).setMeta((Class)null, "a");
     }
 
     @Test(expected = NullPointerException.class)
     public void addMetaEntryRequiresNonNullParameterForValue() {
-        PropertyValue.create("k").setMeta("a", null);
+        PropertyValue.createObject("k").setMeta("a", null);
     }
 
     @Test
-    public void setValueRequiresNullParameterForValue() {
-        PropertyValue.create("k").setValue(null);
+    public void newXXX() {
+        assertNotNull(PropertyValue.createValue("", null));
+        assertNotNull(PropertyValue.createObject());
+        assertNotNull(PropertyValue.createObject(""));
+        assertNotNull(PropertyValue.createList());
+        assertNotNull(PropertyValue.createList(""));
     }
 
     @Test
-    public void create() {
-        assertNotNull(PropertyValue.create());
-        assertTrue(PropertyValue.create().isRoot());
-        PropertyValue n = PropertyValue.create().getOrCreateChild("child");
-        assertFalse(n.isRoot());
-    }
-
-    @Test
-    public void create_String() {
-        PropertyValue foo = PropertyValue.create("foo");
+    public void valueOf() {
+        PropertyValue foo = PropertyValue.createValue("foo", "bar");
         assertNotNull(foo);
         assertEquals("foo", foo.getKey());
-        PropertyValue n = PropertyValue.create("bar").getOrCreateChild("child");
-        assertFalse(n.isRoot());
-    }
-
-    @Test
-    public void getOrCreateChild() {
-        PropertyValue root = PropertyValue.create("bar");
-        assertTrue(root.getChildren().isEmpty());
-        assertNotNull(root.getOrCreateChild("foo"));
-        assertFalse(root.getChildren().isEmpty());
-        assertFalse(root.getChildren("foo").isEmpty());
-        assertTrue(root.getOrCreateChild("foo") == root.getOrCreateChild("foo"));
-        assertTrue(root.getChildren("bar").isEmpty());
-        assertTrue(root.getOrCreateChild("bar") == root.getOrCreateChild("bar"));
-        assertFalse(root.getChildren("bar").isEmpty());
+        assertEquals("bar", foo.getValue());
     }
 
     @Test
-    public void getChild() {
-        PropertyValue root = PropertyValue.create("bar");
-        assertNull(root.getChild("foo"));
-        root.getOrCreateChild("foo");
-        assertNotNull(root.getChild("foo"));
+    public void arrayOf() {
+        ListValue foo = PropertyValue.createList("foo");
+        assertNotNull(foo);
+        assertEquals("foo", foo.getKey());
     }
 
     @Test
-    public void createChild_Indexed() {
-        PropertyValue root = PropertyValue.create("a");
-        assertNotNull(root.createChild("a", true));
-        List<PropertyValue> nodes = root.getChildren("a");
-        assertEquals(1, nodes.size());
-        assertTrue(root.createChild("a").isIndexed());
-        nodes = root.getChildren("a");
-        assertEquals(2, nodes.size());
-        assertFalse(root.createChild("b").isIndexed());
-        assertTrue(root.createChild("b").isIndexed());
+    public void objectOf() {
+        ObjectValue root = PropertyValue.createObject("bar");
+        assertTrue(root.getSize() == 0);
+        assertNotNull(root.setField("foo", null));
+        assertFalse(root.getSize()==0);
+        assertNotNull(root.getField("foo"));
+        assertNull(root.getField("foo").getValue());
+        assertNotNull(root.setField("foo", "bar"));
+        assertEquals(root.getField("foo").getValue(), "bar");
+        assertTrue(root.getSize()==1);
     }
 
     @Test
     public void addMeta() {
-        PropertyValue root = PropertyValue.create();
+        PropertyValue root = PropertyValue.createObject();
         assertNotNull(root.setMeta("a"));
         root.setMeta("a", Integer.valueOf(3));
         assertEquals(Integer.valueOf(3), root.getMeta("a"));
@@ -275,91 +252,81 @@ public class PropertyValueTest {
 
     @Test
     public void getKey() {
-        PropertyValue root = PropertyValue.create("a");
+        PropertyValue root = PropertyValue.createObject("a");
         assertEquals("a", root.getKey());
     }
 
     @Test
     public void getQualifiedKey() {
-        PropertyValue root = PropertyValue.create("a");
+        ObjectValue root = PropertyValue.createObject("a");
         assertEquals("a", root.getQualifiedKey());
-        PropertyValue n = root.createChild("b");
-        assertEquals("a.b", n.getQualifiedKey());
-        PropertyValue added = n.createChild("c");
+        ObjectValue child = PropertyValue.createObject("b");
+        ObjectValue n = root.set(child);
+        assertEquals("a.b", child.getQualifiedKey());
+        PropertyValue added = child.setField("c", null);
         assertEquals("a.b.c", added.getQualifiedKey());
-        added = n.createChild("c");
-        assertEquals("a.b.c[1]", added.getQualifiedKey());
-        assertEquals("a.b.c[0]", n.getChildWithIndex("c",0).getQualifiedKey());
-    }
-
-    @Test
-    public void isIndexed() {
-        PropertyValue n = PropertyValue.create();
-        assertFalse(n.isIndexed());
-        assertFalse(n.createChild("a").isIndexed());
-        assertFalse(n.createChild("b").isIndexed());
-        assertFalse(n.createChild("c").isIndexed());
-        assertTrue(n.createChild("c").isIndexed());
     }
 
     @Test
     public void isLeaf() {
-        PropertyValue n = PropertyValue.create();
+        PropertyValue n = PropertyValue.createValue("", "");
         assertTrue(n.isLeaf());
-        n.createChild("b");
+        n = PropertyValue.createList("");
         assertFalse(n.isLeaf());
     }
 
     @Test
     public void getParent() {
-        PropertyValue n = PropertyValue.create();
+        ObjectValue n = PropertyValue.createObject("");
         assertNull(n.getParent());
-        n = n.createChild("b");
-        assertNotNull(n.getParent());
-    }
-
-    @Test
-    public void getChildren_Filtered() {
-        PropertyValue n = PropertyValue.create();
-        n.createChild("a");
-        n.createChild("b");
-        n.createChild("c");
-        n.createChild("c");
-        List<PropertyValue> nodes = n.getChildren("a");
-        assertNotNull(nodes);
-        assertEquals(1, nodes.size());
-        assertEquals("a", nodes.get(0).getKey());
-
-        nodes = n.getChildren("c");
-        assertEquals(2, nodes.size());
-        assertEquals("c", nodes.get(0).getKey());
-        assertEquals("c", nodes.get(1).getKey());
-    }
-
-    @Test
-    public void getChildren() {
-        PropertyValue n = PropertyValue.create();
-        n.createChild("a");
-        n.createChild("b");
-        n.createChild("c");
-        n.createChild("c");
-        List<PropertyValue> nodes = n.getChildren();
-        assertNotNull(nodes);
-        assertEquals(4, nodes.size());
-        assertEquals("a", nodes.get(0).getKey());
-        assertEquals("b", nodes.get(1).getKey());
-        assertEquals("c", nodes.get(2).getKey());
-        assertEquals("c", nodes.get(3).getKey());
-    }
+        n.setFieldObject("b");
+        assertNotNull(n.getField("b"));
+        assertNotNull(n.getField("b").getParent());
+    }
+
+//    @Test
+//    public void getChildren_Filtered() {
+//        PropertyValue n = PropertyValue.createObject();
+//        n.setField("a");
+//        n.setField("b");
+//        n.setField("c");
+//        n.setField("c");
+//        List<PropertyValue> nodes = n.getList("a");
+//        assertNotNull(nodes);
+//        assertEquals(1, nodes.size());
+//        assertEquals("a", nodes.getField(0).getKey());
+//
+//        nodes = n.getList("c");
+//        assertEquals(2, nodes.size());
+//        assertEquals("c", nodes.getField(0).getKey());
+//        assertEquals("c", nodes.getField(1).getKey());
+//    }
+//
+//    @Test
+//    public void getList() {
+//        PropertyValue n = PropertyValue.createObject();
+//        n.setField("a");
+//        n.setField("b");
+//        n.setField("c");
+//        n.setField("c");
+//        List<PropertyValue> nodes = n.getList();
+//        assertNotNull(nodes);
+//        assertEquals(4, nodes.size());
+//        assertEquals("a", nodes.getField(0).getKey());
+//        assertEquals("b", nodes.getField(1).getKey());
+//        assertEquals("c", nodes.getField(2).getKey());
+//        assertEquals("c", nodes.getField(3).getKey());
+//    }
 
     @Test
     public void asMap() {
-        PropertyValue n = PropertyValue.create();
-        n.createChild("a", "aVal");
-        n.createChild("b").createChild("b2").createChild("b3", "b3Val");
-        n.createChild("c", "cVal1");
-        n.createChild("c", "cVal2");
-        Map<String,String> map = n.asMap();
+        ObjectValue n = PropertyValue.createObject("");
+        n.setField("a", "aVal");
+        n.setFieldObject("b").setFieldObject("b2").setField("b3", "b3Val");
+        ListValue array = n.setFieldList("c");
+        array.addValue("cVal1");
+        array.addValue("cVal2");
+        Map<String,String> map = n.toMap();
         System.out.println(map);
         assertEquals(4, map.size());
         assertEquals("aVal", map.get("a"));
@@ -370,34 +337,31 @@ public class PropertyValueTest {
 
     @Test
     public void asString() {
-        PropertyValue n = PropertyValue.create();
-        n.createChild("a", "aVal");
-        n.createChild("b").createChild("b2").createChild("b3", "b3Val");
-        n.createChild("c", "cVal1");
-        n.createChild("c", "cVal2");
+        ObjectValue n = PropertyValue.createObject();
+        n.setField("a", "aVal");
+        n.setField("b.b2.b3", "b3Val");
+        n.setField("c", "cVal2");
         assertEquals("a = aVal\n" +
                 "b.b2.b3 = b3Val\n" +
-                "c[0] = cVal1\n" +
-                "c[1] = cVal2\n", n.asString());
+                "c = cVal2\n", n.asString());
     }
 
     @Test
     public void equals() {
-        assertEquals(PropertyValue.create(), PropertyValue.create());
-        assertNotEquals(PropertyValue.create("a"), PropertyValue.create());
-        assertEquals(PropertyValue.create("b"), PropertyValue.create("b"));
-        PropertyValue root = PropertyValue.create();
+        assertEquals(PropertyValue.createObject(), PropertyValue.createObject());
+        assertNotEquals(PropertyValue.createObject("a"), PropertyValue.createObject());
+        assertEquals(PropertyValue.createObject(""), PropertyValue.createObject());
+        PropertyValue root = PropertyValue.createObject();
         assertEquals(root, root);
     }
 
     @Test
     public void testToString() {
-        PropertyValue n = PropertyValue.create();
-        n.createChild("a", "aVal");
-        n.createChild("b").createChild("b2").createChild("b3", "b3Val");
-        n.createChild("c", "cVal1");
-        n.createChild("c", "cVal2");
-        assertEquals("PropertyValue{'', children='4'}", n.toString());
+        ObjectValue n = PropertyValue.createObject("");
+        n.setField("a", "aVal");
+        n.setField("b.b2.b3", "b3Val");
+        n.setFieldList("c").addValue("cVal1");
+        assertEquals("PropertyValue[OBJECT]{'', size='3'}", n.toString());
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
----------------------------------------------------------------------
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 90218aa..77f0e85 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
@@ -25,6 +25,7 @@ import java.net.URL;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
+import java.util.function.Supplier;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -72,17 +73,17 @@ public class ServiceContextManagerTest {
         }
 
         @Override
-        public <T> T getService(Class<T> serviceType) {
+        public <T> T getService(Class<T> serviceType, Supplier<T> supplier) {
             return null;
         }
 
         @Override
-        public <T> T create(Class<T> serviceType) {
+        public <T> T create(Class<T> serviceType, Supplier<T> supplier) {
             return null;
         }
 
         @Override
-        public <T> List<T> getServices(Class<T> serviceType) {
+        public <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier) {
             return Collections.emptyList();
         }
 
@@ -95,6 +96,16 @@ public class ServiceContextManagerTest {
         public URL getResource(String resource) {
             return null;
         }
+
+        @Override
+        public <T> T register(Class<T> type, T instance, boolean force) {
+            return instance;
+        }
+
+        @Override
+        public <T> List<T> register(Class<T> type, List<T> instancea, boolean force) {
+            return instancea;
+        }
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
----------------------------------------------------------------------
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
index 65db2af..afa33bc 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
@@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.io.IOException;
 import java.net.URL;
 import java.util.*;
+import java.util.function.Supplier;
 
 import org.junit.Test;
 
@@ -46,7 +47,7 @@ public class ServiceContextTest {
         }
 
         @Override
-        public <T> T getService(Class<T> serviceType) {
+        public <T> T getService(Class<T> serviceType, Supplier<T> supplier) {
             if(String.class.equals(serviceType)){
                 return serviceType.cast("ServiceContextTest");
             }
@@ -54,13 +55,12 @@ public class ServiceContextTest {
         }
 
         @Override
-        public <T> T create(Class<T> serviceType) {
+        public <T> T create(Class<T> serviceType, Supplier<T> supplier) {
             return getService(serviceType);
         }
 
-        @SuppressWarnings("unchecked")
-		@Override
-        public <T> List<T> getServices(Class<T> serviceType) {
+        @Override
+        public <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier) {
             if(String.class.equals(serviceType)){
                 List<String> list = new ArrayList<>();
                 list.add("ServiceContextTest");
@@ -69,6 +69,16 @@ public class ServiceContextTest {
             return Collections.emptyList();
         }
 
+        @Override
+        public <T> T register(Class<T> type, T instance, boolean force) {
+            return instance;
+        }
+
+        @Override
+        public <T> List<T> register(Class<T> type, List<T> instances, boolean force) {
+            return instances;
+        }
+
     };
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java
----------------------------------------------------------------------
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 24f3fe4..b7f2991 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
@@ -21,6 +21,7 @@ package org.apache.tamaya.spi;
 import java.io.IOException;
 import java.net.URL;
 import java.util.*;
+import java.util.function.Supplier;
 
 /**
  * This class implements the (default)
@@ -51,16 +52,31 @@ public final class TestLowerOrdinalServiceContext implements ServiceContext {
     }
 
     @Override
+    public <T> T getService(Class<T> serviceType, Supplier<T> supplier) {
+        return null;
+    }
+
+    @Override
     public <T> T create(Class<T> serviceType) {
         throw ex;
     }
 
     @Override
+    public <T> T create(Class<T> serviceType, Supplier<T> supplier) {
+        throw ex;
+    }
+
+    @Override
     public <T> List<T> getServices(Class<T> serviceType) {
         throw ex;
     }
 
     @Override
+    public <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier) {
+        throw ex;
+    }
+
+    @Override
     public Enumeration<URL> getResources(String resource) throws IOException {
         throw ex;
     }
@@ -70,4 +86,14 @@ public final class TestLowerOrdinalServiceContext implements ServiceContext {
         throw ex;
     }
 
+    @Override
+    public <T> T register(Class<T> type, T instance, boolean force) {
+        throw ex;
+    }
+
+    @Override
+    public <T> List<T> register(Class<T> type, List<T> instancea, boolean force) {
+        throw ex;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
----------------------------------------------------------------------
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 805e07c..9aae439 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
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.net.URL;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -57,12 +58,11 @@ public final class TestServiceContext implements ServiceContext {
         return 5;
     }
 
-    @SuppressWarnings("rawtypes")
-	@Override
-    public <T> T getService(Class<T> serviceType) {
+    @Override
+    public <T> T getService(Class<T> serviceType, Supplier<T> supplier) {
         T cached = serviceType.cast(singletons.get(serviceType));
         if(cached==null) {
-            cached = create(serviceType);
+            cached = create(serviceType, supplier);
             singletons.put((Class)serviceType, cached);
         }
         if (cached == Object.class) {
@@ -71,42 +71,45 @@ public final class TestServiceContext implements ServiceContext {
         return cached;
     }
 
-    @SuppressWarnings("unchecked")
-	@Override
-    public <T> T create(Class<T> serviceType) {
-        Collection<T> services = getServices(serviceType);
-        if (services.isEmpty()) {
-            return (T) Object.class; // as marker for 'nothing here'
-        }
-        else{
-            return services.iterator().next();
+    @Override
+    public <T> T create(Class<T> serviceType, Supplier<T> supplier) {
+        try {
+            for (T t : ServiceLoader.load(serviceType)) {
+                return t;
+            }
+        }catch(Exception e){
+            if(supplier!=null) {
+                T instance = supplier.get();
+                if(instance instanceof ClassloaderAware){
+                    ((ClassloaderAware)instance).init(this.classLoader);
+                }
+                return instance;
+            }
+            throw new IllegalArgumentException("Failed to instantiate instance:");
         }
+        return null;
     }
 
-    /**
-     * Loads and registers services.
-     *
-     * @param   <T>          the concrete type.
-     *
-     * @param   serviceType  The service type.
-     * @return  the items found, never {@code null}.
-     */
     @Override
-    public <T> List<T> getServices(Class<T> serviceType) {
+    public <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier) {
+        List<T> services;
         try {
-            List<T> services = new ArrayList<>();
+            services = new ArrayList<>();
             for (T t : ServiceLoader.load(serviceType)) {
                 services.add(t);
             }
             services = Collections.unmodifiableList(services);
-            @SuppressWarnings("unchecked")
-			final List<T> previousServices = List.class.cast(servicesLoaded.putIfAbsent(serviceType, (List<Object>)services));
-            return previousServices != null ? previousServices : services;
         } catch (Exception e) {
-            Logger.getLogger(TestServiceContext.class.getName()).log(Level.WARNING,
-                                      "Error loading services current type " + serviceType, e);
-            return Collections.emptyList();
+            if(supplier==null){
+                Logger.getLogger(TestServiceContext.class.getName()).log(Level.WARNING,
+                        "Error loading services current type " + serviceType, e);
+                return Collections.emptyList();
+            }
+            services = Collections.unmodifiableList(supplier.get());
         }
+        @SuppressWarnings("unchecked")
+        final List<T> previousServices = List.class.cast(servicesLoaded.putIfAbsent(serviceType, (List<Object>)services));
+        return previousServices != null ? previousServices : services;
     }
 
     @Override
@@ -119,4 +122,24 @@ public final class TestServiceContext implements ServiceContext {
         return classLoader.getResource(resource);
     }
 
+    @Override
+    public <T> T register(Class<T> type, T instance, boolean force) {
+        if(force){
+            servicesLoaded.put(type, Collections.singletonList(instance));
+        }else{
+            servicesLoaded.putIfAbsent(type, Collections.singletonList(instance));
+        }
+        return (T)servicesLoaded.get(type).get(0);
+    }
+
+    @Override
+    public <T> List<T> register(Class<T> type, List<T> instances, boolean force) {
+        if(force){
+            servicesLoaded.put(type, Collections.singletonList(instances));
+        }else {
+            servicesLoaded.putIfAbsent(type, Collections.singletonList(instances));
+        }
+        return (List<T>)servicesLoaded.get(type);
+    }
+
 }