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 2016/02/18 00:43:09 UTC

[1/8] incubator-tamaya git commit: Initial version of collections module documentation.

Repository: incubator-tamaya
Updated Branches:
  refs/heads/master f50397f3e -> 8fc95128e


Initial version of collections module documentation.


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

Branch: refs/heads/master
Commit: 5fa631bad4fff95eb74164b87b464448d98b80a2
Parents: f50397f
Author: anatole <an...@apache.org>
Authored: Wed Feb 17 22:09:36 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Wed Feb 17 22:09:36 2016 +0100

----------------------------------------------------------------------
 .../asciidoc/extensions/mod_collections.adoc    | 163 +++++++++++++++++++
 1 file changed, 163 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/5fa631ba/src/site/asciidoc/extensions/mod_collections.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/extensions/mod_collections.adoc b/src/site/asciidoc/extensions/mod_collections.adoc
new file mode 100644
index 0000000..41e97c8
--- /dev/null
+++ b/src/site/asciidoc/extensions/mod_collections.adoc
@@ -0,0 +1,163 @@
+// 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.
+
+= Apache Tamaya -- Extension: Integration with Apache Camel
+
+:name: Tamaya
+:rootpackage: org.apache.tamaya.integration.camel
+:title: Apache Tamaya Extension: Integration with Apache Camel
+:revdate: December 2015
+:authorinitials: ATR
+:author: Anatole Tresch
+:email: <an...@apache.org>
+:source-highlighter: coderay
+:website: http://tamaya.incubator.apache.org/
+:toc:
+:toc-placement: manual
+:encoding: UTF-8
+:numbered:
+
+'''
+
+<<<
+
+toc::[]
+
+<<<
+:numbered!:
+<<<
+[[Optional]]
+== Integration with Apache Camel (Extension Module)
+=== Overview
+
+The Tamaya Camel integration module provides different artifacts which allows integration of Apachae Tamaya
+configuration with Apache Camel.
+
+
+=== Compatibility
+
+The module is based on Java 7, so it will not run on Java 7 and beyond.
+
+
+=== Installation
+
+To benefit from configuration builder support you only must add the corresponding dependency to your module:
+
+[source, xml]
+-----------------------------------------------
+<dependency>
+  <groupId>org.apache.tamaya.ext</groupId>
+  <artifactId>tamaya-camel</artifactId>
+  <version>{tamayaVersion}</version>
+</dependency>
+-----------------------------------------------
+
+
+=== The Extensions Provided
+
+Camel integration comes basically with three artifacts:
+
+* A Camel +ResolverFunction+ implementation adding explicit property resolution
+  (+org.apache.tamaya.integration.camel.TamayaPropertyResolver+).
+* A Camel +PropertiesComponent+ implementation, which allows implicitly preconfigures the resolvers from above and
+  additionally allows using Tamaya configuration as Camel _overrides_
+  (+org.apache.tamaya.integration.camel.TamayaPropertiesComponent+).
+
+
+=== Configuring using Camel Java DSL
+
+Camel integration using Java DSL is basically simple:
+
+[source, java]
+-----------------------------------------------
+import org.apache.tamaya.integration.camel.TamayaPropertiesComponent;
+
+camelContext.addComponent("properties", new TamayaPropertiesComponent());
+-----------------------------------------------
+
+Given so you can then use +cfg+ or +tamaya+ as prefix for resolving entries with Tamaya as follows:
+
+[source, java]
+-----------------------------------------------
+RouteBuilder builder = new RouteBuilder() {
+    public void configure() {
+        from("direct:hello1").transform().simple("{{cfg:message}}");
+    }
+};
+camelContext.addRoutes(builder);
+builder = new RouteBuilder() {
+    public void configure() {
+        from("direct:hello2").transform().simple("{{tamaya:message}}");
+    }
+};
+camelContext.addRoutes(builder);
+-----------------------------------------------
+
+
+Optionally you can also configure +TamayaPropertiesComponent+ that all currently known Tamaya properties are used
+as Camel overrides, meaning they are evaluated prior to all other available resolver functions in the Camel
++PropertiesComponent+:
+
+[source, java]
+-----------------------------------------------
+TamayaPropertiesComponent props = new TamayaPropertiesComponent();
+props.setTamayaOverrides(true);
+-----------------------------------------------
+
+
+=== Configuring using Camel XML DSL
+
+Camel integration using XML DSL is basically very similar. You just have to add the +properties+ component as bean
+as well. All other configuration parameters (e.g. file URIs are similar supported). In the example code below we
+again use Tamaya as the main configuration solutions only using Camel's default behaviour as a fallback:
+
+[source, xml]
+-----------------------------------------------
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+    <routeContext id="myCoolRoutes" xmlns="http://camel.apache.org/schema/spring">
+        <route id="r1">
+            <from uri="direct:hello1"/>
+            <transform>
+                <simple>{{message}}</simple>
+            </transform>
+        </route>
+        <route id="r2">
+            <from uri="direct:hello2"/>
+            <transform>
+                <simple>{{cfg:message}}</simple>
+            </transform>
+        </route>
+        <route id="r3">
+            <from uri="direct:hello3"/>
+            <transform>
+                <simple>{{tamaya:message}}</simple>
+            </transform>
+        </route>
+    </routeContext>
+
+    <bean id="properties" class="org.apache.tamaya.integration.camel.TamayaPropertiesComponent">
+        <property name="tamayaOverrides" value="true"/>
+    </bean>
+
+</beans>
+-----------------------------------------------
\ No newline at end of file


[7/8] incubator-tamaya git commit: Redesigned component slightly.

Posted by an...@apache.org.
Redesigned component slightly.


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

Branch: refs/heads/master
Commit: a231ff05dfe5a5589f76fd7374d2cf492d26f4fb
Parents: 1547d4a
Author: anatole <an...@apache.org>
Authored: Thu Feb 18 00:41:01 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Thu Feb 18 00:41:01 2016 +0100

----------------------------------------------------------------------
 .../mutableconfig/MutableConfiguration.java     |  76 ++++-----
 .../MutableConfigurationQuery.java              | 163 ++++++++++++-------
 .../DefaultConfigurationBackendSpi.java         |  14 +-
 .../spi/AbstractMutableConfiguration.java       |  91 ++---------
 .../MutableConfigurationBackendProviderSpi.java |   7 +-
 .../spi/MutableConfigurationBackendSpi.java     |   4 +-
 .../MutableConfigurationQueryTest.java          |  16 +-
 .../PropertiesFileConfigBackendTest.java        |  31 ++--
 .../asciidoc/extensions/mod_mutable_config.adoc |  74 +++++----
 9 files changed, 230 insertions(+), 246 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a231ff05/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
index fed3151..468c3cd 100644
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
@@ -18,6 +18,8 @@
  */
 package org.apache.tamaya.mutableconfig;
 
+import org.apache.tamaya.Configuration;
+
 import java.net.URI;
 import java.util.Collection;
 import java.util.Map;
@@ -28,21 +30,16 @@ import java.util.Map;
  * Hereby not all configuration entries are necessarily mutable, since some entries may be read from non
  * mutable areas of configuration. Of course, it is always possible to add a mutable shadow layer on top of all
  * configuration to enable whatever changes applied. The exact management and storage persistence algorithm should be
- * transparent.<br>
- * As a consequence clients should first check, using the corresponding methods, if entries are to edited or removed
+ * transparent.
+ *
+ * As a consequence clients should first check, using the corresponding methods, if entries are to edited or
+ * removedProperties
  * actually are eligible for change/creation or removal.
  */
-public interface MutableConfiguration {
-
-    /**
-     * Get the unique id of this change request (UUID).
-     *
-     * @return the unique id of this change request (UUID).
-     */
-    String getRequestID();
+public interface MutableConfiguration extends Configuration {
 
     /**
-     * Identifies the configuration backends that participate in this request instance and which are
+     * Identifies the configuration backends that are targeted by this instance and which are
      * also responsible for writing back the changes applied.
      *
      * @return the backend URI, never null.
@@ -60,7 +57,7 @@ public interface MutableConfiguration {
 
     /**
      * Checks if a configuration key is removable. This also implies that it is writable, but there might be writable
-     * keys that cannot be removed.
+     * keys that cannot be removedProperties.
      *
      * @param keyExpression the keyExpression the key to be cheched for write access (including creation), not null.
      *                      Here this could also
@@ -70,7 +67,7 @@ public interface MutableConfiguration {
     boolean isRemovable(String keyExpression);
 
     /**
-     * Checks if any keys of the given type already exist in the backend. <b>NOTE:</b> there may be backends that
+     * Checks if any keys of the given type already exist in the write backend. <b>NOTE:</b> there may be backends that
      * are not able to support lookups with regular expressions. In most such cases you should pass the keys to
      * lookup explicitly.
      *
@@ -78,7 +75,7 @@ public interface MutableConfiguration {
      *                      also be a regular expression, such "as a.b.c.*".
      * @return true, if there is any key found matching the expression.
      */
-    boolean exists(String keyExpression);
+    boolean isExisting(String keyExpression);
 
     /**
      * Sets a property.
@@ -93,28 +90,32 @@ public interface MutableConfiguration {
     /**
      * Puts all given configuration entries. This method should check that all given properties are
      * basically removable, as defined by #isWritable. If any of the passed keys is not writable during this initial
-     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
-     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
-     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
-     * remove all entries as far as possible and abort the writing operation.
+     * check, the operation should not perform any configuration changes and throw a
+     * {@link org.apache.tamaya.ConfigException}. If errors occur afterwards, when the properties are effectively
+     * written back to the backends, the errors should be collected and returned as part of the ConfigException
+     * payload. Nevertheless the operation should in that case remove all entries as far as possible and abort the
+     * writing operation.
      *
      * @param properties the properties tobe written, not null.
      * @return the config change request
-     * @throws org.apache.tamaya.ConfigException if any of the given properties could not be written, or the request is read-only.
+     * @throws org.apache.tamaya.ConfigException if any of the given properties could not be written, or the request
+     * is read-only.
      */
     MutableConfiguration putAll(Map<String, String> properties);
 
     /**
      * Removes all given configuration entries. This method should check that all given properties are
      * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
-     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * check, the operation should not perform any configuration changes and throw a
+     * {@link org.apache.tamaya.ConfigException}. If errors
      * occur afterwards, when the properties are effectively written back to the backends, the errors should be
      * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
      * remove all entries as far as possible and abort the writing operation.
      *
-     * @param keys the property's keys to be removed, not null.
+     * @param keys the property's keys to be removedProperties, not null.
      * @return the config change request
-     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
+     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removedProperties, or the
+     * request is read-only.
      */
     MutableConfiguration remove(Collection<String> keys);
 
@@ -126,39 +127,26 @@ public interface MutableConfiguration {
      * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
      * remove all entries as far as possible and abort the writing operation.
      *
-     * @param keys the property's keys to be removed, not null.
+     * @param keys the property's keys to be removedProperties, not null.
      * @return the config change request
-     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
+     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removedProperties, or the request is read-only.
      */
     MutableConfiguration remove(String... keys);
 
     /**
      * Commits the request. After a commit the change is not editable anymore. All changes applied will be written to
      * the corresponding configuration backend.
-     * " @throws ConfigException if the request already has been committed or cancelled, or the commit fails.
-     */
-    void commit();
-
-    /**
-     * Cancel the given request, leaving everything unchanged. Cancelled requests are read-only and can not be used
-     * for preparing/submitting any configuration changes.
      *
-     * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled.
+     * NOTE that changes applied must not necessarily be visible in the current {@link Configuration} instance,
+     * since visibility of changes also depends on the ordinals set on the {@link org.apache.tamaya.spi.PropertySource}s
+     * configured.
+     * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled, or the commit fails.
      */
-    void cancel();
+    void commit();
 
     /**
-     * Operation to check, if the current request is closed (either commited or cancelled). Closed requests are
-     * read-only and can not be used for preparing/submitting any configuration changes.
-     *
-     * @return true, if this instance is closed.
+     * Rollback any changes leaving everything unchanged. This will rollback all changes applied since the last commit.
      */
-    boolean isClosed();
+    void rollback();
 
-    /**
-     * Method to set the request id to be used.
-     * @param requestId the id to  be used, not null
-     * @throws IllegalStateException if the request is already closed.
-     */
-    void setRequestId(String requestId);
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a231ff05/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
index 7aaf2bf..31d6697 100644
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
@@ -19,7 +19,13 @@
 package org.apache.tamaya.mutableconfig;
 
 import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
+import org.apache.tamaya.ConfigOperator;
+import org.apache.tamaya.ConfigQuery;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.TypeLiteral;
+import org.apache.tamaya.mutableconfig.spi.AbstractMutableConfiguration;
+import org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendSpi;
+import org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi;
 import org.apache.tamaya.spi.ServiceContextManager;
 
 import java.net.URI;
@@ -31,16 +37,27 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.UUID;
 
 
 /**
  * Accessor for creating {@link MutableConfiguration} instances to change and commit configuration.
  */
-public final class MutableConfigurationQuery {
+public final class MutableConfigurationQuery implements ConfigQuery<MutableConfiguration> {
+
+    /**
+     * URIs used by this query instance to identify the backends to use for write operations.
+     */
+    private List<MutableConfigurationBackendSpi> targets = new ArrayList<>();
 
     /** Singleton constructor. */
-    private MutableConfigurationQuery(){}
+    private MutableConfigurationQuery(List<MutableConfigurationBackendSpi> targets){
+        this.targets.addAll(targets);
+    }
+
+    @Override
+    public MutableConfiguration query(Configuration config) {
+        return new DefaultMutableConfiguration(config, targets);
+    }
 
     /**
      * Creates a new change request for the given configurationSource
@@ -52,13 +69,13 @@ public final class MutableConfigurationQuery {
      * @return a new ChangeRequest
      * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
      */
-    public static MutableConfiguration createChangeRequest(String... configurationTargets){
+    public static MutableConfigurationQuery of(String... configurationTargets){
         try {
             URI[] uris = new URI[configurationTargets.length];
             for (int i = 0; i < configurationTargets.length; i++) {
                 uris[i] = new URI(configurationTargets[i]);
             }
-            return createChangeRequest(uris);
+            return of(uris);
         } catch(URISyntaxException e){
             throw new ConfigException("Invalid URIs enocuntered in " + Arrays.toString(configurationTargets));
         }
@@ -74,15 +91,15 @@ public final class MutableConfigurationQuery {
      * @return a new ChangeRequest
      * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
      */
-    public static MutableConfiguration createChangeRequest(URI... configurationTargets){
+    public static MutableConfigurationQuery of(URI... configurationTargets){
         if(Objects.requireNonNull(configurationTargets).length==0){
             throw new IllegalArgumentException("At least one target URI is required.");
         }
-        List<MutableConfiguration> targets = new ArrayList<>();
-        for(ConfigChangeManagerSpi spi:ServiceContextManager.getServiceContext()
-                .getServices(ConfigChangeManagerSpi.class)){
+        List<MutableConfigurationBackendSpi> targets = new ArrayList<>();
+        for(MutableConfigurationBackendProviderSpi spi:ServiceContextManager.getServiceContext()
+                .getServices(MutableConfigurationBackendProviderSpi.class)){
             for(URI target:configurationTargets) {
-                MutableConfiguration req = spi.createChangeRequest(target);
+                MutableConfigurationBackendSpi req = spi.getBackend(target);
                 if (req != null) {
                     targets.add(req);
                 }
@@ -92,43 +109,36 @@ public final class MutableConfigurationQuery {
             throw new ConfigException("Not an editable configuration target for: " +
                     Arrays.toString(configurationTargets));
         }
-        if(targets.size()==1){
-            return targets.get(0);
-        }
-        return new CompoundConfigChangeRequest(targets);
+        return new MutableConfigurationQuery(targets);
     }
 
 
     /**
      * Compound request that contains internally multiple change requests. Changes are committed to all members.
      */
-    private static final class CompoundConfigChangeRequest implements MutableConfiguration {
+    private static final class DefaultMutableConfiguration extends AbstractMutableConfiguration
+            implements MutableConfiguration {
 
-        private final List<MutableConfiguration> targets;
-        private final List<URI> backendURIs = new ArrayList<>();
-        private String requestId = UUID.randomUUID().toString();
+        private final List<MutableConfigurationBackendSpi> targets;
+        private final Configuration config;
 
-        CompoundConfigChangeRequest(List<MutableConfiguration> targets){
-            this.targets = targets;
-            for(MutableConfiguration req:targets){
-                req.setRequestId(requestId);
-                backendURIs.addAll(req.getBackendURIs());
-            }
-        }
-
-        @Override
-        public String getRequestID() {
-            return requestId;
+        DefaultMutableConfiguration(Configuration config, List<MutableConfigurationBackendSpi> targets){
+            this.targets = Objects.requireNonNull(targets);
+            this.config = Objects.requireNonNull(config);
         }
 
         @Override
         public List<URI> getBackendURIs() {
-            return Collections.unmodifiableList(backendURIs);
+            List<URI> result = new ArrayList<>(getBackendURIs().size());
+            for(MutableConfigurationBackendSpi backend: targets){
+                result.add(backend.getBackendURI());
+            }
+            return Collections.unmodifiableList(result);
         }
 
         @Override
         public boolean isWritable(String keyExpression) {
-            for(MutableConfiguration req:targets){
+            for(MutableConfigurationBackendSpi req:targets){
                 if(req.isWritable(keyExpression)){
                     return true;
                 }
@@ -138,7 +148,7 @@ public final class MutableConfigurationQuery {
 
         @Override
         public boolean isRemovable(String keyExpression) {
-            for(MutableConfiguration req:targets){
+            for(MutableConfigurationBackendSpi req:targets){
                 if(req.isRemovable(keyExpression)){
                     return true;
                 }
@@ -147,9 +157,9 @@ public final class MutableConfigurationQuery {
         }
 
         @Override
-        public boolean exists(String keyExpression) {
-            for(MutableConfiguration req:targets){
-                if(req.exists(keyExpression)){
+        public boolean isExisting(String keyExpression) {
+            for(MutableConfigurationBackendSpi req:targets){
+                if(req.isExisting(keyExpression)){
                     return true;
                 }
             }
@@ -158,80 +168,111 @@ public final class MutableConfigurationQuery {
 
         @Override
         public MutableConfiguration put(String key, String value) {
-            for(MutableConfiguration req:targets){
+            for(MutableConfigurationBackendSpi req:targets){
                 if(req.isWritable(key)){
                     req.put(key, value);
                 }
             }
-            return this;
+            return super.put(key, value);
         }
 
         @Override
         public MutableConfiguration putAll(Map<String, String> properties) {
-            for(MutableConfiguration req:targets){
+            for(MutableConfigurationBackendSpi req:targets){
                 for(Map.Entry<String,String> en:properties.entrySet()) {
                     if (req.isWritable(en.getKey())) {
                         req.put(en.getKey(), en.getValue());
                     }
                 }
             }
-            return this;
+            return super.putAll(properties);
         }
 
         @Override
         public MutableConfiguration remove(String... keys) {
-            for(MutableConfiguration req:targets){
+            for(MutableConfigurationBackendSpi req:targets){
                 for(String key:keys){
                     if (req.isRemovable(key)) {
                         req.remove(key);
                     }
                 }
             }
-            return this;
+            return super.remove(keys);
         }
 
         @Override
         public MutableConfiguration remove(Collection<String> keys) {
-            for(MutableConfiguration req:targets){
+            for(MutableConfigurationBackendSpi req:targets){
                 for(String key:keys){
                     if (req.isRemovable(key)) {
                         req.remove(key);
                     }
                 }
             }
-            return this;
+            return super.remove(keys);
         }
 
         @Override
-        public void commit() {
-            for(MutableConfiguration req:targets){
+        protected void commitInternal() {
+            for(MutableConfigurationBackendSpi req:targets){
                 req.commit();
             }
         }
 
         @Override
-        public void rollback() {
-            for(MutableConfiguration req:targets){
-                req.rollback();
-            }
+        public String get(String key) {
+            return config.get(key);
         }
 
         @Override
-        public boolean isClosed() {
-            for(MutableConfiguration req:targets){
-                if(req.isClosed()){
-                    return true;
-                }
-            }
-            return false;
+        public String getOrDefault(String key, String defaultValue) {
+            return config.getOrDefault(key, defaultValue);
+        }
+
+        @Override
+        public <T> T getOrDefault(String key, Class<T> type, T defaultValue) {
+            return config.getOrDefault(key, type, defaultValue);
+        }
+
+        @Override
+        public <T> T get(String key, Class<T> type) {
+            return config.get(key, type);
+        }
+
+        @Override
+        public <T> T get(String key, TypeLiteral<T> type) {
+            return config.get(key, type);
+        }
+
+        @Override
+        public <T> T getOrDefault(String key, TypeLiteral<T> type, T defaultValue) {
+            return config.getOrDefault(key, type, defaultValue);
         }
 
         @Override
-        public void setRequestId(String requestId) {
-            if(isClosed()){
-                throw new IllegalStateException("Cannot set requestId, already closed.");
+        public Map<String, String> getProperties() {
+            return config.getProperties();
+        }
+
+        @Override
+        public Configuration with(ConfigOperator operator) {
+            return operator.operate(this);
+        }
+
+        @Override
+        public <T> T query(ConfigQuery<T> query) {
+            if(query instanceof MutableConfigurationQuery){
+                throw new ConfigException("Cannot query a mutable configuration, already is one!");
             }
-            this.requestId = Objects.requireNonNull(requestId);
+            return query.query(this);
+        }
+
+        @Override
+        public String toString() {
+            return "DefaultMutableConfiguration{" +
+                    "config=" + config +
+                    ", targets=" + targets +
+                    '}';
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a231ff05/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
index e5def2e..cfdfe29 100644
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tamaya.mutableconfig.internal;
 
-import org.apache.tamaya.mutableconfig.MutableConfiguration;
-import org.apache.tamaya.mutableconfig.spi.ConfigurationBackendSpi;
+import org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendSpi;
+import org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi;
 
 import java.io.File;
 import java.net.URI;
@@ -30,18 +30,18 @@ import java.util.logging.Logger;
  * Mutable Config Request factory that tries to convert given URIs to file references, if successful, it returns
  * ConfigChangeRequests fir .properties and .xml files.
  */
-public class DefaultConfigurationBackendSpi implements ConfigurationBackendSpi {
+public class DefaultConfigurationBackendSpi implements MutableConfigurationBackendProviderSpi {
 
-    private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
+    private static final Logger LOG = Logger.getLogger(DefaultConfigurationBackendSpi.class.getName());
 
     @Override
-    public MutableConfiguration getBackend(URI uri) {
+    public MutableConfigurationBackendSpi getBackend(URI uri) {
         try{
             File f = new File(uri);
             if(f.getName().endsWith(".properties")){
-                return new PropertiesFileConfigChangeRequest(f);
+                return new PropertiesFileConfigBackendSpi(f);
             }else if(f.getName().endsWith(".xml")){
-                return new XmlPropertiesFileConfigChangeRequest(f);
+                return new XmlPropertiesFileConfigBackendSpi(f);
             }
         } catch(Exception e){
             LOG.log(Level.FINEST, "URI not convertible to file, ignoring " + uri, e);

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a231ff05/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
index 2dd9a20..d1afaf6 100644
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
@@ -18,72 +18,35 @@
  */
 package org.apache.tamaya.mutableconfig.spi;
 
-import org.apache.tamaya.ConfigException;
 import org.apache.tamaya.mutableconfig.MutableConfiguration;
 
-import java.net.URI;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
-import java.util.UUID;
 
 /**
  * Base class for implementing a ConfigChangeRequest.
  */
 public abstract class AbstractMutableConfiguration implements MutableConfiguration {
 
-    private final List<URI> uris = new ArrayList<>();
-    private String requestID = UUID.randomUUID().toString();
     /**
      * The Properties.
      */
-    protected final Map<String,String> properties = new HashMap<>();
+    protected final Map<String,String> addedProperties = new HashMap<>();
     /**
      * The Removed.
      */
-    protected final Set<String> removed = new HashSet<>();
-    private boolean closed = false;
+    protected final Set<String> removedProperties = new HashSet<>();
 
-    protected Set<String> getRemoved() {
-        return removed;
+    protected Set<String> getRemovedProperties() {
+        return removedProperties;
     }
 
-    protected Map<String,String> getProperties() {
-        return properties;
-    }
-
-    /**
-     * Instantiates a new Abstract config change request.
-     *
-     * @param uris the uris
-     */
-    protected AbstractMutableConfiguration(URI... uris){
-        for(URI uri:uris){
-            this.uris.add(Objects.requireNonNull(uri));
-        }
-        if(this.uris.isEmpty()){
-            throw new IllegalArgumentException("At least one URI should be provided.");
-        }
-    }
-
-    /**
-     * Get the unique id of this change request (UUID).
-     * @return the unique id of this change request (UUID).
-     */
-    @Override
-    public String getRequestID(){
-        return requestID;
-    }
-
-    @Override
-    public final Collection<URI> getBackendURIs() {
-        return Collections.unmodifiableCollection(uris);
+    protected Map<String,String> getAddedProperties() {
+        return addedProperties;
     }
 
     @Override
@@ -97,47 +60,37 @@ public abstract class AbstractMutableConfiguration implements MutableConfigurati
     }
 
     @Override
-    public abstract boolean exists(String keyExpression);
-
-    @Override
-    public void setRequestId(String requestId) {
-        checkClosed();
-        this.requestID = Objects.requireNonNull(requestId);
-    }
+    public abstract boolean isExisting(String keyExpression);
 
     @Override
     public MutableConfiguration put(String key, String value) {
-        checkClosed();
-        this.properties.put(key, value);
+        this.addedProperties.put(key, value);
         return this;
     }
 
     @Override
     public MutableConfiguration putAll(Map<String, String> properties) {
-        checkClosed();
-        this.properties.putAll(properties);
+        this.addedProperties.putAll(properties);
         return this;
     }
 
     @Override
     public MutableConfiguration remove(String... keys) {
-        checkClosed();
-        Collections.addAll(this.removed, keys);
+        Collections.addAll(this.removedProperties, keys);
         return this;
     }
 
     @Override
     public MutableConfiguration remove(Collection<String> keys) {
-        checkClosed();
-        this.removed.addAll(keys);
+        this.removedProperties.addAll(keys);
         return this;
     }
 
     @Override
     public final void commit() {
-        checkClosed();
         commitInternal();
-        closed = true;
+        this.removedProperties.clear();
+        this.addedProperties.clear();
     }
 
     /**
@@ -147,21 +100,7 @@ public abstract class AbstractMutableConfiguration implements MutableConfigurati
 
     @Override
     public final void rollback() {
-        checkClosed();
-        closed = true;
-    }
-
-    @Override
-    public final boolean isClosed() {
-        return closed;
-    }
-
-    /**
-     * Check closed.
-     */
-    protected void checkClosed(){
-        if(closed){
-            throw new ConfigException("Change request already closed.");
-        }
+        this.removedProperties.clear();
+        this.addedProperties.clear();
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a231ff05/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
index 98d4eb7..5e8300b 100644
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
@@ -18,13 +18,10 @@
  */
 package org.apache.tamaya.mutableconfig.spi;
 
-import org.apache.tamaya.mutableconfig.MutableConfiguration;
-import org.apache.tamaya.mutableconfig.MutableConfigurationQuery;
-
 import java.net.URI;
 
 /**
- * Provider SPI used by {@link MutableConfigurationQuery}. Providers may override
+ * Provider SPI used by {@link org.apache.tamaya.mutableconfig.MutableConfigurationQuery}. Providers may override
  * other providers registering with a higher {@link javax.annotation.Priority} value annotated.
  */
 public interface MutableConfigurationBackendProviderSpi {
@@ -35,6 +32,6 @@ public interface MutableConfigurationBackendProviderSpi {
     * @param backendURI the backend uri
     * @return the requested backend, or null if the given backend URI is not supported by the given SPI.
     */
-   MutableConfigurationBackend getBackend(URI backendURI);
+   MutableConfigurationBackendSpi getBackend(URI backendURI);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a231ff05/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendSpi.java
index a1825d7..0c05807 100644
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendSpi.java
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendSpi.java
@@ -18,8 +18,6 @@
  */
 package org.apache.tamaya.mutableconfig.spi;
 
-import org.apache.tamaya.Configuration;
-
 import java.net.URI;
 import java.util.Collection;
 import java.util.Map;
@@ -128,7 +126,7 @@ public interface MutableConfigurationBackendSpi {
      * Commits the request. After a commit the change is not editable anymore. All changes applied will be written to
      * the corresponding configuration backend.
      *
-     * NOTE that changes applied must not necessarily be visible in the current {@link Configuration} instance,
+     * NOTE that changes applied must not necessarily be visible in the current {@link org.apache.tamaya.Configuration} instance,
      * since visibility of changes also depends on the ordinals set on the {@link org.apache.tamaya.spi.PropertySource}s
      * configured.
      * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled, or the commit fails.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a231ff05/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/MutableConfigurationQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/MutableConfigurationQueryTest.java b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/MutableConfigurationQueryTest.java
index b235149..6ab394d 100644
--- a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/MutableConfigurationQueryTest.java
+++ b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/MutableConfigurationQueryTest.java
@@ -19,6 +19,7 @@
 package org.apache.tamaya.mutableconfig;
 
 import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.ConfigurationProvider;
 import org.junit.Test;
 
 import java.io.File;
@@ -39,10 +40,12 @@ public class MutableConfigurationQueryTest {
     @Test
     public void testCreateChangeRequest() throws Exception {
         File f = File.createTempFile("ConfigChangeRequest",".properties");
-        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        MutableConfiguration req = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(f.toURI()));
         assertNotNull(req);
         f = File.createTempFile("ConfigChangeRequest",".xml");
-        req = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        req = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(f.toURI()));
         assertNotNull(req);
     }
 
@@ -53,7 +56,8 @@ public class MutableConfigurationQueryTest {
      */
     @Test(expected=ConfigException.class)
     public void testInvalidCreateChangeRequest() throws Exception {
-        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(new URI("foo:bar"));
+        MutableConfiguration req = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(new URI("foo:bar")));
     }
 
     /**
@@ -63,7 +67,8 @@ public class MutableConfigurationQueryTest {
      */
     @Test(expected=NullPointerException.class)
     public void testNullCreateChangeRequest1() throws Exception {
-        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest((URI[])null);
+        MutableConfiguration req = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of((URI[])null));
     }
 
     /**
@@ -73,6 +78,7 @@ public class MutableConfigurationQueryTest {
      */
     @Test(expected=NullPointerException.class)
     public void testNullCreateChangeRequest2() throws Exception {
-        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest((String[])null);
+        MutableConfiguration req = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of((String[])null));
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a231ff05/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendTest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendTest.java b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendTest.java
index c2e220e..a4fe1f2 100644
--- a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendTest.java
+++ b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tamaya.mutableconfig.internal;
 
+import org.apache.tamaya.ConfigurationProvider;
 import org.apache.tamaya.mutableconfig.MutableConfigurationQuery;
 import org.apache.tamaya.mutableconfig.MutableConfiguration;
 import org.junit.Test;
@@ -31,7 +32,7 @@ import java.util.Properties;
 import static org.junit.Assert.*;
 
 /**
- * Tests for {@link PropertiesFileConfigBackend}.
+ * Tests for {@link PropertiesFileConfigBackendSpi}.
  */
 public class PropertiesFileConfigBackendTest {
     /**
@@ -43,14 +44,13 @@ public class PropertiesFileConfigBackendTest {
     public void testReadWriteProperties_WithCancel() throws IOException {
         File f = File.createTempFile("testReadWriteProperties_WithCancel",".properties");
         f.delete();
-        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f.toURI());
-        assertTrue(req instanceof PropertiesFileConfigBackend);
+        MutableConfiguration req = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(f.toURI()));
         req.put("key1", "value1");
         Map<String,String> cm = new HashMap<>();
         cm.put("key2", "value2");
         cm.put("key3", "value3");
         req.rollback();;
-        assertTrue(req.isClosed());
         assertFalse(f.exists());
     }
 
@@ -63,17 +63,17 @@ public class PropertiesFileConfigBackendTest {
     public void testReadWriteProperties_WithCommit() throws IOException {
         File f = File.createTempFile("testReadWriteProperties_WithCommit",".properties");
         f.delete();
-        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f.toURI());
-        assertTrue(req instanceof PropertiesFileConfigBackend);
+        MutableConfiguration req = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(f.toURI()));
         req.put("key1", "value1");
         Map<String,String> cm = new HashMap<>();
         cm.put("key2", "value2");
         cm.put("key3", "value3");
         req.putAll(cm);
         req.commit();;
-        assertTrue(req.isClosed());
         assertTrue(f.exists());
-        MutableConfiguration req2 = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        MutableConfiguration req2 = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(f.toURI()));
         assertTrue(req != req2);
         req2.remove("foo");
         req2.remove("key3");
@@ -97,17 +97,17 @@ public class PropertiesFileConfigBackendTest {
     public void testReadWriteXmlProperties_WithCommit() throws IOException {
         File f = File.createTempFile("testReadWriteProperties_WithCommit",".xml");
         f.delete();
-        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f.toURI());
-        assertTrue(req instanceof XmlPropertiesFileConfigChangeRequest);
+        MutableConfiguration req = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(f.toURI()));
         req.put("key1", "value1");
         Map<String,String> cm = new HashMap<>();
         cm.put("key2", "value2");
         cm.put("key3", "value3");
         req.putAll(cm);
         req.commit();;
-        assertTrue(req.isClosed());
         assertTrue(f.exists());
-        MutableConfiguration req2 = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        MutableConfiguration req2 = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(f.toURI()));
         assertTrue(req != req2);
         req2.remove("foo");
         req2.remove("key3");
@@ -128,17 +128,18 @@ public class PropertiesFileConfigBackendTest {
         f1.delete();
         File f2 = File.createTempFile("testReadWrite_Compound",".properties");
         f2.delete();
-        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f1.toURI(),f2.toURI());
+        MutableConfiguration req = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(f1.toURI(), f2.toURI()));
         req.put("key1", "value1");
         Map<String,String> cm = new HashMap<>();
         cm.put("key2", "value2");
         cm.put("key3", "value3");
         req.putAll(cm);
         req.commit();;
-        assertTrue(req.isClosed());
         assertTrue(f1.exists());
         assertTrue(f2.exists());
-        MutableConfiguration req2 = MutableConfigurationQuery.createChangeRequest(f1.toURI(),f2.toURI());
+        MutableConfiguration req2 = ConfigurationProvider.getConfiguration().query(
+                MutableConfigurationQuery.of(f1.toURI(), f2.toURI()));
         assertTrue(req != req2);
         req2.remove("foo");
         req2.remove("key3");

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/a231ff05/src/site/asciidoc/extensions/mod_mutable_config.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/extensions/mod_mutable_config.adoc b/src/site/asciidoc/extensions/mod_mutable_config.adoc
index b9a0668..4fca404 100644
--- a/src/site/asciidoc/extensions/mod_mutable_config.adoc
+++ b/src/site/asciidoc/extensions/mod_mutable_config.adoc
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-= Apache Tamaya -- Extension: Events
+= Apache Tamaya -- Extension: Mutable Configuration
 
 :name: Tamaya
 :rootpackage: org.apache.tamaya.mutableconfig
@@ -47,9 +47,8 @@ toc::[]
 == Tamaya Mutable Configuration (Extension Module)
 === Overview
 
-Tamaya Configuration by default is read-only, which covers must of the use cases. Make it writable through out
-creates also a bunch of new issues, especially with distributed configuration services and eventual consistency.
-Therefore mutability of configuration is modelled in Tamaya as a separate concern. This module defines the API
+Tamaya Configuration by default is read-only, which covers must of the use cases. But there are many legit use cases
+where configuration should be written back to some backend systems or the local file system. This module defines the API
 to be used, whereas multiple mutable backends can register their mechanism to write configuration properties.
 
 === Compatibility
@@ -71,29 +70,26 @@ To benefit from configuration mutability support you only must add the correspon
 
 === Core Architecture
 
-The core of the module is the +ConfigChangeManager+ singleton, which creates a +ConfigChangeReuqest+ class for
-one or multiple +configurationTargets+ passed. The supported target +URIs+ hereby are determined (and must be
-documented) by the registered backend spis. If not sure you can call +getSupportedURIInfo()+ to see, which kind of URI's
-supported.
+The core of the module is the +MutableConfigQuery+ singleton, which is a +ConfigQuery+ that creates a new
++Mutableonfiguration+ based on a +Configuration+ and a set of target backend +URIs+. If not sure you can call
++getSupportedURIInfo()+ to see, which kind of URI's are  currently supported.
 As an example writing configuration entries to an +etcd+ server can be done as follows:
 
 [source,java]
-.Writing configuration to etcd
+.Accessing a mutable configuration backed by etcd
 --------------------------------------------
-ConfigChangeRequest request = ConfigChangeManager.createChangeRequest(
-    new URI("etc:http://127.0.0.1:4441"),
-    new URI("file:/home/etcd/backup-config.properties"));
-ChangeSummary summary = request
-                .set("newKey", "newValue").set("anotherKey", "updatedValue")
-                .remove("valueNotValid")
-                .commit();
+MutableConfiguration config = ConfigChangeManager.getConfiguration().query(
+    MutableConfigurationQuery.of("etc:http://127.0.0.1:4441", "file:/home/etcd/backup-config.properties");
+config.set("newKey", "newValue").set("anotherKey", "updatedValue")
+      .remove("valueNotValid")
+      .commit();
 --------------------------------------------
 
 The effective effect of your changes to the overall configuration changes cannot be easily predicted, since it depends
 on several aspects:
 
 . is the corresponding configuration resource configured as part of the current system's configuration?
-. what is the +PropertySource's+ ordinal? Is it overriding or overriden by other sources?
+. what is the +PropertySource's+ ordinal? Is it overriding or overridden by other sources?
 . is the change directly visible to the configuration system? E.g. injected values are normally not updated,
   whereas injecting a +DynamicValue<T>+ instance allows to detect and react single value changes. Also the
   +PropertySources+ implementation must be able to detect any configuration changes and adapt its values returned
@@ -101,21 +97,22 @@ on several aspects:
 . Is configuration cached, or written/collected directly on access?
 . can the changes applied be committed at all?
 
-So it is part of your application configuration design to clearly define, which confoguration may be read-only, which
-may be mutable, how overridings should work and to which backends finally any changes should be written back. To
-support such fine granular scenarios the +ConfigChangeRequest+ interface also has methods to determine if a key
-is writable at all for a given configuration target:
+So it is part of your application configuration design to clearly define, which configuration may be read-only, which
+may be mutable, how overriding should work and to which backends finally any changes should be written back. To
+support such fine granular scenarios a +MutableConfiguration+ also offers methods to determine if a key
+is writable at all or can be removed or updated:
 
 [source,java]
 .Checking for mutability
 --------------------------------------------
-ConfigChangeRequest request = ConfigChangeManager.createChangeRequest(new URI("file://$USER_HOME/.myapp/mapp.properties"));
-if(request,isWritable("mycluster.shared.appKey")){
-    request.set("newKey", "newValue")
+MutableConfiguration config = ConfigChangeManager.getConfiguration().query(
+    MutableConfigurationQuery.of("etc:http://127.0.0.1:4441", "file:/home/etcd/backup-config.properties");
+if(config,isWritable("mycluster.shared.appKey")){
+    config.set("newKey", "newValue")
     .remove("valueNotValid")
      .commit();
 }else{
-    request.cancel();
+    config.rollbacks();
 }
 --------------------------------------------
 
@@ -126,22 +123,39 @@ several ways, e.g. by:
 
 * using the _tamaya-events_ extension, which can be used to observe the system's configuration and
   publishing events when things have been changed.
-* The SPI implementing the +ConfigChangeManagerSpi+ may inform/update any affected +PropertySource,
+* The SPI implementing the +MutableConfigurationBackendSpi+ may inform/update any affected +PropertySource,
   PropertySourceProvider+ instances about the changes applied.
 
+=== Supported Backends modules
+
+Multiple backends are supported. E.g. the _etcd_ and _consul_ integration modules of Tamaya also registers
+corresponding SPI implementations/backends. By default the following backends are available:
+
+* +.properties+ resources, e.g. files or resources located on a web server, following the +java.util.Properties+
+  format.
+* +.xml+ resources, e.g. files or resources located on a web server, following the +java.util.Properties+ XML format.
+
 
 === SPIs
 
-The module defines only one single SPI, that must be implemented to implement the fabric method
-+createChangeRequest(URI)+ of the +ConfigChangeManager+ singleton:
+The module defines only one single SPI +MutableConfigurationBackendProviderSpi+, that must be implemented. It
+defines a fabric method +MutableConfigurationBackendSpi getBackend(URI)+ used by the +MutableConfigurationQuery+
+accessor:
 
 [source,java]
 .SPI: ConfigEventSpi
 --------------------------------------------------
-public interface ConfigChangeManagerSpi {
-    ConfigChangeRequest createChangeRequest(URI backendURI);
+public interface MutableConfigurationBackendProviderSpi {
+    MutableConfigurationBackendSpi getBackend(URI backendURI);
 }
 --------------------------------------------------
 
 Implementations are registered with the current +ServiceContext+, be default as with
  +java.util.ServiceLoader+.
+
+
+As convenience the following base classes are provided:
+
+* +org.apache.tamaya.mutableconfig.spi.AbstractMutableConfiguration+ simplifying implementation of +MutableConfiguration+.
+* +org.apache.tamaya.mutableconfig.spi.AbstractMutableConfigurationBackendSpi+ simplifying the implemenation of
+  +MutableConfigurationBackendSpi+.
\ No newline at end of file


[4/8] incubator-tamaya git commit: Finalized module config for collection module, synched with impl.

Posted by an...@apache.org.
Finalized module config for collection module, synched with impl.


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

Branch: refs/heads/master
Commit: 89bf98125b34139cbba64dd9a8d5c40deb8acd6a
Parents: ad5a794
Author: anatole <an...@apache.org>
Authored: Wed Feb 17 22:16:59 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Wed Feb 17 22:16:59 2016 +0100

----------------------------------------------------------------------
 .../asciidoc/extensions/mod_collections.adoc    | 264 +++++++++++++------
 1 file changed, 184 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/89bf9812/src/site/asciidoc/extensions/mod_collections.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/extensions/mod_collections.adoc b/src/site/asciidoc/extensions/mod_collections.adoc
index 41e97c8..02a1c5e 100644
--- a/src/site/asciidoc/extensions/mod_collections.adoc
+++ b/src/site/asciidoc/extensions/mod_collections.adoc
@@ -15,12 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
-= Apache Tamaya -- Extension: Integration with Apache Camel
+= Apache Tamaya -- Extension: Collection Support
 
 :name: Tamaya
-:rootpackage: org.apache.tamaya.integration.camel
-:title: Apache Tamaya Extension: Integration with Apache Camel
-:revdate: December 2015
+:rootpackage: org.apache.tamaya.collection
+:title: Apache Tamaya Extension: Collection Support
+:revdate: February 2016
 :authorinitials: ATR
 :author: Anatole Tresch
 :email: <an...@apache.org>
@@ -41,12 +41,12 @@ toc::[]
 :numbered!:
 <<<
 [[Optional]]
-== Integration with Apache Camel (Extension Module)
+== Tamaya Collection Support (Extension Module)
 === Overview
 
-The Tamaya Camel integration module provides different artifacts which allows integration of Apachae Tamaya
-configuration with Apache Camel.
-
+All configuration in Tamaya is expressed as simple key, value pairs. Nevertheless this concept allows similarly
+the modelling of collection typed values such as lists, sets, maps or simple collections of things. The Tamaya
+Collections extension adds this functionality to the Tamaya eco-system.
 
 === Compatibility
 
@@ -55,109 +55,213 @@ The module is based on Java 7, so it will not run on Java 7 and beyond.
 
 === Installation
 
-To benefit from configuration builder support you only must add the corresponding dependency to your module:
+To use Tamaya collection support you only must add the corresponding dependency to your module:
 
 [source, xml]
 -----------------------------------------------
 <dependency>
   <groupId>org.apache.tamaya.ext</groupId>
-  <artifactId>tamaya-camel</artifactId>
+  <artifactId>tamaya-collections</artifactId>
   <version>{tamayaVersion}</version>
 </dependency>
 -----------------------------------------------
 
 
-=== The Extensions Provided
+=== Overview
 
-Camel integration comes basically with three artifacts:
+Tamaya Collections adds +PropertyConverter+ implementations that are able to access configuration data
+as lists, maps or sets. By default this works out of the box as easy as accessing any other type of
+configuration data, e.g.
 
-* A Camel +ResolverFunction+ implementation adding explicit property resolution
-  (+org.apache.tamaya.integration.camel.TamayaPropertyResolver+).
-* A Camel +PropertiesComponent+ implementation, which allows implicitly preconfigures the resolvers from above and
-  additionally allows using Tamaya configuration as Camel _overrides_
-  (+org.apache.tamaya.integration.camel.TamayaPropertiesComponent+).
+[source, java]
+-----------------------------------------------
+Configuration config = ConfigurationProvider.getConfiguration();
 
+// Without any content specification, a list of String is returned.
+List<String> simpleList = config.get("my.list.config.entry", List.class);
 
-=== Configuring using Camel Java DSL
+// Using a TypeLiteral allows to use every convertible sub type supported by the system.
+List<Integer> intList = config.get("my.list.config.entry", new TypeLiteral<List<Integer>>(){});
+-----------------------------------------------
 
-Camel integration using Java DSL is basically simple:
+Configuration in that case, by default, is a simple comma-separated list of entries, e.g.
 
-[source, java]
+[source, properties]
+-----------------------------------------------
+my.list.config.entry=1,34454,23,344545,3445
 -----------------------------------------------
-import org.apache.tamaya.integration.camel.TamayaPropertiesComponent;
 
-camelContext.addComponent("properties", new TamayaPropertiesComponent());
+Additionally the module allows adding additional meta-entries, which allows to tweak some of the
+inner-workings, e.g.
+
+* using your own +PropertyConverter+ implementation for parsing entries.
+* specifying a custom separator String to be used to split the items (default is {{','}}.
+* specifying a custom separator String to be used to split key/value paris when parsing map entries.
+* specifying the implementation type of the collection instance to be returned.
+* specifying if the resulting collection should be returned as a modifiable collection.
+
+=== Supported Types
+
+This module supports the following types:
+
+* +java.util.Collection+
+* +java.util.List+
+* +java.util.ArrayList+
+* +java.util.LinkedList+
+* +java.util.Set+
+* +java.util.SortedSet+
+* +java.util.TreeSet+
+* +java.util.HashSet+
+* +java.util.Map+
+* +java.util.SortedMap+
+* +java.util.HashMap+
+* +java.util.TreeMap+
+
+Hereby the type is determined primarly by the parameter type accessed, e.g.
++config.get("mylist", ArrayList.class)+ will always return an +ArrayList+
+as result.
+
+==== Configuring the target implementation type
+
+Tamaya Collections allows you to configure the target collection type by adding the
+following meta-configuration entry (shown for the +mylist+ entry). Hereby the package part +java.util.+
+can be ommitted:
+
+[ source, properties]
+-----------------------------------------------
+mylist=a,b,c
+_mylist.collection-type=LinkedList
 -----------------------------------------------
 
-Given so you can then use +cfg+ or +tamaya+ as prefix for resolving entries with Tamaya as follows:
+When calling +config.get("mylist", ArrayList.class)+ this parameter does not have any effect, so you will still
+get an +ArrayList+ as a result. However when you call +config.get("mylist", List.class)+ you will
+get a +LinkedList+ as implementation type.
 
-[source, java]
+This mechanism similarly applies to all kind of collections, so you can use it similarly to define the implementation
+type returned when accessing +List+, +Map+ or +Collection+.
+
+
+=== Collecting Configuration Entries instead of Overriding
+
+By default Tamaya applies always an overriding +CombinationPolicy+, where only the configuration entry for
+the most significant configuration entry is used. In case of collections (and maybe also other use cases),
+overriding is not always the mechanism of choice. E.g. when you want to have all entries added to your
+configuration to be *combined* to a new entry containing all values provided by any property sources.
+
+Therefore Tamaya Collections also provides a more sophistiated +CombinationPolicy+ (automatically configured)
+that allows to adapt the way how configuration entries are combined. All you must do is declaring
+the mechanism to be applied by an according meta-configuration parameter, e.g. for +my.list+ your config may
+look as follows:
+
+[source, properties]
 -----------------------------------------------
-RouteBuilder builder = new RouteBuilder() {
-    public void configure() {
-        from("direct:hello1").transform().simple("{{cfg:message}}");
-    }
-};
-camelContext.addRoutes(builder);
-builder = new RouteBuilder() {
-    public void configure() {
-        from("direct:hello2").transform().simple("{{tamaya:message}}");
-    }
-};
-camelContext.addRoutes(builder);
+# from PropertSource 1
+my.list=1,2,3
+
+# from PropertSource 2
+my.list=4,5,6
+
+# without any additional meta-info these entries would be combined to
+my.list=4,5,6
 -----------------------------------------------
 
+With Tamaya Collections you can now configure the combination policy as follows:
 
-Optionally you can also configure +TamayaPropertiesComponent+ that all currently known Tamaya properties are used
-as Camel overrides, meaning they are evaluated prior to all other available resolver functions in the Camel
-+PropertiesComponent+:
+[source, properties]
+-----------------------------------------------
+# use one of the default policies: override / collect
+_my.list.combination-policy=collect
 
-[source, java]
+# use an custom CombinationPolicy to combine the values
+_my.list.combination-policy=com.mycomp.app.MyCombincationPolicy
 -----------------------------------------------
-TamayaPropertiesComponent props = new TamayaPropertiesComponent();
-props.setTamayaOverrides(true);
+
+So declaring the +collect+ policy the resulting raw output of the entry looks as follows:
+
+[source, properties]
+-----------------------------------------------
+# result when applying the collect policy:
+my.list=1,2,3,4,5,6
 -----------------------------------------------
 
+The customizable policy mechanism of Tamaya Collections also honors the +item-separator+ meta-configuration
+parameter explained later in this document.
 
-=== Configuring using Camel XML DSL
 
-Camel integration using XML DSL is basically very similar. You just have to add the +properties+ component as bean
-as well. All other configuration parameters (e.g. file URIs are similar supported). In the example code below we
-again use Tamaya as the main configuration solutions only using Camel's default behaviour as a fallback:
+=== Format of Collection Configuration
 
-[source, xml]
+By default collections are modelled as simple String values, that are tokenized into individual parts using a
+defined +item-separator+ (by default +','+). So a given configuration entry of +1,2,3+ is mapped to +"1","2","3".
+If the target context type is something different than String the smae conversion logic is used as when mapping
+configuration parameters directly to non-String target types (implemented as +PropertyConverter+ classes, manahed
+within the current +ConfigurationContext+. The procedure is identical for all collection types, including +Map+ types,
+with the difference that each token in the list is parsed once more for separating it into a +key+ and a +value+.
+The default separator for map entries hereby is +"::"+. Map keys, as of now, are always of type +String+, whereas
+for values the same logic is applied as for non-map collection types.
+
+[source, properties]
+-----------------------------------------------
+# a list, using the default format
+list=1,2,3,4,5,6
+
+# a map, using the default format
+map=a::b, c::d
+-----------------------------------------------
+
+==== Trimming of entries
+
+By default all tokens parsed are trimmed _before_ adding them to the final collection. In case of map entries this is
+also the case for key/value entries. So the following configuration results in the identical values for
++list1,list2+ and +map1,map2+:
+
+[source, properties]
+-----------------------------------------------
+# a list, using the default format
+list1=1,2,3,4,5,6
+list2=1, 2, 3, 4, 5, 6
+
+# a map, using the default format
+map1=a::b, c::d
+map2=a :: b, c :: d
+-----------------------------------------------
+
+Nevertheless truncation can be controlled by the usage of brackets, e.g. the last list or map entry will have a single
+space character as value:
+
+[source, properties]
+-----------------------------------------------
+# a list, with a ' ' value at the end
+list3=1, 2, 3, 4, 5, [ ]
+
+# a map, with a ' ' value for key '0'
+map3=1 :: a, 2 :: b, 0::[ ]
+-----------------------------------------------
+
+Hereby +\[+ escapes the sequence.
+
+
+==== Customizing the format
+
+The item and entry separators (by default +','+ and +"::"+) can be customized by setting corresponding meta-data
+entries as follows, resulting in the same values as in the prevoius listing:
+
+[source, properties]
+-----------------------------------------------
+# a list, with a ' ' value at the end
+list3=1__2__3__ 4__ 5__[ ]
+_list3.item-separator=__
+
+# a map, with a ' ' value for key '0'
+map3=1->a, 2->b, 0->[ ]
+_map3.map-entry-separator=->
+-----------------------------------------------
+
+Of course these settings also can be combined:
+
+[source, properties]
 -----------------------------------------------
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="
-       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
-       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
-    ">
-
-    <routeContext id="myCoolRoutes" xmlns="http://camel.apache.org/schema/spring">
-        <route id="r1">
-            <from uri="direct:hello1"/>
-            <transform>
-                <simple>{{message}}</simple>
-            </transform>
-        </route>
-        <route id="r2">
-            <from uri="direct:hello2"/>
-            <transform>
-                <simple>{{cfg:message}}</simple>
-            </transform>
-        </route>
-        <route id="r3">
-            <from uri="direct:hello3"/>
-            <transform>
-                <simple>{{tamaya:message}}</simple>
-            </transform>
-        </route>
-    </routeContext>
-
-    <bean id="properties" class="org.apache.tamaya.integration.camel.TamayaPropertiesComponent">
-        <property name="tamayaOverrides" value="true"/>
-    </bean>
-
-</beans>
+# a reformatted map
+redefined-map=0==none | 1==single | 2==any
+_redefined-map.map-entry-separator===
+_redefined-map.item-separator=|
 -----------------------------------------------
\ No newline at end of file


[6/8] incubator-tamaya git commit: Redesigned component slightly.

Posted by an...@apache.org.
Redesigned component slightly.


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

Branch: refs/heads/master
Commit: 1547d4a9c0c05b50a605f2e44ae871b77a467266
Parents: 89bf981
Author: anatole <an...@apache.org>
Authored: Thu Feb 18 00:38:01 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Thu Feb 18 00:38:01 2016 +0100

----------------------------------------------------------------------
 ...aya.mutableconfig.spi.ConfigChangeManagerSpi |  19 --
 ...g.spi.MutableConfigurationBackendProviderSpi |  19 ++
 .../mutableconfig/ConfigChangeManager.java      | 238 -------------------
 .../mutableconfig/ConfigChangeRequest.java      | 164 -------------
 .../mutableconfig/MutableConfiguration.java     | 164 +++++++++++++
 .../MutableConfigurationQuery.java              | 238 +++++++++++++++++++
 .../internal/DefaultConfigChangeManagerSpi.java |  52 ----
 .../DefaultConfigurationBackendSpi.java         |  52 ++++
 .../PropertiesFileConfigBackendSpi.java         | 114 +++++++++
 .../PropertiesFileConfigChangeRequest.java      | 116 ---------
 .../XmlPropertiesFileConfigBackendSpi.java      | 114 +++++++++
 .../XmlPropertiesFileConfigChangeRequest.java   | 116 ---------
 .../spi/AbstractConfigChangeRequest.java        | 167 -------------
 .../spi/AbstractMutableConfiguration.java       | 167 +++++++++++++
 ...stractMutableConfigurationBackendSpiSpi.java | 107 +++++++++
 .../spi/ConfigChangeManagerSpi.java             |  39 ---
 .../MutableConfigurationBackendProviderSpi.java |  40 ++++
 .../spi/MutableConfigurationBackendSpi.java     | 143 +++++++++++
 ...aya.mutableconfig.spi.ConfigChangeManagerSpi |  19 --
 ...g.spi.MutableConfigurationBackendProviderSpi |  19 ++
 .../mutableconfig/ConfigChangeManagerTest.java  |  78 ------
 .../MutableConfigurationQueryTest.java          |  78 ++++++
 .../PropertiesFileConfigBackendTest.java        | 161 +++++++++++++
 .../PropertiesFileConfigChangeRequestTest.java  | 161 -------------
 24 files changed, 1416 insertions(+), 1169 deletions(-)
----------------------------------------------------------------------


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

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

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java
deleted file mode 100644
index 8142fcc..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java
+++ /dev/null
@@ -1,238 +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.mutableconfig;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
-import org.apache.tamaya.spi.ServiceContextManager;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.UUID;
-
-
-/**
- * Accessor for creating {@link ConfigChangeRequest} instances to change and commit configuration.
- */
-public final class ConfigChangeManager {
-
-    /** Singleton constructor. */
-    private ConfigChangeManager(){}
-
-    /**
-     * Creates a new change request for the given configurationSource
-     *
-     * @param configurationTargets the configuration targets (String to create URIs) to use to write the changes/config. By passing multiple
-     *                             URIs you can write back changes into multiple configuration backends, e.g.
-     *                             one for redistributing changes using multicast mechanism, a local property file
-     *                             for failover as well as the shared etcd server.
-     * @return a new ChangeRequest
-     * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
-     */
-    public static ConfigChangeRequest createChangeRequest(String... configurationTargets){
-        try {
-            URI[] uris = new URI[configurationTargets.length];
-            for (int i = 0; i < configurationTargets.length; i++) {
-                uris[i] = new URI(configurationTargets[i]);
-            }
-            return createChangeRequest(uris);
-        } catch(URISyntaxException e){
-            throw new ConfigException("Invalid URIs enocuntered in " + Arrays.toString(configurationTargets));
-        }
-    }
-
-    /**
-     * Creates a new change request for the given configurationSource
-     *
-     * @param configurationTargets the configuration targets to use to write the changes/config. By passing multiple
-     *                             URIs you can write back changes into multiple configuration backends, e.g.
-     *                             one for redistributing changes using multicast mechanism, a local property file
-     *                             for failover as well as the shared etcd server.
-     * @return a new ChangeRequest
-     * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
-     */
-    public static ConfigChangeRequest createChangeRequest(URI... configurationTargets){
-        if(Objects.requireNonNull(configurationTargets).length==0){
-            throw new IllegalArgumentException("At least one target URI is required.");
-        }
-        List<ConfigChangeRequest> targets = new ArrayList<>();
-        for(ConfigChangeManagerSpi spi:ServiceContextManager.getServiceContext()
-                .getServices(ConfigChangeManagerSpi.class)){
-            for(URI target:configurationTargets) {
-                ConfigChangeRequest req = spi.createChangeRequest(target);
-                if (req != null) {
-                    targets.add(req);
-                }
-            }
-        }
-        if(targets.isEmpty()) {
-            throw new ConfigException("Not an editable configuration target for: " +
-                    Arrays.toString(configurationTargets));
-        }
-        if(targets.size()==1){
-            return targets.get(0);
-        }
-        return new CompoundConfigChangeRequest(targets);
-    }
-
-
-    /**
-     * Compound request that contains internally multiple change requests. Changes are committed to all members.
-     */
-    private static final class CompoundConfigChangeRequest implements ConfigChangeRequest{
-
-        private final List<ConfigChangeRequest> targets;
-        private final List<URI> backendURIs = new ArrayList<>();
-        private String requestId = UUID.randomUUID().toString();
-
-        CompoundConfigChangeRequest(List<ConfigChangeRequest> targets){
-            this.targets = targets;
-            for(ConfigChangeRequest req:targets){
-                req.setRequestId(requestId);
-                backendURIs.addAll(req.getBackendURIs());
-            }
-        }
-
-        @Override
-        public String getRequestID() {
-            return requestId;
-        }
-
-        @Override
-        public List<URI> getBackendURIs() {
-            return Collections.unmodifiableList(backendURIs);
-        }
-
-        @Override
-        public boolean isWritable(String keyExpression) {
-            for(ConfigChangeRequest req:targets){
-                if(req.isWritable(keyExpression)){
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public boolean isRemovable(String keyExpression) {
-            for(ConfigChangeRequest req:targets){
-                if(req.isRemovable(keyExpression)){
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public boolean exists(String keyExpression) {
-            for(ConfigChangeRequest req:targets){
-                if(req.exists(keyExpression)){
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public ConfigChangeRequest put(String key, String value) {
-            for(ConfigChangeRequest req:targets){
-                if(req.isWritable(key)){
-                    req.put(key, value);
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public ConfigChangeRequest putAll(Map<String, String> properties) {
-            for(ConfigChangeRequest req:targets){
-                for(Map.Entry<String,String> en:properties.entrySet()) {
-                    if (req.isWritable(en.getKey())) {
-                        req.put(en.getKey(), en.getValue());
-                    }
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public ConfigChangeRequest remove(String... keys) {
-            for(ConfigChangeRequest req:targets){
-                for(String key:keys){
-                    if (req.isRemovable(key)) {
-                        req.remove(key);
-                    }
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public ConfigChangeRequest remove(Collection<String> keys) {
-            for(ConfigChangeRequest req:targets){
-                for(String key:keys){
-                    if (req.isRemovable(key)) {
-                        req.remove(key);
-                    }
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public void commit() {
-            for(ConfigChangeRequest req:targets){
-                req.commit();
-            }
-        }
-
-        @Override
-        public void cancel() {
-            for(ConfigChangeRequest req:targets){
-                req.cancel();
-            }
-        }
-
-        @Override
-        public boolean isClosed() {
-            for(ConfigChangeRequest req:targets){
-                if(req.isClosed()){
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public void setRequestId(String requestId) {
-            if(isClosed()){
-                throw new IllegalStateException("Cannot set requestId, already closed.");
-            }
-            this.requestId = Objects.requireNonNull(requestId);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java
deleted file mode 100644
index a192f50..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java
+++ /dev/null
@@ -1,164 +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.mutableconfig;
-
-import java.net.URI;
-import java.util.Collection;
-import java.util.Map;
-
-
-/**
- * This interface extends the Configuration interface hereby adding methods to change configuration entries.
- * Hereby not all configuration entries are necessarily mutable, since some entries may be read from non
- * mutable areas of configuration. Of course, it is always possible to add a mutable shadow layer on top of all
- * configuration to enable whatever changes applied. The exact management and storage persistence algorithm should be
- * transparent.<br>
- * As a consequence clients should first check, using the corresponding methods, if entries are to edited or removed
- * actually are eligible for change/creation or removal.
- */
-public interface ConfigChangeRequest {
-
-    /**
-     * Get the unique id of this change request (UUID).
-     *
-     * @return the unique id of this change request (UUID).
-     */
-    String getRequestID();
-
-    /**
-     * Identifies the configuration backends that participate in this request instance and which are
-     * also responsible for writing back the changes applied.
-     *
-     * @return the backend URI, never null.
-     */
-    Collection<URI> getBackendURIs();
-
-    /**
-     * Checks if a configuration key is writable (or it can be added).
-     *
-     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could also
-     *                      be a regular expression, such "as a.b.c.*".
-     * @return the boolean
-     */
-    boolean isWritable(String keyExpression);
-
-    /**
-     * Checks if a configuration key is removable. This also implies that it is writable, but there might be writable
-     * keys that cannot be removed.
-     *
-     * @param keyExpression the keyExpression the key to be cheched for write access (including creation), not null.
-     *                      Here this could also
-     *                      be a regulat expression, such "as a.b.c.*".
-     * @return the boolean
-     */
-    boolean isRemovable(String keyExpression);
-
-    /**
-     * Checks if any keys of the given type already exist in the backend. <b>NOTE:</b> there may be backends that
-     * are not able to support lookups with regular expressions. In most such cases you should pass the keys to
-     * lookup explicitly.
-     *
-     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could
-     *                      also be a regular expression, such "as a.b.c.*".
-     * @return true, if there is any key found matching the expression.
-     */
-    boolean exists(String keyExpression);
-
-    /**
-     * Sets a property.
-     *
-     * @param key   the property's key, not null.
-     * @param value the property's value, not null.
-     * @return the former property value, or null.
-     * @throws org.apache.tamaya.ConfigException if the key/value cannot be added, or the request is read-only.
-     */
-    ConfigChangeRequest put(String key, String value);
-
-    /**
-     * Puts all given configuration entries. This method should check that all given properties are
-     * basically removable, as defined by #isWritable. If any of the passed keys is not writable during this initial
-     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
-     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
-     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
-     * remove all entries as far as possible and abort the writing operation.
-     *
-     * @param properties the properties tobe written, not null.
-     * @return the config change request
-     * @throws org.apache.tamaya.ConfigException if any of the given properties could not be written, or the request is read-only.
-     */
-    ConfigChangeRequest putAll(Map<String, String> properties);
-
-    /**
-     * Removes all given configuration entries. This method should check that all given properties are
-     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
-     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
-     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
-     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
-     * remove all entries as far as possible and abort the writing operation.
-     *
-     * @param keys the property's keys to be removed, not null.
-     * @return the config change request
-     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
-     */
-    ConfigChangeRequest remove(Collection<String> keys);
-
-    /**
-     * Removes all given configuration entries. This method should check that all given properties are
-     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
-     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
-     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
-     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
-     * remove all entries as far as possible and abort the writing operation.
-     *
-     * @param keys the property's keys to be removed, not null.
-     * @return the config change request
-     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
-     */
-    ConfigChangeRequest remove(String... keys);
-
-    /**
-     * Commits the request. After a commit the change is not editable anymore. All changes applied will be written to
-     * the corresponding configuration backend.
-     * " @throws ConfigException if the request already has been committed or cancelled, or the commit fails.
-     */
-    void commit();
-
-    /**
-     * Cancel the given request, leaving everything unchanged. Cancelled requests are read-only and can not be used
-     * for preparing/submitting any configuration changes.
-     *
-     * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled.
-     */
-    void cancel();
-
-    /**
-     * Operation to check, if the current request is closed (either commited or cancelled). Closed requests are
-     * read-only and can not be used for preparing/submitting any configuration changes.
-     *
-     * @return true, if this instance is closed.
-     */
-    boolean isClosed();
-
-    /**
-     * Method to set the request id to be used.
-     * @param requestId the id to  be used, not null
-     * @throws IllegalStateException if the request is already closed.
-     */
-    void setRequestId(String requestId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
new file mode 100644
index 0000000..fed3151
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
@@ -0,0 +1,164 @@
+/*
+ * 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.mutableconfig;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Map;
+
+
+/**
+ * This interface extends the Configuration interface hereby adding methods to change configuration entries.
+ * Hereby not all configuration entries are necessarily mutable, since some entries may be read from non
+ * mutable areas of configuration. Of course, it is always possible to add a mutable shadow layer on top of all
+ * configuration to enable whatever changes applied. The exact management and storage persistence algorithm should be
+ * transparent.<br>
+ * As a consequence clients should first check, using the corresponding methods, if entries are to edited or removed
+ * actually are eligible for change/creation or removal.
+ */
+public interface MutableConfiguration {
+
+    /**
+     * Get the unique id of this change request (UUID).
+     *
+     * @return the unique id of this change request (UUID).
+     */
+    String getRequestID();
+
+    /**
+     * Identifies the configuration backends that participate in this request instance and which are
+     * also responsible for writing back the changes applied.
+     *
+     * @return the backend URI, never null.
+     */
+    Collection<URI> getBackendURIs();
+
+    /**
+     * Checks if a configuration key is writable (or it can be added).
+     *
+     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could also
+     *                      be a regular expression, such "as a.b.c.*".
+     * @return the boolean
+     */
+    boolean isWritable(String keyExpression);
+
+    /**
+     * Checks if a configuration key is removable. This also implies that it is writable, but there might be writable
+     * keys that cannot be removed.
+     *
+     * @param keyExpression the keyExpression the key to be cheched for write access (including creation), not null.
+     *                      Here this could also
+     *                      be a regulat expression, such "as a.b.c.*".
+     * @return the boolean
+     */
+    boolean isRemovable(String keyExpression);
+
+    /**
+     * Checks if any keys of the given type already exist in the backend. <b>NOTE:</b> there may be backends that
+     * are not able to support lookups with regular expressions. In most such cases you should pass the keys to
+     * lookup explicitly.
+     *
+     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could
+     *                      also be a regular expression, such "as a.b.c.*".
+     * @return true, if there is any key found matching the expression.
+     */
+    boolean exists(String keyExpression);
+
+    /**
+     * Sets a property.
+     *
+     * @param key   the property's key, not null.
+     * @param value the property's value, not null.
+     * @return the former property value, or null.
+     * @throws org.apache.tamaya.ConfigException if the key/value cannot be added, or the request is read-only.
+     */
+    MutableConfiguration put(String key, String value);
+
+    /**
+     * Puts all given configuration entries. This method should check that all given properties are
+     * basically removable, as defined by #isWritable. If any of the passed keys is not writable during this initial
+     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+     * remove all entries as far as possible and abort the writing operation.
+     *
+     * @param properties the properties tobe written, not null.
+     * @return the config change request
+     * @throws org.apache.tamaya.ConfigException if any of the given properties could not be written, or the request is read-only.
+     */
+    MutableConfiguration putAll(Map<String, String> properties);
+
+    /**
+     * Removes all given configuration entries. This method should check that all given properties are
+     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
+     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+     * remove all entries as far as possible and abort the writing operation.
+     *
+     * @param keys the property's keys to be removed, not null.
+     * @return the config change request
+     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
+     */
+    MutableConfiguration remove(Collection<String> keys);
+
+    /**
+     * Removes all given configuration entries. This method should check that all given properties are
+     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
+     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+     * remove all entries as far as possible and abort the writing operation.
+     *
+     * @param keys the property's keys to be removed, not null.
+     * @return the config change request
+     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
+     */
+    MutableConfiguration remove(String... keys);
+
+    /**
+     * Commits the request. After a commit the change is not editable anymore. All changes applied will be written to
+     * the corresponding configuration backend.
+     * " @throws ConfigException if the request already has been committed or cancelled, or the commit fails.
+     */
+    void commit();
+
+    /**
+     * Cancel the given request, leaving everything unchanged. Cancelled requests are read-only and can not be used
+     * for preparing/submitting any configuration changes.
+     *
+     * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled.
+     */
+    void cancel();
+
+    /**
+     * Operation to check, if the current request is closed (either commited or cancelled). Closed requests are
+     * read-only and can not be used for preparing/submitting any configuration changes.
+     *
+     * @return true, if this instance is closed.
+     */
+    boolean isClosed();
+
+    /**
+     * Method to set the request id to be used.
+     * @param requestId the id to  be used, not null
+     * @throws IllegalStateException if the request is already closed.
+     */
+    void setRequestId(String requestId);
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
new file mode 100644
index 0000000..7aaf2bf
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
@@ -0,0 +1,238 @@
+/*
+ * 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.mutableconfig;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
+import org.apache.tamaya.spi.ServiceContextManager;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+
+/**
+ * Accessor for creating {@link MutableConfiguration} instances to change and commit configuration.
+ */
+public final class MutableConfigurationQuery {
+
+    /** Singleton constructor. */
+    private MutableConfigurationQuery(){}
+
+    /**
+     * Creates a new change request for the given configurationSource
+     *
+     * @param configurationTargets the configuration targets (String to create URIs) to use to write the changes/config. By passing multiple
+     *                             URIs you can write back changes into multiple configuration backends, e.g.
+     *                             one for redistributing changes using multicast mechanism, a local property file
+     *                             for failover as well as the shared etcd server.
+     * @return a new ChangeRequest
+     * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
+     */
+    public static MutableConfiguration createChangeRequest(String... configurationTargets){
+        try {
+            URI[] uris = new URI[configurationTargets.length];
+            for (int i = 0; i < configurationTargets.length; i++) {
+                uris[i] = new URI(configurationTargets[i]);
+            }
+            return createChangeRequest(uris);
+        } catch(URISyntaxException e){
+            throw new ConfigException("Invalid URIs enocuntered in " + Arrays.toString(configurationTargets));
+        }
+    }
+
+    /**
+     * Creates a new change request for the given configurationSource
+     *
+     * @param configurationTargets the configuration targets to use to write the changes/config. By passing multiple
+     *                             URIs you can write back changes into multiple configuration backends, e.g.
+     *                             one for redistributing changes using multicast mechanism, a local property file
+     *                             for failover as well as the shared etcd server.
+     * @return a new ChangeRequest
+     * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
+     */
+    public static MutableConfiguration createChangeRequest(URI... configurationTargets){
+        if(Objects.requireNonNull(configurationTargets).length==0){
+            throw new IllegalArgumentException("At least one target URI is required.");
+        }
+        List<MutableConfiguration> targets = new ArrayList<>();
+        for(ConfigChangeManagerSpi spi:ServiceContextManager.getServiceContext()
+                .getServices(ConfigChangeManagerSpi.class)){
+            for(URI target:configurationTargets) {
+                MutableConfiguration req = spi.createChangeRequest(target);
+                if (req != null) {
+                    targets.add(req);
+                }
+            }
+        }
+        if(targets.isEmpty()) {
+            throw new ConfigException("Not an editable configuration target for: " +
+                    Arrays.toString(configurationTargets));
+        }
+        if(targets.size()==1){
+            return targets.get(0);
+        }
+        return new CompoundConfigChangeRequest(targets);
+    }
+
+
+    /**
+     * Compound request that contains internally multiple change requests. Changes are committed to all members.
+     */
+    private static final class CompoundConfigChangeRequest implements MutableConfiguration {
+
+        private final List<MutableConfiguration> targets;
+        private final List<URI> backendURIs = new ArrayList<>();
+        private String requestId = UUID.randomUUID().toString();
+
+        CompoundConfigChangeRequest(List<MutableConfiguration> targets){
+            this.targets = targets;
+            for(MutableConfiguration req:targets){
+                req.setRequestId(requestId);
+                backendURIs.addAll(req.getBackendURIs());
+            }
+        }
+
+        @Override
+        public String getRequestID() {
+            return requestId;
+        }
+
+        @Override
+        public List<URI> getBackendURIs() {
+            return Collections.unmodifiableList(backendURIs);
+        }
+
+        @Override
+        public boolean isWritable(String keyExpression) {
+            for(MutableConfiguration req:targets){
+                if(req.isWritable(keyExpression)){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public boolean isRemovable(String keyExpression) {
+            for(MutableConfiguration req:targets){
+                if(req.isRemovable(keyExpression)){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public boolean exists(String keyExpression) {
+            for(MutableConfiguration req:targets){
+                if(req.exists(keyExpression)){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public MutableConfiguration put(String key, String value) {
+            for(MutableConfiguration req:targets){
+                if(req.isWritable(key)){
+                    req.put(key, value);
+                }
+            }
+            return this;
+        }
+
+        @Override
+        public MutableConfiguration putAll(Map<String, String> properties) {
+            for(MutableConfiguration req:targets){
+                for(Map.Entry<String,String> en:properties.entrySet()) {
+                    if (req.isWritable(en.getKey())) {
+                        req.put(en.getKey(), en.getValue());
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        public MutableConfiguration remove(String... keys) {
+            for(MutableConfiguration req:targets){
+                for(String key:keys){
+                    if (req.isRemovable(key)) {
+                        req.remove(key);
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        public MutableConfiguration remove(Collection<String> keys) {
+            for(MutableConfiguration req:targets){
+                for(String key:keys){
+                    if (req.isRemovable(key)) {
+                        req.remove(key);
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        public void commit() {
+            for(MutableConfiguration req:targets){
+                req.commit();
+            }
+        }
+
+        @Override
+        public void rollback() {
+            for(MutableConfiguration req:targets){
+                req.rollback();
+            }
+        }
+
+        @Override
+        public boolean isClosed() {
+            for(MutableConfiguration req:targets){
+                if(req.isClosed()){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public void setRequestId(String requestId) {
+            if(isClosed()){
+                throw new IllegalStateException("Cannot set requestId, already closed.");
+            }
+            this.requestId = Objects.requireNonNull(requestId);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java
deleted file mode 100644
index d1d8371..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java
+++ /dev/null
@@ -1,52 +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.mutableconfig.internal;
-
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
-
-import java.io.File;
-import java.net.URI;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Mutable Config Request factory that tries to convert given URIs to file references, if successful, it returns
- * ConfigChangeRequests fir .properties and .xml files.
- */
-public class DefaultConfigChangeManagerSpi implements ConfigChangeManagerSpi{
-
-    private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
-
-    @Override
-    public ConfigChangeRequest createChangeRequest(URI uri) {
-        try{
-            File f = new File(uri);
-            if(f.getName().endsWith(".properties")){
-                return new PropertiesFileConfigChangeRequest(f);
-            }else if(f.getName().endsWith(".xml")){
-                return new XmlPropertiesFileConfigChangeRequest(f);
-            }
-        } catch(Exception e){
-            LOG.log(Level.FINEST, "URI not convertible to file, ignoring " + uri, e);
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
new file mode 100644
index 0000000..e5def2e
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
@@ -0,0 +1,52 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.mutableconfig.spi.ConfigurationBackendSpi;
+
+import java.io.File;
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Mutable Config Request factory that tries to convert given URIs to file references, if successful, it returns
+ * ConfigChangeRequests fir .properties and .xml files.
+ */
+public class DefaultConfigurationBackendSpi implements ConfigurationBackendSpi {
+
+    private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
+
+    @Override
+    public MutableConfiguration getBackend(URI uri) {
+        try{
+            File f = new File(uri);
+            if(f.getName().endsWith(".properties")){
+                return new PropertiesFileConfigChangeRequest(f);
+            }else if(f.getName().endsWith(".xml")){
+                return new XmlPropertiesFileConfigChangeRequest(f);
+            }
+        } catch(Exception e){
+            LOG.log(Level.FINEST, "URI not convertible to file, ignoring " + uri, e);
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java
new file mode 100644
index 0000000..15a68cb
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java
@@ -0,0 +1,114 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.spi.AbstractMutableConfigurationBackendSpiSpi;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Change Request implementation based on .properties file.
+ */
+class PropertiesFileConfigBackendSpi extends AbstractMutableConfigurationBackendSpiSpi {
+
+    private static final Logger LOG = Logger.getLogger(PropertiesFileConfigBackendSpi.class.getName());
+
+    private final File file;
+
+    private final Properties properties = new Properties();
+
+    /**
+     * Instantiates a new Properties file config change request.
+     *
+     * @param file the file
+     */
+    PropertiesFileConfigBackendSpi(File file){
+        super(file.toURI());
+        this.file = file;
+        if(file.exists()) {
+            try (InputStream is = getBackendURI().toURL().openStream()) {
+                properties.load(is);
+            } catch (Exception e) {
+                LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
+            }
+        }
+    }
+
+    @Override
+    public boolean isExisting(String keyExpression) {
+        if(properties.containsKey(keyExpression)){
+            return true;
+        }
+        for(Object key:properties.keySet()){
+            if(key.toString().matches(keyExpression)){
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    @Override
+    protected void commitInternal() {
+        if(!file.exists()){
+            try {
+                if(!file.createNewFile()){
+                    throw new ConfigException("Failed to create config file " + file);
+                }
+            } catch (IOException e) {
+                throw new ConfigException("Failed to create config file " + file, e);
+            }
+        }
+        for(Map.Entry<String,String> en:super.addedProperties.entrySet()){
+            int index = en.getKey().indexOf('?');
+            if(index>0){
+                this.properties.put(en.getKey().substring(0, index), en.getValue());
+            }else{
+                this.properties.put(en.getKey(), en.getValue());
+            }
+        }
+        for(String rmKey:super.removedProperties){
+            this.properties.remove(rmKey);
+        }
+        try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
+            properties.store(bos, "Properties written from Tamaya on : " + new Date());
+            bos.flush();
+        }
+        catch(Exception e){
+            throw new ConfigException("Failed to write config to " + file, e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "PropertiesFileConfigBackend{" +
+                "file=" + file +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java
deleted file mode 100644
index 94d3f2e..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java
+++ /dev/null
@@ -1,116 +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.mutableconfig.internal;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.AbstractConfigChangeRequest;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Map;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Change Request implementation based on .properties file.
- */
-class PropertiesFileConfigChangeRequest extends AbstractConfigChangeRequest{
-
-    private static final Logger LOG = Logger.getLogger(PropertiesFileConfigChangeRequest.class.getName());
-
-    private final File file;
-
-    private final Properties properties = new Properties();
-
-    /**
-     * Instantiates a new Properties file config change request.
-     *
-     * @param file the file
-     */
-    PropertiesFileConfigChangeRequest(File file){
-        super(file.toURI());
-        this.file = file;
-        if(file.exists()) {
-            for(URI uri:getBackendURIs()) {
-                try (InputStream is = uri.toURL().openStream()) {
-                    properties.load(is);
-                } catch (Exception e) {
-                    LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean exists(String keyExpression) {
-        if(properties.containsKey(keyExpression)){
-            return true;
-        }
-        for(Object key:properties.keySet()){
-            if(key.toString().matches(keyExpression)){
-                return true;
-            }
-        }
-        return false;
-    }
-
-
-    @Override
-    protected void commitInternal() {
-        if(!file.exists()){
-            try {
-                if(!file.createNewFile()){
-                    throw new ConfigException("Failed to create config file " + file);
-                }
-            } catch (IOException e) {
-                throw new ConfigException("Failed to create config file " + file, e);
-            }
-        }
-        for(Map.Entry<String,String> en:super.properties.entrySet()){
-            int index = en.getKey().indexOf('?');
-            if(index>0){
-                this.properties.put(en.getKey().substring(0, index), en.getValue());
-            }else{
-                this.properties.put(en.getKey(), en.getValue());
-            }
-        }
-        for(String rmKey:super.removed){
-            this.properties.remove(rmKey);
-        }
-        try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
-            properties.store(bos, "Properties written from Tamaya, request: " + getRequestID());
-            bos.flush();
-        }
-        catch(Exception e){
-            throw new ConfigException("Failed to write config to " + file, e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "PropertiesFileConfigChangeRequest{" +
-                "file=" + file +
-                '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java
new file mode 100644
index 0000000..cdca80d
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java
@@ -0,0 +1,114 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.spi.AbstractMutableConfigurationBackendSpiSpi;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Change Request implementation based on .xml properties file.
+ */
+class XmlPropertiesFileConfigBackendSpi extends AbstractMutableConfigurationBackendSpiSpi {
+
+    private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigBackendSpi.class.getName());
+
+    private final File file;
+
+    private final Properties properties = new Properties();
+
+    /**
+     * Instantiates a new Xml properties file config change request.
+     *
+     * @param file the file
+     */
+    XmlPropertiesFileConfigBackendSpi(File file){
+        super(file.toURI());
+        this.file = file;
+        if(file.exists()) {
+            try (InputStream is = getBackendURI().toURL().openStream()) {
+                properties.loadFromXML(is);
+            } catch (Exception e) {
+                LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
+            }
+        }
+    }
+
+    @Override
+    public boolean isExisting(String keyExpression) {
+        if(properties.containsKey(keyExpression)){
+            return true;
+        }
+        for(Object key:properties.keySet()){
+            if(key.toString().matches(keyExpression)){
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    @Override
+    protected void commitInternal() {
+        if(!file.exists()){
+            try {
+                if(!file.createNewFile()){
+                    throw new ConfigException("Failed to create config file " + file);
+                }
+            } catch (IOException e) {
+                throw new ConfigException("Failed to create config file " + file, e);
+            }
+        }
+        for(Map.Entry<String,String> en:super.addedProperties.entrySet()){
+            int index = en.getKey().indexOf('?');
+            if(index>0){
+                this.properties.put(en.getKey().substring(0, index), en.getValue());
+            }else{
+                this.properties.put(en.getKey(), en.getValue());
+            }
+        }
+        for(String rmKey:super.removedProperties){
+            this.properties.remove(rmKey);
+        }
+        try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
+            properties.storeToXML(bos, "Properties written from Tamaya on " + new Date());
+            bos.flush();
+        }
+        catch(Exception e){
+            throw new ConfigException("Failed to write config to " + file, e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "XmlPropertiesFileConfigBackend{" +
+                "file=" + file +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java
deleted file mode 100644
index 9211641..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java
+++ /dev/null
@@ -1,116 +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.mutableconfig.internal;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.AbstractConfigChangeRequest;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Map;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Change Request implementation based on .xml properties file.
- */
-class XmlPropertiesFileConfigChangeRequest extends AbstractConfigChangeRequest{
-
-    private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
-
-    private final File file;
-
-    private final Properties properties = new Properties();
-
-    /**
-     * Instantiates a new Xml properties file config change request.
-     *
-     * @param file the file
-     */
-    XmlPropertiesFileConfigChangeRequest(File file){
-        super(file.toURI());
-        this.file = file;
-        if(file.exists()) {
-            for(URI uri:getBackendURIs()) {
-                try (InputStream is = uri.toURL().openStream()) {
-                    properties.loadFromXML(is);
-                } catch (Exception e) {
-                    LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean exists(String keyExpression) {
-        if(properties.containsKey(keyExpression)){
-            return true;
-        }
-        for(Object key:properties.keySet()){
-            if(key.toString().matches(keyExpression)){
-                return true;
-            }
-        }
-        return false;
-    }
-
-
-    @Override
-    protected void commitInternal() {
-        if(!file.exists()){
-            try {
-                if(!file.createNewFile()){
-                    throw new ConfigException("Failed to create config file " + file);
-                }
-            } catch (IOException e) {
-                throw new ConfigException("Failed to create config file " + file, e);
-            }
-        }
-        for(Map.Entry<String,String> en:super.properties.entrySet()){
-            int index = en.getKey().indexOf('?');
-            if(index>0){
-                this.properties.put(en.getKey().substring(0, index), en.getValue());
-            }else{
-                this.properties.put(en.getKey(), en.getValue());
-            }
-        }
-        for(String rmKey:super.removed){
-            this.properties.remove(rmKey);
-        }
-        try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
-            properties.storeToXML(bos, "Properties written from Tamaya, request: " + getRequestID());
-            bos.flush();
-        }
-        catch(Exception e){
-            throw new ConfigException("Failed to write config to " + file, e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "XmlPropertiesFileConfigChangeRequest{" +
-                "file=" + file +
-                '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java
deleted file mode 100644
index 5e319db..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java
+++ /dev/null
@@ -1,167 +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.mutableconfig.spi;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Base class for implementing a ConfigChangeRequest.
- */
-public abstract class AbstractConfigChangeRequest implements ConfigChangeRequest {
-
-    private final List<URI> uris = new ArrayList<>();
-    private String requestID = UUID.randomUUID().toString();
-    /**
-     * The Properties.
-     */
-    protected final Map<String,String> properties = new HashMap<>();
-    /**
-     * The Removed.
-     */
-    protected final Set<String> removed = new HashSet<>();
-    private boolean closed = false;
-
-    protected Set<String> getRemoved() {
-        return removed;
-    }
-
-    protected Map<String,String> getProperties() {
-        return properties;
-    }
-
-    /**
-     * Instantiates a new Abstract config change request.
-     *
-     * @param uris the uris
-     */
-    protected AbstractConfigChangeRequest(URI... uris){
-        for(URI uri:uris){
-            this.uris.add(Objects.requireNonNull(uri));
-        }
-        if(this.uris.isEmpty()){
-            throw new IllegalArgumentException("At least one URI should be provided.");
-        }
-    }
-
-    /**
-     * Get the unique id of this change request (UUID).
-     * @return the unique id of this change request (UUID).
-     */
-    @Override
-    public String getRequestID(){
-        return requestID;
-    }
-
-    @Override
-    public final Collection<URI> getBackendURIs() {
-        return Collections.unmodifiableCollection(uris);
-    }
-
-    @Override
-    public boolean isWritable(String keyExpression) {
-        return true;
-    }
-
-    @Override
-    public boolean isRemovable(String keyExpression) {
-        return true;
-    }
-
-    @Override
-    public abstract boolean exists(String keyExpression);
-
-    @Override
-    public void setRequestId(String requestId) {
-        checkClosed();
-        this.requestID = Objects.requireNonNull(requestId);
-    }
-
-    @Override
-    public ConfigChangeRequest put(String key, String value) {
-        checkClosed();
-        this.properties.put(key, value);
-        return this;
-    }
-
-    @Override
-    public ConfigChangeRequest putAll(Map<String, String> properties) {
-        checkClosed();
-        this.properties.putAll(properties);
-        return this;
-    }
-
-    @Override
-    public ConfigChangeRequest remove(String... keys) {
-        checkClosed();
-        Collections.addAll(this.removed, keys);
-        return this;
-    }
-
-    @Override
-    public ConfigChangeRequest remove(Collection<String> keys) {
-        checkClosed();
-        this.removed.addAll(keys);
-        return this;
-    }
-
-    @Override
-    public final void commit() {
-        checkClosed();
-        commitInternal();
-        closed = true;
-    }
-
-    /**
-     * Commit internal.
-     */
-    protected abstract void commitInternal();
-
-    @Override
-    public final void cancel() {
-        checkClosed();
-        closed = true;
-    }
-
-    @Override
-    public final boolean isClosed() {
-        return closed;
-    }
-
-    /**
-     * Check closed.
-     */
-    protected void checkClosed(){
-        if(closed){
-            throw new ConfigException("Change request already closed.");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
new file mode 100644
index 0000000..2dd9a20
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
@@ -0,0 +1,167 @@
+/*
+ * 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.mutableconfig.spi;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Base class for implementing a ConfigChangeRequest.
+ */
+public abstract class AbstractMutableConfiguration implements MutableConfiguration {
+
+    private final List<URI> uris = new ArrayList<>();
+    private String requestID = UUID.randomUUID().toString();
+    /**
+     * The Properties.
+     */
+    protected final Map<String,String> properties = new HashMap<>();
+    /**
+     * The Removed.
+     */
+    protected final Set<String> removed = new HashSet<>();
+    private boolean closed = false;
+
+    protected Set<String> getRemoved() {
+        return removed;
+    }
+
+    protected Map<String,String> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Instantiates a new Abstract config change request.
+     *
+     * @param uris the uris
+     */
+    protected AbstractMutableConfiguration(URI... uris){
+        for(URI uri:uris){
+            this.uris.add(Objects.requireNonNull(uri));
+        }
+        if(this.uris.isEmpty()){
+            throw new IllegalArgumentException("At least one URI should be provided.");
+        }
+    }
+
+    /**
+     * Get the unique id of this change request (UUID).
+     * @return the unique id of this change request (UUID).
+     */
+    @Override
+    public String getRequestID(){
+        return requestID;
+    }
+
+    @Override
+    public final Collection<URI> getBackendURIs() {
+        return Collections.unmodifiableCollection(uris);
+    }
+
+    @Override
+    public boolean isWritable(String keyExpression) {
+        return true;
+    }
+
+    @Override
+    public boolean isRemovable(String keyExpression) {
+        return true;
+    }
+
+    @Override
+    public abstract boolean exists(String keyExpression);
+
+    @Override
+    public void setRequestId(String requestId) {
+        checkClosed();
+        this.requestID = Objects.requireNonNull(requestId);
+    }
+
+    @Override
+    public MutableConfiguration put(String key, String value) {
+        checkClosed();
+        this.properties.put(key, value);
+        return this;
+    }
+
+    @Override
+    public MutableConfiguration putAll(Map<String, String> properties) {
+        checkClosed();
+        this.properties.putAll(properties);
+        return this;
+    }
+
+    @Override
+    public MutableConfiguration remove(String... keys) {
+        checkClosed();
+        Collections.addAll(this.removed, keys);
+        return this;
+    }
+
+    @Override
+    public MutableConfiguration remove(Collection<String> keys) {
+        checkClosed();
+        this.removed.addAll(keys);
+        return this;
+    }
+
+    @Override
+    public final void commit() {
+        checkClosed();
+        commitInternal();
+        closed = true;
+    }
+
+    /**
+     * Commit internal.
+     */
+    protected abstract void commitInternal();
+
+    @Override
+    public final void rollback() {
+        checkClosed();
+        closed = true;
+    }
+
+    @Override
+    public final boolean isClosed() {
+        return closed;
+    }
+
+    /**
+     * Check closed.
+     */
+    protected void checkClosed(){
+        if(closed){
+            throw new ConfigException("Change request already closed.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java
new file mode 100644
index 0000000..15cbe87
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java
@@ -0,0 +1,107 @@
+/*
+ * 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.mutableconfig.spi;
+
+import java.net.URI;
+import java.util.*;
+
+/**
+ * Base class for implementing a MutableConfigurationBackend.
+ */
+public abstract class AbstractMutableConfigurationBackendSpiSpi implements MutableConfigurationBackendSpi {
+
+    private final URI backendURI;
+
+    /**
+     * The Properties.
+     */
+    protected final Map<String,String> addedProperties = new HashMap<>();
+    /**
+     * The Removed.
+     */
+    protected final Set<String> removedProperties = new HashSet<>();
+
+    protected Set<String> getRemovedProperties() {
+        return removedProperties;
+    }
+
+    protected Map<String,String> getAddedProperties() {
+        return addedProperties;
+    }
+
+    protected AbstractMutableConfigurationBackendSpiSpi(URI backendURI){
+        this.backendURI = Objects.requireNonNull(backendURI);
+    }
+
+    @Override
+    public URI getBackendURI() {
+        return backendURI;
+    }
+
+    @Override
+    public boolean isWritable(String keyExpression) {
+        return true;
+    }
+
+    @Override
+    public boolean isRemovable(String keyExpression) {
+        return true;
+    }
+
+    @Override
+    public abstract boolean isExisting(String keyExpression);
+
+    @Override
+    public void put(String key, String value) {
+        this.addedProperties.put(key, value);
+    }
+
+    @Override
+    public void putAll(Map<String, String> properties) {
+        this.addedProperties.putAll(properties);
+    }
+
+    @Override
+    public void remove(String... keys) {
+        Collections.addAll(this.removedProperties, keys);
+    }
+
+    @Override
+    public void remove(Collection<String> keys) {
+        this.removedProperties.addAll(keys);
+    }
+
+    @Override
+    public final void commit() {
+        commitInternal();
+        this.removedProperties.clear();
+        this.addedProperties.clear();
+    }
+
+    /**
+     * Commit internal.
+     */
+    protected abstract void commitInternal();
+
+    @Override
+    public final void rollback() {
+        this.removedProperties.clear();
+        this.addedProperties.clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java
deleted file mode 100644
index fa78708..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java
+++ /dev/null
@@ -1,39 +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.mutableconfig.spi;
-
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-
-import java.net.URI;
-
-/**
- * Provider SPI for the {@link org.apache.tamaya.mutableconfig.ConfigChangeManager}. Providers may override
- * other providers registering with a higher {@link javax.annotation.Priority} value annotated.
- */
-public interface ConfigChangeManagerSpi {
-
-   /**
-    * Creates a new change request for the given Configuration.
-    *
-    * @param backendURI the backend uri
-    * @return a new ChangeRequest, or null if the given backend URI cannot be edited.
-    */
-   ConfigChangeRequest createChangeRequest(URI backendURI);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
new file mode 100644
index 0000000..98d4eb7
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
@@ -0,0 +1,40 @@
+/*
+ * 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.mutableconfig.spi;
+
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.mutableconfig.MutableConfigurationQuery;
+
+import java.net.URI;
+
+/**
+ * Provider SPI used by {@link MutableConfigurationQuery}. Providers may override
+ * other providers registering with a higher {@link javax.annotation.Priority} value annotated.
+ */
+public interface MutableConfigurationBackendProviderSpi {
+
+   /**
+    * Creates a new configuration backend for applying changes to.
+    *
+    * @param backendURI the backend uri
+    * @return the requested backend, or null if the given backend URI is not supported by the given SPI.
+    */
+   MutableConfigurationBackend getBackend(URI backendURI);
+
+}


[2/8] incubator-tamaya git commit: Simplified implementation, defined final parameter naming, synched with documentation.

Posted by an...@apache.org.
Simplified implementation, defined final parameter naming, synched with documentation.


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

Branch: refs/heads/master
Commit: 7b4cb8e803cd9ddec5db4903a5d6c3c05bffb8fe
Parents: 5fa631b
Author: anatole <an...@apache.org>
Authored: Wed Feb 17 22:13:46 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Wed Feb 17 22:13:46 2016 +0100

----------------------------------------------------------------------
 .../internal/AdaptiveCombinationPolicy.java     | 133 ++++++++++---------
 .../internal/ArrayListConverter.java            |   5 +-
 .../internal/ConcurrentHashMapConverter.java    |  32 +----
 .../collections/internal/HashMapConverter.java  |  49 ++-----
 .../collections/internal/HashSetConverter.java  |  29 ++--
 .../collections/internal/ItemTokenizer.java     |   5 +-
 .../internal/LinkedListConverter.java           |  30 ++---
 .../collections/internal/TreeMapConverter.java  |  18 ++-
 .../collections/internal/TreeSetConverter.java  |  30 ++---
 .../collections/CollectionAdvancedTests.java    |  21 +++
 .../META-INF/javaconfiguration.properties       |   6 +-
 11 files changed, 161 insertions(+), 197 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/AdaptiveCombinationPolicy.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/AdaptiveCombinationPolicy.java b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/AdaptiveCombinationPolicy.java
index ac5af36..3234e37 100644
--- a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/AdaptiveCombinationPolicy.java
+++ b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/AdaptiveCombinationPolicy.java
@@ -33,13 +33,45 @@ import java.util.logging.Logger;
 
 /**
  * PropertyValueCombinationPolicy that allows to configure a PropertyValueCombinationPolicy for each key
- * individually, by adding a configured entry of the form {@code key{combinationPolicy}=fqPolicyClassName}.
+ * individually, by adding a configured entry of the form
+ * {@code _key.combination-policy=collect|override|fqPolicyClassName}.
  */
 @Priority(100)
 public class AdaptiveCombinationPolicy implements PropertyValueCombinationPolicy {
-
+    /** Logger. */
     private static final Logger LOG = Logger.getLogger(AdaptiveCombinationPolicy.class.getName());
 
+    /**
+     * Collecting combination policy using (optional) {@code item-separator} parameter for determining the sparator
+     * to combine multiple config entries found.
+     */
+    private static final PropertyValueCombinationPolicy COLLECTING_POLICY = new PropertyValueCombinationPolicy(){
+        @Override
+        public Map<String, String> collect(Map<String, String> currentValue, String key, PropertySource propertySource) {
+            // check for default collection combination policies for lists, sets, maps etc.
+            final String SEPARATOR = ConfigurationProvider.getConfiguration().getOrDefault('_' + key+".item-separator", ",");
+            PropertyValue newValue = propertySource.get(key);
+            if(newValue!=null){
+                Map<String,String> newMapValue = new HashMap<>();
+                if(currentValue!=null){
+                    newMapValue.putAll(currentValue);
+                }
+                String oldVal = newMapValue.get(key);
+                newMapValue.putAll(newValue.getConfigEntries());
+                if(oldVal!=null){
+                    newMapValue.put(key,oldVal + SEPARATOR + newValue.getValue());
+                }
+                return newMapValue;
+            }else{
+                if(currentValue!=null){
+                    return currentValue;
+                }
+                return Collections.emptyMap();
+            }
+        }
+    };
+
+    /** Cache for loaded custom combination policies. */
     private Map<Class, PropertyValueCombinationPolicy> configuredPolicies = new ConcurrentHashMap<>();
 
     @Override
@@ -51,69 +83,44 @@ public class AdaptiveCombinationPolicy implements PropertyValueCombinationPolicy
             }
             return currentValue;
         }
-        String adaptiveCombinationPolicyClass  = ConfigurationProvider.getConfiguration().get('_' + key+".combinationPolicy");
-        if(adaptiveCombinationPolicyClass!=null){
-            PropertyValueCombinationPolicy delegatePolicy = null;
-            try{
-                Class clazz = Class.forName(adaptiveCombinationPolicyClass);
-                delegatePolicy = configuredPolicies.get(clazz);
-                if(delegatePolicy==null){
-                    delegatePolicy = PropertyValueCombinationPolicy.class.cast(clazz.newInstance());
-                    configuredPolicies.put(clazz, delegatePolicy);
+        String adaptiveCombinationPolicyClass  = ConfigurationProvider.getConfiguration().getOrDefault(
+                '_' + key+".combination-policy", "override");
+        PropertyValueCombinationPolicy combinationPolicy = null;
+        switch(adaptiveCombinationPolicyClass){
+            case "collect":
+            case "COLLECT":
+                if(LOG.isLoggable(Level.FINEST)){
+                    LOG.finest("Using collecting combination policy for key: " + key + ".");
                 }
-                return delegatePolicy.collect(currentValue, key, propertySource);
-            }
-            catch(Exception e){
-                LOG.log(Level.SEVERE, "Error loading configured PropertyValueCombinationPolicy for key: " + key, e);
-            }
-        }
-        // check for default collection combination policies for lists, sets, maps etc.
-        final String SEPARATOR = ConfigurationProvider.getConfiguration().getOrDefault('_' + key+".collection-separator", ",");
-        String collectionType = ConfigurationProvider.getConfiguration().get('_' + key+".collection-type");
-        if(collectionType!=null) {
-            if (collectionType.startsWith("java.util.")) {
-                collectionType = collectionType.substring("java.util.".length());
-            }
-            switch(collectionType){
-                case "List":
-                case "ArrayList":
-                case "LinkedList":
-                case "Collection":
-                case "Set":
-                case "HashSet":
-                case "TreeSet":
-                case "SortedSet":
-                case "Map":
-                case "HashMap":
-                case "ConcurrentHashMap":
-                case "TreeMap":
-                case "SortedMap":
-                    PropertyValue newValue = propertySource.get(key);
-                    if(newValue!=null){
-                        Map<String,String> newMapValue = new HashMap<>();
-                        if(currentValue!=null){
-                            newMapValue.putAll(currentValue);
-                        }
-                        String oldVal = newMapValue.get(key);
-                        newMapValue.putAll(newValue.getConfigEntries());
-                        if(oldVal!=null){
-                            newMapValue.put(key,oldVal + SEPARATOR + newValue.getValue());
-                        }
-                        return newMapValue;
-                    }else{
-                        if(currentValue!=null){
-                            return currentValue;
-                        }
-                        return Collections.emptyMap();
+                combinationPolicy = COLLECTING_POLICY;
+                break;
+            case "override":
+            case "OVERRIDE":
+                if(LOG.isLoggable(Level.FINEST)){
+                    LOG.finest("Using default (overriding) combination policy for key: " + key + ".");
+                }
+                combinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR;
+                break;
+            default:
+                try{
+                    Class<PropertyValueCombinationPolicy> clazz = (Class<PropertyValueCombinationPolicy>)
+                            Class.forName(adaptiveCombinationPolicyClass);
+                    combinationPolicy = configuredPolicies.get(clazz);
+                    if(combinationPolicy==null){
+                        combinationPolicy = clazz.newInstance();
+                        configuredPolicies.put(clazz, combinationPolicy);
                     }
-                default:
-                    LOG.log(Level.SEVERE, "Unsupported collection-type for key: " + key + ": " + collectionType);
-            }
-        }
-        PropertyValue newValue = propertySource.get(key);
-        if(newValue!=null){
-            return newValue.getConfigEntries();
+                    if(LOG.isLoggable(Level.FINEST)){
+                        LOG.finest("Using custom combination policy "+adaptiveCombinationPolicyClass+" for " +
+                                "key: " + key + ".");
+                    }
+                }
+                catch(Exception e){
+                    LOG.log(Level.SEVERE, "Error loading configured PropertyValueCombinationPolicy for " +
+                            "key: " + key + ", using default (overriding) policy.", e);
+                    combinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR;
+                }
         }
-        return currentValue;
+        return combinationPolicy.collect(currentValue, key, propertySource);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ArrayListConverter.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ArrayListConverter.java b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ArrayListConverter.java
index 3e95438..8281395 100644
--- a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ArrayListConverter.java
+++ b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ArrayListConverter.java
@@ -48,10 +48,7 @@ public class ArrayListConverter implements PropertyConverter<ArrayList> {
 
     @Override
     public ArrayList convert(String value, ConversionContext context) {
-        final String SEPARATOR = ConfigurationProvider.getConfiguration().getOrDefault(
-                '_' + context.getKey()+".collection-separator", ",");
-        List<String> rawList = ItemTokenizer.split(value, SEPARATOR);
-
+        List<String> rawList = ItemTokenizer.split(value, context);
         ArrayList<Object> mlist = new ArrayList<>();
         for(String raw:rawList){
             Object convValue = ItemTokenizer.convertValue(raw, context);

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ConcurrentHashMapConverter.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ConcurrentHashMapConverter.java b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ConcurrentHashMapConverter.java
index 07aecc8..131b41c 100644
--- a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ConcurrentHashMapConverter.java
+++ b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ConcurrentHashMapConverter.java
@@ -22,6 +22,7 @@ import org.apache.tamaya.TypeLiteral;
 import org.apache.tamaya.spi.ConversionContext;
 import org.apache.tamaya.spi.PropertyConverter;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Level;
@@ -47,33 +48,14 @@ public class ConcurrentHashMapConverter implements PropertyConverter<ConcurrentH
     @Override
     public ConcurrentHashMap convert(String value, ConversionContext context) {
         List<String> rawList = ItemTokenizer.split(value, context);
-        String converterClass = context.getConfiguration().get('_' + context.getKey()+".collection-parser");
-        if(converterClass!=null){
-            try {
-                PropertyConverter<?> valueConverter = (PropertyConverter<?>) Class.forName(converterClass).newInstance();
-                ConcurrentHashMap<String,Object> mlist = new ConcurrentHashMap<>();
-                ConversionContext ctx = new ConversionContext.Builder(context.getConfiguration(),
-                        context.getConfigurationContext(), context.getKey(),
-                        TypeLiteral.of(context.getTargetType().getType())).build();
-                for(String raw:rawList){
-                    String[] items = ItemTokenizer.splitMapEntry(raw, context);
-                    Object convValue = valueConverter.convert(items[1], ctx);
-                    if(convValue!=null){
-                        mlist.put(items[0], convValue);
-                        continue;
-                    }
-                }
-                return mlist;
-
-            } catch (Exception e) {
-                LOG.log(Level.SEVERE, "Error convertion config to HashMap type.", e);
-            }
-        }
-        ConcurrentHashMap<String,String> result = new ConcurrentHashMap<>();
+        ConcurrentHashMap result = new ConcurrentHashMap(rawList.size());
         for(String raw:rawList){
             String[] items = ItemTokenizer.splitMapEntry(raw, context);
-            if(items!=null){
-                result.put(items[0], items[1]);
+            Object convValue = ItemTokenizer.convertValue(items[1], context);
+            if(convValue!=null){
+                result.put(items[0], convValue);
+            }else{
+                LOG.log(Level.SEVERE, "Failed to convert collection value type for '"+raw+"'.");
             }
         }
         return result;

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashMapConverter.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashMapConverter.java b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashMapConverter.java
index 29d7ad7..6a3ac97 100644
--- a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashMapConverter.java
+++ b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashMapConverter.java
@@ -47,51 +47,18 @@ public class HashMapConverter implements PropertyConverter<HashMap> {
     @Override
     public HashMap convert(String value, ConversionContext context) {
         List<String> rawList = ItemTokenizer.split(value, context);
-        String converterClass = context.getConfiguration().get('_' + context.getKey()+".collection-parser");
-        if(converterClass!=null){
-            try {
-                PropertyConverter<?> valueConverter = (PropertyConverter<?>) Class.forName(converterClass).newInstance();
-                HashMap<String,Object> mlist = new HashMap<>();
-                ConversionContext ctx = new ConversionContext.Builder(context.getConfiguration(),
-                        context.getConfigurationContext(), context.getKey(),
-                        TypeLiteral.of(context.getTargetType().getType())).build();
-                for(String raw:rawList){
-                    String[] items = splitItems(raw);
-                    Object convValue = valueConverter.convert(items[1], ctx);
-                    if(convValue!=null){
-                        mlist.put(items[0], convValue);
-                        continue;
-                    }
-                }
-                return mlist;
-
-            } catch (Exception e) {
-                LOG.log(Level.SEVERE, "Error convertion config to HashMap type.", e);
-            }
-        }
-        HashMap<String,String> result = new HashMap<>();
+        HashMap result = new HashMap(rawList.size());
         for(String raw:rawList){
-            String[] items = splitItems(raw);
-            if(items!=null){
-                result.put(items[0], items[1]);
+            String[] items = ItemTokenizer.splitMapEntry(raw, context);
+            Object convValue = ItemTokenizer.convertValue(items[1], context);
+            if(convValue!=null){
+                result.put(items[0], convValue);
+            }else{
+                LOG.log(Level.SEVERE, "Failed to convert collection value type for '"+raw+"'.");
             }
         }
         return result;
     }
 
-    static String[] splitItems(String raw) {
-        String[] items = raw.split("::");
-        if(items[0].trim().startsWith("[")){
-            items[0]= items[0].trim();
-            items[0] = items[0].substring(1);
-        }else{
-            items[0]= items[0].trim();
-        }
-        if(items[1].trim().endsWith("]")){
-            items[1] = items[1].substring(0,items[1].length()-1);
-        }else{
-            items[1]= items[1].trim();
-        }
-        return items;
-    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashSetConverter.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashSetConverter.java b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashSetConverter.java
index 47c32f6..40b204f 100644
--- a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashSetConverter.java
+++ b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/HashSetConverter.java
@@ -50,27 +50,16 @@ public class HashSetConverter implements PropertyConverter<HashSet> {
     @Override
     public HashSet convert(String value, ConversionContext context) {
         List<String> rawList = ItemTokenizer.split(value, context);
-        String converterClass = context.getConfiguration().get('_' + context.getKey()+".collection-parser");
-        if(converterClass!=null){
-            try {
-                PropertyConverter<?> valueConverter = (PropertyConverter<?>) Class.forName(converterClass).newInstance();
-                HashSet<Object> mlist = new HashSet<>();
-                ConversionContext ctx = new ConversionContext.Builder(context.getConfiguration(),
-                        context.getConfigurationContext(), context.getKey(),
-                        TypeLiteral.of(context.getTargetType().getType())).build();
-                for(String raw:rawList){
-                    Object convValue = valueConverter.convert(raw, ctx);
-                    if(convValue!=null){
-                        mlist.add(convValue);
-                        continue;
-                    }
-                }
-                return mlist;
-
-            } catch (Exception e) {
-                LOG.log(Level.SEVERE, "Error convertion config to HashSet type.", e);
+        HashSet<Object> result = new HashSet<>();
+        for(String raw:rawList){
+            String[] items = ItemTokenizer.splitMapEntry(raw, context);
+            Object convValue = ItemTokenizer.convertValue(items[1], context);
+            if(convValue!=null){
+                result.add(convValue);
+            }else{
+                LOG.log(Level.SEVERE, "Failed to convert collection value type for '"+raw+"'.");
             }
         }
-        return new HashSet(rawList);
+        return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ItemTokenizer.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ItemTokenizer.java b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ItemTokenizer.java
index 37f7cf1..98831e1 100644
--- a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ItemTokenizer.java
+++ b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/ItemTokenizer.java
@@ -50,7 +50,8 @@ final class ItemTokenizer {
      */
     public static List<String> split(String value, ConversionContext context){
         return split(value, ConfigurationProvider.getConfiguration().getOrDefault(
-                '_' + context.getKey()+".collection-separator", ","));
+                '_' + context.getKey()+"." +
+                        "item-separator", ","));
     }
 
     /**
@@ -91,7 +92,7 @@ final class ItemTokenizer {
      */
     public static String[] splitMapEntry(String mapEntry, ConversionContext context){
         return splitMapEntry(mapEntry, ConfigurationProvider.getConfiguration().getOrDefault(
-                '_' + context.getKey()+".collection-map-separator", ","));
+                '_' + context.getKey()+".map-entry-separator", "::"));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/LinkedListConverter.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/LinkedListConverter.java b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/LinkedListConverter.java
index 986a303..4389a54 100644
--- a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/LinkedListConverter.java
+++ b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/LinkedListConverter.java
@@ -47,28 +47,18 @@ public class LinkedListConverter implements PropertyConverter<LinkedList> {
     @Override
     public LinkedList convert(String value, ConversionContext context) {
         List<String> rawList = ItemTokenizer.split(value, context);
-        String converterClass = context.getConfiguration().get('_' + context.getKey()+".collection-parser");
-        if(converterClass!=null){
-            try {
-                PropertyConverter<?> valueConverter = (PropertyConverter<?>) Class.forName(converterClass).newInstance();
-                LinkedList<Object> mlist = new LinkedList<>();
-                ConversionContext ctx = new ConversionContext.Builder(context.getConfiguration(),
-                        context.getConfigurationContext(), context.getKey(),
-                        TypeLiteral.of(context.getTargetType().getType())).build();
-                for(String raw:rawList){
-                    Object convValue = valueConverter.convert(raw, ctx);
-                    if(convValue!=null){
-                        mlist.add(convValue);
-                        continue;
-                    }
-                }
-                return mlist;
-
-            } catch (Exception e) {
-                LOG.log(Level.SEVERE, "Error convertion config to ArrayList type.", e);
+        LinkedList<Object> result = new LinkedList<>();
+        for(String raw:rawList){
+            String[] items = ItemTokenizer.splitMapEntry(raw, context);
+            Object convValue = ItemTokenizer.convertValue(items[1], context);
+            if(convValue!=null){
+                result.add(convValue);
+                continue;
+            }else{
+                LOG.log(Level.SEVERE, "Failed to convert collection value type for '"+raw+"'.");
             }
         }
-        return new LinkedList(rawList);
+        return result;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeMapConverter.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeMapConverter.java b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeMapConverter.java
index b350944..fef25fe 100644
--- a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeMapConverter.java
+++ b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeMapConverter.java
@@ -21,12 +21,17 @@ package org.apache.tamaya.collections.internal;
 import org.apache.tamaya.spi.ConversionContext;
 import org.apache.tamaya.spi.PropertyConverter;
 
+import java.util.List;
 import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  *  PropertyConverter for gnerating HashMap representation of a values.
  */
 public class TreeMapConverter implements PropertyConverter<TreeMap> {
+    /** Logger used. */
+    private static final Logger LOG = Logger.getLogger(HashMapConverter.class.getName());
 
     /** The shared instance, used by other collection converters in this package.*/
     private static TreeMapConverter INSTANCE = new TreeMapConverter();
@@ -41,6 +46,17 @@ public class TreeMapConverter implements PropertyConverter<TreeMap> {
 
     @Override
     public TreeMap convert(String value, ConversionContext context) {
-        return new TreeMap<>(HashMapConverter.getInstance().convert(value, context));
+        List<String> rawList = ItemTokenizer.split(value, context);
+        TreeMap result = new TreeMap();
+        for(String raw:rawList){
+            String[] items = ItemTokenizer.splitMapEntry(raw, context);
+            Object convValue = ItemTokenizer.convertValue(items[1], context);
+            if(convValue!=null){
+                result.put(items[0], convValue);
+            }else{
+                LOG.log(Level.SEVERE, "Failed to convert collection value type for '"+raw+"'.");
+            }
+        }
+        return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeSetConverter.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeSetConverter.java b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeSetConverter.java
index f9cba02..9206f07 100644
--- a/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeSetConverter.java
+++ b/sandbox/collections/src/main/java/org/apache/tamaya/collections/internal/TreeSetConverter.java
@@ -48,27 +48,17 @@ public class TreeSetConverter implements PropertyConverter<TreeSet> {
     @Override
     public TreeSet convert(String value, ConversionContext context) {
         List<String> rawList = ItemTokenizer.split(value, context);
-        String converterClass = context.getConfiguration().get('_' + context.getKey()+".collection-parser");
-        if(converterClass!=null){
-            try {
-                PropertyConverter<?> valueConverter = (PropertyConverter<?>) Class.forName(converterClass).newInstance();
-                TreeSet<Object> mlist = new TreeSet<>();
-                ConversionContext ctx = new ConversionContext.Builder(context.getConfiguration(),
-                        context.getConfigurationContext(), context.getKey(),
-                        TypeLiteral.of(context.getTargetType().getType())).build();
-                for(String raw:rawList){
-                    Object convValue = valueConverter.convert(raw, ctx);
-                    if(convValue!=null){
-                        mlist.add(convValue);
-                        continue;
-                    }
-                }
-                return mlist;
-
-            } catch (Exception e) {
-                LOG.log(Level.SEVERE, "Error convertion config to HashSet type.", e);
+        TreeSet<Object> result = new TreeSet<>();
+        for(String raw:rawList){
+            String[] items = ItemTokenizer.splitMapEntry(raw, context);
+            Object convValue = ItemTokenizer.convertValue(items[1], context);
+            if(convValue!=null){
+                result.add(convValue);
+                continue;
+            }else{
+                LOG.log(Level.SEVERE, "Failed to convert collection value type for '"+raw+"'.");
             }
         }
-        return new TreeSet<>(rawList);
+        return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/test/java/org/apache/tamaya/collections/CollectionAdvancedTests.java
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/test/java/org/apache/tamaya/collections/CollectionAdvancedTests.java b/sandbox/collections/src/test/java/org/apache/tamaya/collections/CollectionAdvancedTests.java
index 435ed5d..ddabb23 100644
--- a/sandbox/collections/src/test/java/org/apache/tamaya/collections/CollectionAdvancedTests.java
+++ b/sandbox/collections/src/test/java/org/apache/tamaya/collections/CollectionAdvancedTests.java
@@ -7,6 +7,7 @@ import org.junit.Test;
 
 import java.util.Currency;
 import java.util.List;
+import java.util.Map;
 
 import static junit.framework.TestCase.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -75,4 +76,24 @@ public class CollectionAdvancedTests {
         assertEquals("(B)", items.get(1));
         assertEquals("(C)", items.get(2));
     }
+
+    /**
+     * Redefined map format parsing, Config is as follows:
+     * <pre>
+     *  redefined-map=0==none | 1==single | 2==any
+     *  _redefined-map.map-entry-separator===
+     *  _redefined-map.item-separator=|
+     * </pre>
+     */
+    @Test
+    public void testCustomMapParser(){
+        Configuration config = ConfigurationProvider.getConfiguration();
+        Map<String,String> items = config.get("redefined-map", Map.class);
+        assertNotNull(items);
+        assertFalse(items.isEmpty());
+        assertEquals(3, items.size());
+        assertEquals("none", items.get("0"));
+        assertEquals("single", items.get("1"));
+        assertEquals("any", items.get("2"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/7b4cb8e8/sandbox/collections/src/test/resources/META-INF/javaconfiguration.properties
----------------------------------------------------------------------
diff --git a/sandbox/collections/src/test/resources/META-INF/javaconfiguration.properties b/sandbox/collections/src/test/resources/META-INF/javaconfiguration.properties
index 2bb8414..e9a234c 100644
--- a/sandbox/collections/src/test/resources/META-INF/javaconfiguration.properties
+++ b/sandbox/collections/src/test/resources/META-INF/javaconfiguration.properties
@@ -59,7 +59,7 @@ _typed.treemap.collection-type=TreeMap
 # Config for advanced tests
 sep-list=a,b,c|d,e,f|g,h,i
 _sep-list.collection-type=List
-_sep-list.collection-separator=|
+_sep-list.item-separator=|
 currency-list=CHF,USD,USS
 _currency-list.collection-type=List
 
@@ -67,3 +67,7 @@ parser-list=a,b,c
 _parser-list.collection-type=List
 _parser-list.item-converter=org.apache.tamaya.collections.MyUpperCaseConverter
 
+redefined-map=0==none | 1==single | 2==any
+_redefined-map.map-entry-separator===
+_redefined-map.item-separator=|
+


[3/8] incubator-tamaya git commit: Added link to collections module docs.

Posted by an...@apache.org.
Added link to collections module docs.


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

Branch: refs/heads/master
Commit: ad5a794629749d2b3a116209ae35c71335c1b26e
Parents: 7b4cb8e
Author: anatole <an...@apache.org>
Authored: Wed Feb 17 22:14:36 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Wed Feb 17 22:14:36 2016 +0100

----------------------------------------------------------------------
 src/site/asciidoc/extensions/index.adoc | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ad5a7946/src/site/asciidoc/extensions/index.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/extensions/index.adoc b/src/site/asciidoc/extensions/index.adoc
index fa3a02f..9a1b193 100644
--- a/src/site/asciidoc/extensions/index.adoc
+++ b/src/site/asciidoc/extensions/index.adoc
@@ -100,9 +100,9 @@ very carefully and especially give us feedback, so we can improve them before pr
 |=======
 |_Artifact_                                 |_Description_                                          |_Links_
 |+org.apache.tamaya.ext:tamaya-jodatime+    |Provides support for JodaTime.                         | link:mod_jodatime.html[Documentation]
-|+org.apache.tamaya.ext:tamaya-staged+      |Simple configuration extension to add staged config.   |link:mod_metamodel-staged.html[Documentation]
-|+org.apache.tamaya.ext:tamaya-collections+ |Collections support.                                   | -
-|+org.apache.tamaya.ext:tamaya-ui+          |JSF based UI for Managing Configuration.               | -
+|+org.apache.tamaya.ext:tamaya-staged+      |Simple configuration extension to add staged config.   | link:mod_metamodel-staged.html[Documentation]
+|+org.apache.tamaya.ext:tamaya-collections+ |Collections support.                                   | link:mod_collections.html[Documentation]
+|+org.apache.tamaya.ext:tamaya-ui+          |UI for Managing Configuration.                         | -
 |=======
 
 


[5/8] incubator-tamaya git commit: Redesigned component slightly.

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendSpi.java
new file mode 100644
index 0000000..a1825d7
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendSpi.java
@@ -0,0 +1,143 @@
+/*
+ * 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.mutableconfig.spi;
+
+import org.apache.tamaya.Configuration;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Map;
+
+
+/**
+ * This interface models a writable backend for configuration data.
+ *
+ * As a consequence clients should first check, using the corresponding methods, if entries are to edited or removedProperties
+ * actually are eligible for change/creation or removal.
+ */
+public interface MutableConfigurationBackendSpi {
+
+    /**
+     * Identifies the configuration backend that is targeted by this instance and which is
+     * also responsible for writing back the changes applied.
+     *
+     * @return the backend URI, never null.
+     */
+    URI getBackendURI();
+
+    /**
+     * Checks if a configuration key is writable (or it can be added).
+     *
+     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could also
+     *                      be a regular expression, such "as a.b.c.*".
+     * @return the boolean
+     */
+    boolean isWritable(String keyExpression);
+
+    /**
+     * Checks if a configuration key is removable. This also implies that it is writable, but there might be writable
+     * keys that cannot be removedProperties.
+     *
+     * @param keyExpression the keyExpression the key to be cheched for write access (including creation), not null.
+     *                      Here this could also
+     *                      be a regulat expression, such "as a.b.c.*".
+     * @return the boolean
+     */
+    boolean isRemovable(String keyExpression);
+
+    /**
+     * Checks if any keys of the given type already exist in the write backend. <b>NOTE:</b> there may be backends that
+     * are not able to support lookups with regular expressions. In most such cases you should pass the keys to
+     * lookup explicitly.
+     *
+     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could
+     *                      also be a regular expression, such "as a.b.c.*".
+     * @return true, if there is any key found matching the expression.
+     */
+    boolean isExisting(String keyExpression);
+
+    /**
+     * Sets a property.
+     *
+     * @param key   the property's key, not null.
+     * @param value the property's value, not null.
+     * @return the former property value, or null.
+     * @throws org.apache.tamaya.ConfigException if the key/value cannot be added, or the request is read-only.
+     */
+    void put(String key, String value);
+
+    /**
+     * Puts all given configuration entries. This method should check that all given properties are
+     * basically removable, as defined by #isWritable. If any of the passed keys is not writable during this initial
+     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+     * remove all entries as far as possible and abort the writing operation.
+     *
+     * @param properties the properties tobe written, not null.
+     * @return the config change request
+     * @throws org.apache.tamaya.ConfigException if any of the given properties could not be written, or the request is read-only.
+     */
+    void putAll(Map<String, String> properties);
+
+    /**
+     * Removes all given configuration entries. This method should check that all given properties are
+     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
+     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+     * remove all entries as far as possible and abort the writing operation.
+     *
+     * @param keys the property's keys to be removedProperties, not null.
+     * @return the config change request
+     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removedProperties, or the request is read-only.
+     */
+    void remove(Collection<String> keys);
+
+    /**
+     * Removes all given configuration entries. This method should check that all given properties are
+     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
+     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+     * remove all entries as far as possible and abort the writing operation.
+     *
+     * @param keys the property's keys to be removedProperties, not null.
+     * @return the config change request
+     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removedProperties, or the request is read-only.
+     */
+    void remove(String... keys);
+
+    /**
+     * Commits the request. After a commit the change is not editable anymore. All changes applied will be written to
+     * the corresponding configuration backend.
+     *
+     * NOTE that changes applied must not necessarily be visible in the current {@link Configuration} instance,
+     * since visibility of changes also depends on the ordinals set on the {@link org.apache.tamaya.spi.PropertySource}s
+     * configured.
+     * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled, or the commit fails.
+     */
+    void commit();
+
+    /**
+     * Rollback any changes leaving everything unchanged. This will rollback all changes applied since the last commit.
+     */
+    void rollback();
+
+}

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

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

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/ConfigChangeManagerTest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/ConfigChangeManagerTest.java b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/ConfigChangeManagerTest.java
deleted file mode 100644
index 8f4305c..0000000
--- a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/ConfigChangeManagerTest.java
+++ /dev/null
@@ -1,78 +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.mutableconfig;
-
-import org.apache.tamaya.ConfigException;
-import org.junit.Test;
-
-import java.io.File;
-import java.net.URI;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests for {@link ConfigChangeManager}.
- */
-public class ConfigChangeManagerTest {
-
-    /**
-     * Test create change request.
-     *
-     * @throws Exception the exception
-     */
-    @Test
-    public void testCreateChangeRequest() throws Exception {
-        File f = File.createTempFile("ConfigChangeRequest",".properties");
-        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest(f.toURI());
-        assertNotNull(req);
-        f = File.createTempFile("ConfigChangeRequest",".xml");
-        req = ConfigChangeManager.createChangeRequest(f.toURI());
-        assertNotNull(req);
-    }
-
-    /**
-     * Test invalid create change request.
-     *
-     * @throws Exception the exception
-     */
-    @Test(expected=ConfigException.class)
-    public void testInvalidCreateChangeRequest() throws Exception {
-        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest(new URI("foo:bar"));
-    }
-
-    /**
-     * Test null create change request.
-     *
-     * @throws Exception the exception
-     */
-    @Test(expected=NullPointerException.class)
-    public void testNullCreateChangeRequest1() throws Exception {
-        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest((URI[])null);
-    }
-
-    /**
-     * Test null create change request.
-     *
-     * @throws Exception the exception
-     */
-    @Test(expected=NullPointerException.class)
-    public void testNullCreateChangeRequest2() throws Exception {
-        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest((String[])null);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/MutableConfigurationQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/MutableConfigurationQueryTest.java b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/MutableConfigurationQueryTest.java
new file mode 100644
index 0000000..b235149
--- /dev/null
+++ b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/MutableConfigurationQueryTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.mutableconfig;
+
+import org.apache.tamaya.ConfigException;
+import org.junit.Test;
+
+import java.io.File;
+import java.net.URI;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link MutableConfigurationQuery}.
+ */
+public class MutableConfigurationQueryTest {
+
+    /**
+     * Test create change request.
+     *
+     * @throws Exception the exception
+     */
+    @Test
+    public void testCreateChangeRequest() throws Exception {
+        File f = File.createTempFile("ConfigChangeRequest",".properties");
+        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        assertNotNull(req);
+        f = File.createTempFile("ConfigChangeRequest",".xml");
+        req = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        assertNotNull(req);
+    }
+
+    /**
+     * Test invalid create change request.
+     *
+     * @throws Exception the exception
+     */
+    @Test(expected=ConfigException.class)
+    public void testInvalidCreateChangeRequest() throws Exception {
+        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(new URI("foo:bar"));
+    }
+
+    /**
+     * Test null create change request.
+     *
+     * @throws Exception the exception
+     */
+    @Test(expected=NullPointerException.class)
+    public void testNullCreateChangeRequest1() throws Exception {
+        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest((URI[])null);
+    }
+
+    /**
+     * Test null create change request.
+     *
+     * @throws Exception the exception
+     */
+    @Test(expected=NullPointerException.class)
+    public void testNullCreateChangeRequest2() throws Exception {
+        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest((String[])null);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendTest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendTest.java b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendTest.java
new file mode 100644
index 0000000..c2e220e
--- /dev/null
+++ b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.mutableconfig.MutableConfigurationQuery;
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for {@link PropertiesFileConfigBackend}.
+ */
+public class PropertiesFileConfigBackendTest {
+    /**
+     * Test read write properties with rollback.
+     *
+     * @throws IOException the io exception
+     */
+    @Test
+    public void testReadWriteProperties_WithCancel() throws IOException {
+        File f = File.createTempFile("testReadWriteProperties_WithCancel",".properties");
+        f.delete();
+        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        assertTrue(req instanceof PropertiesFileConfigBackend);
+        req.put("key1", "value1");
+        Map<String,String> cm = new HashMap<>();
+        cm.put("key2", "value2");
+        cm.put("key3", "value3");
+        req.rollback();;
+        assertTrue(req.isClosed());
+        assertFalse(f.exists());
+    }
+
+    /**
+     * Test read write properties with commit.
+     *
+     * @throws IOException the io exception
+     */
+    @Test
+    public void testReadWriteProperties_WithCommit() throws IOException {
+        File f = File.createTempFile("testReadWriteProperties_WithCommit",".properties");
+        f.delete();
+        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        assertTrue(req instanceof PropertiesFileConfigBackend);
+        req.put("key1", "value1");
+        Map<String,String> cm = new HashMap<>();
+        cm.put("key2", "value2");
+        cm.put("key3", "value3");
+        req.putAll(cm);
+        req.commit();;
+        assertTrue(req.isClosed());
+        assertTrue(f.exists());
+        MutableConfiguration req2 = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        assertTrue(req != req2);
+        req2.remove("foo");
+        req2.remove("key3");
+        req2.put("key1", "value1.2");
+        req2.put("key4", "value4");
+        req2.commit();
+        Properties props = new Properties();
+        props.load(f.toURL().openStream());
+        assertEquals(3, props.size());
+        assertEquals("value1.2", props.getProperty("key1"));
+        assertEquals("value2", props.getProperty("key2"));
+        assertEquals("value4", props.getProperty("key4"));
+    }
+
+    /**
+     * Test read write xml properties with commit.
+     *
+     * @throws IOException the io exception
+     */
+    @Test
+    public void testReadWriteXmlProperties_WithCommit() throws IOException {
+        File f = File.createTempFile("testReadWriteProperties_WithCommit",".xml");
+        f.delete();
+        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        assertTrue(req instanceof XmlPropertiesFileConfigChangeRequest);
+        req.put("key1", "value1");
+        Map<String,String> cm = new HashMap<>();
+        cm.put("key2", "value2");
+        cm.put("key3", "value3");
+        req.putAll(cm);
+        req.commit();;
+        assertTrue(req.isClosed());
+        assertTrue(f.exists());
+        MutableConfiguration req2 = MutableConfigurationQuery.createChangeRequest(f.toURI());
+        assertTrue(req != req2);
+        req2.remove("foo");
+        req2.remove("key3");
+        req2.put("key1", "value1.2");
+        req2.put("key4", "value4");
+        req2.commit();
+        Properties props = new Properties();
+        props.loadFromXML(f.toURL().openStream());
+        assertEquals(3, props.size());
+        assertEquals("value1.2", props.getProperty("key1"));
+        assertEquals("value2", props.getProperty("key2"));
+        assertEquals("value4", props.getProperty("key4"));
+    }
+
+    @Test
+    public void testReadWrite_Compound() throws IOException {
+        File f1 = File.createTempFile("testReadWrite_Compound",".xml");
+        f1.delete();
+        File f2 = File.createTempFile("testReadWrite_Compound",".properties");
+        f2.delete();
+        MutableConfiguration req = MutableConfigurationQuery.createChangeRequest(f1.toURI(),f2.toURI());
+        req.put("key1", "value1");
+        Map<String,String> cm = new HashMap<>();
+        cm.put("key2", "value2");
+        cm.put("key3", "value3");
+        req.putAll(cm);
+        req.commit();;
+        assertTrue(req.isClosed());
+        assertTrue(f1.exists());
+        assertTrue(f2.exists());
+        MutableConfiguration req2 = MutableConfigurationQuery.createChangeRequest(f1.toURI(),f2.toURI());
+        assertTrue(req != req2);
+        req2.remove("foo");
+        req2.remove("key3");
+        req2.put("key1", "value1.2");
+        req2.put("key4", "value4");
+        req2.commit();
+        Properties props = new Properties();
+        props.load(f2.toURL().openStream());
+        assertEquals(3, props.size());
+        assertEquals("value1.2", props.getProperty("key1"));
+        assertEquals("value2", props.getProperty("key2"));
+        assertEquals("value4", props.getProperty("key4"));
+        props = new Properties();
+        props.loadFromXML(f1.toURL().openStream());
+        assertEquals(3, props.size());
+        assertEquals("value1.2", props.getProperty("key1"));
+        assertEquals("value2", props.getProperty("key2"));
+        assertEquals("value4", props.getProperty("key4"));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequestTest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequestTest.java b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequestTest.java
deleted file mode 100644
index 2f59554..0000000
--- a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequestTest.java
+++ /dev/null
@@ -1,161 +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.mutableconfig.internal;
-
-import org.apache.tamaya.mutableconfig.ConfigChangeManager;
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests for {@link PropertiesFileConfigChangeRequest}.
- */
-public class PropertiesFileConfigChangeRequestTest {
-    /**
-     * Test read write properties with cancel.
-     *
-     * @throws IOException the io exception
-     */
-    @Test
-    public void testReadWriteProperties_WithCancel() throws IOException {
-        File f = File.createTempFile("testReadWriteProperties_WithCancel",".properties");
-        f.delete();
-        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest(f.toURI());
-        assertTrue(req instanceof PropertiesFileConfigChangeRequest);
-        req.put("key1", "value1");
-        Map<String,String> cm = new HashMap<>();
-        cm.put("key2", "value2");
-        cm.put("key3", "value3");
-        req.cancel();;
-        assertTrue(req.isClosed());
-        assertFalse(f.exists());
-    }
-
-    /**
-     * Test read write properties with commit.
-     *
-     * @throws IOException the io exception
-     */
-    @Test
-    public void testReadWriteProperties_WithCommit() throws IOException {
-        File f = File.createTempFile("testReadWriteProperties_WithCommit",".properties");
-        f.delete();
-        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest(f.toURI());
-        assertTrue(req instanceof PropertiesFileConfigChangeRequest);
-        req.put("key1", "value1");
-        Map<String,String> cm = new HashMap<>();
-        cm.put("key2", "value2");
-        cm.put("key3", "value3");
-        req.putAll(cm);
-        req.commit();;
-        assertTrue(req.isClosed());
-        assertTrue(f.exists());
-        ConfigChangeRequest req2 = ConfigChangeManager.createChangeRequest(f.toURI());
-        assertTrue(req != req2);
-        req2.remove("foo");
-        req2.remove("key3");
-        req2.put("key1", "value1.2");
-        req2.put("key4", "value4");
-        req2.commit();
-        Properties props = new Properties();
-        props.load(f.toURL().openStream());
-        assertEquals(3, props.size());
-        assertEquals("value1.2", props.getProperty("key1"));
-        assertEquals("value2", props.getProperty("key2"));
-        assertEquals("value4", props.getProperty("key4"));
-    }
-
-    /**
-     * Test read write xml properties with commit.
-     *
-     * @throws IOException the io exception
-     */
-    @Test
-    public void testReadWriteXmlProperties_WithCommit() throws IOException {
-        File f = File.createTempFile("testReadWriteProperties_WithCommit",".xml");
-        f.delete();
-        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest(f.toURI());
-        assertTrue(req instanceof XmlPropertiesFileConfigChangeRequest);
-        req.put("key1", "value1");
-        Map<String,String> cm = new HashMap<>();
-        cm.put("key2", "value2");
-        cm.put("key3", "value3");
-        req.putAll(cm);
-        req.commit();;
-        assertTrue(req.isClosed());
-        assertTrue(f.exists());
-        ConfigChangeRequest req2 = ConfigChangeManager.createChangeRequest(f.toURI());
-        assertTrue(req != req2);
-        req2.remove("foo");
-        req2.remove("key3");
-        req2.put("key1", "value1.2");
-        req2.put("key4", "value4");
-        req2.commit();
-        Properties props = new Properties();
-        props.loadFromXML(f.toURL().openStream());
-        assertEquals(3, props.size());
-        assertEquals("value1.2", props.getProperty("key1"));
-        assertEquals("value2", props.getProperty("key2"));
-        assertEquals("value4", props.getProperty("key4"));
-    }
-
-    @Test
-    public void testReadWrite_Compound() throws IOException {
-        File f1 = File.createTempFile("testReadWrite_Compound",".xml");
-        f1.delete();
-        File f2 = File.createTempFile("testReadWrite_Compound",".properties");
-        f2.delete();
-        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest(f1.toURI(),f2.toURI());
-        req.put("key1", "value1");
-        Map<String,String> cm = new HashMap<>();
-        cm.put("key2", "value2");
-        cm.put("key3", "value3");
-        req.putAll(cm);
-        req.commit();;
-        assertTrue(req.isClosed());
-        assertTrue(f1.exists());
-        assertTrue(f2.exists());
-        ConfigChangeRequest req2 = ConfigChangeManager.createChangeRequest(f1.toURI(),f2.toURI());
-        assertTrue(req != req2);
-        req2.remove("foo");
-        req2.remove("key3");
-        req2.put("key1", "value1.2");
-        req2.put("key4", "value4");
-        req2.commit();
-        Properties props = new Properties();
-        props.load(f2.toURL().openStream());
-        assertEquals(3, props.size());
-        assertEquals("value1.2", props.getProperty("key1"));
-        assertEquals("value2", props.getProperty("key2"));
-        assertEquals("value4", props.getProperty("key4"));
-        props = new Properties();
-        props.loadFromXML(f1.toURL().openStream());
-        assertEquals(3, props.size());
-        assertEquals("value1.2", props.getProperty("key1"));
-        assertEquals("value2", props.getProperty("key2"));
-        assertEquals("value4", props.getProperty("key4"));
-    }
-}
\ No newline at end of file


[8/8] incubator-tamaya git commit: Redesigned mutable-config component slightly.

Posted by an...@apache.org.
Redesigned mutable-config component slightly.


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

Branch: refs/heads/master
Commit: 8fc95128e4a625fe7777971847ea214365b137b2
Parents: a231ff0
Author: anatole <an...@apache.org>
Authored: Thu Feb 18 00:42:38 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Thu Feb 18 00:42:38 2016 +0100

----------------------------------------------------------------------
 .../java/org/apache/tamaya/etcd/EtcdPropertySource.java  |  2 +-
 .../tamaya/etcd/internal/EtcdConfigChangeRequest.java    | 11 +++++------
 .../tamaya/etcd/internal/MutableConfigSupport.java       |  8 ++++----
 3 files changed, 10 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/8fc95128/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java
index db3902b..bb52432 100644
--- a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java
+++ b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java
@@ -69,7 +69,7 @@ public class EtcdPropertySource implements PropertySource{
     @Override
     public PropertyValue get(String key) {
         // check prefix, if key does not start with it, it is not part of our name space
-        // if so, the prefix part must be removed, so etcd can resolve without it
+        // if so, the prefix part must be removedProperties, so etcd can resolve without it
         if(!key.startsWith(prefix)){
             return null;
         } else{

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/8fc95128/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java
index 06ef1df..edd140b 100644
--- a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java
+++ b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java
@@ -20,7 +20,7 @@ package org.apache.tamaya.etcd.internal;
 
 import org.apache.tamaya.etcd.EtcdAccessor;
 import org.apache.tamaya.etcd.EtcdBackends;
-import org.apache.tamaya.mutableconfig.spi.AbstractConfigChangeRequest;
+import org.apache.tamaya.mutableconfig.spi.AbstractMutableConfigurationBackendSpiSpi;
 
 import java.net.URI;
 import java.util.Map;
@@ -33,7 +33,7 @@ import java.util.logging.Logger;
  * {@code changeRequest.set("myTimedKey?ttl=30", "myValue");} will set a key {@code myTimedKey} valid only for
  * 30 seconds.
  */
-class EtcdConfigChangeRequest extends AbstractConfigChangeRequest{
+class EtcdConfigChangeRequest extends AbstractMutableConfigurationBackendSpiSpi {
 
     private static final Logger LOG = Logger.getLogger(EtcdConfigChangeRequest.class.getName());
 
@@ -42,7 +42,7 @@ class EtcdConfigChangeRequest extends AbstractConfigChangeRequest{
     }
 
     @Override
-    public boolean exists(String keyExpression) {
+    public boolean isExisting(String keyExpression) {
         for(EtcdAccessor accessor: EtcdBackends.getEtcdBackends()){
             try{
                 Map<String,String> props = accessor.get(keyExpression);
@@ -60,16 +60,15 @@ class EtcdConfigChangeRequest extends AbstractConfigChangeRequest{
 
     @Override
     protected void commitInternal() {
-        checkClosed();
         for(EtcdAccessor accessor: EtcdBackends.getEtcdBackends()){
             try{
-                for(String k:getRemoved()){
+                for(String k: getRemovedProperties()){
                     Map<String,String> res = accessor.delete(k);
                     if(res.get("_ERROR")!=null){
                         LOG.info("Failed to remove key from etcd: " + k);
                     }
                 }
-                for(Map.Entry<String,String> en:getProperties().entrySet()){
+                for(Map.Entry<String,String> en:getAddedProperties().entrySet()){
                     String key = en.getKey();
                     Integer ttl = null;
                     int index = en.getKey().indexOf('?');

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/8fc95128/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/MutableConfigSupport.java
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/MutableConfigSupport.java b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/MutableConfigSupport.java
index bfcd18c..eb445e3 100644
--- a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/MutableConfigSupport.java
+++ b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/MutableConfigSupport.java
@@ -18,15 +18,15 @@
  */
 package org.apache.tamaya.etcd.internal;
 
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
+import org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendSpi;
+import org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi;
 
 import java.net.URI;
 
 /**
  * Created by atsticks on 15.01.16.
  */
-public class MutableConfigSupport implements ConfigChangeManagerSpi{
+public class MutableConfigSupport implements MutableConfigurationBackendProviderSpi {
 
     private URI backendURI;
 
@@ -35,7 +35,7 @@ public class MutableConfigSupport implements ConfigChangeManagerSpi{
     }
 
     @Override
-    public ConfigChangeRequest createChangeRequest(URI uri) {
+    public MutableConfigurationBackendSpi getBackend(URI uri) {
         if(backendURI.equals(uri)) {
             return new EtcdConfigChangeRequest(backendURI);
         }