You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2018/01/03 00:09:02 UTC
[06/18] incubator-tamaya-extensions git commit: Adapted to comply
with JSR API, fixed bugs. Imrpved API regarding sections, section filtering.
Adapted to comply with JSR API, fixed bugs. Imrpved API regarding sections, section filtering.
Signed-off-by: Anatole Tresch <an...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/commit/36b44661
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/tree/36b44661
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/diff/36b44661
Branch: refs/heads/configjsr
Commit: 36b446614d7c95b2ed1db9e15ff6ddaeeca1f7ab
Parents: 581c92e
Author: Anatole Tresch <an...@apache.org>
Authored: Wed Dec 27 12:37:03 2017 +0100
Committer: Anatole Tresch <an...@apache.org>
Committed: Wed Dec 27 12:37:03 2017 +0100
----------------------------------------------------------------------
modules/functions/pom.xml | 5 +-
.../tamaya/functions/ConfigSourceFunctions.java | 451 +++++++++++++++++++
.../functions/ConfigurationFunctions.java | 2 +-
.../tamaya/functions/EnrichedConfigSource.java | 93 ++++
.../functions/EnrichedPropertySource.java | 103 -----
.../tamaya/functions/FilteredConfigSource.java | 89 ++++
.../functions/FilteredPropertySource.java | 93 ----
.../tamaya/functions/MappedConfigSource.java | 109 +++++
.../tamaya/functions/MappedPropertySource.java | 119 -----
.../functions/PropertySourceFunctions.java | 410 -----------------
.../functions/ValueMappedConfigSource.java | 75 +++
.../functions/ValueMappedPropertySource.java | 86 ----
.../functions/CombinedConfigurationTest.java | 1 -
.../functions/ConfigSourceFunctionsTest.java | 434 ++++++++++++++++++
.../functions/EnrichedConfigSourceTest.java | 216 +++++++++
.../functions/EnrichedConfigurationTest.java | 4 -
.../functions/EnrichedPropertySourceTest.java | 250 ----------
.../functions/FilteredConfigSourceTest.java | 188 ++++++++
.../functions/FilteredPropertySourceTest.java | 214 ---------
.../tamaya/functions/InMemoryConfigSource.java | 68 +++
.../tamaya/functions/InMemoryConfiguration.java | 35 --
.../functions/InMemoryPropertySource.java | 86 ----
.../functions/MappedConfigSourceTest.java | 159 +++++++
.../functions/MappedPropertySourceTest.java | 176 --------
.../functions/PropertySourceFunctionsTest.java | 367 ---------------
.../functions/ValueMappedConfigSourceTest.java | 148 ++++++
.../ValueMappedPropertySourceTest.java | 183 --------
27 files changed, 2033 insertions(+), 2131 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/pom.xml
----------------------------------------------------------------------
diff --git a/modules/functions/pom.xml b/modules/functions/pom.xml
index 17de980..4baa580 100644
--- a/modules/functions/pom.xml
+++ b/modules/functions/pom.xml
@@ -41,10 +41,9 @@ under the License.
</dependency>
<dependency>
<groupId>org.apache.tamaya</groupId>
- <artifactId>tamaya-spisupport</artifactId>
- <version>${project.version}</version>
+ <artifactId>tamaya-base</artifactId>
+ <version>${tamaya-apicore.version}</version>
</dependency>
-
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/ConfigSourceFunctions.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/ConfigSourceFunctions.java b/modules/functions/src/main/java/org/apache/tamaya/functions/ConfigSourceFunctions.java
new file mode 100644
index 0000000..90081ed
--- /dev/null
+++ b/modules/functions/src/main/java/org/apache/tamaya/functions/ConfigSourceFunctions.java
@@ -0,0 +1,451 @@
+/*
+ * 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.functions;
+
+import javax.config.ConfigProvider;
+import javax.config.spi.ConfigSource;
+import java.util.*;
+import java.util.function.Function;
+
+/**
+ * Accessor that provides useful functions along with configuration.
+ */
+public final class ConfigSourceFunctions {
+ /**
+ * Implementation of an empty propertySource.
+ */
+ private static final ConfigSource EMPTY_PROPERTYSOURCE = new ConfigSource() {
+
+ @Override
+ public int getOrdinal() {
+ return 0;
+ }
+
+ @Override
+ public String getName() {
+ return "<empty>";
+ }
+
+ @Override
+ public String getValue(String key) {
+ return null;
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public String toString() {
+ return "ConfigSource<empty>";
+ }
+ };
+
+
+ private static final Function<String,Integer> DEFAULT_AREA_CALCULATOR =
+ s -> s.lastIndexOf('.');
+
+ /**
+ * Private singleton constructor.
+ */
+ private ConfigSourceFunctions() {
+ }
+
+ /**
+ * Calculates the current section key and compares it to the given key.
+ *
+ * @param key the fully qualified entry key, not null
+ * @param sectionKey the section key, not null
+ * @param sectionCalculator function to calculate the split point of a key's section, e.g. {@code key.lastIndexOf('.')},
+ * not null.
+ * @param directChildrenOnly if true, only keys with the same area match. Otherwise also containing super-areas can
+ * match.
+ * @return true, if the entry is exact in this section
+ */
+ private static boolean isKeyInSection(String key, String sectionKey,
+ Function<String,Integer> sectionCalculator, boolean directChildrenOnly) {
+ Objects.requireNonNull(key, "Key must be given.");
+ Objects.requireNonNull(sectionCalculator, "Section calculator must be given.");
+ Objects.requireNonNull(sectionKey, "Section key must be given.");
+
+ sectionKey = normalizeSectionKey(sectionKey);
+
+ int lastIndex = sectionCalculator.apply(key);
+ String curAreaKey = lastIndex > 0 ? key.substring(0, lastIndex) : "";
+ if(directChildrenOnly) {
+ return curAreaKey.equals(sectionKey);
+ }else{
+ return curAreaKey.startsWith(sectionKey);
+ }
+ }
+
+ private static String normalizeKey(String key) {
+ return normalizeKey(key, DEFAULT_AREA_CALCULATOR);
+ }
+
+ private static String normalizeKey(String key, Function<String,Integer> sectionCalculator) {
+ if(key.isEmpty()){
+ return key;
+ }
+ int index = sectionCalculator.apply(key.substring(0,1));
+ if(index==0){
+ return key.substring(1);
+ }
+ return key;
+ }
+
+ private static String normalizeSectionKey(String sectionKey) {
+ return normalizeSectionKey(sectionKey, DEFAULT_AREA_CALCULATOR);
+ }
+
+ private static String normalizeSectionKey(String sectionKey, Function<String,Integer> areaCalculator) {
+ // Ignore unneeded and trailing dot at the end of the section key
+ if(sectionKey.isEmpty()){
+ return sectionKey;
+ }
+ int lastIndex = areaCalculator.apply(sectionKey);
+ int firstIndex = areaCalculator.apply(sectionKey.substring(0,1));
+
+ String normalizedKey = lastIndex==(sectionKey.length()-1)
+ ? sectionKey.substring(0, sectionKey.length() - 1)
+ : sectionKey;
+
+ normalizedKey = firstIndex==0 ? sectionKey.length() == 1 ? ""
+ : normalizedKey.substring(1)
+ : normalizedKey;
+
+ return normalizedKey;
+ }
+
+ /**
+ * Checks if the given key is <i>directly</i> included in one of the given sections.
+ *
+ * @param key the fully qualified entry key, not {@code null}
+ * @param sectionKeys the section keys, not {@code null}
+ * @return true, if the entry is in one of the given sections
+ */
+ public static boolean isKeyInSection(String key, String... sectionKeys) {
+ return isKeyInSection(key, true, DEFAULT_AREA_CALCULATOR, sectionKeys);
+ }
+
+ /**
+ * Checks if the given key is included in one of the given sections.
+ *
+ * @param key the fully qualified entry key, not {@code null}
+ * @param sectionKeys the section keys, not {@code null}
+ * @param directChildrenOnly if true, then only keys match, which are a direct child of the given section.
+ * @return true, if the entry is in one of the given sections
+ */
+ public static boolean isKeyInSection(String key, boolean directChildrenOnly, String... sectionKeys) {
+ return isKeyInSection(key, directChildrenOnly, DEFAULT_AREA_CALCULATOR, sectionKeys);
+ }
+
+ /**
+ * Checks if the given key is included in one of the given sections, using the given separator to identify sections.
+ *
+ * @param key the fully qualified entry key, not {@code null}
+ * @param sectionKeys the section keys, not {@code null}
+ * @param areaCalculator the function to calculate the split point to identify the section of a key.
+ * @param directChildrenOnly if true, then only keys match, which are a direct child of the given section.
+ * @return true, if the entry is in one of the given sections
+ */
+ public static boolean isKeyInSection(String key, boolean directChildrenOnly,
+ Function<String,Integer> areaCalculator, String... sectionKeys) {
+ Objects.requireNonNull(key, "Key must be given.");
+ Objects.requireNonNull(sectionKeys, "Section keys must be given.");
+
+ for (String areaKey : sectionKeys) {
+ if (areaKey == null) {
+ continue;
+ }
+ if (isKeyInSection(key, areaKey, areaCalculator, directChildrenOnly)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualified section names. This method should return the sections as accurate as possible,
+ * but may not provide a complete set of sections that are finally accessible, especially when the underlying storage
+ * does not support key iteration.
+ *
+ * @param properties properties to find sections in.
+ * @return set with all sections, never {@code null}.
+ */
+ public static Set<String> sections(Map<String, String> properties) {
+ return sections(properties, DEFAULT_AREA_CALCULATOR);
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualified section names. This method should return the sections as accurate as possible,
+ * but may not provide a complete set of sections that are finally accessible, especially when the underlying storage
+ * does not support key iteration.
+ *
+ * @param properties properties to find sections in.
+ * @return set with all sections, never {@code null}.
+ */
+ public static Set<String> sections(Map<String, String> properties, Function<String,Integer> areaCalculator) {
+ final Set<String> areas = new HashSet<>();
+ for (String key : properties.keySet()) {
+ String normalizedKey = normalizeKey(key, areaCalculator);
+
+ int index = areaCalculator.apply(normalizedKey);
+ if (index > 0) {
+ areas.add(normalizedKey.substring(0, index));
+ } else {
+ areas.add("<root>");
+ }
+ }
+ return areas;
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualified section names, containing the transitive closure also including all
+ * subarea names, regardless if properties are accessible or not. This method should return the sections as accurate
+ * as possible, but may not provide a complete set of sections that are finally accessible, especially when the
+ * underlying storage does not support key iteration.
+ *
+ * @param properties properties to find transitive sections in.
+ * @return s set with all transitive sections, never {@code null}.
+ */
+ public static Set<String> transitiveSections(Map<String, String> properties) {
+ return transitiveSections(properties, DEFAULT_AREA_CALCULATOR);
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualified section names, containing the transitive closure also including all
+ * subarea names, regardless if properties are accessible or not. This method should return the sections as accurate
+ * as possible, but may not provide a complete set of sections that are finally accessible, especially when the
+ * underlying storage does not support key iteration.
+ *
+ * @param properties properties to find transitive sections in.
+ * @return s set with all transitive sections, never {@code null}.
+ */
+ public static Set<String> transitiveSections(Map<String, String> properties, Function<String,Integer> areaCalculator) {
+ final Set<String> transitiveAreas = new HashSet<>();
+ for (String section : sections(properties, areaCalculator)) {
+ section = normalizeSectionKey(section, areaCalculator);
+
+ int index = areaCalculator.apply(section);
+ if (index < 0 && section.isEmpty()) {
+ transitiveAreas.add("<root>");
+ } if (index < 0) {
+ transitiveAreas.add(section);
+ } else {
+ while (index > 0) {
+ section = section.substring(0, index);
+ transitiveAreas.add(section);
+ index = section.lastIndexOf('.');
+ }
+ }
+ }
+ return transitiveAreas;
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualified section names, containing only the
+ * sections that match the predicate and have properties attached. This method should return the sections as accurate as possible,
+ * but may not provide a complete set of sections that are finally accessible, especially when the underlying storage
+ * does not support key iteration.
+ *
+ * @param properties properties to find sections in.
+ * @param predicate A predicate to determine, which sections should be returned, not {@code null}.
+ * @return s set with all sections, never {@code null}.
+ */
+ public static Set<String> sections(Map<String, String> properties, final Predicate<String> predicate) {
+ Set<String> treeSet = new TreeSet<>();
+ for (String area : sections(properties)) {
+ if (predicate.test(area)) {
+ treeSet.add(area);
+ }
+ }
+ return treeSet;
+ }
+
+ /**
+ * Return a query to evaluate the set with all fully qualified section names, containing the transitive closure also including all
+ * subarea names, regardless if properties are accessible or not. This method should return the sections as accurate as possible,
+ * but may not provide a complete set of sections that are finally accessible, especially when the underlying storage
+ * does not support key iteration.
+ *
+ * @param properties properties to find transitive sections in.
+ * @param predicate A predicate to determine, which sections should be returned, not {@code null}.
+ * @return s set with all transitive sections, never {@code null}.
+ */
+ public static Set<String> transitiveSections(Map<String, String> properties, Predicate<String> predicate) {
+ Set<String> treeSet = new TreeSet<>();
+ for (String area : transitiveSections(properties)) {
+ if (predicate.test(area)) {
+ treeSet.add(area);
+ }
+ }
+ return treeSet;
+ }
+
+
+ /**
+ *Extracts the submap containing only entries with keys
+ * that are contained in the given sections. Hereby
+ * the section key is stripped away from the Map of the resulting keys.
+ *
+ * @param properties properties to find recursive sections in.
+ * @param sectionKeys the section keys, not null
+ * @return the section configuration, with the areaKey stripped away.
+ */
+ public static Map<String, String> sectionsRecursive(Map<String, String> properties, String... sectionKeys) {
+ return sectionsRecursive(properties, true, sectionKeys);
+ }
+
+ /**
+ * Extracts the submap containing only entries with keys
+ * that are contained in the given section and it's subsections.
+ *
+ * @param properties properties to find sections in.
+ * @param sectionKeys the section keys, not null
+ * @param stripKeys if set to true, the section key is stripped away fromMap the resulting key.
+ * @return the section configuration, with the areaKey stripped away.
+ */
+ public static Map<String, String> sectionsRecursive(Map<String, String> properties, boolean stripKeys, String... sectionKeys) {
+ Map<String, String> result = new HashMap<>(properties.size());
+ for (Map.Entry<String, String> en : properties.entrySet()) {
+ if (isKeyInSection(en.getKey(), false,DEFAULT_AREA_CALCULATOR, sectionKeys)) {
+ if (stripKeys) {
+ result.put(stripSectionKeys(en.getKey(), sectionKeys), en.getValue());
+ }else {
+ result.put(en.getKey(), en.getValue());
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Strips the section key of the given absolute key, if it is one of the areaKeys passed.
+ *
+ * @param key the current key, not null.
+ * @param areaKeys the areaKeys, not null.
+ * @return the stripped key, or the original key (if no section was matching).
+ */
+ static String stripSectionKeys(String key, String... areaKeys) {
+ for (String areaKey : areaKeys) {
+ if (key.startsWith(areaKey + '.')) {
+ return key.substring(areaKey.length() + 1);
+ }
+ }
+ return key;
+ }
+
+ /**
+ * Creates a ConfigOperator that adds the given items.
+ *
+ * @param propertySource source property source that is changed.
+ * @param items the items to be added/replaced.
+ * @param override if true, all items existing are overridden by the new ones passed.
+ * @return the ConfigOperator, never null.
+ */
+ public static ConfigSource addItems(ConfigSource propertySource, final Map<String, String> items, final boolean override) {
+ return new EnrichedConfigSource(propertySource, items, override);
+ }
+
+ /**
+ * Creates an operator that adds items to the instance (existing items will not be overridden).
+ *
+ * @param propertySource source property source that is changed.
+ * @param items the items, not null.
+ * @return the operator, never null.
+ */
+ public static ConfigSource addItems(ConfigSource propertySource, Map<String, String> items) {
+ return addItems(propertySource, items, false);
+ }
+
+ /**
+ * Creates an operator that replaces the given items.
+ *
+ * @param propertySource source property source that is changed.
+ * @param items the items.
+ * @return the operator for replacing the items.
+ */
+ public static ConfigSource replaceItems(ConfigSource propertySource, Map<String, String> items) {
+ return addItems(propertySource, items, true);
+ }
+
+ /**
+ * Accesses an empty PropertySource.
+ *
+ * @return an empty PropertySource, never null.
+ */
+ public static ConfigSource emptyConfigSource() {
+ return EMPTY_PROPERTYSOURCE;
+ }
+
+ /**
+ * Find all {@link ConfigSource} instances managed by the current
+ * {@link javax.config.Config} that are assignable to the given type.
+ *
+ * @param expression the regular expression to match the source's name.
+ * @return the list of all {@link ConfigSource} instances matching, never null.
+ */
+ public static Collection<? extends ConfigSource> findPropertySourcesByName(String expression) {
+ List result = new ArrayList<>();
+ for (ConfigSource src : ConfigProvider.getConfig().getConfigSources()) {
+ if (src.getName().matches(expression)) {
+ result.add(src);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Get a list of all {@link ConfigSource} instances managed by the current
+ * {@link javax.config.Config} that are assignable to the given type.
+ *
+ * @param <T> the type of the property source instances requested
+ * @param type target type to filter for property sources.
+ * @return the list of all {@link ConfigSource} instances matching, never null.
+ */
+ public static <T> Collection<T> getPropertySources(Class<T> type) {
+ List<T> result = new ArrayList<>();
+ for (ConfigSource src : ConfigProvider.getConfig().getConfigSources()) {
+ if (type.isAssignableFrom(src.getClass())) {
+ result.add((T) src);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Get a list of all {@link ConfigSource} instances managed by the current
+ * {@link javax.config.Config} that are assignable to the given type.
+ *
+ * @param <T> the type of the property source instances requested
+ * @param type target type to filter for property sources.
+ * @return the list of all {@link ConfigSource} instances matching, never null.
+ */
+ public static <T> T getPropertySource(Class<T> type) {
+ for (ConfigSource src : ConfigProvider.getConfig().getConfigSources()) {
+ if (type.isAssignableFrom(src.getClass())) {
+ return (T) src;
+ }
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/ConfigurationFunctions.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/ConfigurationFunctions.java b/modules/functions/src/main/java/org/apache/tamaya/functions/ConfigurationFunctions.java
index 76581b7..15e6242 100644
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/ConfigurationFunctions.java
+++ b/modules/functions/src/main/java/org/apache/tamaya/functions/ConfigurationFunctions.java
@@ -303,7 +303,7 @@ public final class ConfigurationFunctions {
if (stripKeys) {
return new MappedConfiguration(
filtered,
- k -> PropertySourceFunctions.stripSectionKeys(k, sectionKeys),
+ k -> ConfigSourceFunctions.stripSectionKeys(k, sectionKeys),
"stripped");
}
return filtered;
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/EnrichedConfigSource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/EnrichedConfigSource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/EnrichedConfigSource.java
new file mode 100644
index 0000000..c628a95
--- /dev/null
+++ b/modules/functions/src/main/java/org/apache/tamaya/functions/EnrichedConfigSource.java
@@ -0,0 +1,93 @@
+/*
+ * 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.functions;
+
+import org.apache.tamaya.base.configsource.ConfigSourceComparator;
+
+import javax.config.spi.ConfigSource;
+import java.util.*;
+
+/**
+ * PropertySource, that has values added or overridden.
+ */
+class EnrichedConfigSource implements ConfigSource {
+
+ private final ConfigSource basePropertySource;
+
+ private final Map<String, String> addedProperties = new HashMap<>();
+
+ private final boolean overriding;
+
+ /**
+ * Constructor.
+ *
+ * @param propertySource the base property source, not null.
+ * @param properties the properties to be added.
+ * @param overriding flag if existing properties are overridden.
+ */
+ EnrichedConfigSource(ConfigSource propertySource, Map<String, String> properties, boolean overriding) {
+ this.basePropertySource = Objects.requireNonNull(propertySource);
+ for(Map.Entry<String,String> en:properties.entrySet()){
+ this.addedProperties.putAll(properties);
+ }
+ this.overriding = overriding;
+ }
+
+
+ @Override
+ public int getOrdinal() {
+ return ConfigSourceComparator.getOrdinal(basePropertySource);
+ }
+
+ @Override
+ public String getName() {
+ return basePropertySource.getName();
+ }
+
+ @Override
+ public String getValue(String key) {
+ if (overriding) {
+ String val = addedProperties.get(key);
+ if (val != null) {
+ return val;
+ }
+ return basePropertySource.getValue(key);
+ }
+ String val = basePropertySource.getValue(key);
+ if (val != null) {
+ return val;
+ }
+ return addedProperties.get(key);
+
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ Map<String, String> allProps = new HashMap<>();
+ if (overriding) {
+ allProps.putAll(basePropertySource.getProperties());
+ allProps.putAll(addedProperties);
+ } else {
+ allProps.putAll(addedProperties);
+ allProps.putAll(basePropertySource.getProperties());
+ }
+ return allProps;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/EnrichedPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/EnrichedPropertySource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/EnrichedPropertySource.java
deleted file mode 100644
index c1367b8..0000000
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/EnrichedPropertySource.java
+++ /dev/null
@@ -1,103 +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.functions;
-
-import org.apache.tamaya.spi.PropertySource;
-import org.apache.tamaya.spi.PropertyValue;
-import org.apache.tamaya.spisupport.PropertySourceComparator;
-
-import java.util.*;
-
-/**
- * PropertySource, that has values added or overridden.
- */
-class EnrichedPropertySource implements PropertySource {
-
- private final PropertySource basePropertySource;
-
- private final Map<String, PropertyValue> addedProperties = new HashMap<>();
-
- private final boolean overriding;
-
- /**
- * Constructor.
- *
- * @param propertySource the base property source, not null.
- * @param properties the properties to be added.
- * @param overriding flag if existing properties are overridden.
- */
- EnrichedPropertySource(PropertySource propertySource, Map<String, String> properties, boolean overriding) {
- this.basePropertySource = Objects.requireNonNull(propertySource);
- for(Map.Entry<String,String> en:properties.entrySet()){
- this.addedProperties.put(en.getKey(), PropertyValue.of(en.getKey(), en.getValue(), propertySource.getName()));
- }
- this.overriding = overriding;
- }
-
-
- @Override
- public int getOrdinal() {
- return PropertySourceComparator.getOrdinal(basePropertySource);
- }
-
- @Override
- public String getName() {
- return basePropertySource.getName();
- }
-
- @Override
- public PropertyValue get(String key) {
- if (overriding) {
- PropertyValue val = addedProperties.get(key);
- if (val != null) {
- return val;
- }
- return basePropertySource.get(key);
- }
- PropertyValue val = basePropertySource.get(key);
- if (val != null) {
- return val;
- }
- return addedProperties.get(key);
-
- }
-
- @Override
- public Map<String, PropertyValue> getProperties() {
- Map<String, PropertyValue> allProps;
- if (overriding) {
- allProps = new HashMap<>();
- for(PropertyValue val:basePropertySource.getProperties().values()){
- allProps.put(val.getKey(), val);
- }
- allProps.putAll(addedProperties);
- } else {
- allProps = new HashMap<>(addedProperties);
- for(PropertyValue val:basePropertySource.getProperties().values()){
- allProps.put(val.getKey(), val);
- }
- }
- return allProps;
- }
-
- @Override
- public boolean isScannable() {
- return basePropertySource.isScannable();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/FilteredConfigSource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/FilteredConfigSource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/FilteredConfigSource.java
new file mode 100644
index 0000000..51ccb3b
--- /dev/null
+++ b/modules/functions/src/main/java/org/apache/tamaya/functions/FilteredConfigSource.java
@@ -0,0 +1,89 @@
+/*
+ * 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.functions;
+
+
+import org.apache.tamaya.base.configsource.ConfigSourceComparator;
+
+import javax.config.spi.ConfigSource;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * PropertySource that on the fly filters out part of the key/values of the underlying PropertySource.
+ */
+class FilteredConfigSource implements ConfigSource {
+
+ private final ConfigSource baseSource;
+ private final Predicate<String> filter;
+
+ /**
+ * Creates a new instance
+ * @param baseSource the underlying PropertySource
+ * @param filter the filter to be applied.
+ */
+ public FilteredConfigSource(ConfigSource baseSource, Predicate<String> filter){
+ this.baseSource = Objects.requireNonNull(baseSource);
+ this.filter = Objects.requireNonNull(filter);
+ }
+
+ @Override
+ public int getOrdinal(){
+ return ConfigSourceComparator.getOrdinal(getBaseSource());
+ }
+
+ @Override
+ public String getName() {
+ return baseSource.getName();
+ }
+
+ @Override
+ public String getValue(String key) {
+ String val = this.getBaseSource().getValue(key);
+ if(val!=null && filter.test(key)) {
+ return val;
+ }
+ return null;
+ }
+
+ @Override
+ public Map<String, String> getProperties(){
+ final Map<String,String> result = new HashMap<>();
+ for(Map.Entry<String,String> en: this.getBaseSource().getProperties().entrySet()) {
+ if (filter.test(en.getKey())) {
+ result.put(en.getKey(), en.getValue());
+ }
+ }
+ return result;
+ }
+
+ protected ConfigSource getBaseSource() {
+ return baseSource;
+ }
+
+ @Override
+ public String toString() {
+ return "FilteredPropertySource{" +
+ "baseSource=" + getBaseSource() +
+ ", filter=" + filter +
+ '}';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/FilteredPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/FilteredPropertySource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/FilteredPropertySource.java
deleted file mode 100644
index 133862d..0000000
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/FilteredPropertySource.java
+++ /dev/null
@@ -1,93 +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.functions;
-
-import org.apache.tamaya.spi.PropertySource;
-import org.apache.tamaya.spi.PropertyValue;
-import org.apache.tamaya.spisupport.PropertySourceComparator;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * PropertySource that on the fly filters out part of the key/values of the underlying PropertySource.
- */
-class FilteredPropertySource implements PropertySource {
-
- private final PropertySource baseSource;
- private final Predicate<String> filter;
-
- /**
- * Creates a new instance
- * @param baseSource the underlying PropertySource
- * @param filter the filter to be applied.
- */
- public FilteredPropertySource(PropertySource baseSource, Predicate<String> filter){
- this.baseSource = Objects.requireNonNull(baseSource);
- this.filter = Objects.requireNonNull(filter);
- }
-
- @Override
- public int getOrdinal(){
- return PropertySourceComparator.getOrdinal(getBaseSource());
- }
-
- @Override
- public String getName() {
- return baseSource.getName();
- }
-
- @Override
- public PropertyValue get(String key) {
- PropertyValue val = this.getBaseSource().get(key);
- if(val!=null && filter.test(val.getKey())) {
- return val;
- }
- return null;
- }
-
- @Override
- public Map<String, PropertyValue> getProperties(){
- final Map<String,PropertyValue> result = new HashMap<>();
- for(PropertyValue val: this.getBaseSource().getProperties().values()) {
- if (filter.test(val.getKey())) {
- result.put(val.getKey(), val);
- }
- }
- return result;
- }
-
- @Override
- public boolean isScannable() {
- return getBaseSource().isScannable();
- }
-
- @Override
- public String toString() {
- return "FilteredPropertySource{" +
- "baseSource=" + getBaseSource() +
- ", filter=" + filter +
- '}';
- }
-
- protected PropertySource getBaseSource() {
- return baseSource;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/MappedConfigSource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/MappedConfigSource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/MappedConfigSource.java
new file mode 100644
index 0000000..1b3881b
--- /dev/null
+++ b/modules/functions/src/main/java/org/apache/tamaya/functions/MappedConfigSource.java
@@ -0,0 +1,109 @@
+/*
+ * 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.functions;
+
+
+import org.apache.tamaya.base.configsource.ConfigSourceComparator;
+
+import javax.config.spi.ConfigSource;
+import java.util.*;
+
+/**
+ * PropertySource implementation that maps certain parts (defined by an {@code UnaryOperator<String>}) to alternate sections.
+ */
+class MappedConfigSource implements ConfigSource {
+
+ private static final long serialVersionUID = 8690637705511432083L;
+
+ /**
+ * The mapping operator.
+ */
+ private final KeyMapper keyMapper;
+
+ /**
+ * The base configuration.
+ */
+ private final ConfigSource propertySource;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param config the base configuration, not null
+ * @param keyMapper The mapping operator, not null
+ */
+ public MappedConfigSource(ConfigSource config, KeyMapper keyMapper) {
+ this.propertySource = Objects.requireNonNull(config);
+ this.keyMapper = Objects.requireNonNull(keyMapper);
+ }
+
+ @Override
+ public int getOrdinal() {
+ return ConfigSourceComparator.getOrdinal(this.propertySource);
+ }
+
+ @Override
+ public String getName() {
+ return this.propertySource.getName() + "[mapped]";
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ Map<String,String> result = new HashMap<>();
+ for (Map.Entry<String,String> en : this.propertySource.getProperties().entrySet()) {
+ String targetKey = keyMapper.mapKey(en.getKey());
+ if (targetKey != null) {
+ result.put(targetKey, en.getValue());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * <p>Access a property by its key.</p>
+ *
+ * <p>
+ * The key of the property to be returned must be equal to the key
+ * returned by the mapping operator (key mapper) and not equal
+ * to the key of the base configuration.
+ * </p>
+ *
+ * @param key the property's key, not {@code null}.
+ * @return the property value map, where {@code map.get(key) == value},
+ * including also any metadata. In case a value is {@code null},
+ * simply return {@code null}.
+ */
+ @Override
+ public String getValue(String key) {
+ Objects.requireNonNull(key, "Key must be given.");
+
+ String mappedKey = keyMapper.mapKey(key);
+ String result = null;
+
+ if (mappedKey != null) {
+ for (Map.Entry<String,String> en : propertySource.getProperties().entrySet()) {
+ String newKey = keyMapper.mapKey(en.getKey());
+ if (mappedKey.equals(newKey)) {
+ return en.getValue();
+ }
+ }
+ }
+ return result;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/MappedPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/MappedPropertySource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/MappedPropertySource.java
deleted file mode 100644
index 7e48f22..0000000
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/MappedPropertySource.java
+++ /dev/null
@@ -1,119 +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.functions;
-
-import org.apache.tamaya.spi.PropertySource;
-import org.apache.tamaya.spi.PropertyValue;
-import org.apache.tamaya.spisupport.PropertySourceComparator;
-
-import java.util.*;
-
-/**
- * PropertySource implementation that maps certain parts (defined by an {@code UnaryOperator<String>}) to alternate sections.
- */
-class MappedPropertySource implements PropertySource {
-
- private static final long serialVersionUID = 8690637705511432083L;
-
- /**
- * The mapping operator.
- */
- private final KeyMapper keyMapper;
-
- /**
- * The base configuration.
- */
- private final PropertySource propertySource;
-
- /**
- * Creates a new instance.
- *
- * @param config the base configuration, not null
- * @param keyMapper The mapping operator, not null
- */
- public MappedPropertySource(PropertySource config, KeyMapper keyMapper) {
- this.propertySource = Objects.requireNonNull(config);
- this.keyMapper = Objects.requireNonNull(keyMapper);
- }
-
- @Override
- public int getOrdinal() {
- return PropertySourceComparator.getOrdinal(this.propertySource);
- }
-
- @Override
- public String getName() {
- return this.propertySource.getName() + "[mapped]";
- }
-
- @Override
- public Map<String, PropertyValue> getProperties() {
- Map<String,PropertyValue> result = new HashMap<>();
- for (PropertyValue en : this.propertySource.getProperties().values()) {
- String targetKey = keyMapper.mapKey(en.getKey());
- if (targetKey != null) {
- result.put(targetKey, PropertyValue.of(targetKey, en.getValue(), getName()));
- }
- }
- return result;
- }
-
- @Override
- public boolean isScannable() {
- return propertySource.isScannable();
- }
-
-
- /**
- * <p>Access a property by its key.</p>
- *
- * <p>
- * The key of the property to be returned must be equal to the key
- * returned by the mapping operator (key mapper) and not equal
- * to the key of the base configuration.
- * </p>
- *
- * @param key the property's key, not {@code null}.
- * @return the property value map, where {@code map.get(key) == value},
- * including also any metadata. In case a value is {@code null},
- * simply return {@code null}.
- */
- @Override
- public PropertyValue get(String key) {
- Objects.requireNonNull(key, "Key must be given.");
-
- String mappedKey = keyMapper.mapKey(key);
- PropertyValue result = null;
-
- if (mappedKey != null) {
- for (PropertyValue property : propertySource.getProperties().values()) {
- String newKey = keyMapper.mapKey(property.getKey());
-
- if (mappedKey.equals(newKey)) {
- String mappedName = getName();
- return property.toBuilder().mapKey(newKey)
- .setSource(mappedName).build();
- }
- }
- }
-
- return result;
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/PropertySourceFunctions.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/PropertySourceFunctions.java b/modules/functions/src/main/java/org/apache/tamaya/functions/PropertySourceFunctions.java
deleted file mode 100644
index 6f20d6f..0000000
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/PropertySourceFunctions.java
+++ /dev/null
@@ -1,410 +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.functions;
-
-import org.apache.tamaya.ConfigurationProvider;
-import org.apache.tamaya.spi.PropertySource;
-import org.apache.tamaya.spi.PropertyValue;
-
-import java.util.*;
-
-import static java.lang.System.arraycopy;
-
-/**
- * Accessor that provides useful functions along with configuration.
- */
-public final class PropertySourceFunctions {
- /**
- * Implementation of an empty propertySource.
- */
- private static final PropertySource EMPTY_PROPERTYSOURCE = new PropertySource() {
-
- @Override
- public int getOrdinal() {
- return 0;
- }
-
- @Override
- public String getName() {
- return "<empty>";
- }
-
- @Override
- public PropertyValue get(String key) {
- return null;
- }
-
- @Override
- public Map<String, PropertyValue> getProperties() {
- return Collections.emptyMap();
- }
-
- @Override
- public boolean isScannable() {
- return true;
- }
-
- @Override
- public String toString() {
- return "PropertySource<empty>";
- }
- };
-
- /**
- * Private singleton constructor.
- */
- private PropertySourceFunctions() {
- }
-
- /**
- * Calculates the current section key and compares it to the given key.
- *
- * @param key the fully qualified entry key, not null
- * @param sectionKey the section key, not null
- *
- * @return true, if the entry is exact in this section
- */
- public static boolean isKeyInSection(String key, String sectionKey) {
- Objects.requireNonNull(key, "Key must be given.");
- Objects.requireNonNull(sectionKey, "Section key must be given.");
-
- sectionKey = normalizeSectionKey(sectionKey);
-
- int lastIndex = key.lastIndexOf('.');
- String curAreaKey = lastIndex > 0 ? key.substring(0, lastIndex) : "";
- return curAreaKey.equals(sectionKey);
- }
-
- private static String normalizeKey(String key) {
- return key.startsWith(".") ? key.substring(1)
- : key;
- }
-
- static String normalizeSectionKey(String sectionKey) {
- // Ignore unneeded and trailing dot at the end of the section key
-
- String normalizedKey = sectionKey.endsWith(".")
- ? sectionKey.substring(0, sectionKey.length() - 1)
- : sectionKey;
-
- normalizedKey = sectionKey.startsWith(".") ? sectionKey.length() == 1 ? ""
- : normalizedKey.substring(1)
- : normalizedKey;
-
- return normalizedKey;
- }
-
- /**
- * Calculates the current section key and compares it to the given section keys.
- *
- * @param key the fully qualified entry key, not {@code null}
- * @param sectionKey the section keys, not {@code null}
- * @param moreSectionKeys the more section keys, not {@code null}
- *
- * @return true, if the entry is in one of the given sections
- */
- public static boolean isKeyInSections(String key, String sectionKey, String... moreSectionKeys) {
- Objects.requireNonNull(key, "Key must be given.");
- Objects.requireNonNull(sectionKey, "At least one section key must be given.");
- Objects.requireNonNull(moreSectionKeys, "Additional section keys must not be null.");
-
- String[] sectionKeys = new String[moreSectionKeys.length + 1];
- sectionKeys[0] = sectionKey;
-
- if (moreSectionKeys.length > 0) {
- arraycopy(moreSectionKeys, 0, sectionKeys, 1, moreSectionKeys.length);
- }
-
- return isKeyInSections(key, sectionKeys);
- }
-
- /**
- * Calculates the current section key and compares it to the given section keys.
- *
- * @param key the fully qualified entry key, not {@code null}
- * @param sectionKeys the section keys, not {@code null}
- *
- * @return true, if the entry is in one of the given sections
- */
- public static boolean isKeyInSections(String key, String[] sectionKeys) {
- Objects.requireNonNull(key, "Key must be given.");
- Objects.requireNonNull(sectionKeys, "Section keys must be given.");
-
- boolean result = false;
-
- for (String areaKey : sectionKeys) {
- if (areaKey == null) {
- continue;
- }
-
- if (isKeyInSection(key, areaKey)) {
- result = true;
- break;
- }
- }
-
- return result;
- }
-
- /**
- * Return a query to evaluate the set with all fully qualified section names. This method should return the sections as accurate as possible,
- * but may not provide a complete set of sections that are finally accessible, especially when the underlying storage
- * does not support key iteration.
- *
- * @param properties properties to find sections in.
- * @return set with all sections, never {@code null}.
- */
- public static Set<String> sections(Map<String, String> properties) {
- final Set<String> areas = new HashSet<>();
- for (String key : properties.keySet()) {
- String normalizedKey = normalizeKey(key);
-
- int index = normalizedKey.lastIndexOf('.');
- if (index > 0) {
- areas.add(normalizedKey.substring(0, index));
- } else {
- areas.add("<root>");
- }
- }
- return areas;
- }
-
- /**
- * Return a query to evaluate the set with all fully qualified section names, containing the transitive closure also including all
- * subarea names, regardless if properties are accessible or not. This method should return the sections as accurate
- * as possible, but may not provide a complete set of sections that are finally accessible, especially when the
- * underlying storage does not support key iteration.
- *
- * @param properties properties to find transitive sections in.
- * @return s set with all transitive sections, never {@code null}.
- */
- public static Set<String> transitiveSections(Map<String, String> properties) {
- final Set<String> transitiveAreas = new HashSet<>();
- for (String section : sections(properties)) {
- section = normalizeSectionKey(section);
-
- int index = section.lastIndexOf('.');
- if (index < 0 && section.isEmpty()) {
- transitiveAreas.add("<root>");
- } if (index < 0) {
- transitiveAreas.add(section);
- } else {
- while (index > 0) {
- section = section.substring(0, index);
- transitiveAreas.add(section);
- index = section.lastIndexOf('.');
- }
- }
- }
- return transitiveAreas;
- }
-
- /**
- * Return a query to evaluate the set with all fully qualified section names, containing only the
- * sections that match the predicate and have properties attached. This method should return the sections as accurate as possible,
- * but may not provide a complete set of sections that are finally accessible, especially when the underlying storage
- * does not support key iteration.
- *
- * @param properties properties to find sections in.
- * @param predicate A predicate to determine, which sections should be returned, not {@code null}.
- * @return s set with all sections, never {@code null}.
- */
- public static Set<String> sections(Map<String, String> properties, final Predicate<String> predicate) {
- Set<String> treeSet = new TreeSet<>();
- for (String area : sections(properties)) {
- if (predicate.test(area)) {
- treeSet.add(area);
- }
- }
- return treeSet;
- }
-
- /**
- * Return a query to evaluate the set with all fully qualified section names, containing the transitive closure also including all
- * subarea names, regardless if properties are accessible or not. This method should return the sections as accurate as possible,
- * but may not provide a complete set of sections that are finally accessible, especially when the underlying storage
- * does not support key iteration.
- *
- * @param properties properties to find transitive sections in.
- * @param predicate A predicate to determine, which sections should be returned, not {@code null}.
- * @return s set with all transitive sections, never {@code null}.
- */
- public static Set<String> transitiveSections(Map<String, String> properties, Predicate<String> predicate) {
- Set<String> treeSet = new TreeSet<>();
- for (String area : transitiveSections(properties)) {
- if (predicate.test(area)) {
- treeSet.add(area);
- }
- }
- return treeSet;
- }
-
-
- /**
- * Creates a ConfigOperator that creates a Configuration containing only keys
- * that are contained in the given section (recursive). Hereby
- * the section key is stripped away from the Map of the resulting keys.
- *
- * @param properties properties to find recursive sections in.
- * @param sectionKeys the section keys, not null
- * @return the section configuration, with the areaKey stripped away.
- */
- public static Map<String, String> sectionsRecursive(Map<String, String> properties, String... sectionKeys) {
- return sectionRecursive(properties, true, sectionKeys);
- }
-
- /**
- * Creates a ConfigOperator that creates a Configuration containing only keys
- * that are contained in the given section (recursive).
- *
- * @param properties properties to find sections in.
- * @param sectionKeys the section keys, not null
- * @param stripKeys if set to true, the section key is stripped away fromMap the resulting key.
- * @return the section configuration, with the areaKey stripped away.
- */
- public static Map<String, String> sectionRecursive(Map<String, String> properties, boolean stripKeys, String... sectionKeys) {
- Map<String, String> result = new HashMap<>(properties.size());
- if (stripKeys) {
- for (Map.Entry<String, String> en : properties.entrySet()) {
- if (isKeyInSections(en.getKey(), sectionKeys)) {
- result.put(en.getKey(), en.getValue());
- }
- }
- } else {
- for (Map.Entry<String, String> en : properties.entrySet()) {
- if (isKeyInSections(en.getKey(), sectionKeys)) {
- result.put(stripSectionKeys(en.getKey(), sectionKeys), en.getValue());
- }
- }
- }
- return result;
- }
-
- /**
- * Strips the section key of the given absolute key, if it is one of the areaKeys passed.
- *
- * @param key the current key, not null.
- * @param areaKeys the areaKeys, not null.
- * @return the stripped key, or the original key (if no section was matching).
- */
- static String stripSectionKeys(String key, String... areaKeys) {
- for (String areaKey : areaKeys) {
- if (key.startsWith(areaKey + '.')) {
- return key.substring(areaKey.length() + 1);
- }
- }
- return key;
- }
-
- /**
- * Creates a ConfigOperator that adds the given items.
- *
- * @param propertySource source property source that is changed.
- * @param items the items to be added/replaced.
- * @param override if true, all items existing are overridden by the new ones passed.
- * @return the ConfigOperator, never null.
- */
- public static PropertySource addItems(PropertySource propertySource, final Map<String, String> items, final boolean override) {
- return new EnrichedPropertySource(propertySource, items, override);
- }
-
- /**
- * Creates an operator that adds items to the instance.
- *
- * @param propertySource source property source that is changed.
- * @param items the items, not null.
- * @return the operator, never null.
- */
- public static PropertySource addItems(PropertySource propertySource, Map<String, String> items) {
- return addItems(propertySource, items, false);
- }
-
- /**
- * Creates an operator that replaces the given items.
- *
- * @param propertySource source property source that is changed.
- * @param items the items.
- * @return the operator for replacing the items.
- */
- public static PropertySource replaceItems(PropertySource propertySource, Map<String, String> items) {
- return addItems(propertySource, items, true);
- }
-
- /**
- * Accesses an empty PropertySource.
- *
- * @return an empty PropertySource, never null.
- */
- public static PropertySource emptyPropertySource() {
- return EMPTY_PROPERTYSOURCE;
- }
-
- /**
- * Find all {@link PropertySource} instances managed by the current
- * {@link org.apache.tamaya.spi.ConfigurationContext} that are assignable to the given type.
- *
- * @param expression the regular expression to match the source's name.
- * @return the list of all {@link PropertySource} instances matching, never null.
- */
- public static Collection<? extends PropertySource> findPropertySourcesByName(String expression) {
- List result = new ArrayList<>();
- for (PropertySource src : ConfigurationProvider.getConfigurationContext().getPropertySources()) {
- if (src.getName().matches(expression)) {
- result.add(src);
- }
- }
- return result;
- }
-
- /**
- * Get a list of all {@link PropertySource} instances managed by the current
- * {@link org.apache.tamaya.spi.ConfigurationContext} that are assignable to the given type.
- *
- * @param <T> the type of the property source instances requested
- * @param type target type to filter for property sources.
- * @return the list of all {@link PropertySource} instances matching, never null.
- */
- public static <T> Collection<T> getPropertySources(Class<T> type) {
- List<T> result = new ArrayList<>();
- for (PropertySource src : ConfigurationProvider.getConfigurationContext().getPropertySources()) {
- if (type.isAssignableFrom(src.getClass())) {
- result.add((T) src);
- }
- }
- return result;
- }
-
- /**
- * Get a list of all {@link PropertySource} instances managed by the current
- * {@link org.apache.tamaya.spi.ConfigurationContext} that are assignable to the given type.
- *
- * @param <T> the type of the property source instances requested
- * @param type target type to filter for property sources.
- * @return the list of all {@link PropertySource} instances matching, never null.
- */
- public static <T> T getPropertySource(Class<T> type) {
- for (PropertySource src : ConfigurationProvider.getConfigurationContext().getPropertySources()) {
- if (type.isAssignableFrom(src.getClass())) {
- return (T) src;
- }
- }
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedConfigSource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedConfigSource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedConfigSource.java
new file mode 100644
index 0000000..dd23c66
--- /dev/null
+++ b/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedConfigSource.java
@@ -0,0 +1,75 @@
+/*
+ * 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.functions;
+
+import org.apache.tamaya.base.configsource.ConfigSourceComparator;
+
+import javax.config.spi.ConfigSource;
+import java.util.*;
+
+
+/**
+ * Property source which filters any key/values dynamically.
+ */
+class ValueMappedConfigSource implements ConfigSource{
+
+ private final String name;
+ private final PropertyMapper valueFilter;
+ private final ConfigSource source;
+
+ public ValueMappedConfigSource(String name, PropertyMapper valueFilter, ConfigSource current) {
+ this.name = name!=null?name:"<valueFiltered> -> name="+current.getName()+", valueFilter="+valueFilter.toString();
+ this.valueFilter = valueFilter;
+ this.source = Objects.requireNonNull(current);
+ }
+
+ @Override
+ public int getOrdinal() {
+ return ConfigSourceComparator.getOrdinal(source);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getValue(String key) {
+ return this.source.getValue(key);
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ Map<String,String> result = new HashMap<>();
+ for(Map.Entry<String,String> en: source.getProperties().entrySet()) {
+ String mappedValue = valueFilter.mapProperty(en.getKey(), en.getValue());
+ result.put(en.getKey(), mappedValue);
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ValueMappedConfigSource{" +
+ "source=" + source.getName() +
+ ", name='" + name + '\'' +
+ ", valueFilter=" + valueFilter +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedPropertySource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedPropertySource.java
deleted file mode 100644
index dfb128f..0000000
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedPropertySource.java
+++ /dev/null
@@ -1,86 +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.functions;
-
-import org.apache.tamaya.spi.PropertySource;
-import org.apache.tamaya.spi.PropertyValue;
-import org.apache.tamaya.spisupport.PropertySourceComparator;
-
-import java.util.*;
-
-
-/**
- * Property source which filters any key/values dynamically.
- */
-class ValueMappedPropertySource implements PropertySource{
-
- private final String name;
- private final PropertyMapper valueFilter;
- private final PropertySource source;
-
- public ValueMappedPropertySource(String name, PropertyMapper valueFilter, PropertySource current) {
- this.name = name!=null?name:"<valueFiltered> -> name="+current.getName()+", valueFilter="+valueFilter.toString();
- this.valueFilter = valueFilter;
- this.source = Objects.requireNonNull(current);
- }
-
- @Override
- public int getOrdinal() {
- return PropertySourceComparator.getOrdinal(source);
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public PropertyValue get(String key) {
- PropertyValue value = this.source.get(key);
- if(value!=null) {
- return PropertyValue.of(key, valueFilter.mapProperty(key, value.getValue()), getName());
- }
- return null;
- }
-
- @Override
- public Map<String, PropertyValue> getProperties() {
- Map<String,PropertyValue> result = new HashMap<>();
- for(PropertyValue val : source.getProperties().values()) {
- String mappedValue = valueFilter.mapProperty(val.getKey(), val.getValue());
- PropertyValue value = val.toBuilder().setValue(mappedValue).build();
- result.put(val.getKey(), value);
- }
- return result;
- }
-
- @Override
- public boolean isScannable() {
- return source.isScannable();
- }
-
- @Override
- public String toString() {
- return "ValueMappedPropertySource{" +
- "source=" + source.getName() +
- ", name='" + name + '\'' +
- ", valueFilter=" + valueFilter +
- '}';
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/test/java/org/apache/tamaya/functions/CombinedConfigurationTest.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/test/java/org/apache/tamaya/functions/CombinedConfigurationTest.java b/modules/functions/src/test/java/org/apache/tamaya/functions/CombinedConfigurationTest.java
index bb27ccd..432c5c0 100644
--- a/modules/functions/src/test/java/org/apache/tamaya/functions/CombinedConfigurationTest.java
+++ b/modules/functions/src/test/java/org/apache/tamaya/functions/CombinedConfigurationTest.java
@@ -20,7 +20,6 @@ package org.apache.tamaya.functions;
import org.apache.tamaya.base.DefaultConfigBuilder;
import org.apache.tamaya.base.configsource.SimpleConfigSource;
-import org.apache.tamaya.spisupport.DefaultConfiguration;
import org.assertj.core.api.ThrowableAssert;
import org.junit.Test;
import org.mockito.Mockito;
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/36b44661/modules/functions/src/test/java/org/apache/tamaya/functions/ConfigSourceFunctionsTest.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/test/java/org/apache/tamaya/functions/ConfigSourceFunctionsTest.java b/modules/functions/src/test/java/org/apache/tamaya/functions/ConfigSourceFunctionsTest.java
new file mode 100644
index 0000000..06734db
--- /dev/null
+++ b/modules/functions/src/test/java/org/apache/tamaya/functions/ConfigSourceFunctionsTest.java
@@ -0,0 +1,434 @@
+/*
+ * 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.functions;
+
+import org.apache.tamaya.base.configsource.SimpleConfigSource;
+import org.assertj.core.api.ThrowableAssert;
+import org.junit.Test;
+
+import javax.config.spi.ConfigSource;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.tamaya.functions.ConfigSourceFunctions.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.entry;
+import static org.junit.Assert.*;
+
+
+public class ConfigSourceFunctionsTest {
+
+ /*
+ * Tests for isKeyInSection(String, String)
+ */
+
+ @Test
+ public void isKeyInSectionThrowsNPEIfKeyIsNull() {
+ assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
+ @Override
+ public void call() throws Throwable {
+ isKeyInSection("a.b.c", null);
+ }
+ }).isInstanceOf(NullPointerException.class)
+ .hasMessage("Section keys must be given.");
+ }
+
+ @Test
+ public void isKeyInSectionThrowsNPEIfSectionKeyIsNull() {
+ assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
+ @Override
+ public void call() throws Throwable {
+ isKeyInSection(null, "a.b.c");
+ }
+ }).isInstanceOf(NullPointerException.class)
+ .hasMessage("Key must be given.");
+ }
+
+ @Test
+ public void isKeyInSectionForKeyInRootSection() {
+ String key = "key";
+ String sectionKey = "";
+
+ boolean result = isKeyInSection(key, sectionKey);
+
+ assertThat(result).describedAs("Key '%s' is in root section '%s'")
+ .isTrue();
+ }
+
+ @Test
+ public void isKeyInSectionForKeyInExplicitRootSection() {
+ String key = "key";
+ String sectionKey = ".";
+
+ boolean result = isKeyInSection(key, sectionKey);
+
+ assertThat(result).describedAs("Key '%s' is in root section '%s'")
+ .isTrue();
+ }
+
+ @Test
+ public void isKeyInSectionForKeyInSection() throws Exception {
+ String key = "abc.def.g.h.key";
+ String section = "abc.def.g.h";
+
+ boolean result = isKeyInSection(key, section);
+
+ assertThat(result).describedAs("Key %s is in section %s", key, section)
+ .isTrue();
+ }
+
+ @Test
+ public void isKeyInSectionForKeyNotInSection() throws Exception {
+ String key = "abc.def.g.h.i.key";
+ String section = "abc.def.g.h";
+
+ boolean result = isKeyInSection(key, section);
+
+ assertThat(result).describedAs("Key %s is not in section %s", key, section)
+ .isFalse();
+ }
+
+ @Test
+ public void isKeyInSectionIgnoresTrailingDotAtTheEndOfTheSection() throws Exception {
+ String key = "abc.def.g.h.key";
+ String section = "abc.def.g.h.";
+
+ boolean result = isKeyInSection(key, section);
+
+ assertThat(result).describedAs("Key %s is in section %s", key, section)
+ .isTrue();
+ }
+
+
+ /*
+ * Tests for isKeyInSection(String, String, String...)
+ */
+
+ @Test
+ public void isKeyInSectionsStringStringStringVarargThrowsNPEIfKeyIsNull() {
+ assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
+ @Override
+ public void call() throws Throwable {
+ ConfigSourceFunctions.isKeyInSection(null, "a.b.", "a.b", "b.c");
+ }
+ }).isInstanceOf(NullPointerException.class)
+ .hasMessage("Key must be given.");
+ }
+
+ @Test
+ public void isKeyInSectionStringStringStringVarargshrowsNPEIfMoreSectionKeysIsNull() {
+ // null should not cause any problems
+ boolean result = isKeyInSection("key", "l.b", (String) null);
+
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void isKeyInSectionStringStringStringVaragrsSectioOfKeyIsAtEndOfVarargs() {
+ String section = "abc.def.";
+ String key = section + "key";
+
+ // null should not cause any problems
+ boolean result = ConfigSourceFunctions.isKeyInSection(key, "l.b", null, "abc", section);
+
+ assertThat(result).describedAs("Key '%s' is in section '%s'.", key, section).isTrue();
+ }
+
+
+ /*
+ * Tests for sections(Map<String, String>)
+ */
+
+ // null as parameter
+
+ // empty as parameter
+
+ // all keys in root section
+
+ // some keys in packages
+
+ @Test
+ public void sectionsMapReturnsAllSectionsForGivenKeysInMap() {
+ HashMap<String, String> kv = new HashMap<>();
+
+ kv.put("abc.key", "v");
+ kv.put("abc.def.key", "v");
+ kv.put("a.key", "v");
+ kv.put("b.key", "v");
+ kv.put("key", "v");
+
+ Set<String> result = sections(kv);
+
+ assertThat(result).isNotNull()
+ .isNotEmpty()
+ .contains("abc", "abc.def", "a", "b", "<root>");
+ }
+
+ @Test
+ public void sectionsMapTreatsLeadingDotAsOptional() {
+ HashMap<String, String> kv = new HashMap<>();
+
+ kv.put(".abc.key", "v");
+ kv.put(".abc.def.key", "v");
+ kv.put(".a.key", "v");
+ kv.put(".b.key", "v");
+ kv.put(".key", "v");
+
+ Set<String> result = sections(kv);
+
+ assertThat(result).isNotNull()
+ .isNotEmpty()
+ .contains("abc", "abc.def", "a", "b", "<root>");
+ }
+
+ /*
+ * Tests for sections(Map<String, String> , Predicate<String>)
+ */
+
+ @Test
+ public void sectionsMapPredicateFiltersAccordingToFilter() {
+ HashMap<String, String> kv = new HashMap<>();
+
+ kv.put(".abc.key", "v");
+ kv.put(".abc.def.key", "v");
+ kv.put(".a.key", "v");
+ kv.put(".b.key", "v");
+ kv.put(".key", "v");
+
+ Set<String> result = sections(kv, new Predicate<String>() {
+ @Override
+ public boolean test(String s) {
+ return !s.startsWith("a");
+ }
+ });
+
+ assertThat(result).isNotNull()
+ .isNotEmpty()
+ .contains("b", "<root>");
+ }
+
+ /*
+ * Tests for transitiveSections(Map<String, String>)
+ */
+
+ @Test
+ public void bla() {
+ HashMap<String, String> kv = new HashMap<>();
+
+ kv.put(".abc.key", "v");
+ kv.put(".abc.def.key", "v");
+ kv.put(".abc.def.ghi.key", "v");
+ kv.put(".a.key", "v");
+ kv.put(".b.key", "v");
+ kv.put(".key", "v");
+
+ Set<String> result = transitiveSections(kv);
+
+ for (String s : result) {
+ System.out.println(s);
+ }
+
+
+ assertThat(result).isNotNull()
+ .isNotEmpty()
+ .contains("abc", "abc.def", "a", "b", "<root>");
+
+
+ }
+
+
+ @Test
+ public void testIsKeyInSections() throws Exception {
+ SimpleConfigSource configSource = SimpleConfigSource.builder("test")
+ .withProperty("a", "1")
+ .withProperty("a.a.1", "1.1.1")
+ .withProperty("a.a.2", "1.1.2")
+ .withProperty("a.b", "1.2")
+ .withProperty("b", "2")
+ .build();
+
+ assertTrue(ConfigSourceFunctions.isKeyInSection("a.1", "a", "b"));
+ assertTrue(ConfigSourceFunctions.isKeyInSection("a.1", "b", "a"));
+ assertFalse(ConfigSourceFunctions.isKeyInSection("a.1", ""));
+ assertFalse(ConfigSourceFunctions.isKeyInSection("a.b.1", "a"));
+ assertTrue(ConfigSourceFunctions.isKeyInSection("a.b.1", "a.b"));
+ assertFalse(ConfigSourceFunctions.isKeyInSection("a.b.1", "", "a"));
+ assertTrue(ConfigSourceFunctions.isKeyInSection("a.b.1", "", "a.b"));
+ assertFalse(ConfigSourceFunctions.isKeyInSection("c.a", "","c.a"));
+ assertFalse(ConfigSourceFunctions.isKeyInSection("a.3", "b"));
+ }
+
+
+ @Test
+ public void testTransitiveSections() throws Exception {
+ Map<String,String> sections = new HashMap<>();
+ sections.put("a.b.c.d.e", "1");
+ sections.put("a.x.y", "2");
+ sections.put("bb", "2");
+ Set<String> transitiveSections = ConfigSourceFunctions.transitiveSections(sections);
+ assertThat(transitiveSections)
+ .isNotNull()
+ .contains("a", "a.b", "a.b.c", "<root>");
+ }
+
+
+ @Test
+ public void testSectionsRecursive() throws Exception {
+ Map<String,String> sections = new HashMap<>();
+ sections.put("a.b.c.d.e", "1");
+ sections.put("a.x.y", "2");
+ sections.put("b.b", "2");
+ sections.put("bb", "2");
+ Map<String,String> recursiveSections = ConfigSourceFunctions.sectionsRecursive(sections, true,"a.b");
+ assertThat(recursiveSections)
+ .isNotNull()
+ .hasSize(1)
+ .contains(entry("c.d.e", "1"));
+ recursiveSections = ConfigSourceFunctions.sectionsRecursive(sections, true,"a");
+ assertThat(recursiveSections)
+ .isNotNull()
+ .hasSize(2)
+ .contains(entry("b.c.d.e", "1"), entry("x.y", "2"));
+ recursiveSections = ConfigSourceFunctions.sectionsRecursive(sections, true,"b");
+ assertThat(recursiveSections)
+ .isNotNull()
+ .hasSize(1)
+ .contains(entry("b", "2"));
+ recursiveSections = ConfigSourceFunctions.sectionsRecursive(sections, false,"a.b");
+ assertThat(recursiveSections)
+ .isNotNull()
+ .hasSize(1)
+ .contains(entry("a.b.c.d.e", "1"));
+ recursiveSections = ConfigSourceFunctions.sectionsRecursive(sections, false,"a");
+ assertThat(recursiveSections)
+ .isNotNull()
+ .hasSize(2)
+ .contains(entry("a.b.c.d.e", "1"), entry("a.x.y", "2"));
+ recursiveSections = ConfigSourceFunctions.sectionsRecursive(sections, false,"b");
+ assertThat(recursiveSections)
+ .isNotNull()
+ .hasSize(1)
+ .contains(entry("b.b", "2"));
+ recursiveSections = ConfigSourceFunctions.sectionsRecursive(sections, true,"b");
+ assertThat(recursiveSections)
+ .isNotNull()
+ .hasSize(1)
+ .contains(entry("b", "2"));
+ }
+
+ @Test
+ public void testStripSectionKeys() throws Exception {
+ String result = ConfigSourceFunctions.stripSectionKeys("a.b.c", new String[]{ "a.b", "a"});
+ assertThat(result)
+ .isNotNull().isEqualTo("c");
+ result = ConfigSourceFunctions.stripSectionKeys("a", new String[]{ "a"});
+ assertThat(result)
+ .isNotNull().isEqualTo("a");
+ result = ConfigSourceFunctions.stripSectionKeys("foo.bar", new String[]{ ""});
+ assertThat(result)
+ .isNotNull().isEqualTo("foo.bar");
+ }
+
+ @Test
+ public void testAddItems_Override_Default() throws Exception {
+ ConfigSource cs = SimpleConfigSource.builder("test")
+ .withProperty("a", "1")
+ .withProperty("b", "2")
+ .build();
+ Map<String, String> additions = new HashMap<>();
+ additions.put("b", "2-added");
+ additions.put("c", "3");
+ ConfigSource configSource = ConfigSourceFunctions.addItems(cs, additions);
+ assertNotNull(configSource);
+ assertThat(configSource.getPropertyNames())
+ .isNotNull()
+ .contains("a", "b", "c");
+ assertThat(configSource.getProperties())
+ .isNotNull()
+ .contains(entry("a", "1"), entry("b", "2"), entry("c", "3"));
+ }
+
+ @Test
+ public void testAddItemsOverride_Explicit() throws Exception {
+ ConfigSource cs = SimpleConfigSource.builder("test")
+ .withProperty("a", "1")
+ .withProperty("b", "2")
+ .build();
+ Map<String, String> additions = new HashMap<>();
+ additions.put("b", "2-added");
+ additions.put("c", "3");
+ ConfigSource configSource = ConfigSourceFunctions.addItems(cs, additions, true);
+ assertNotNull(configSource);
+ assertThat(configSource.getPropertyNames())
+ .isNotNull()
+ .contains("a", "b", "c");
+ assertThat(configSource.getProperties())
+ .isNotNull()
+ .contains(entry("a", "1"), entry("b", "2-added"), entry("c", "3"));
+ }
+
+ @Test
+ public void testAddItemsOverride_False() throws Exception {
+ ConfigSource cs = SimpleConfigSource.builder("test")
+ .withProperty("a", "1")
+ .withProperty("b", "2")
+ .build();
+ Map<String, String> additions = new HashMap<>();
+ additions.put("b", "2-added");
+ additions.put("c", "3");
+ ConfigSource configSource = ConfigSourceFunctions.addItems(cs, additions, false);
+ assertNotNull(configSource);
+ assertThat(configSource.getPropertyNames())
+ .isNotNull()
+ .contains("a", "b", "c");
+ assertThat(configSource.getProperties())
+ .isNotNull()
+ .contains(entry("a", "1"), entry("b", "2"), entry("c", "3"));
+ }
+
+ @Test
+ public void testReplaceItems() throws Exception {
+ ConfigSource cs = SimpleConfigSource.builder("test")
+ .withProperty("a", "1")
+ .withProperty("b", "2")
+ .build();
+ Map<String, String> replacements = new HashMap<>();
+ replacements.put("b", "2-added");
+ replacements.put("c", "3");
+ ConfigSource configSource = ConfigSourceFunctions.replaceItems(cs, replacements);
+ assertNotNull(configSource);
+ assertThat(configSource.getPropertyNames())
+ .isNotNull()
+ .contains("a", "b", "c");
+ assertThat(configSource.getProperties())
+ .isNotNull()
+ .contains(entry("a", "1"), entry("b", "2-added"), entry("c", "3"));
+ }
+
+ @Test
+ public void testEmptyPropertySource() throws Exception {
+ ConfigSource ps = ConfigSourceFunctions.emptyConfigSource();
+ assertThat(ps).isNotNull();
+ assertNotNull(ps.getProperties());
+ assertTrue(ps.getProperties().isEmpty());
+ assertEquals(ps.getName(), "<empty>" );
+ }
+}
\ No newline at end of file