You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by st...@apache.org on 2014/12/27 14:58:15 UTC

[31/34] incubator-tamaya git commit: move intermediately changed stuff to dormant as well

move intermediately changed stuff to dormant as well


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

Branch: refs/heads/master
Commit: 278a6c681b2cfd52ac375b84e2e90aa2b579e12e
Parents: 30bdbb9
Author: Mark Struberg <st...@apache.org>
Authored: Sat Dec 27 11:09:17 2014 +0100
Committer: Mark Struberg <st...@apache.org>
Committed: Sat Dec 27 11:10:12 2014 +0100

----------------------------------------------------------------------
 .../tamaya/core/ConfigurationFunctions.java     | 213 ------------
 .../core/properties/ConfigurationFormat.java    | 111 ------
 .../core/properties/FrozenPropertySource.java   |  80 -----
 .../core/properties/MappedPropertySource.java   |  53 ---
 .../core/properties/PropertyChangeSet.java      | 169 ---------
 .../properties/PropertyChangeSetBuilder.java    | 347 -------------------
 .../properties/PropertySourceFunctions.java     |  65 ----
 ...e.tamaya.core.properties.ConfigurationFormat |  21 --
 .../tamaya/core/ConfigurationFunctions.java     | 213 ++++++++++++
 .../core/properties/ConfigurationFormat.java    | 111 ++++++
 .../core/properties/FrozenPropertySource.java   |  80 +++++
 .../core/properties/MappedPropertySource.java   |  53 +++
 .../core/properties/PropertyChangeSet.java      | 169 +++++++++
 .../properties/PropertyChangeSetBuilder.java    | 347 +++++++++++++++++++
 .../properties/PropertySourceFunctions.java     |  65 ++++
 ...e.tamaya.core.properties.ConfigurationFormat |  21 ++
 16 files changed, 1059 insertions(+), 1059 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java b/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
deleted file mode 100644
index b1c2522..0000000
--- a/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core;
-
-import org.apache.tamaya.Configuration;
-import org.apache.tamaya.core.properties.PropertySourceBuilder;
-
-import java.util.*;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-import java.util.stream.Collectors;
-
-/**
- * Accessor that provides useful functions along with configuration.
- */
-public final class ConfigurationFunctions {
-    /**
-     * Private singleton constructor.
-     */
-    private ConfigurationFunctions() {
-    }
-
-    /**
-     * Creates a ConfigOperator that creates a Configuration containing only keys
-     * that are contained in the given area (non recursive). Hereby
-     * the area key is stripped away fromMap the resulting key.
-     *
-     * @param areaKey the area key, not null
-     * @return the area configuration, with the areaKey stripped away.
-     */
-    public static UnaryOperator<Configuration> selectArea(String areaKey) {
-        return selectArea(areaKey, true);
-    }
-
-    /**
-     * Creates a ConfigOperator that creates a Configuration containing only keys
-     * that are contained in the given area (non recursive).
-     *
-     * @param areaKey   the area key, not null
-     * @param stripKeys if set to true, the area key is stripped away fromMap the resulting key.
-     * @return the area configuration, with the areaKey stripped away.
-     */
-    public static UnaryOperator<Configuration> selectArea(String areaKey, boolean stripKeys) {
-        return config -> {
-            Map<String, String> area = new HashMap<>();
-            area.putAll(
-                    config.getProperties().entrySet().stream()
-                            .filter(e -> isKeyInArea(e.getKey(), areaKey))
-                            .collect(Collectors.toMap(
-                                    e -> stripKeys ? e.getKey().substring(areaKey.length() + 1) : e.getKey(),
-                                    Map.Entry::getValue)));
-            return Configuration.from(PropertySourceBuilder.of("area: " + areaKey).addMap(area).build());
-        };
-    }
-
-    /**
-     * Calculates the current area key and compares it with the given key.
-     *
-     * @param key     the fully qualified entry key, not null
-     * @param areaKey the area key, not null
-     * @return true, if the entry is exact in this area
-     */
-    public static boolean isKeyInArea(String key, String areaKey) {
-        int lastIndex = key.lastIndexOf('.');
-        String curAreaKey = lastIndex > 0 ? key.substring(0, lastIndex) : "";
-        return curAreaKey.equals(areaKey);
-    }
-
-    /**
-     * Return a query to evaluate the set with all fully qualifies area names. This method should return the areas as accurate as possible,
-     * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
-     * does not support key iteration.
-     *
-     * @return s set with all areas, never {@code null}.
-     */
-    public static Function<Configuration,Set<String>> getAreas() {
-        return config -> {
-            final Set<String> areas = new HashSet<>();
-            config.getProperties().keySet().forEach(s -> {
-                int index = s.lastIndexOf('.');
-                if (index > 0) {
-                    areas.add(s.substring(0, index));
-                } else {
-                    areas.add("<root>");
-                }
-            });
-            return areas;
-        };
-    }
-
-    /**
-     * Return a query to evaluate the set with all fully qualified area names, containing the transitive closure also including all
-     * subarea names, regardless if properties are accessible or not. This method should return the areas as accurate
-     * as possible, but may not provide a complete set of areas that are finally accessible, especially when the
-     * underlying storage does not support key iteration.
-     *
-     * @return s set with all transitive areas, never {@code null}.
-     */
-    public static Function<Configuration,Set<String>> getTransitiveAreas() {
-        return config -> {
-            final Set<String> transitiveAreas = new HashSet<>();
-            config.query(getAreas()).forEach(s -> {
-                int index = s.lastIndexOf('.');
-                if (index < 0) {
-                    transitiveAreas.add("<root>");
-                } else {
-                    while (index > 0) {
-                        s = s.substring(0, index);
-                        transitiveAreas.add(s);
-                        index = s.lastIndexOf('.');
-                    }
-                }
-            });
-            return transitiveAreas;
-        };
-    }
-
-    /**
-     * Return a query to evaluate the set with all fully qualified area names, containing only the
-     * areas that match the predicate and have properties attached. This method should return the areas as accurate as possible,
-     * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
-     * does not support key iteration.
-     *
-     * @param predicate A predicate to deternine, which areas should be returned, not {@code null}.
-     * @return s set with all areas, never {@code null}.
-     */
-    public static Function<Configuration,Set<String>> getAreas(final Predicate<String> predicate) {
-        return config -> {
-            return config.query(getAreas()).stream().filter(predicate).collect(Collectors.toCollection(TreeSet::new));
-        };
-    }
-
-    /**
-     * Return a query to evaluate the set with all fully qualified area names, containing the transitive closure also including all
-     * subarea names, regardless if properties are accessible or not. This method should return the areas as accurate as possible,
-     * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
-     * does not support key iteration.
-     *
-     * @param predicate A predicate to deternine, which areas should be returned, not {@code null}.
-     * @return s set with all transitive areas, never {@code null}.
-     */
-    public static Function<Configuration,Set<String>> getTransitiveAreas(Predicate<String> predicate) {
-        return config -> {
-            return config.query(getTransitiveAreas()).stream().filter(predicate).collect(Collectors.toCollection(TreeSet::new));
-        };
-    }
-
-    /**
-     * Return a query to evaluate to evaluate if an area exists. In case where the underlying storage implementation does not allow
-     * querying the keys available, {@code false} should be returned.
-     *
-     * @param areaKey the configuration area (sub)path.
-     * @return {@code true}, if such a node exists.
-     */
-    public static Function<Configuration,Boolean> containsArea(String areaKey) {
-        return config -> {
-            return config.query(getAreas()).contains(areaKey);
-        };
-    }
-
-    /**
-     * Creates a ConfigOperator that creates a Configuration containing only keys
-     * that are contained in the given area (recursive). Hereby
-     * the area key is stripped away fromMap the resulting key.
-     *
-     * @param areaKey the area key, not null
-     * @return the area configuration, with the areaKey stripped away.
-     */
-    public static UnaryOperator<Configuration> selectAreaRecursive(String areaKey) {
-        return selectAreaRecursive(areaKey, true);
-    }
-
-    /**
-     * Creates a ConfigOperator that creates a Configuration containing only keys
-     * that are contained in the given area (recursive).
-     *
-     * @param areaKey   the area key, not null
-     * @param stripKeys if set to true, the area key is stripped away fromMap the resulting key.
-     * @return the area configuration, with the areaKey stripped away.
-     */
-    public static UnaryOperator<Configuration> selectAreaRecursive(String areaKey, boolean stripKeys) {
-        return config -> {
-            Map<String, String> area = new HashMap<>();
-            String lookupKey = areaKey + '.';
-            area.putAll(
-                    config.getProperties().entrySet().stream()
-                            .filter(e -> e.getKey().startsWith(lookupKey))
-                            .collect(Collectors.toMap(
-                                    e -> stripKeys ? e.getKey().substring(areaKey.length() + 1) : e.getKey(),
-                                    Map.Entry::getValue)));
-            return Configuration.from(PropertySourceBuilder.of("area (recursive): " + areaKey).addMap(area).build());
-        };
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java b/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
deleted file mode 100644
index cf94d99..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.core.resource.Resource;
-import org.apache.tamaya.core.spi.ConfigurationFormatSpi;
-import org.apache.tamaya.spi.ServiceContext;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Implementations current this class encapsulate the mechanism how to read a
- * resource URI including interpreting the format correctly (e.g. xml vs.
- * properties).
- */
-public interface ConfigurationFormat{
-
-    /**
-     * Returns a unique identifier that identifies each format.
-     *
-     * @return the unique format id, mever null.
-     */
-    public String getFormatName();
-
-    /**
-     * Check if the given {@link java.net.URI} and path xpression qualify that this format should be
-     * able to read them, e.g. checking for compatible file endings.
-     *
-     * @param resource   the configuration location, not null
-     * @return {@code true} if the given resource is in a format supported by
-     * this instance.
-     */
-    boolean isAccepted(Resource resource);
-
-    /**
-     * Reads a {@link org.apache.tamaya.PropertySource} fromMap the given URI, using this format.
-     *
-     * @param resource    the configuration location, not null
-     * @return the corresponding {@link java.util.Map}, never {@code null}.
-     */
-    Map<String,String> readConfiguration(Resource resource);
-
-    /**
-     * Access a {@link ConfigurationFormat}.
-     *
-     * @param formatName the format name
-     * @return the corresponding {@link ConfigurationFormat}, or {@code null}, if
-     * not available for the given environment.
-     */
-    public static ConfigurationFormat of(String formatName){
-        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormat(formatName);
-    }
-
-    /**
-     * Get a collection current the keys current the registered {@link ConfigurationFormat} instances.
-     *
-     * @return a collection current the keys current the registered {@link ConfigurationFormat} instances.
-     */
-    public static Collection<String> getFormatNames(){
-        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormatNames();
-    }
-
-    /**
-     * Evaluate the matching format for a given resource.
-     *
-     * @param resource The resource
-     * @return a matching configuration format, or {@code null} if no matching format could be determined.
-     */
-    public static ConfigurationFormat from(Resource resource){
-        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormat(resource);
-
-    }
-
-    /**
-     * Get an instance for reading configuration fromMap a {@code .properties} file,
-     * as defined by {@link java.util.Properties#load(java.io.InputStream)}.
-     *
-     * @return a format instance for reading configuration fromMap a {@code .properties} file, never null.
-     */
-    public static ConfigurationFormat getPropertiesFormat(){
-        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getPropertiesFormat();
-    }
-
-    /**
-     * Get an instance for reading configuration fromMap a {@code .xml} properties file,
-     * as defined by {@link java.util.Properties#loadFromXML(java.io.InputStream)}.
-     *
-     * @return a format instance for reading configuration fromMap a {@code .xml} properties file, never null.
-     */
-    public static ConfigurationFormat getXmlPropertiesFormat(){
-        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getXmlPropertiesFormat();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java b/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
deleted file mode 100644
index 743655e..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.*;
-
-import java.io.Serializable;
-import java.util.Map;
-
-/**
- * Configuration implementation that stores all current values current a given (possibly dynamic, contextual and non remote
- * capable instance) and is fully serializable.
- */
-final class FrozenPropertySource extends AbstractPropertySource implements Serializable{
-    private static final long serialVersionUID = -6373137316556444171L;
-
-    private PropertySource properties;
-
-    /**
-     * Constructor.
-     * @param config The base configuration.
-     */
-    private FrozenPropertySource(PropertySource config){
-        super(config.getName());
-        this.properties = PropertySourceBuilder.of(config).buildFrozen();
-    }
-
-    public static final PropertySource of(PropertySource config){
-        if(config instanceof FrozenPropertySource){
-            return config;
-        }
-        return new FrozenPropertySource(config);
-    }
-
-    @Override
-    public Map<String,String> getProperties(){
-        return properties.getProperties();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        FrozenPropertySource that = (FrozenPropertySource) o;
-
-        if (!properties.equals(that.properties)) return false;
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = properties.hashCode();
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "FreezedConfiguration{" +
-                "properties=" + properties +
-                ", name=" + name +
-                '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java b/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
deleted file mode 100644
index 160d6c4..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.apache.tamaya.core.properties;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.UnaryOperator;
-
-import org.apache.tamaya.Configuration;
-import org.apache.tamaya.PropertySource;
-import org.apache.tamaya.core.properties.AbstractPropertySource;
-
-/**
- * PropertySource implementation that maps certain parts (defined by an {@code UnaryOperator<String>}) to alternate areas.
- */
-class MappedPropertySource extends AbstractPropertySource {
-
-	private static final long serialVersionUID = 8690637705511432083L;
-
-	/** The mapping operator. */
-    private UnaryOperator<String> keyMapper;
-    /** The base configuration. */
-    private PropertySource config;
-
-    /**
-     * Creates a new instance.
-     * @param config the base configuration, not null
-     * @param keyMapper The mapping operator, not null
-     */
-    public MappedPropertySource(PropertySource config, UnaryOperator<String> keyMapper) {
-        super(config.getName());
-        this.config = Objects.requireNonNull(config);
-        this.keyMapper = Objects.requireNonNull(keyMapper);
-    }
-
-    @Override
-    public Map<String, String> getProperties() {
-        Map<String, String> result = new HashMap<>();
-        Map<String, String> map = this.config.getProperties();
-        map.forEach((k,v) -> {
-            String targetKey = keyMapper.apply(k);
-            if(targetKey!=null){
-                result.put(targetKey, v);
-            }
-        });
-        return result;
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return this.config.isEmpty();
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java b/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
deleted file mode 100644
index 3cf6b31..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.PropertySource;
-
-import java.beans.PropertyChangeEvent;
-import java.io.Serializable;
-import java.util.*;
-
-/**
- * Event that contains a set current changes that were applied or could be applied.
- * This class is immutable and thread-safe. To create instances use
- * {@link PropertyChangeSetBuilder}.
- *
- * Created by Anatole on 22.10.2014.
- */
-public final class PropertyChangeSet implements Serializable{
-
-    private static final long serialVersionUID = 1l;
-    /** The base property provider/configuration. */
-    private PropertySource propertySource;
-    /** The base version, usable for optimistic locking. */
-    private String baseVersion;
-    /** The recorded changes. */
-    private Map<String,PropertyChangeEvent> changes = new HashMap<>();
-
-    /**
-     * Get an empty change set for the given provider.
-     * @param propertyProvider The base property provider/configuration, not null.
-     * @return an empty ConfigChangeSet instance.
-     */
-    public static PropertyChangeSet emptyChangeSet(PropertySource propertyProvider){
-        return new PropertyChangeSet(propertyProvider, Collections.emptySet());
-    }
-
-    /**
-     * Constructor used by {@link PropertyChangeSetBuilder}.
-     * @param propertySource The base property provider/configuration, not null.
-     * @param changes The recorded changes, not null.
-     */
-    PropertyChangeSet(PropertySource propertySource, Collection<PropertyChangeEvent> changes) {
-        this.propertySource = Objects.requireNonNull(propertySource);
-        changes.forEach((c) -> this.changes.put(c.getPropertyName(), c));
-    }
-
-    /**
-     * Get the underlying property provider/configuration.
-     * @return the underlying property provider/configuration, never null.
-     */
-    public PropertySource getPropertySource(){
-        return this.propertySource;
-    }
-
-    /**
-     * Get the base version, usable for optimistic locking.
-     * @return the base version.
-     */
-    public String getBaseVersion(){
-        return baseVersion;
-    }
-
-    /**
-     * Get the changes recorded.
-     * @return the recorded changes, never null.
-     */
-    public Collection<PropertyChangeEvent> getEvents(){
-        return Collections.unmodifiableCollection(this.changes.values());
-    }
-
-    /**
-     * Access the number current removed entries.
-     * @return the number current removed entries.
-     */
-    public int getRemovedSize() {
-        return (int) this.changes.values().stream().filter((e) -> e.getNewValue() == null).count();
-    }
-
-    /**
-     * Access the number current added entries.
-     * @return the number current added entries.
-     */
-    public int getAddedSize() {
-        return (int) this.changes.values().stream().filter((e) -> e.getOldValue() == null).count();
-    }
-
-    /**
-     * Access the number current updated entries.
-     * @return the number current updated entries.
-     */
-    public int getUpdatedSize() {
-        return (int) this.changes.values().stream().filter((e) -> e.getOldValue()!=null && e.getNewValue()!=null).count();
-    }
-
-
-    /**
-     * Checks if the given key was removed.
-     * @param key the target key, not null.
-     * @return true, if the given key was removed.
-     */
-    public boolean isRemoved(String key) {
-        PropertyChangeEvent change = this.changes.get(key);
-        return change != null && change.getNewValue() == null;
-    }
-
-    /**
-     * Checks if the given key was added.
-     * @param key the target key, not null.
-     * @return true, if the given key was added.
-     */
-    public boolean isAdded(String key) {
-        PropertyChangeEvent change = this.changes.get(key);
-        return change != null && change.getOldValue() == null;
-    }
-
-    /**
-     * Checks if the given key was updated.
-     * @param key the target key, not null.
-     * @return true, if the given key was updated.
-     */
-    public boolean isUpdated(String key) {
-        PropertyChangeEvent change = this.changes.get(key);
-        return change != null && change.getOldValue() != null && change.getNewValue() != null;
-    }
-
-    /**
-     * Checks if the given key is added, or updated AND NOT removed.
-     * @param key the target key, not null.
-     * @return true, if the given key was added, or updated BUT NOT removed.
-     */
-    public boolean containsKey(String key) {
-        PropertyChangeEvent change = this.changes.get(key);
-        return change != null && change.getNewValue() != null;
-    }
-
-    /**
-     * CHecks if the current change set does not contain any changes.
-     * @return tru, if the change set is empty.
-     */
-    public boolean isEmpty(){
-        return this.changes.isEmpty();
-    }
-
-
-    @Override
-    public String toString() {
-        return "ConfigChangeSet{" +
-                "properties=" + propertySource +
-                ", baseVersion=" + baseVersion +
-                ", changes=" + changes +
-                '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java b/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
deleted file mode 100644
index b6e22f8..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.PropertySource;
-
-import java.beans.PropertyChangeEvent;
-import java.util.*;
-import java.util.function.Function;
-
-/**
- * Models a set current changes to be applied to a configuration/property provider.  Such a set can be applied
- * to any {@link org.apache.tamaya.PropertySource} instance. If the provider is mutable it may check the
- * version given and applyChanges the changes to the provider/configuration, including triggering current regarding
- * change events.
- * <p>
- * For appropriate conversion a {@code Function<String, Codec>} can be applied, which performs correct conversion,
- * when changed values are set. This function enables connecting e.g. setters on a configuration template with
- * the corresponding conversion logic, so the template calls are correctly converted back.
- */
-public final class PropertyChangeSetBuilder {
-    /**
-     * The recorded changes.
-     */
-    final SortedMap<String, PropertyChangeEvent> delta = new TreeMap<>();
-    /**
-     * The underlying configuration/provider.
-     */
-    PropertySource source;
-
-    /**
-     * Constructor.
-     *
-     * @param source      the underlying configuration/provider, not null.
-     */
-    private PropertyChangeSetBuilder(PropertySource source) {
-        this.source = Objects.requireNonNull(source);
-    }
-
-    /**
-     * Creates a new instance current this builder.
-     *
-     * @param source the underlying property provider/configuration, not null.
-     * @return the builder for chaining.
-     */
-    public static PropertyChangeSetBuilder of(PropertySource source) {
-        return new PropertyChangeSetBuilder(source);
-    }
-
-    /**
-     * This method records all changes to be applied to the base property provider/configuration to
-     * achieve the given target state.
-     *
-     * @param newState the new target state, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder addChanges(PropertySource newState) {
-        compare(newState, this.source).forEach((c) -> this.delta.put(c.getPropertyName(), c));
-        return this;
-    }
-
-    /**
-     * Get the current values, also considering any changes recorded within this change set.
-     *
-     * @param key the key current the entry, not null.
-     * @return the keys, or null.
-     */
-    public String get(String key) {
-        PropertyChangeEvent change = this.delta.get(key);
-        if (change != null && !(change.getNewValue() == null)) {
-            return (String) change.getNewValue();
-        }
-        return null;
-    }
-
-    /**
-     * Marks the given key(s) fromMap the configuration/properties to be removed.
-     *
-     * @param key       the key current the entry, not null.
-     * @param otherKeys additional keys to be removed (convenience), not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder remove(String key, String... otherKeys) {
-        String oldValue = this.source.get(key).orElse(null);
-        if (oldValue == null) {
-            this.delta.remove(key);
-        }
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, oldValue, null));
-        for (String addKey : otherKeys) {
-            oldValue = this.source.get(addKey).orElse(null);
-            if (oldValue == null) {
-                this.delta.remove(addKey);
-            }
-            this.delta.put(addKey, new PropertyChangeEvent(this.source, addKey, oldValue, null));
-        }
-        return this;
-    }
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder put(String key, boolean value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
-        return this;
-    }
-
-    /**
-     s* Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder put(String key, byte value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
-        return this;
-    }
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder put(String key, char value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
-        return this;
-    }
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder put(String key, short value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
-        return this;
-    }
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder put(String key, int value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
-        return this;
-    }
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder put(String key, long value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
-        return this;
-    }
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder put(String key, float value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
-        return this;
-    }
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder put(String key, double value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
-        return this;
-    }
-
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder put(String key, String value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
-        return this;
-    }
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @return the builder for chaining.
-     * @throws org.apache.tamaya.ConfigException if no matching Codec could be found.
-     */
-    public <T> PropertyChangeSetBuilder put(String key, Class<T> type, T value) {
-        put(key, type, value, null);
-        return this;
-    }
-
-    /**
-     * Applies the given keys.
-     *
-     * @param key   the key current the entry, not null.
-     * @param value the keys to be applied, not null.
-     * @param adapter the codec to be used, if set overrides any other codecs that may apply. If null an appropriate
-     *              codec is tried to be evaluated as needed.
-     * @return the builder for chaining.
-     * @throws org.apache.tamaya.ConfigException if no matching Codec could be found.
-     */
-    public <T> PropertyChangeSetBuilder put(String key, Class<T> type, T value, Function<T,String> adapter) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), adapter.apply(Objects.requireNonNull(value))));
-        return this;
-    }
-
-
-    /**
-     * Apply all the given values to the base configuration/properties.
-     * Note that all values passed must be convertible to String, either
-     * <ul>
-     * <li>the registered codecs provider provides codecs for the corresponding keys, or </li>
-     * <li>default codecs are present for the given type, or</li>
-     * <li>the value is an instanceof String</li>
-     * </ul>
-     *
-     * @param changes the changes to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder putAll(Map<String, String> changes) {
-        changes.putAll(changes);
-        return this;
-    }
-
-    /**
-     * This method will create a change set that clears all entries fromMap the given base configuration/properties.
-     *
-     * @return the builder for chaining.
-     */
-    public PropertyChangeSetBuilder deleteAll() {
-        this.delta.clear();
-        this.source.getProperties().forEach((k, v) ->
-                this.delta.put(k, new PropertyChangeEvent(this.source, k, v, null)));
-        return this;
-    }
-
-    /**
-     * Checks if the change set is empty, i.e. does not contain any changes.
-     *
-     * @return true, if the set is empty.
-     */
-    public boolean isEmpty() {
-        return this.delta.isEmpty();
-    }
-
-    /**
-     * Resets this change set instance. This will clear all changes done to this builder, so the
-     * set will be empty.
-     */
-    public void reset() {
-        this.delta.clear();
-    }
-
-    /**
-     * Builds the corresponding change set.
-     *
-     * @return the new change set, never null.
-     */
-    public PropertyChangeSet build() {
-        return new PropertyChangeSet(this.source, Collections.unmodifiableCollection(this.delta.values()));
-    }
-
-    /**
-     * Compares the two property config/configurations and creates a collection current all changes
-     * that must be appied to render {@code map1} into {@code map2}.
-     *
-     * @param map1 the source map, not null.
-     * @param map2 the target map, not null.
-     * @return a collection current change events, never null.
-     */
-    public static Collection<PropertyChangeEvent> compare(PropertySource map1, PropertySource map2) {
-        List<PropertyChangeEvent> changes = new ArrayList<>();
-        for (Map.Entry<String, String> en : map1.getProperties().entrySet()) {
-            Optional<String> val = map2.get(en.getKey());
-            if (!val.isPresent()) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
-            } else if (!val.get().equals(en.getValue())) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), val.get(), en.getValue()));
-            }
-        }
-        for (Map.Entry<String, String> en : map2.getProperties().entrySet()) {
-            Optional<String> val = map1.get(en.getKey());
-            if (!val.isPresent()) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
-            } else if (!val.equals(Optional.ofNullable(en.getValue()))) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), val.get(), en.getValue()));
-            }
-        }
-        return changes;
-    }
-
-    /*
-     * (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "PropertyChangeEventBuilder [source=" + source + ", " +
-                ", delta=" + delta + "]";
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java b/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java
deleted file mode 100644
index 5fcf895..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.PropertySource;
-
-import java.util.*;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-import java.util.stream.Collectors;
-
-/**
- * Accessor that provides useful functions along with configuration.
- */
-public final class PropertySourceFunctions {
-    /**
-     * Private singleton constructor.
-     */
-    private PropertySourceFunctions() {
-    }
-
-    /**
-     * Creates a ConfigOperator that creates a Configuration containing only keys
-     * that are contained in the given area (non recursive). Hereby
-     * the area key is stripped away fromMap the resulting key.
-     *
-     * @param areaKey       the area key, not null
-     * @param mappedAreaKey the target key, not null
-     * @return the area configuration, with the areaKey stripped away.
-     */
-    public static UnaryOperator<PropertySource> mapArea(String areaKey, String mappedAreaKey) {
-        return mapKeys(key -> key.startsWith(areaKey + '.') ?
-                mappedAreaKey + key.substring(areaKey.length()) : key);
-    }
-
-    /**
-     * Creates a {@link java.util.function.UnaryOperator} that creates a {@link org.apache.tamaya.Configuration} that maps any keys as
-     * defined by the {@code keyMapper} given. If the {@code keyMapper} returns
-     * {@code null} for a keys, it is removed from the resulting map.
-     *
-     * @param keyMapper the key mapper, not null
-     * @return the area configuration, with the areaKey stripped away.
-     */
-    public static UnaryOperator<PropertySource> mapKeys(UnaryOperator<String> keyMapper) {
-        return (c) -> new MappedPropertySource(c, keyMapper);
-    }
-
-}

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

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java b/dormant/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
new file mode 100644
index 0000000..b1c2522
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
@@ -0,0 +1,213 @@
+/*
+ * 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;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.core.properties.PropertySourceBuilder;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import java.util.stream.Collectors;
+
+/**
+ * Accessor that provides useful functions along with configuration.
+ */
+public final class ConfigurationFunctions {
+    /**
+     * Private singleton constructor.
+     */
+    private ConfigurationFunctions() {
+    }
+
+    /**
+     * Creates a ConfigOperator that creates a Configuration containing only keys
+     * that are contained in the given area (non recursive). Hereby
+     * the area key is stripped away fromMap the resulting key.
+     *
+     * @param areaKey the area key, not null
+     * @return the area configuration, with the areaKey stripped away.
+     */
+    public static UnaryOperator<Configuration> selectArea(String areaKey) {
+        return selectArea(areaKey, true);
+    }
+
+    /**
+     * Creates a ConfigOperator that creates a Configuration containing only keys
+     * that are contained in the given area (non recursive).
+     *
+     * @param areaKey   the area key, not null
+     * @param stripKeys if set to true, the area key is stripped away fromMap the resulting key.
+     * @return the area configuration, with the areaKey stripped away.
+     */
+    public static UnaryOperator<Configuration> selectArea(String areaKey, boolean stripKeys) {
+        return config -> {
+            Map<String, String> area = new HashMap<>();
+            area.putAll(
+                    config.getProperties().entrySet().stream()
+                            .filter(e -> isKeyInArea(e.getKey(), areaKey))
+                            .collect(Collectors.toMap(
+                                    e -> stripKeys ? e.getKey().substring(areaKey.length() + 1) : e.getKey(),
+                                    Map.Entry::getValue)));
+            return Configuration.from(PropertySourceBuilder.of("area: " + areaKey).addMap(area).build());
+        };
+    }
+
+    /**
+     * Calculates the current area key and compares it with the given key.
+     *
+     * @param key     the fully qualified entry key, not null
+     * @param areaKey the area key, not null
+     * @return true, if the entry is exact in this area
+     */
+    public static boolean isKeyInArea(String key, String areaKey) {
+        int lastIndex = key.lastIndexOf('.');
+        String curAreaKey = lastIndex > 0 ? key.substring(0, lastIndex) : "";
+        return curAreaKey.equals(areaKey);
+    }
+
+    /**
+     * Return a query to evaluate the set with all fully qualifies area names. This method should return the areas as accurate as possible,
+     * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
+     * does not support key iteration.
+     *
+     * @return s set with all areas, never {@code null}.
+     */
+    public static Function<Configuration,Set<String>> getAreas() {
+        return config -> {
+            final Set<String> areas = new HashSet<>();
+            config.getProperties().keySet().forEach(s -> {
+                int index = s.lastIndexOf('.');
+                if (index > 0) {
+                    areas.add(s.substring(0, index));
+                } else {
+                    areas.add("<root>");
+                }
+            });
+            return areas;
+        };
+    }
+
+    /**
+     * Return a query to evaluate the set with all fully qualified area names, containing the transitive closure also including all
+     * subarea names, regardless if properties are accessible or not. This method should return the areas as accurate
+     * as possible, but may not provide a complete set of areas that are finally accessible, especially when the
+     * underlying storage does not support key iteration.
+     *
+     * @return s set with all transitive areas, never {@code null}.
+     */
+    public static Function<Configuration,Set<String>> getTransitiveAreas() {
+        return config -> {
+            final Set<String> transitiveAreas = new HashSet<>();
+            config.query(getAreas()).forEach(s -> {
+                int index = s.lastIndexOf('.');
+                if (index < 0) {
+                    transitiveAreas.add("<root>");
+                } else {
+                    while (index > 0) {
+                        s = s.substring(0, index);
+                        transitiveAreas.add(s);
+                        index = s.lastIndexOf('.');
+                    }
+                }
+            });
+            return transitiveAreas;
+        };
+    }
+
+    /**
+     * Return a query to evaluate the set with all fully qualified area names, containing only the
+     * areas that match the predicate and have properties attached. This method should return the areas as accurate as possible,
+     * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
+     * does not support key iteration.
+     *
+     * @param predicate A predicate to deternine, which areas should be returned, not {@code null}.
+     * @return s set with all areas, never {@code null}.
+     */
+    public static Function<Configuration,Set<String>> getAreas(final Predicate<String> predicate) {
+        return config -> {
+            return config.query(getAreas()).stream().filter(predicate).collect(Collectors.toCollection(TreeSet::new));
+        };
+    }
+
+    /**
+     * Return a query to evaluate the set with all fully qualified area names, containing the transitive closure also including all
+     * subarea names, regardless if properties are accessible or not. This method should return the areas as accurate as possible,
+     * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
+     * does not support key iteration.
+     *
+     * @param predicate A predicate to deternine, which areas should be returned, not {@code null}.
+     * @return s set with all transitive areas, never {@code null}.
+     */
+    public static Function<Configuration,Set<String>> getTransitiveAreas(Predicate<String> predicate) {
+        return config -> {
+            return config.query(getTransitiveAreas()).stream().filter(predicate).collect(Collectors.toCollection(TreeSet::new));
+        };
+    }
+
+    /**
+     * Return a query to evaluate to evaluate if an area exists. In case where the underlying storage implementation does not allow
+     * querying the keys available, {@code false} should be returned.
+     *
+     * @param areaKey the configuration area (sub)path.
+     * @return {@code true}, if such a node exists.
+     */
+    public static Function<Configuration,Boolean> containsArea(String areaKey) {
+        return config -> {
+            return config.query(getAreas()).contains(areaKey);
+        };
+    }
+
+    /**
+     * Creates a ConfigOperator that creates a Configuration containing only keys
+     * that are contained in the given area (recursive). Hereby
+     * the area key is stripped away fromMap the resulting key.
+     *
+     * @param areaKey the area key, not null
+     * @return the area configuration, with the areaKey stripped away.
+     */
+    public static UnaryOperator<Configuration> selectAreaRecursive(String areaKey) {
+        return selectAreaRecursive(areaKey, true);
+    }
+
+    /**
+     * Creates a ConfigOperator that creates a Configuration containing only keys
+     * that are contained in the given area (recursive).
+     *
+     * @param areaKey   the area key, not null
+     * @param stripKeys if set to true, the area key is stripped away fromMap the resulting key.
+     * @return the area configuration, with the areaKey stripped away.
+     */
+    public static UnaryOperator<Configuration> selectAreaRecursive(String areaKey, boolean stripKeys) {
+        return config -> {
+            Map<String, String> area = new HashMap<>();
+            String lookupKey = areaKey + '.';
+            area.putAll(
+                    config.getProperties().entrySet().stream()
+                            .filter(e -> e.getKey().startsWith(lookupKey))
+                            .collect(Collectors.toMap(
+                                    e -> stripKeys ? e.getKey().substring(areaKey.length() + 1) : e.getKey(),
+                                    Map.Entry::getValue)));
+            return Configuration.from(PropertySourceBuilder.of("area (recursive): " + areaKey).addMap(area).build());
+        };
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
new file mode 100644
index 0000000..cf94d99
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.properties;
+
+import org.apache.tamaya.core.resource.Resource;
+import org.apache.tamaya.core.spi.ConfigurationFormatSpi;
+import org.apache.tamaya.spi.ServiceContext;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Implementations current this class encapsulate the mechanism how to read a
+ * resource URI including interpreting the format correctly (e.g. xml vs.
+ * properties).
+ */
+public interface ConfigurationFormat{
+
+    /**
+     * Returns a unique identifier that identifies each format.
+     *
+     * @return the unique format id, mever null.
+     */
+    public String getFormatName();
+
+    /**
+     * Check if the given {@link java.net.URI} and path xpression qualify that this format should be
+     * able to read them, e.g. checking for compatible file endings.
+     *
+     * @param resource   the configuration location, not null
+     * @return {@code true} if the given resource is in a format supported by
+     * this instance.
+     */
+    boolean isAccepted(Resource resource);
+
+    /**
+     * Reads a {@link org.apache.tamaya.PropertySource} fromMap the given URI, using this format.
+     *
+     * @param resource    the configuration location, not null
+     * @return the corresponding {@link java.util.Map}, never {@code null}.
+     */
+    Map<String,String> readConfiguration(Resource resource);
+
+    /**
+     * Access a {@link ConfigurationFormat}.
+     *
+     * @param formatName the format name
+     * @return the corresponding {@link ConfigurationFormat}, or {@code null}, if
+     * not available for the given environment.
+     */
+    public static ConfigurationFormat of(String formatName){
+        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormat(formatName);
+    }
+
+    /**
+     * Get a collection current the keys current the registered {@link ConfigurationFormat} instances.
+     *
+     * @return a collection current the keys current the registered {@link ConfigurationFormat} instances.
+     */
+    public static Collection<String> getFormatNames(){
+        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormatNames();
+    }
+
+    /**
+     * Evaluate the matching format for a given resource.
+     *
+     * @param resource The resource
+     * @return a matching configuration format, or {@code null} if no matching format could be determined.
+     */
+    public static ConfigurationFormat from(Resource resource){
+        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormat(resource);
+
+    }
+
+    /**
+     * Get an instance for reading configuration fromMap a {@code .properties} file,
+     * as defined by {@link java.util.Properties#load(java.io.InputStream)}.
+     *
+     * @return a format instance for reading configuration fromMap a {@code .properties} file, never null.
+     */
+    public static ConfigurationFormat getPropertiesFormat(){
+        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getPropertiesFormat();
+    }
+
+    /**
+     * Get an instance for reading configuration fromMap a {@code .xml} properties file,
+     * as defined by {@link java.util.Properties#loadFromXML(java.io.InputStream)}.
+     *
+     * @return a format instance for reading configuration fromMap a {@code .xml} properties file, never null.
+     */
+    public static ConfigurationFormat getXmlPropertiesFormat(){
+        return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getXmlPropertiesFormat();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
new file mode 100644
index 0000000..743655e
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.properties;
+
+import org.apache.tamaya.*;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * Configuration implementation that stores all current values current a given (possibly dynamic, contextual and non remote
+ * capable instance) and is fully serializable.
+ */
+final class FrozenPropertySource extends AbstractPropertySource implements Serializable{
+    private static final long serialVersionUID = -6373137316556444171L;
+
+    private PropertySource properties;
+
+    /**
+     * Constructor.
+     * @param config The base configuration.
+     */
+    private FrozenPropertySource(PropertySource config){
+        super(config.getName());
+        this.properties = PropertySourceBuilder.of(config).buildFrozen();
+    }
+
+    public static final PropertySource of(PropertySource config){
+        if(config instanceof FrozenPropertySource){
+            return config;
+        }
+        return new FrozenPropertySource(config);
+    }
+
+    @Override
+    public Map<String,String> getProperties(){
+        return properties.getProperties();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        FrozenPropertySource that = (FrozenPropertySource) o;
+
+        if (!properties.equals(that.properties)) return false;
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = properties.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "FreezedConfiguration{" +
+                "properties=" + properties +
+                ", name=" + name +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
new file mode 100644
index 0000000..160d6c4
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
@@ -0,0 +1,53 @@
+package org.apache.tamaya.core.properties;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.UnaryOperator;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.PropertySource;
+import org.apache.tamaya.core.properties.AbstractPropertySource;
+
+/**
+ * PropertySource implementation that maps certain parts (defined by an {@code UnaryOperator<String>}) to alternate areas.
+ */
+class MappedPropertySource extends AbstractPropertySource {
+
+	private static final long serialVersionUID = 8690637705511432083L;
+
+	/** The mapping operator. */
+    private UnaryOperator<String> keyMapper;
+    /** The base configuration. */
+    private PropertySource config;
+
+    /**
+     * Creates a new instance.
+     * @param config the base configuration, not null
+     * @param keyMapper The mapping operator, not null
+     */
+    public MappedPropertySource(PropertySource config, UnaryOperator<String> keyMapper) {
+        super(config.getName());
+        this.config = Objects.requireNonNull(config);
+        this.keyMapper = Objects.requireNonNull(keyMapper);
+    }
+
+    @Override
+    public Map<String, String> getProperties() {
+        Map<String, String> result = new HashMap<>();
+        Map<String, String> map = this.config.getProperties();
+        map.forEach((k,v) -> {
+            String targetKey = keyMapper.apply(k);
+            if(targetKey!=null){
+                result.put(targetKey, v);
+            }
+        });
+        return result;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return this.config.isEmpty();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
new file mode 100644
index 0000000..3cf6b31
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.properties;
+
+import org.apache.tamaya.PropertySource;
+
+import java.beans.PropertyChangeEvent;
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Event that contains a set current changes that were applied or could be applied.
+ * This class is immutable and thread-safe. To create instances use
+ * {@link PropertyChangeSetBuilder}.
+ *
+ * Created by Anatole on 22.10.2014.
+ */
+public final class PropertyChangeSet implements Serializable{
+
+    private static final long serialVersionUID = 1l;
+    /** The base property provider/configuration. */
+    private PropertySource propertySource;
+    /** The base version, usable for optimistic locking. */
+    private String baseVersion;
+    /** The recorded changes. */
+    private Map<String,PropertyChangeEvent> changes = new HashMap<>();
+
+    /**
+     * Get an empty change set for the given provider.
+     * @param propertyProvider The base property provider/configuration, not null.
+     * @return an empty ConfigChangeSet instance.
+     */
+    public static PropertyChangeSet emptyChangeSet(PropertySource propertyProvider){
+        return new PropertyChangeSet(propertyProvider, Collections.emptySet());
+    }
+
+    /**
+     * Constructor used by {@link PropertyChangeSetBuilder}.
+     * @param propertySource The base property provider/configuration, not null.
+     * @param changes The recorded changes, not null.
+     */
+    PropertyChangeSet(PropertySource propertySource, Collection<PropertyChangeEvent> changes) {
+        this.propertySource = Objects.requireNonNull(propertySource);
+        changes.forEach((c) -> this.changes.put(c.getPropertyName(), c));
+    }
+
+    /**
+     * Get the underlying property provider/configuration.
+     * @return the underlying property provider/configuration, never null.
+     */
+    public PropertySource getPropertySource(){
+        return this.propertySource;
+    }
+
+    /**
+     * Get the base version, usable for optimistic locking.
+     * @return the base version.
+     */
+    public String getBaseVersion(){
+        return baseVersion;
+    }
+
+    /**
+     * Get the changes recorded.
+     * @return the recorded changes, never null.
+     */
+    public Collection<PropertyChangeEvent> getEvents(){
+        return Collections.unmodifiableCollection(this.changes.values());
+    }
+
+    /**
+     * Access the number current removed entries.
+     * @return the number current removed entries.
+     */
+    public int getRemovedSize() {
+        return (int) this.changes.values().stream().filter((e) -> e.getNewValue() == null).count();
+    }
+
+    /**
+     * Access the number current added entries.
+     * @return the number current added entries.
+     */
+    public int getAddedSize() {
+        return (int) this.changes.values().stream().filter((e) -> e.getOldValue() == null).count();
+    }
+
+    /**
+     * Access the number current updated entries.
+     * @return the number current updated entries.
+     */
+    public int getUpdatedSize() {
+        return (int) this.changes.values().stream().filter((e) -> e.getOldValue()!=null && e.getNewValue()!=null).count();
+    }
+
+
+    /**
+     * Checks if the given key was removed.
+     * @param key the target key, not null.
+     * @return true, if the given key was removed.
+     */
+    public boolean isRemoved(String key) {
+        PropertyChangeEvent change = this.changes.get(key);
+        return change != null && change.getNewValue() == null;
+    }
+
+    /**
+     * Checks if the given key was added.
+     * @param key the target key, not null.
+     * @return true, if the given key was added.
+     */
+    public boolean isAdded(String key) {
+        PropertyChangeEvent change = this.changes.get(key);
+        return change != null && change.getOldValue() == null;
+    }
+
+    /**
+     * Checks if the given key was updated.
+     * @param key the target key, not null.
+     * @return true, if the given key was updated.
+     */
+    public boolean isUpdated(String key) {
+        PropertyChangeEvent change = this.changes.get(key);
+        return change != null && change.getOldValue() != null && change.getNewValue() != null;
+    }
+
+    /**
+     * Checks if the given key is added, or updated AND NOT removed.
+     * @param key the target key, not null.
+     * @return true, if the given key was added, or updated BUT NOT removed.
+     */
+    public boolean containsKey(String key) {
+        PropertyChangeEvent change = this.changes.get(key);
+        return change != null && change.getNewValue() != null;
+    }
+
+    /**
+     * CHecks if the current change set does not contain any changes.
+     * @return tru, if the change set is empty.
+     */
+    public boolean isEmpty(){
+        return this.changes.isEmpty();
+    }
+
+
+    @Override
+    public String toString() {
+        return "ConfigChangeSet{" +
+                "properties=" + propertySource +
+                ", baseVersion=" + baseVersion +
+                ", changes=" + changes +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
new file mode 100644
index 0000000..b6e22f8
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
@@ -0,0 +1,347 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.properties;
+
+import org.apache.tamaya.PropertySource;
+
+import java.beans.PropertyChangeEvent;
+import java.util.*;
+import java.util.function.Function;
+
+/**
+ * Models a set current changes to be applied to a configuration/property provider.  Such a set can be applied
+ * to any {@link org.apache.tamaya.PropertySource} instance. If the provider is mutable it may check the
+ * version given and applyChanges the changes to the provider/configuration, including triggering current regarding
+ * change events.
+ * <p>
+ * For appropriate conversion a {@code Function<String, Codec>} can be applied, which performs correct conversion,
+ * when changed values are set. This function enables connecting e.g. setters on a configuration template with
+ * the corresponding conversion logic, so the template calls are correctly converted back.
+ */
+public final class PropertyChangeSetBuilder {
+    /**
+     * The recorded changes.
+     */
+    final SortedMap<String, PropertyChangeEvent> delta = new TreeMap<>();
+    /**
+     * The underlying configuration/provider.
+     */
+    PropertySource source;
+
+    /**
+     * Constructor.
+     *
+     * @param source      the underlying configuration/provider, not null.
+     */
+    private PropertyChangeSetBuilder(PropertySource source) {
+        this.source = Objects.requireNonNull(source);
+    }
+
+    /**
+     * Creates a new instance current this builder.
+     *
+     * @param source the underlying property provider/configuration, not null.
+     * @return the builder for chaining.
+     */
+    public static PropertyChangeSetBuilder of(PropertySource source) {
+        return new PropertyChangeSetBuilder(source);
+    }
+
+    /**
+     * This method records all changes to be applied to the base property provider/configuration to
+     * achieve the given target state.
+     *
+     * @param newState the new target state, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder addChanges(PropertySource newState) {
+        compare(newState, this.source).forEach((c) -> this.delta.put(c.getPropertyName(), c));
+        return this;
+    }
+
+    /**
+     * Get the current values, also considering any changes recorded within this change set.
+     *
+     * @param key the key current the entry, not null.
+     * @return the keys, or null.
+     */
+    public String get(String key) {
+        PropertyChangeEvent change = this.delta.get(key);
+        if (change != null && !(change.getNewValue() == null)) {
+            return (String) change.getNewValue();
+        }
+        return null;
+    }
+
+    /**
+     * Marks the given key(s) fromMap the configuration/properties to be removed.
+     *
+     * @param key       the key current the entry, not null.
+     * @param otherKeys additional keys to be removed (convenience), not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder remove(String key, String... otherKeys) {
+        String oldValue = this.source.get(key).orElse(null);
+        if (oldValue == null) {
+            this.delta.remove(key);
+        }
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, oldValue, null));
+        for (String addKey : otherKeys) {
+            oldValue = this.source.get(addKey).orElse(null);
+            if (oldValue == null) {
+                this.delta.remove(addKey);
+            }
+            this.delta.put(addKey, new PropertyChangeEvent(this.source, addKey, oldValue, null));
+        }
+        return this;
+    }
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder put(String key, boolean value) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+        return this;
+    }
+
+    /**
+     s* Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder put(String key, byte value) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+        return this;
+    }
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder put(String key, char value) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+        return this;
+    }
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder put(String key, short value) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+        return this;
+    }
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder put(String key, int value) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+        return this;
+    }
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder put(String key, long value) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+        return this;
+    }
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder put(String key, float value) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+        return this;
+    }
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder put(String key, double value) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+        return this;
+    }
+
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder put(String key, String value) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+        return this;
+    }
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @return the builder for chaining.
+     * @throws org.apache.tamaya.ConfigException if no matching Codec could be found.
+     */
+    public <T> PropertyChangeSetBuilder put(String key, Class<T> type, T value) {
+        put(key, type, value, null);
+        return this;
+    }
+
+    /**
+     * Applies the given keys.
+     *
+     * @param key   the key current the entry, not null.
+     * @param value the keys to be applied, not null.
+     * @param adapter the codec to be used, if set overrides any other codecs that may apply. If null an appropriate
+     *              codec is tried to be evaluated as needed.
+     * @return the builder for chaining.
+     * @throws org.apache.tamaya.ConfigException if no matching Codec could be found.
+     */
+    public <T> PropertyChangeSetBuilder put(String key, Class<T> type, T value, Function<T,String> adapter) {
+        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), adapter.apply(Objects.requireNonNull(value))));
+        return this;
+    }
+
+
+    /**
+     * Apply all the given values to the base configuration/properties.
+     * Note that all values passed must be convertible to String, either
+     * <ul>
+     * <li>the registered codecs provider provides codecs for the corresponding keys, or </li>
+     * <li>default codecs are present for the given type, or</li>
+     * <li>the value is an instanceof String</li>
+     * </ul>
+     *
+     * @param changes the changes to be applied, not null.
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder putAll(Map<String, String> changes) {
+        changes.putAll(changes);
+        return this;
+    }
+
+    /**
+     * This method will create a change set that clears all entries fromMap the given base configuration/properties.
+     *
+     * @return the builder for chaining.
+     */
+    public PropertyChangeSetBuilder deleteAll() {
+        this.delta.clear();
+        this.source.getProperties().forEach((k, v) ->
+                this.delta.put(k, new PropertyChangeEvent(this.source, k, v, null)));
+        return this;
+    }
+
+    /**
+     * Checks if the change set is empty, i.e. does not contain any changes.
+     *
+     * @return true, if the set is empty.
+     */
+    public boolean isEmpty() {
+        return this.delta.isEmpty();
+    }
+
+    /**
+     * Resets this change set instance. This will clear all changes done to this builder, so the
+     * set will be empty.
+     */
+    public void reset() {
+        this.delta.clear();
+    }
+
+    /**
+     * Builds the corresponding change set.
+     *
+     * @return the new change set, never null.
+     */
+    public PropertyChangeSet build() {
+        return new PropertyChangeSet(this.source, Collections.unmodifiableCollection(this.delta.values()));
+    }
+
+    /**
+     * Compares the two property config/configurations and creates a collection current all changes
+     * that must be appied to render {@code map1} into {@code map2}.
+     *
+     * @param map1 the source map, not null.
+     * @param map2 the target map, not null.
+     * @return a collection current change events, never null.
+     */
+    public static Collection<PropertyChangeEvent> compare(PropertySource map1, PropertySource map2) {
+        List<PropertyChangeEvent> changes = new ArrayList<>();
+        for (Map.Entry<String, String> en : map1.getProperties().entrySet()) {
+            Optional<String> val = map2.get(en.getKey());
+            if (!val.isPresent()) {
+                changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
+            } else if (!val.get().equals(en.getValue())) {
+                changes.add(new PropertyChangeEvent(map1, en.getKey(), val.get(), en.getValue()));
+            }
+        }
+        for (Map.Entry<String, String> en : map2.getProperties().entrySet()) {
+            Optional<String> val = map1.get(en.getKey());
+            if (!val.isPresent()) {
+                changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
+            } else if (!val.equals(Optional.ofNullable(en.getValue()))) {
+                changes.add(new PropertyChangeEvent(map1, en.getKey(), val.get(), en.getValue()));
+            }
+        }
+        return changes;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "PropertyChangeEventBuilder [source=" + source + ", " +
+                ", delta=" + delta + "]";
+    }
+
+}