You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by st...@apache.org on 2014/12/27 14:58:15 UTC
[31/34] incubator-tamaya git commit: move intermediately changed
stuff to dormant as well
move intermediately changed stuff to dormant as well
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/278a6c68
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/278a6c68
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/278a6c68
Branch: refs/heads/master
Commit: 278a6c681b2cfd52ac375b84e2e90aa2b579e12e
Parents: 30bdbb9
Author: Mark Struberg <st...@apache.org>
Authored: Sat Dec 27 11:09:17 2014 +0100
Committer: Mark Struberg <st...@apache.org>
Committed: Sat Dec 27 11:10:12 2014 +0100
----------------------------------------------------------------------
.../tamaya/core/ConfigurationFunctions.java | 213 ------------
.../core/properties/ConfigurationFormat.java | 111 ------
.../core/properties/FrozenPropertySource.java | 80 -----
.../core/properties/MappedPropertySource.java | 53 ---
.../core/properties/PropertyChangeSet.java | 169 ---------
.../properties/PropertyChangeSetBuilder.java | 347 -------------------
.../properties/PropertySourceFunctions.java | 65 ----
...e.tamaya.core.properties.ConfigurationFormat | 21 --
.../tamaya/core/ConfigurationFunctions.java | 213 ++++++++++++
.../core/properties/ConfigurationFormat.java | 111 ++++++
.../core/properties/FrozenPropertySource.java | 80 +++++
.../core/properties/MappedPropertySource.java | 53 +++
.../core/properties/PropertyChangeSet.java | 169 +++++++++
.../properties/PropertyChangeSetBuilder.java | 347 +++++++++++++++++++
.../properties/PropertySourceFunctions.java | 65 ++++
...e.tamaya.core.properties.ConfigurationFormat | 21 ++
16 files changed, 1059 insertions(+), 1059 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java b/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
deleted file mode 100644
index b1c2522..0000000
--- a/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core;
-
-import org.apache.tamaya.Configuration;
-import org.apache.tamaya.core.properties.PropertySourceBuilder;
-
-import java.util.*;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-import java.util.stream.Collectors;
-
-/**
- * Accessor that provides useful functions along with configuration.
- */
-public final class ConfigurationFunctions {
- /**
- * Private singleton constructor.
- */
- private ConfigurationFunctions() {
- }
-
- /**
- * Creates a ConfigOperator that creates a Configuration containing only keys
- * that are contained in the given area (non recursive). Hereby
- * the area key is stripped away fromMap the resulting key.
- *
- * @param areaKey the area key, not null
- * @return the area configuration, with the areaKey stripped away.
- */
- public static UnaryOperator<Configuration> selectArea(String areaKey) {
- return selectArea(areaKey, true);
- }
-
- /**
- * Creates a ConfigOperator that creates a Configuration containing only keys
- * that are contained in the given area (non recursive).
- *
- * @param areaKey the area key, not null
- * @param stripKeys if set to true, the area key is stripped away fromMap the resulting key.
- * @return the area configuration, with the areaKey stripped away.
- */
- public static UnaryOperator<Configuration> selectArea(String areaKey, boolean stripKeys) {
- return config -> {
- Map<String, String> area = new HashMap<>();
- area.putAll(
- config.getProperties().entrySet().stream()
- .filter(e -> isKeyInArea(e.getKey(), areaKey))
- .collect(Collectors.toMap(
- e -> stripKeys ? e.getKey().substring(areaKey.length() + 1) : e.getKey(),
- Map.Entry::getValue)));
- return Configuration.from(PropertySourceBuilder.of("area: " + areaKey).addMap(area).build());
- };
- }
-
- /**
- * Calculates the current area key and compares it with the given key.
- *
- * @param key the fully qualified entry key, not null
- * @param areaKey the area key, not null
- * @return true, if the entry is exact in this area
- */
- public static boolean isKeyInArea(String key, String areaKey) {
- int lastIndex = key.lastIndexOf('.');
- String curAreaKey = lastIndex > 0 ? key.substring(0, lastIndex) : "";
- return curAreaKey.equals(areaKey);
- }
-
- /**
- * Return a query to evaluate the set with all fully qualifies area names. This method should return the areas as accurate as possible,
- * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
- * does not support key iteration.
- *
- * @return s set with all areas, never {@code null}.
- */
- public static Function<Configuration,Set<String>> getAreas() {
- return config -> {
- final Set<String> areas = new HashSet<>();
- config.getProperties().keySet().forEach(s -> {
- int index = s.lastIndexOf('.');
- if (index > 0) {
- areas.add(s.substring(0, index));
- } else {
- areas.add("<root>");
- }
- });
- return areas;
- };
- }
-
- /**
- * Return a query to evaluate the set with all fully qualified area names, containing the transitive closure also including all
- * subarea names, regardless if properties are accessible or not. This method should return the areas as accurate
- * as possible, but may not provide a complete set of areas that are finally accessible, especially when the
- * underlying storage does not support key iteration.
- *
- * @return s set with all transitive areas, never {@code null}.
- */
- public static Function<Configuration,Set<String>> getTransitiveAreas() {
- return config -> {
- final Set<String> transitiveAreas = new HashSet<>();
- config.query(getAreas()).forEach(s -> {
- int index = s.lastIndexOf('.');
- if (index < 0) {
- transitiveAreas.add("<root>");
- } else {
- while (index > 0) {
- s = s.substring(0, index);
- transitiveAreas.add(s);
- index = s.lastIndexOf('.');
- }
- }
- });
- return transitiveAreas;
- };
- }
-
- /**
- * Return a query to evaluate the set with all fully qualified area names, containing only the
- * areas that match the predicate and have properties attached. This method should return the areas as accurate as possible,
- * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
- * does not support key iteration.
- *
- * @param predicate A predicate to deternine, which areas should be returned, not {@code null}.
- * @return s set with all areas, never {@code null}.
- */
- public static Function<Configuration,Set<String>> getAreas(final Predicate<String> predicate) {
- return config -> {
- return config.query(getAreas()).stream().filter(predicate).collect(Collectors.toCollection(TreeSet::new));
- };
- }
-
- /**
- * Return a query to evaluate the set with all fully qualified area names, containing the transitive closure also including all
- * subarea names, regardless if properties are accessible or not. This method should return the areas as accurate as possible,
- * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
- * does not support key iteration.
- *
- * @param predicate A predicate to deternine, which areas should be returned, not {@code null}.
- * @return s set with all transitive areas, never {@code null}.
- */
- public static Function<Configuration,Set<String>> getTransitiveAreas(Predicate<String> predicate) {
- return config -> {
- return config.query(getTransitiveAreas()).stream().filter(predicate).collect(Collectors.toCollection(TreeSet::new));
- };
- }
-
- /**
- * Return a query to evaluate to evaluate if an area exists. In case where the underlying storage implementation does not allow
- * querying the keys available, {@code false} should be returned.
- *
- * @param areaKey the configuration area (sub)path.
- * @return {@code true}, if such a node exists.
- */
- public static Function<Configuration,Boolean> containsArea(String areaKey) {
- return config -> {
- return config.query(getAreas()).contains(areaKey);
- };
- }
-
- /**
- * Creates a ConfigOperator that creates a Configuration containing only keys
- * that are contained in the given area (recursive). Hereby
- * the area key is stripped away fromMap the resulting key.
- *
- * @param areaKey the area key, not null
- * @return the area configuration, with the areaKey stripped away.
- */
- public static UnaryOperator<Configuration> selectAreaRecursive(String areaKey) {
- return selectAreaRecursive(areaKey, true);
- }
-
- /**
- * Creates a ConfigOperator that creates a Configuration containing only keys
- * that are contained in the given area (recursive).
- *
- * @param areaKey the area key, not null
- * @param stripKeys if set to true, the area key is stripped away fromMap the resulting key.
- * @return the area configuration, with the areaKey stripped away.
- */
- public static UnaryOperator<Configuration> selectAreaRecursive(String areaKey, boolean stripKeys) {
- return config -> {
- Map<String, String> area = new HashMap<>();
- String lookupKey = areaKey + '.';
- area.putAll(
- config.getProperties().entrySet().stream()
- .filter(e -> e.getKey().startsWith(lookupKey))
- .collect(Collectors.toMap(
- e -> stripKeys ? e.getKey().substring(areaKey.length() + 1) : e.getKey(),
- Map.Entry::getValue)));
- return Configuration.from(PropertySourceBuilder.of("area (recursive): " + areaKey).addMap(area).build());
- };
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java b/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
deleted file mode 100644
index cf94d99..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.core.resource.Resource;
-import org.apache.tamaya.core.spi.ConfigurationFormatSpi;
-import org.apache.tamaya.spi.ServiceContext;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Implementations current this class encapsulate the mechanism how to read a
- * resource URI including interpreting the format correctly (e.g. xml vs.
- * properties).
- */
-public interface ConfigurationFormat{
-
- /**
- * Returns a unique identifier that identifies each format.
- *
- * @return the unique format id, mever null.
- */
- public String getFormatName();
-
- /**
- * Check if the given {@link java.net.URI} and path xpression qualify that this format should be
- * able to read them, e.g. checking for compatible file endings.
- *
- * @param resource the configuration location, not null
- * @return {@code true} if the given resource is in a format supported by
- * this instance.
- */
- boolean isAccepted(Resource resource);
-
- /**
- * Reads a {@link org.apache.tamaya.PropertySource} fromMap the given URI, using this format.
- *
- * @param resource the configuration location, not null
- * @return the corresponding {@link java.util.Map}, never {@code null}.
- */
- Map<String,String> readConfiguration(Resource resource);
-
- /**
- * Access a {@link ConfigurationFormat}.
- *
- * @param formatName the format name
- * @return the corresponding {@link ConfigurationFormat}, or {@code null}, if
- * not available for the given environment.
- */
- public static ConfigurationFormat of(String formatName){
- return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormat(formatName);
- }
-
- /**
- * Get a collection current the keys current the registered {@link ConfigurationFormat} instances.
- *
- * @return a collection current the keys current the registered {@link ConfigurationFormat} instances.
- */
- public static Collection<String> getFormatNames(){
- return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormatNames();
- }
-
- /**
- * Evaluate the matching format for a given resource.
- *
- * @param resource The resource
- * @return a matching configuration format, or {@code null} if no matching format could be determined.
- */
- public static ConfigurationFormat from(Resource resource){
- return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormat(resource);
-
- }
-
- /**
- * Get an instance for reading configuration fromMap a {@code .properties} file,
- * as defined by {@link java.util.Properties#load(java.io.InputStream)}.
- *
- * @return a format instance for reading configuration fromMap a {@code .properties} file, never null.
- */
- public static ConfigurationFormat getPropertiesFormat(){
- return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getPropertiesFormat();
- }
-
- /**
- * Get an instance for reading configuration fromMap a {@code .xml} properties file,
- * as defined by {@link java.util.Properties#loadFromXML(java.io.InputStream)}.
- *
- * @return a format instance for reading configuration fromMap a {@code .xml} properties file, never null.
- */
- public static ConfigurationFormat getXmlPropertiesFormat(){
- return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getXmlPropertiesFormat();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java b/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
deleted file mode 100644
index 743655e..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.*;
-
-import java.io.Serializable;
-import java.util.Map;
-
-/**
- * Configuration implementation that stores all current values current a given (possibly dynamic, contextual and non remote
- * capable instance) and is fully serializable.
- */
-final class FrozenPropertySource extends AbstractPropertySource implements Serializable{
- private static final long serialVersionUID = -6373137316556444171L;
-
- private PropertySource properties;
-
- /**
- * Constructor.
- * @param config The base configuration.
- */
- private FrozenPropertySource(PropertySource config){
- super(config.getName());
- this.properties = PropertySourceBuilder.of(config).buildFrozen();
- }
-
- public static final PropertySource of(PropertySource config){
- if(config instanceof FrozenPropertySource){
- return config;
- }
- return new FrozenPropertySource(config);
- }
-
- @Override
- public Map<String,String> getProperties(){
- return properties.getProperties();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- FrozenPropertySource that = (FrozenPropertySource) o;
-
- if (!properties.equals(that.properties)) return false;
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = properties.hashCode();
- return result;
- }
-
- @Override
- public String toString() {
- return "FreezedConfiguration{" +
- "properties=" + properties +
- ", name=" + name +
- '}';
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java b/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
deleted file mode 100644
index 160d6c4..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.apache.tamaya.core.properties;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.UnaryOperator;
-
-import org.apache.tamaya.Configuration;
-import org.apache.tamaya.PropertySource;
-import org.apache.tamaya.core.properties.AbstractPropertySource;
-
-/**
- * PropertySource implementation that maps certain parts (defined by an {@code UnaryOperator<String>}) to alternate areas.
- */
-class MappedPropertySource extends AbstractPropertySource {
-
- private static final long serialVersionUID = 8690637705511432083L;
-
- /** The mapping operator. */
- private UnaryOperator<String> keyMapper;
- /** The base configuration. */
- private PropertySource config;
-
- /**
- * Creates a new instance.
- * @param config the base configuration, not null
- * @param keyMapper The mapping operator, not null
- */
- public MappedPropertySource(PropertySource config, UnaryOperator<String> keyMapper) {
- super(config.getName());
- this.config = Objects.requireNonNull(config);
- this.keyMapper = Objects.requireNonNull(keyMapper);
- }
-
- @Override
- public Map<String, String> getProperties() {
- Map<String, String> result = new HashMap<>();
- Map<String, String> map = this.config.getProperties();
- map.forEach((k,v) -> {
- String targetKey = keyMapper.apply(k);
- if(targetKey!=null){
- result.put(targetKey, v);
- }
- });
- return result;
- }
-
- @Override
- public boolean isEmpty() {
- return this.config.isEmpty();
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java b/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
deleted file mode 100644
index 3cf6b31..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.PropertySource;
-
-import java.beans.PropertyChangeEvent;
-import java.io.Serializable;
-import java.util.*;
-
-/**
- * Event that contains a set current changes that were applied or could be applied.
- * This class is immutable and thread-safe. To create instances use
- * {@link PropertyChangeSetBuilder}.
- *
- * Created by Anatole on 22.10.2014.
- */
-public final class PropertyChangeSet implements Serializable{
-
- private static final long serialVersionUID = 1l;
- /** The base property provider/configuration. */
- private PropertySource propertySource;
- /** The base version, usable for optimistic locking. */
- private String baseVersion;
- /** The recorded changes. */
- private Map<String,PropertyChangeEvent> changes = new HashMap<>();
-
- /**
- * Get an empty change set for the given provider.
- * @param propertyProvider The base property provider/configuration, not null.
- * @return an empty ConfigChangeSet instance.
- */
- public static PropertyChangeSet emptyChangeSet(PropertySource propertyProvider){
- return new PropertyChangeSet(propertyProvider, Collections.emptySet());
- }
-
- /**
- * Constructor used by {@link PropertyChangeSetBuilder}.
- * @param propertySource The base property provider/configuration, not null.
- * @param changes The recorded changes, not null.
- */
- PropertyChangeSet(PropertySource propertySource, Collection<PropertyChangeEvent> changes) {
- this.propertySource = Objects.requireNonNull(propertySource);
- changes.forEach((c) -> this.changes.put(c.getPropertyName(), c));
- }
-
- /**
- * Get the underlying property provider/configuration.
- * @return the underlying property provider/configuration, never null.
- */
- public PropertySource getPropertySource(){
- return this.propertySource;
- }
-
- /**
- * Get the base version, usable for optimistic locking.
- * @return the base version.
- */
- public String getBaseVersion(){
- return baseVersion;
- }
-
- /**
- * Get the changes recorded.
- * @return the recorded changes, never null.
- */
- public Collection<PropertyChangeEvent> getEvents(){
- return Collections.unmodifiableCollection(this.changes.values());
- }
-
- /**
- * Access the number current removed entries.
- * @return the number current removed entries.
- */
- public int getRemovedSize() {
- return (int) this.changes.values().stream().filter((e) -> e.getNewValue() == null).count();
- }
-
- /**
- * Access the number current added entries.
- * @return the number current added entries.
- */
- public int getAddedSize() {
- return (int) this.changes.values().stream().filter((e) -> e.getOldValue() == null).count();
- }
-
- /**
- * Access the number current updated entries.
- * @return the number current updated entries.
- */
- public int getUpdatedSize() {
- return (int) this.changes.values().stream().filter((e) -> e.getOldValue()!=null && e.getNewValue()!=null).count();
- }
-
-
- /**
- * Checks if the given key was removed.
- * @param key the target key, not null.
- * @return true, if the given key was removed.
- */
- public boolean isRemoved(String key) {
- PropertyChangeEvent change = this.changes.get(key);
- return change != null && change.getNewValue() == null;
- }
-
- /**
- * Checks if the given key was added.
- * @param key the target key, not null.
- * @return true, if the given key was added.
- */
- public boolean isAdded(String key) {
- PropertyChangeEvent change = this.changes.get(key);
- return change != null && change.getOldValue() == null;
- }
-
- /**
- * Checks if the given key was updated.
- * @param key the target key, not null.
- * @return true, if the given key was updated.
- */
- public boolean isUpdated(String key) {
- PropertyChangeEvent change = this.changes.get(key);
- return change != null && change.getOldValue() != null && change.getNewValue() != null;
- }
-
- /**
- * Checks if the given key is added, or updated AND NOT removed.
- * @param key the target key, not null.
- * @return true, if the given key was added, or updated BUT NOT removed.
- */
- public boolean containsKey(String key) {
- PropertyChangeEvent change = this.changes.get(key);
- return change != null && change.getNewValue() != null;
- }
-
- /**
- * CHecks if the current change set does not contain any changes.
- * @return tru, if the change set is empty.
- */
- public boolean isEmpty(){
- return this.changes.isEmpty();
- }
-
-
- @Override
- public String toString() {
- return "ConfigChangeSet{" +
- "properties=" + propertySource +
- ", baseVersion=" + baseVersion +
- ", changes=" + changes +
- '}';
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java b/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
deleted file mode 100644
index b6e22f8..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.PropertySource;
-
-import java.beans.PropertyChangeEvent;
-import java.util.*;
-import java.util.function.Function;
-
-/**
- * Models a set current changes to be applied to a configuration/property provider. Such a set can be applied
- * to any {@link org.apache.tamaya.PropertySource} instance. If the provider is mutable it may check the
- * version given and applyChanges the changes to the provider/configuration, including triggering current regarding
- * change events.
- * <p>
- * For appropriate conversion a {@code Function<String, Codec>} can be applied, which performs correct conversion,
- * when changed values are set. This function enables connecting e.g. setters on a configuration template with
- * the corresponding conversion logic, so the template calls are correctly converted back.
- */
-public final class PropertyChangeSetBuilder {
- /**
- * The recorded changes.
- */
- final SortedMap<String, PropertyChangeEvent> delta = new TreeMap<>();
- /**
- * The underlying configuration/provider.
- */
- PropertySource source;
-
- /**
- * Constructor.
- *
- * @param source the underlying configuration/provider, not null.
- */
- private PropertyChangeSetBuilder(PropertySource source) {
- this.source = Objects.requireNonNull(source);
- }
-
- /**
- * Creates a new instance current this builder.
- *
- * @param source the underlying property provider/configuration, not null.
- * @return the builder for chaining.
- */
- public static PropertyChangeSetBuilder of(PropertySource source) {
- return new PropertyChangeSetBuilder(source);
- }
-
- /**
- * This method records all changes to be applied to the base property provider/configuration to
- * achieve the given target state.
- *
- * @param newState the new target state, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder addChanges(PropertySource newState) {
- compare(newState, this.source).forEach((c) -> this.delta.put(c.getPropertyName(), c));
- return this;
- }
-
- /**
- * Get the current values, also considering any changes recorded within this change set.
- *
- * @param key the key current the entry, not null.
- * @return the keys, or null.
- */
- public String get(String key) {
- PropertyChangeEvent change = this.delta.get(key);
- if (change != null && !(change.getNewValue() == null)) {
- return (String) change.getNewValue();
- }
- return null;
- }
-
- /**
- * Marks the given key(s) fromMap the configuration/properties to be removed.
- *
- * @param key the key current the entry, not null.
- * @param otherKeys additional keys to be removed (convenience), not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder remove(String key, String... otherKeys) {
- String oldValue = this.source.get(key).orElse(null);
- if (oldValue == null) {
- this.delta.remove(key);
- }
- this.delta.put(key, new PropertyChangeEvent(this.source, key, oldValue, null));
- for (String addKey : otherKeys) {
- oldValue = this.source.get(addKey).orElse(null);
- if (oldValue == null) {
- this.delta.remove(addKey);
- }
- this.delta.put(addKey, new PropertyChangeEvent(this.source, addKey, oldValue, null));
- }
- return this;
- }
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder put(String key, boolean value) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
- return this;
- }
-
- /**
- s* Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder put(String key, byte value) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
- return this;
- }
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder put(String key, char value) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
- return this;
- }
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder put(String key, short value) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
- return this;
- }
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder put(String key, int value) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
- return this;
- }
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder put(String key, long value) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
- return this;
- }
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder put(String key, float value) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
- return this;
- }
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder put(String key, double value) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
- return this;
- }
-
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder put(String key, String value) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
- return this;
- }
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @return the builder for chaining.
- * @throws org.apache.tamaya.ConfigException if no matching Codec could be found.
- */
- public <T> PropertyChangeSetBuilder put(String key, Class<T> type, T value) {
- put(key, type, value, null);
- return this;
- }
-
- /**
- * Applies the given keys.
- *
- * @param key the key current the entry, not null.
- * @param value the keys to be applied, not null.
- * @param adapter the codec to be used, if set overrides any other codecs that may apply. If null an appropriate
- * codec is tried to be evaluated as needed.
- * @return the builder for chaining.
- * @throws org.apache.tamaya.ConfigException if no matching Codec could be found.
- */
- public <T> PropertyChangeSetBuilder put(String key, Class<T> type, T value, Function<T,String> adapter) {
- this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), adapter.apply(Objects.requireNonNull(value))));
- return this;
- }
-
-
- /**
- * Apply all the given values to the base configuration/properties.
- * Note that all values passed must be convertible to String, either
- * <ul>
- * <li>the registered codecs provider provides codecs for the corresponding keys, or </li>
- * <li>default codecs are present for the given type, or</li>
- * <li>the value is an instanceof String</li>
- * </ul>
- *
- * @param changes the changes to be applied, not null.
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder putAll(Map<String, String> changes) {
- changes.putAll(changes);
- return this;
- }
-
- /**
- * This method will create a change set that clears all entries fromMap the given base configuration/properties.
- *
- * @return the builder for chaining.
- */
- public PropertyChangeSetBuilder deleteAll() {
- this.delta.clear();
- this.source.getProperties().forEach((k, v) ->
- this.delta.put(k, new PropertyChangeEvent(this.source, k, v, null)));
- return this;
- }
-
- /**
- * Checks if the change set is empty, i.e. does not contain any changes.
- *
- * @return true, if the set is empty.
- */
- public boolean isEmpty() {
- return this.delta.isEmpty();
- }
-
- /**
- * Resets this change set instance. This will clear all changes done to this builder, so the
- * set will be empty.
- */
- public void reset() {
- this.delta.clear();
- }
-
- /**
- * Builds the corresponding change set.
- *
- * @return the new change set, never null.
- */
- public PropertyChangeSet build() {
- return new PropertyChangeSet(this.source, Collections.unmodifiableCollection(this.delta.values()));
- }
-
- /**
- * Compares the two property config/configurations and creates a collection current all changes
- * that must be appied to render {@code map1} into {@code map2}.
- *
- * @param map1 the source map, not null.
- * @param map2 the target map, not null.
- * @return a collection current change events, never null.
- */
- public static Collection<PropertyChangeEvent> compare(PropertySource map1, PropertySource map2) {
- List<PropertyChangeEvent> changes = new ArrayList<>();
- for (Map.Entry<String, String> en : map1.getProperties().entrySet()) {
- Optional<String> val = map2.get(en.getKey());
- if (!val.isPresent()) {
- changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
- } else if (!val.get().equals(en.getValue())) {
- changes.add(new PropertyChangeEvent(map1, en.getKey(), val.get(), en.getValue()));
- }
- }
- for (Map.Entry<String, String> en : map2.getProperties().entrySet()) {
- Optional<String> val = map1.get(en.getKey());
- if (!val.isPresent()) {
- changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
- } else if (!val.equals(Optional.ofNullable(en.getValue()))) {
- changes.add(new PropertyChangeEvent(map1, en.getKey(), val.get(), en.getValue()));
- }
- }
- return changes;
- }
-
- /*
- * (non-Javadoc)
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return "PropertyChangeEventBuilder [source=" + source + ", " +
- ", delta=" + delta + "]";
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java b/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java
deleted file mode 100644
index 5fcf895..0000000
--- a/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.core.properties;
-
-import org.apache.tamaya.PropertySource;
-
-import java.util.*;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-import java.util.stream.Collectors;
-
-/**
- * Accessor that provides useful functions along with configuration.
- */
-public final class PropertySourceFunctions {
- /**
- * Private singleton constructor.
- */
- private PropertySourceFunctions() {
- }
-
- /**
- * Creates a ConfigOperator that creates a Configuration containing only keys
- * that are contained in the given area (non recursive). Hereby
- * the area key is stripped away fromMap the resulting key.
- *
- * @param areaKey the area key, not null
- * @param mappedAreaKey the target key, not null
- * @return the area configuration, with the areaKey stripped away.
- */
- public static UnaryOperator<PropertySource> mapArea(String areaKey, String mappedAreaKey) {
- return mapKeys(key -> key.startsWith(areaKey + '.') ?
- mappedAreaKey + key.substring(areaKey.length()) : key);
- }
-
- /**
- * Creates a {@link java.util.function.UnaryOperator} that creates a {@link org.apache.tamaya.Configuration} that maps any keys as
- * defined by the {@code keyMapper} given. If the {@code keyMapper} returns
- * {@code null} for a keys, it is removed from the resulting map.
- *
- * @param keyMapper the key mapper, not null
- * @return the area configuration, with the areaKey stripped away.
- */
- public static UnaryOperator<PropertySource> mapKeys(UnaryOperator<String> keyMapper) {
- return (c) -> new MappedPropertySource(c, keyMapper);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/core/src/main/resources/META-INF/services/org.apache.tamaya.core.properties.ConfigurationFormat
----------------------------------------------------------------------
diff --git a/core/src/main/resources/META-INF/services/org.apache.tamaya.core.properties.ConfigurationFormat b/core/src/main/resources/META-INF/services/org.apache.tamaya.core.properties.ConfigurationFormat
deleted file mode 100644
index 7aa2407..0000000
--- a/core/src/main/resources/META-INF/services/org.apache.tamaya.core.properties.ConfigurationFormat
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy current the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-org.apache.tamaya.core.internal.format.PropertiesFormat
-org.apache.tamaya.core.internal.format.PropertiesXmlFormat
-org.apache.tamaya.core.internal.format.IniFormat
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java b/dormant/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
new file mode 100644
index 0000000..b1c2522
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/ConfigurationFunctions.java
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.core.properties.PropertySourceBuilder;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import java.util.stream.Collectors;
+
+/**
+ * Accessor that provides useful functions along with configuration.
+ */
+public final class ConfigurationFunctions {
+ /**
+ * Private singleton constructor.
+ */
+ private ConfigurationFunctions() {
+ }
+
+ /**
+ * Creates a ConfigOperator that creates a Configuration containing only keys
+ * that are contained in the given area (non recursive). Hereby
+ * the area key is stripped away fromMap the resulting key.
+ *
+ * @param areaKey the area key, not null
+ * @return the area configuration, with the areaKey stripped away.
+ */
+ public static UnaryOperator<Configuration> selectArea(String areaKey) {
+ return selectArea(areaKey, true);
+ }
+
+ /**
+ * Creates a ConfigOperator that creates a Configuration containing only keys
+ * that are contained in the given area (non recursive).
+ *
+ * @param areaKey the area key, not null
+ * @param stripKeys if set to true, the area key is stripped away fromMap the resulting key.
+ * @return the area configuration, with the areaKey stripped away.
+ */
+ public static UnaryOperator<Configuration> selectArea(String areaKey, boolean stripKeys) {
+ return config -> {
+ Map<String, String> area = new HashMap<>();
+ area.putAll(
+ config.getProperties().entrySet().stream()
+ .filter(e -> isKeyInArea(e.getKey(), areaKey))
+ .collect(Collectors.toMap(
+ e -> stripKeys ? e.getKey().substring(areaKey.length() + 1) : e.getKey(),
+ Map.Entry::getValue)));
+ return Configuration.from(PropertySourceBuilder.of("area: " + areaKey).addMap(area).build());
+ };
+ }
+
+ /**
+ * Calculates the current area key and compares it with the given key.
+ *
+ * @param key the fully qualified entry key, not null
+ * @param areaKey the area key, not null
+ * @return true, if the entry is exact in this area
+ */
+ public static boolean isKeyInArea(String key, String areaKey) {
+ int lastIndex = key.lastIndexOf('.');
+ String curAreaKey = lastIndex > 0 ? key.substring(0, lastIndex) : "";
+ return curAreaKey.equals(areaKey);
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualifies area names. This method should return the areas as accurate as possible,
+ * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
+ * does not support key iteration.
+ *
+ * @return s set with all areas, never {@code null}.
+ */
+ public static Function<Configuration,Set<String>> getAreas() {
+ return config -> {
+ final Set<String> areas = new HashSet<>();
+ config.getProperties().keySet().forEach(s -> {
+ int index = s.lastIndexOf('.');
+ if (index > 0) {
+ areas.add(s.substring(0, index));
+ } else {
+ areas.add("<root>");
+ }
+ });
+ return areas;
+ };
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualified area names, containing the transitive closure also including all
+ * subarea names, regardless if properties are accessible or not. This method should return the areas as accurate
+ * as possible, but may not provide a complete set of areas that are finally accessible, especially when the
+ * underlying storage does not support key iteration.
+ *
+ * @return s set with all transitive areas, never {@code null}.
+ */
+ public static Function<Configuration,Set<String>> getTransitiveAreas() {
+ return config -> {
+ final Set<String> transitiveAreas = new HashSet<>();
+ config.query(getAreas()).forEach(s -> {
+ int index = s.lastIndexOf('.');
+ if (index < 0) {
+ transitiveAreas.add("<root>");
+ } else {
+ while (index > 0) {
+ s = s.substring(0, index);
+ transitiveAreas.add(s);
+ index = s.lastIndexOf('.');
+ }
+ }
+ });
+ return transitiveAreas;
+ };
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualified area names, containing only the
+ * areas that match the predicate and have properties attached. This method should return the areas as accurate as possible,
+ * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
+ * does not support key iteration.
+ *
+ * @param predicate A predicate to deternine, which areas should be returned, not {@code null}.
+ * @return s set with all areas, never {@code null}.
+ */
+ public static Function<Configuration,Set<String>> getAreas(final Predicate<String> predicate) {
+ return config -> {
+ return config.query(getAreas()).stream().filter(predicate).collect(Collectors.toCollection(TreeSet::new));
+ };
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualified area names, containing the transitive closure also including all
+ * subarea names, regardless if properties are accessible or not. This method should return the areas as accurate as possible,
+ * but may not provide a complete set of areas that are finally accessible, especially when the underlying storage
+ * does not support key iteration.
+ *
+ * @param predicate A predicate to deternine, which areas should be returned, not {@code null}.
+ * @return s set with all transitive areas, never {@code null}.
+ */
+ public static Function<Configuration,Set<String>> getTransitiveAreas(Predicate<String> predicate) {
+ return config -> {
+ return config.query(getTransitiveAreas()).stream().filter(predicate).collect(Collectors.toCollection(TreeSet::new));
+ };
+ }
+
+ /**
+ * Return a query to evaluate to evaluate if an area exists. In case where the underlying storage implementation does not allow
+ * querying the keys available, {@code false} should be returned.
+ *
+ * @param areaKey the configuration area (sub)path.
+ * @return {@code true}, if such a node exists.
+ */
+ public static Function<Configuration,Boolean> containsArea(String areaKey) {
+ return config -> {
+ return config.query(getAreas()).contains(areaKey);
+ };
+ }
+
+ /**
+ * Creates a ConfigOperator that creates a Configuration containing only keys
+ * that are contained in the given area (recursive). Hereby
+ * the area key is stripped away fromMap the resulting key.
+ *
+ * @param areaKey the area key, not null
+ * @return the area configuration, with the areaKey stripped away.
+ */
+ public static UnaryOperator<Configuration> selectAreaRecursive(String areaKey) {
+ return selectAreaRecursive(areaKey, true);
+ }
+
+ /**
+ * Creates a ConfigOperator that creates a Configuration containing only keys
+ * that are contained in the given area (recursive).
+ *
+ * @param areaKey the area key, not null
+ * @param stripKeys if set to true, the area key is stripped away fromMap the resulting key.
+ * @return the area configuration, with the areaKey stripped away.
+ */
+ public static UnaryOperator<Configuration> selectAreaRecursive(String areaKey, boolean stripKeys) {
+ return config -> {
+ Map<String, String> area = new HashMap<>();
+ String lookupKey = areaKey + '.';
+ area.putAll(
+ config.getProperties().entrySet().stream()
+ .filter(e -> e.getKey().startsWith(lookupKey))
+ .collect(Collectors.toMap(
+ e -> stripKeys ? e.getKey().substring(areaKey.length() + 1) : e.getKey(),
+ Map.Entry::getValue)));
+ return Configuration.from(PropertySourceBuilder.of("area (recursive): " + areaKey).addMap(area).build());
+ };
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
new file mode 100644
index 0000000..cf94d99
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/ConfigurationFormat.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.properties;
+
+import org.apache.tamaya.core.resource.Resource;
+import org.apache.tamaya.core.spi.ConfigurationFormatSpi;
+import org.apache.tamaya.spi.ServiceContext;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Implementations current this class encapsulate the mechanism how to read a
+ * resource URI including interpreting the format correctly (e.g. xml vs.
+ * properties).
+ */
+public interface ConfigurationFormat{
+
+ /**
+ * Returns a unique identifier that identifies each format.
+ *
+ * @return the unique format id, mever null.
+ */
+ public String getFormatName();
+
+ /**
+ * Check if the given {@link java.net.URI} and path xpression qualify that this format should be
+ * able to read them, e.g. checking for compatible file endings.
+ *
+ * @param resource the configuration location, not null
+ * @return {@code true} if the given resource is in a format supported by
+ * this instance.
+ */
+ boolean isAccepted(Resource resource);
+
+ /**
+ * Reads a {@link org.apache.tamaya.PropertySource} fromMap the given URI, using this format.
+ *
+ * @param resource the configuration location, not null
+ * @return the corresponding {@link java.util.Map}, never {@code null}.
+ */
+ Map<String,String> readConfiguration(Resource resource);
+
+ /**
+ * Access a {@link ConfigurationFormat}.
+ *
+ * @param formatName the format name
+ * @return the corresponding {@link ConfigurationFormat}, or {@code null}, if
+ * not available for the given environment.
+ */
+ public static ConfigurationFormat of(String formatName){
+ return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormat(formatName);
+ }
+
+ /**
+ * Get a collection current the keys current the registered {@link ConfigurationFormat} instances.
+ *
+ * @return a collection current the keys current the registered {@link ConfigurationFormat} instances.
+ */
+ public static Collection<String> getFormatNames(){
+ return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormatNames();
+ }
+
+ /**
+ * Evaluate the matching format for a given resource.
+ *
+ * @param resource The resource
+ * @return a matching configuration format, or {@code null} if no matching format could be determined.
+ */
+ public static ConfigurationFormat from(Resource resource){
+ return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getFormat(resource);
+
+ }
+
+ /**
+ * Get an instance for reading configuration fromMap a {@code .properties} file,
+ * as defined by {@link java.util.Properties#load(java.io.InputStream)}.
+ *
+ * @return a format instance for reading configuration fromMap a {@code .properties} file, never null.
+ */
+ public static ConfigurationFormat getPropertiesFormat(){
+ return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getPropertiesFormat();
+ }
+
+ /**
+ * Get an instance for reading configuration fromMap a {@code .xml} properties file,
+ * as defined by {@link java.util.Properties#loadFromXML(java.io.InputStream)}.
+ *
+ * @return a format instance for reading configuration fromMap a {@code .xml} properties file, never null.
+ */
+ public static ConfigurationFormat getXmlPropertiesFormat(){
+ return ServiceContext.getInstance().getSingleton(ConfigurationFormatSpi.class).getXmlPropertiesFormat();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
new file mode 100644
index 0000000..743655e
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/FrozenPropertySource.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.properties;
+
+import org.apache.tamaya.*;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * Configuration implementation that stores all current values current a given (possibly dynamic, contextual and non remote
+ * capable instance) and is fully serializable.
+ */
+final class FrozenPropertySource extends AbstractPropertySource implements Serializable{
+ private static final long serialVersionUID = -6373137316556444171L;
+
+ private PropertySource properties;
+
+ /**
+ * Constructor.
+ * @param config The base configuration.
+ */
+ private FrozenPropertySource(PropertySource config){
+ super(config.getName());
+ this.properties = PropertySourceBuilder.of(config).buildFrozen();
+ }
+
+ public static final PropertySource of(PropertySource config){
+ if(config instanceof FrozenPropertySource){
+ return config;
+ }
+ return new FrozenPropertySource(config);
+ }
+
+ @Override
+ public Map<String,String> getProperties(){
+ return properties.getProperties();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ FrozenPropertySource that = (FrozenPropertySource) o;
+
+ if (!properties.equals(that.properties)) return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = properties.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "FreezedConfiguration{" +
+ "properties=" + properties +
+ ", name=" + name +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
new file mode 100644
index 0000000..160d6c4
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/MappedPropertySource.java
@@ -0,0 +1,53 @@
+package org.apache.tamaya.core.properties;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.UnaryOperator;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.PropertySource;
+import org.apache.tamaya.core.properties.AbstractPropertySource;
+
+/**
+ * PropertySource implementation that maps certain parts (defined by an {@code UnaryOperator<String>}) to alternate areas.
+ */
+class MappedPropertySource extends AbstractPropertySource {
+
+ private static final long serialVersionUID = 8690637705511432083L;
+
+ /** The mapping operator. */
+ private UnaryOperator<String> keyMapper;
+ /** The base configuration. */
+ private PropertySource config;
+
+ /**
+ * Creates a new instance.
+ * @param config the base configuration, not null
+ * @param keyMapper The mapping operator, not null
+ */
+ public MappedPropertySource(PropertySource config, UnaryOperator<String> keyMapper) {
+ super(config.getName());
+ this.config = Objects.requireNonNull(config);
+ this.keyMapper = Objects.requireNonNull(keyMapper);
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ Map<String, String> result = new HashMap<>();
+ Map<String, String> map = this.config.getProperties();
+ map.forEach((k,v) -> {
+ String targetKey = keyMapper.apply(k);
+ if(targetKey!=null){
+ result.put(targetKey, v);
+ }
+ });
+ return result;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return this.config.isEmpty();
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
new file mode 100644
index 0000000..3cf6b31
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSet.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.properties;
+
+import org.apache.tamaya.PropertySource;
+
+import java.beans.PropertyChangeEvent;
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Event that contains a set current changes that were applied or could be applied.
+ * This class is immutable and thread-safe. To create instances use
+ * {@link PropertyChangeSetBuilder}.
+ *
+ * Created by Anatole on 22.10.2014.
+ */
+public final class PropertyChangeSet implements Serializable{
+
+ private static final long serialVersionUID = 1l;
+ /** The base property provider/configuration. */
+ private PropertySource propertySource;
+ /** The base version, usable for optimistic locking. */
+ private String baseVersion;
+ /** The recorded changes. */
+ private Map<String,PropertyChangeEvent> changes = new HashMap<>();
+
+ /**
+ * Get an empty change set for the given provider.
+ * @param propertyProvider The base property provider/configuration, not null.
+ * @return an empty ConfigChangeSet instance.
+ */
+ public static PropertyChangeSet emptyChangeSet(PropertySource propertyProvider){
+ return new PropertyChangeSet(propertyProvider, Collections.emptySet());
+ }
+
+ /**
+ * Constructor used by {@link PropertyChangeSetBuilder}.
+ * @param propertySource The base property provider/configuration, not null.
+ * @param changes The recorded changes, not null.
+ */
+ PropertyChangeSet(PropertySource propertySource, Collection<PropertyChangeEvent> changes) {
+ this.propertySource = Objects.requireNonNull(propertySource);
+ changes.forEach((c) -> this.changes.put(c.getPropertyName(), c));
+ }
+
+ /**
+ * Get the underlying property provider/configuration.
+ * @return the underlying property provider/configuration, never null.
+ */
+ public PropertySource getPropertySource(){
+ return this.propertySource;
+ }
+
+ /**
+ * Get the base version, usable for optimistic locking.
+ * @return the base version.
+ */
+ public String getBaseVersion(){
+ return baseVersion;
+ }
+
+ /**
+ * Get the changes recorded.
+ * @return the recorded changes, never null.
+ */
+ public Collection<PropertyChangeEvent> getEvents(){
+ return Collections.unmodifiableCollection(this.changes.values());
+ }
+
+ /**
+ * Access the number current removed entries.
+ * @return the number current removed entries.
+ */
+ public int getRemovedSize() {
+ return (int) this.changes.values().stream().filter((e) -> e.getNewValue() == null).count();
+ }
+
+ /**
+ * Access the number current added entries.
+ * @return the number current added entries.
+ */
+ public int getAddedSize() {
+ return (int) this.changes.values().stream().filter((e) -> e.getOldValue() == null).count();
+ }
+
+ /**
+ * Access the number current updated entries.
+ * @return the number current updated entries.
+ */
+ public int getUpdatedSize() {
+ return (int) this.changes.values().stream().filter((e) -> e.getOldValue()!=null && e.getNewValue()!=null).count();
+ }
+
+
+ /**
+ * Checks if the given key was removed.
+ * @param key the target key, not null.
+ * @return true, if the given key was removed.
+ */
+ public boolean isRemoved(String key) {
+ PropertyChangeEvent change = this.changes.get(key);
+ return change != null && change.getNewValue() == null;
+ }
+
+ /**
+ * Checks if the given key was added.
+ * @param key the target key, not null.
+ * @return true, if the given key was added.
+ */
+ public boolean isAdded(String key) {
+ PropertyChangeEvent change = this.changes.get(key);
+ return change != null && change.getOldValue() == null;
+ }
+
+ /**
+ * Checks if the given key was updated.
+ * @param key the target key, not null.
+ * @return true, if the given key was updated.
+ */
+ public boolean isUpdated(String key) {
+ PropertyChangeEvent change = this.changes.get(key);
+ return change != null && change.getOldValue() != null && change.getNewValue() != null;
+ }
+
+ /**
+ * Checks if the given key is added, or updated AND NOT removed.
+ * @param key the target key, not null.
+ * @return true, if the given key was added, or updated BUT NOT removed.
+ */
+ public boolean containsKey(String key) {
+ PropertyChangeEvent change = this.changes.get(key);
+ return change != null && change.getNewValue() != null;
+ }
+
+ /**
+ * CHecks if the current change set does not contain any changes.
+ * @return tru, if the change set is empty.
+ */
+ public boolean isEmpty(){
+ return this.changes.isEmpty();
+ }
+
+
+ @Override
+ public String toString() {
+ return "ConfigChangeSet{" +
+ "properties=" + propertySource +
+ ", baseVersion=" + baseVersion +
+ ", changes=" + changes +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/278a6c68/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
new file mode 100644
index 0000000..b6e22f8
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertyChangeSetBuilder.java
@@ -0,0 +1,347 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.properties;
+
+import org.apache.tamaya.PropertySource;
+
+import java.beans.PropertyChangeEvent;
+import java.util.*;
+import java.util.function.Function;
+
+/**
+ * Models a set current changes to be applied to a configuration/property provider. Such a set can be applied
+ * to any {@link org.apache.tamaya.PropertySource} instance. If the provider is mutable it may check the
+ * version given and applyChanges the changes to the provider/configuration, including triggering current regarding
+ * change events.
+ * <p>
+ * For appropriate conversion a {@code Function<String, Codec>} can be applied, which performs correct conversion,
+ * when changed values are set. This function enables connecting e.g. setters on a configuration template with
+ * the corresponding conversion logic, so the template calls are correctly converted back.
+ */
+public final class PropertyChangeSetBuilder {
+ /**
+ * The recorded changes.
+ */
+ final SortedMap<String, PropertyChangeEvent> delta = new TreeMap<>();
+ /**
+ * The underlying configuration/provider.
+ */
+ PropertySource source;
+
+ /**
+ * Constructor.
+ *
+ * @param source the underlying configuration/provider, not null.
+ */
+ private PropertyChangeSetBuilder(PropertySource source) {
+ this.source = Objects.requireNonNull(source);
+ }
+
+ /**
+ * Creates a new instance current this builder.
+ *
+ * @param source the underlying property provider/configuration, not null.
+ * @return the builder for chaining.
+ */
+ public static PropertyChangeSetBuilder of(PropertySource source) {
+ return new PropertyChangeSetBuilder(source);
+ }
+
+ /**
+ * This method records all changes to be applied to the base property provider/configuration to
+ * achieve the given target state.
+ *
+ * @param newState the new target state, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder addChanges(PropertySource newState) {
+ compare(newState, this.source).forEach((c) -> this.delta.put(c.getPropertyName(), c));
+ return this;
+ }
+
+ /**
+ * Get the current values, also considering any changes recorded within this change set.
+ *
+ * @param key the key current the entry, not null.
+ * @return the keys, or null.
+ */
+ public String get(String key) {
+ PropertyChangeEvent change = this.delta.get(key);
+ if (change != null && !(change.getNewValue() == null)) {
+ return (String) change.getNewValue();
+ }
+ return null;
+ }
+
+ /**
+ * Marks the given key(s) fromMap the configuration/properties to be removed.
+ *
+ * @param key the key current the entry, not null.
+ * @param otherKeys additional keys to be removed (convenience), not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder remove(String key, String... otherKeys) {
+ String oldValue = this.source.get(key).orElse(null);
+ if (oldValue == null) {
+ this.delta.remove(key);
+ }
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, oldValue, null));
+ for (String addKey : otherKeys) {
+ oldValue = this.source.get(addKey).orElse(null);
+ if (oldValue == null) {
+ this.delta.remove(addKey);
+ }
+ this.delta.put(addKey, new PropertyChangeEvent(this.source, addKey, oldValue, null));
+ }
+ return this;
+ }
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder put(String key, boolean value) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+ return this;
+ }
+
+ /**
+ s* Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder put(String key, byte value) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+ return this;
+ }
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder put(String key, char value) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+ return this;
+ }
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder put(String key, short value) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+ return this;
+ }
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder put(String key, int value) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+ return this;
+ }
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder put(String key, long value) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+ return this;
+ }
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder put(String key, float value) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+ return this;
+ }
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder put(String key, double value) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+ return this;
+ }
+
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder put(String key, String value) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), String.valueOf(value)));
+ return this;
+ }
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @return the builder for chaining.
+ * @throws org.apache.tamaya.ConfigException if no matching Codec could be found.
+ */
+ public <T> PropertyChangeSetBuilder put(String key, Class<T> type, T value) {
+ put(key, type, value, null);
+ return this;
+ }
+
+ /**
+ * Applies the given keys.
+ *
+ * @param key the key current the entry, not null.
+ * @param value the keys to be applied, not null.
+ * @param adapter the codec to be used, if set overrides any other codecs that may apply. If null an appropriate
+ * codec is tried to be evaluated as needed.
+ * @return the builder for chaining.
+ * @throws org.apache.tamaya.ConfigException if no matching Codec could be found.
+ */
+ public <T> PropertyChangeSetBuilder put(String key, Class<T> type, T value, Function<T,String> adapter) {
+ this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key).orElse(null), adapter.apply(Objects.requireNonNull(value))));
+ return this;
+ }
+
+
+ /**
+ * Apply all the given values to the base configuration/properties.
+ * Note that all values passed must be convertible to String, either
+ * <ul>
+ * <li>the registered codecs provider provides codecs for the corresponding keys, or </li>
+ * <li>default codecs are present for the given type, or</li>
+ * <li>the value is an instanceof String</li>
+ * </ul>
+ *
+ * @param changes the changes to be applied, not null.
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder putAll(Map<String, String> changes) {
+ changes.putAll(changes);
+ return this;
+ }
+
+ /**
+ * This method will create a change set that clears all entries fromMap the given base configuration/properties.
+ *
+ * @return the builder for chaining.
+ */
+ public PropertyChangeSetBuilder deleteAll() {
+ this.delta.clear();
+ this.source.getProperties().forEach((k, v) ->
+ this.delta.put(k, new PropertyChangeEvent(this.source, k, v, null)));
+ return this;
+ }
+
+ /**
+ * Checks if the change set is empty, i.e. does not contain any changes.
+ *
+ * @return true, if the set is empty.
+ */
+ public boolean isEmpty() {
+ return this.delta.isEmpty();
+ }
+
+ /**
+ * Resets this change set instance. This will clear all changes done to this builder, so the
+ * set will be empty.
+ */
+ public void reset() {
+ this.delta.clear();
+ }
+
+ /**
+ * Builds the corresponding change set.
+ *
+ * @return the new change set, never null.
+ */
+ public PropertyChangeSet build() {
+ return new PropertyChangeSet(this.source, Collections.unmodifiableCollection(this.delta.values()));
+ }
+
+ /**
+ * Compares the two property config/configurations and creates a collection current all changes
+ * that must be appied to render {@code map1} into {@code map2}.
+ *
+ * @param map1 the source map, not null.
+ * @param map2 the target map, not null.
+ * @return a collection current change events, never null.
+ */
+ public static Collection<PropertyChangeEvent> compare(PropertySource map1, PropertySource map2) {
+ List<PropertyChangeEvent> changes = new ArrayList<>();
+ for (Map.Entry<String, String> en : map1.getProperties().entrySet()) {
+ Optional<String> val = map2.get(en.getKey());
+ if (!val.isPresent()) {
+ changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
+ } else if (!val.get().equals(en.getValue())) {
+ changes.add(new PropertyChangeEvent(map1, en.getKey(), val.get(), en.getValue()));
+ }
+ }
+ for (Map.Entry<String, String> en : map2.getProperties().entrySet()) {
+ Optional<String> val = map1.get(en.getKey());
+ if (!val.isPresent()) {
+ changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
+ } else if (!val.equals(Optional.ofNullable(en.getValue()))) {
+ changes.add(new PropertyChangeEvent(map1, en.getKey(), val.get(), en.getValue()));
+ }
+ }
+ return changes;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "PropertyChangeEventBuilder [source=" + source + ", " +
+ ", delta=" + delta + "]";
+ }
+
+}