This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-configuration.git


The following commit(s) were added to refs/heads/master by this push:
     new 63435b21 feat/configuration-contains-value (#412)
63435b21 is described below

commit 63435b214598bd7ed6c7b3f8f36fdc1feb7f075e
Author: Rikkarth <76500344+rikka...@users.noreply.github.com>
AuthorDate: Wed May 8 01:46:17 2024 +0100

    feat/configuration-contains-value (#412)
    
    * feat: contains value initial implementation
    
    * test: tests adjusted
    
    * chore: remove temp class
    
    * chore: lint fix
    
    * fix: MapConfiguration containsValue
    
    test: moved test
    
    * chore: minor cleanup, renaming
    
    * test: improved err message
    
    * fix: moved contains impl to AbstractConfiguration
    
    * change: simplified contains in AbstractConfiguration.java
    
    * change: adjusted containsValueInternal in DatabaseConfiguration
    
    test: containsValue() in TestDatabaseConfiguration
    
    * docs: add javadoc
    
    * fix: incompatibility issue
    
    * docs: minor javadoc update
    
    * test: nullity tests
    
    * fix: add null validation to contains
    
    test: nullity test adjusted
    
    * docs: javadoc contains in AbstractConfiguration
    
    * docs: javadoc adaption
    
    * feat: add impl to containsValue in ImmutableConfiguration
    
    chore: add final to contains in AbstractConfiguration
    chore: remove white space in DatabaseConfiguration
    chore: add missing public and final to TestAbstractConfiguration
    test: given existing value test containsValue with default impl
    
    * docs: javadoc NonCloneableConfiguration
    
    * docs: complete javadocs
    
    * test: adjusted containsValue tests, test each containsValue implementation
    
    * test: remove string messages from tests
    
    * chore: changed tests signature names
    
    * docs: adjusted javadoc
    
    * docs: adjusted since javadoc version
    
    * docs: add missing javadoc
    
    * workflows update
    
    * Revert "workflows update"
    
    This reverts commit 56fafc9e972aa901c34c3157d9ea72537db8b1b4.
    
    * Add Javadoc since tag
    
    ---------
    
    Co-authored-by: Gary Gregory <garydgreg...@users.noreply.github.com>
---
 .../configuration2/AbstractConfiguration.java      | 47 ++++++++++++++++++++++
 .../AbstractHierarchicalConfiguration.java         | 10 +++++
 .../commons/configuration2/BaseConfiguration.java  | 10 +++++
 .../configuration2/CompositeConfiguration.java     | 10 +++++
 .../commons/configuration2/DataConfiguration.java  | 10 +++++
 .../configuration2/DatabaseConfiguration.java      | 19 +++++++++
 .../DynamicCombinedConfiguration.java              | 10 +++++
 .../configuration2/ImmutableConfiguration.java     | 18 +++++++++
 .../commons/configuration2/JNDIConfiguration.java  | 10 +++++
 .../commons/configuration2/MapConfiguration.java   | 10 +++++
 .../PatternSubtreeConfigurationWrapper.java        | 10 +++++
 .../configuration2/SubsetConfiguration.java        | 10 +++++
 .../configuration2/web/BaseWebConfiguration.java   | 10 +++++
 .../configuration2/NonCloneableConfiguration.java  | 10 +++++
 .../configuration2/TestAbstractConfiguration.java  | 29 +++++++++++++
 .../TestAbstractConfigurationBasicFeatures.java    |  5 +++
 .../TestAbstractHierarchicalConfiguration.java     |  5 +++
 .../configuration2/TestBaseConfiguration.java      |  5 +++
 .../configuration2/TestDataConfiguration.java      |  6 +++
 .../configuration2/TestDatabaseConfiguration.java  | 18 +++++++++
 .../TestDefaultImmutableConfiguration.java         | 10 ++++-
 .../configuration2/TestMapConfiguration.java       |  5 +++
 .../TestPropertiesConfiguration.java               | 10 +++++
 .../web/TestAppletConfiguration.java               |  7 ++++
 .../web/TestServletConfiguration.java              |  7 ++++
 .../web/TestServletContextConfiguration.java       |  7 ++++
 .../web/TestServletFilterConfiguration.java        |  7 ++++
 .../web/TestServletRequestConfiguration.java       |  6 +++
 28 files changed, 319 insertions(+), 2 deletions(-)

diff --git 
a/src/main/java/org/apache/commons/configuration2/AbstractConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/AbstractConfiguration.java
index e0c0ddcf..ba32c599 100644
--- a/src/main/java/org/apache/commons/configuration2/AbstractConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/AbstractConfiguration.java
@@ -419,6 +419,20 @@ public abstract class AbstractConfiguration extends 
BaseEventSource implements C
         }
     }
 
+    /**
+     * {@inheritDoc} This implementation handles synchronization and delegates 
to {@code containsKeyInternal()}.
+     * @since 2.11.0
+     */
+    @Override
+    public final boolean containsValue(final String value) {
+        beginRead(false);
+        try {
+            return containsValueInternal(value);
+        } finally {
+            endRead();
+        }
+    }
+
     /**
      * Actually checks whether the specified key is contained in this 
configuration. This method is called by
      * {@code containsKey()}. It has to be defined by concrete subclasses.
@@ -429,6 +443,22 @@ public abstract class AbstractConfiguration extends 
BaseEventSource implements C
      */
     protected abstract boolean containsKeyInternal(String key);
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first
+     * match but may be more expensive than the {@link #containsKeyInternal 
containsKey} method.
+     * <p>The implementation of this method will be different depending on the 
type of Configuration used.</p>
+     *
+     * <p>Note that this method is identical in functionality to
+     * {@link #containsValue containsValue}, (which is part of the {@link 
ImmutableConfiguration} interface).</p>
+     *
+     * @param value a value to search for
+     * @return {@code true} if and only if some key maps to the {@code value} 
argument in this hashtable as determined
+     * by the {@code equals} method; {@code false} otherwise.
+     * @throws NullPointerException if the value is {@code null}
+     * @since 2.11.0
+     */
+    protected abstract boolean containsValueInternal(String value);
+
     /**
      * Helper method for obtaining a property value with a type conversion.
      *
@@ -1517,6 +1547,23 @@ public abstract class AbstractConfiguration extends 
BaseEventSource implements C
         return size;
     }
 
+    /**
+     * Checks if the specified value exists in the properties structure mapped 
by the provided keys.
+     *
+     * @param keys an Iterator of String keys to search for the value
+     * @param value the String value to search for in the properties
+     * @return true if the value is found in the properties, false otherwise
+     * @since 2.11.0
+     */
+    protected boolean contains(final Iterator<String> keys, final String 
value) {
+        while (keys.hasNext()) {
+            if (value.equals(getProperty(keys.next()))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     public Configuration subset(final String prefix) {
         return new SubsetConfiguration(this, prefix, ".");
diff --git 
a/src/main/java/org/apache/commons/configuration2/AbstractHierarchicalConfiguration.java
 
b/src/main/java/org/apache/commons/configuration2/AbstractHierarchicalConfiguration.java
index 2093ff0e..0f5edb8e 100644
--- 
a/src/main/java/org/apache/commons/configuration2/AbstractHierarchicalConfiguration.java
+++ 
b/src/main/java/org/apache/commons/configuration2/AbstractHierarchicalConfiguration.java
@@ -455,6 +455,16 @@ public abstract class AbstractHierarchicalConfiguration<T> 
extends AbstractConfi
         return getPropertyInternal(key) != null;
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first
+     * match but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(final String value) {
+        return contains(getKeys(), value);
+    }
+
     /**
      * Helper method for resolving the specified key.
      *
diff --git 
a/src/main/java/org/apache/commons/configuration2/BaseConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/BaseConfiguration.java
index da2750ac..f6697c32 100644
--- a/src/main/java/org/apache/commons/configuration2/BaseConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/BaseConfiguration.java
@@ -136,6 +136,16 @@ public class BaseConfiguration extends 
AbstractConfiguration implements Cloneabl
         return store.containsKey(key);
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first
+     * match but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(String value) {
+        return store.containsValue(value);
+    }
+
     /**
      * Gets the list of the keys contained in the configuration repository.
      *
diff --git 
a/src/main/java/org/apache/commons/configuration2/CompositeConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/CompositeConfiguration.java
index e7eba9fe..c70ba271 100644
--- 
a/src/main/java/org/apache/commons/configuration2/CompositeConfiguration.java
+++ 
b/src/main/java/org/apache/commons/configuration2/CompositeConfiguration.java
@@ -298,6 +298,16 @@ public class CompositeConfiguration extends 
AbstractConfiguration implements Clo
         return configList.stream().anyMatch(config -> config.containsKey(key));
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first
+     * match but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(final String value) {
+        return configList.stream().anyMatch(config -> 
config.containsValue(value));
+    }
+
     /**
      * Gets the configuration at the specified index.
      *
diff --git 
a/src/main/java/org/apache/commons/configuration2/DataConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/DataConfiguration.java
index ffd73c80..d63fc39c 100644
--- a/src/main/java/org/apache/commons/configuration2/DataConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/DataConfiguration.java
@@ -213,6 +213,16 @@ public class DataConfiguration extends 
AbstractConfiguration {
         return configuration.containsKey(key);
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first
+     * match but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(final String value) {
+        return configuration.containsValue(value);
+    }
+
     /**
      * Gets an array of BigDecimals associated with the given configuration 
key. If the key doesn't map to an existing object
      * an empty array is returned.
diff --git 
a/src/main/java/org/apache/commons/configuration2/DatabaseConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/DatabaseConfiguration.java
index e4547956..6517e81c 100644
--- a/src/main/java/org/apache/commons/configuration2/DatabaseConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/DatabaseConfiguration.java
@@ -478,6 +478,25 @@ public class DatabaseConfiguration extends 
AbstractConfiguration {
         return result != null && result.booleanValue();
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first
+     * match but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(final String value) {
+        final AbstractJdbcOperation<Boolean> op = new 
AbstractJdbcOperation<Boolean>(ConfigurationErrorEvent.READ, 
ConfigurationErrorEvent.READ, value, null) {
+            @Override
+            protected Boolean performOperation() throws SQLException {
+                try (ResultSet rs = 
openResultSet(String.format(SQL_GET_PROPERTY, table, valueColumn), false, 
value)) {
+                    return rs.next();
+                }
+            }
+        };
+        final Boolean result = op.execute();
+        return result != null && result.booleanValue();
+    }
+
     /**
      * Extracts the value of a property from the given result set. The passed 
in {@code ResultSet} was created by a SELECT
      * statement on the underlying database table. This implementation reads 
the value of the column determined by the
diff --git 
a/src/main/java/org/apache/commons/configuration2/DynamicCombinedConfiguration.java
 
b/src/main/java/org/apache/commons/configuration2/DynamicCombinedConfiguration.java
index 1acb20b4..5c4a6d3d 100644
--- 
a/src/main/java/org/apache/commons/configuration2/DynamicCombinedConfiguration.java
+++ 
b/src/main/java/org/apache/commons/configuration2/DynamicCombinedConfiguration.java
@@ -358,6 +358,16 @@ public class DynamicCombinedConfiguration extends 
CombinedConfiguration {
         return this.getCurrentConfig().containsKey(key);
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first
+     * match but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(String value) {
+        return this.getCurrentConfig().contains(getKeys(), value);
+    }
+
     /**
      * Creates a new, uninitialized child configuration.
      *
diff --git 
a/src/main/java/org/apache/commons/configuration2/ImmutableConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/ImmutableConfiguration.java
index a7659339..57c97ca8 100644
--- 
a/src/main/java/org/apache/commons/configuration2/ImmutableConfiguration.java
+++ 
b/src/main/java/org/apache/commons/configuration2/ImmutableConfiguration.java
@@ -62,6 +62,24 @@ public interface ImmutableConfiguration {
      */
     boolean containsKey(String key);
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first
+     * match but may be more expensive than the {@link #containsKey 
containsKey} method.
+     *
+     * @param value value whose presence in this configuration is to be tested
+     * @return {@code true} if this configuration maps one or more keys to the 
specified value, false otherwise.
+     * @since 2.11.0
+     */
+    default boolean containsValue(final String value) {
+        final Iterator<String> keys = getKeys();
+        while (keys.hasNext()) {
+            if (value.equals(getProperty(keys.next()))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Gets an object of the specified type associated with the given 
configuration key. If the key doesn't map to an
      * existing object, the method returns null unless {@link 
AbstractConfiguration#isThrowExceptionOnMissing()} is set to
diff --git 
a/src/main/java/org/apache/commons/configuration2/JNDIConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/JNDIConfiguration.java
index 07bc02d2..9cc1a27f 100644
--- a/src/main/java/org/apache/commons/configuration2/JNDIConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/JNDIConfiguration.java
@@ -147,6 +147,16 @@ public class JNDIConfiguration extends 
AbstractConfiguration {
         }
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first match
+     * but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(final String value) {
+        return contains(getKeys(), value);
+    }
+
     /**
      * Gets the base context with the prefix applied.
      *
diff --git 
a/src/main/java/org/apache/commons/configuration2/MapConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/MapConfiguration.java
index d4cb8d00..be0df0a5 100644
--- a/src/main/java/org/apache/commons/configuration2/MapConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/MapConfiguration.java
@@ -172,6 +172,16 @@ public class MapConfiguration extends 
AbstractConfiguration implements Cloneable
         return map.containsKey(key);
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first match
+     * but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(final String value) {
+        return map.containsValue(value);
+    }
+
     @Override
     protected Iterator<String> getKeysInternal() {
         return map.keySet().iterator();
diff --git 
a/src/main/java/org/apache/commons/configuration2/PatternSubtreeConfigurationWrapper.java
 
b/src/main/java/org/apache/commons/configuration2/PatternSubtreeConfigurationWrapper.java
index 79c00969..94a678fb 100644
--- 
a/src/main/java/org/apache/commons/configuration2/PatternSubtreeConfigurationWrapper.java
+++ 
b/src/main/java/org/apache/commons/configuration2/PatternSubtreeConfigurationWrapper.java
@@ -130,6 +130,16 @@ public class PatternSubtreeConfigurationWrapper extends 
BaseHierarchicalConfigur
         return config.containsKey(makePath(key));
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first
+     * match but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(String value) {
+        return config.containsValue(value);
+    }
+
     /**
      * Returns the wrapped configuration as a {@code FileBased} object. If 
this cast is not possible, an exception is
      * thrown.
diff --git 
a/src/main/java/org/apache/commons/configuration2/SubsetConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/SubsetConfiguration.java
index 93960826..1f176fb1 100644
--- a/src/main/java/org/apache/commons/configuration2/SubsetConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/SubsetConfiguration.java
@@ -131,6 +131,16 @@ public class SubsetConfiguration extends 
AbstractConfiguration {
         return parent.containsKey(getParentKey(key));
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first match
+     * but may be more expensive than the containsKey method.
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(final String value) {
+        return parent.containsValue(value);
+    }
+
     /**
      * Gets the key in the subset configuration associated to the specified 
key in the parent configuration.
      *
diff --git 
a/src/main/java/org/apache/commons/configuration2/web/BaseWebConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/web/BaseWebConfiguration.java
index 17c12c79..34a0a2ce 100644
--- 
a/src/main/java/org/apache/commons/configuration2/web/BaseWebConfiguration.java
+++ 
b/src/main/java/org/apache/commons/configuration2/web/BaseWebConfiguration.java
@@ -68,6 +68,16 @@ abstract class BaseWebConfiguration extends 
AbstractConfiguration {
         return getPropertyInternal(key) != null;
     }
 
+    /**
+     * Tests whether this configuration contains one or more matches to this 
value. This operation stops at first match
+     * but may be more expensive than the containsKey method
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(final String value) {
+        return contains(getKeys(), value);
+    }
+
     /**
      * Takes care of list delimiters in property values. This method checks if 
delimiter parsing is enabled and the passed
      * in value contains a delimiter character. If this is the case, a split 
operation is performed.
diff --git 
a/src/test/java/org/apache/commons/configuration2/NonCloneableConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/NonCloneableConfiguration.java
index b8899a6f..552c3e57 100644
--- 
a/src/test/java/org/apache/commons/configuration2/NonCloneableConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/NonCloneableConfiguration.java
@@ -45,6 +45,16 @@ public class NonCloneableConfiguration extends 
AbstractConfiguration {
         return false;
     }
 
+    /**
+     * Dummy implementation of this method.
+     *
+     * @since 2.11.0
+     */
+    @Override
+    protected boolean containsValueInternal(String value) {
+        return false;
+    }
+
     /**
      * Dummy implementation of this method.
      */
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestAbstractConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/TestAbstractConfiguration.java
index b3e3ba24..12f68863 100644
--- 
a/src/test/java/org/apache/commons/configuration2/TestAbstractConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/TestAbstractConfiguration.java
@@ -78,6 +78,35 @@ public abstract class TestAbstractConfiguration {
         assertEquals(expected, list);
     }
 
+    @Test
+    public void testContainsValue() {
+        final Configuration config = getConfiguration();
+        assertTrue(config.containsValue("value1"));
+        assertFalse(config.containsValue("value99999"));
+    }
+
+    @Test
+    public void testContains() {
+        final AbstractConfiguration config = getConfiguration();
+        assertTrue(config.contains(config.getKeys(), "value1"));
+        assertFalse(config.contains(config.getKeys(), "value99999"));
+    }
+
+    @Test
+    public void givenNullIteratorTestContains() {
+        final AbstractConfiguration config = getConfiguration();
+
+        assertThrows(NullPointerException.class, () -> config.contains(null, 
"value1"));
+    }
+
+    @Test
+    public void givenNullValueTestContains() {
+        AbstractConfiguration config = getConfiguration();
+        Iterator<String> keys = config.getKeys();
+
+        assertThrows(NullPointerException.class, () -> config.contains(keys, 
null));
+    }
+
     @Test
     public void testClearProperty() {
         final Configuration config = getConfiguration();
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestAbstractConfigurationBasicFeatures.java
 
b/src/test/java/org/apache/commons/configuration2/TestAbstractConfigurationBasicFeatures.java
index 2761c4e8..d61f67d1 100644
--- 
a/src/test/java/org/apache/commons/configuration2/TestAbstractConfigurationBasicFeatures.java
+++ 
b/src/test/java/org/apache/commons/configuration2/TestAbstractConfigurationBasicFeatures.java
@@ -93,6 +93,11 @@ public class TestAbstractConfigurationBasicFeatures {
             return config.containsKey(key);
         }
 
+        @Override
+        protected boolean containsValueInternal(String value) {
+            return config.containsValue(value);
+        }
+
         @Override
         protected Iterator<String> getKeysInternal() {
             return config.getKeys();
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestAbstractHierarchicalConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/TestAbstractHierarchicalConfiguration.java
index 247a74bc..2eee1a2b 100644
--- 
a/src/test/java/org/apache/commons/configuration2/TestAbstractHierarchicalConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/TestAbstractHierarchicalConfiguration.java
@@ -941,4 +941,9 @@ public class TestAbstractHierarchicalConfiguration {
     public void testSize() {
         assertEquals(2, config.size());
     }
+
+    @Test
+    public void testContainsValue() {
+        assertThrows(NullPointerException.class, () -> 
config.containsValue(null));
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestBaseConfiguration.java 
b/src/test/java/org/apache/commons/configuration2/TestBaseConfiguration.java
index b7575614..be797a3f 100644
--- a/src/test/java/org/apache/commons/configuration2/TestBaseConfiguration.java
+++ b/src/test/java/org/apache/commons/configuration2/TestBaseConfiguration.java
@@ -718,4 +718,9 @@ public class TestBaseConfiguration {
     public void testThrowExceptionOnMissing() {
         assertTrue(config.isThrowExceptionOnMissing());
     }
+
+    @Test
+    public void testContainsValue() {
+        assertFalse(config.containsValue(null));
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestDataConfiguration.java 
b/src/test/java/org/apache/commons/configuration2/TestDataConfiguration.java
index dfdec4cc..aff406ba 100644
--- a/src/test/java/org/apache/commons/configuration2/TestDataConfiguration.java
+++ b/src/test/java/org/apache/commons/configuration2/TestDataConfiguration.java
@@ -1965,4 +1965,10 @@ public class TestDataConfiguration {
     public void testNullConfiguration() {
         assertThrows(NullPointerException.class, () -> new 
DataConfiguration(null));
     }
+
+    @Test
+    public void testContainsValue() {
+        final Configuration config = conf.getConfiguration();
+        assertFalse(config.containsValue(null));
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestDatabaseConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/TestDatabaseConfiguration.java
index e2a6df2d..c4aa9f79 100644
--- 
a/src/test/java/org/apache/commons/configuration2/TestDatabaseConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/TestDatabaseConfiguration.java
@@ -173,6 +173,24 @@ public class TestDatabaseConfiguration {
         assertTrue(config.containsKey("boolean"));
     }
 
+    @Test
+    void testContainsValue() throws ConfigurationException {
+        final DatabaseConfiguration config = helper.setUpConfig();
+        config.addPropertyDirect("test", "test1");
+
+        assertTrue(config.containsValue("test1"));
+        assertFalse(config.containsValue("test9999"));
+    }
+
+    @Test
+    void containsValueInternal() throws ConfigurationException {
+        final DatabaseConfiguration config = helper.setUpConfig();
+        config.addPropertyDirect("test", "test1");
+
+        assertTrue(config.containsValueInternal("test1"));
+        assertFalse(config.containsValue("test9999"));
+    }
+
     /**
      * Tests whether a commit is performed after a property was added.
      */
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestDefaultImmutableConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/TestDefaultImmutableConfiguration.java
index a7583320..598b6f9d 100644
--- 
a/src/test/java/org/apache/commons/configuration2/TestDefaultImmutableConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/TestDefaultImmutableConfiguration.java
@@ -19,6 +19,7 @@ package org.apache.commons.configuration2;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -217,8 +218,7 @@ public class TestDefaultImmutableConfiguration {
 
         @Override
         public Iterator<String> getKeys() {
-            // Super is not a default method.
-            return null;
+            return this.map.keySet().iterator();
         }
 
         @Override
@@ -362,6 +362,12 @@ public class TestDefaultImmutableConfiguration {
         assertThrows(ConversionException.class, () -> 
config.getDuration("test.empty"));
     }
 
+    @Test
+    public void testContainsValueDefaultImplementation() {
+        config.map.put("test", "213123");
+        assertTrue(config.containsValue("213123"));
+    }
+
     @Test
     public void testGetDurationUnknown() {
         assertThrows(NoSuchElementException.class, () -> 
config.getDuration("numberNotInConfig"));
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestMapConfiguration.java 
b/src/test/java/org/apache/commons/configuration2/TestMapConfiguration.java
index d0f22d51..39675c55 100644
--- a/src/test/java/org/apache/commons/configuration2/TestMapConfiguration.java
+++ b/src/test/java/org/apache/commons/configuration2/TestMapConfiguration.java
@@ -162,4 +162,9 @@ public class TestMapConfiguration extends 
TestAbstractConfiguration {
         assertThrows(NullPointerException.class, () -> new 
MapConfiguration((Map) null));
         assertThrows(NullPointerException.class, () -> new 
MapConfiguration((Properties) null));
     }
+
+    @Test
+    public void testContainsValue() {
+        assertFalse(getConfiguration().containsValue(null), "should return 
false");
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java
index 6ccc1652..56300efd 100644
--- 
a/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java
@@ -73,6 +73,7 @@ import 
org.apache.commons.configuration2.SynchronizerTestImpl.Methods;
 import 
org.apache.commons.configuration2.builder.FileBasedBuilderParametersImpl;
 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
 import 
org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder;
+import org.apache.commons.configuration2.builder.fluent.Configurations;
 import org.apache.commons.configuration2.builder.fluent.Parameters;
 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
 import org.apache.commons.configuration2.convert.DisabledListDelimiterHandler;
@@ -1214,6 +1215,15 @@ public class TestPropertiesConfiguration {
         assertEquals(Arrays.asList("C:\\path1\\", "C:\\path2\\", 
"C:\\path3\\complex\\test\\"), list);
     }
 
+    @Test
+    void testConfiguration() throws ConfigurationException {
+        Configurations configManager = new Configurations();
+        Configuration config = 
configManager.properties("src/test/resources/config/test.properties");
+
+        assertTrue(config.containsValue("jndivalue2"));
+        assertFalse(config.containsValue("notFound"));
+    }
+
     /**
      * Tests the propertyLoaded() method for a simple property.
      */
diff --git 
a/src/test/java/org/apache/commons/configuration2/web/TestAppletConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/web/TestAppletConfiguration.java
index 17ddb4c4..b564bbad 100644
--- 
a/src/test/java/org/apache/commons/configuration2/web/TestAppletConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/web/TestAppletConfiguration.java
@@ -24,6 +24,7 @@ import java.util.Properties;
 
 import org.apache.commons.configuration2.AbstractConfiguration;
 import org.apache.commons.configuration2.BaseConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.commons.configuration2.TestAbstractConfiguration;
 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
@@ -113,4 +114,10 @@ public class TestAppletConfiguration extends 
TestAbstractConfiguration {
             assertThrows(UnsupportedOperationException.class, 
super::testClearProperty);
         }
     }
+
+    @Test
+    public void testContainsValue() {
+        final Configuration config = getConfiguration();
+        assertThrows(NullPointerException.class, () -> 
config.containsValue(null));
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/configuration2/web/TestServletConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/web/TestServletConfiguration.java
index a741bba9..d333eab7 100644
--- 
a/src/test/java/org/apache/commons/configuration2/web/TestServletConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/web/TestServletConfiguration.java
@@ -28,6 +28,7 @@ import javax.servlet.ServletConfig;
 import javax.servlet.http.HttpServlet;
 
 import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.configuration2.TestAbstractConfiguration;
 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
 import org.junit.jupiter.api.Test;
@@ -97,4 +98,10 @@ public class TestServletConfiguration extends 
TestAbstractConfiguration {
     public void testClearProperty() {
         assertThrows(UnsupportedOperationException.class, 
super::testClearProperty);
     }
+
+    @Test
+    public void testContainsValue() {
+        final Configuration config = getConfiguration();
+        assertThrows(NullPointerException.class, () -> 
config.containsValue(null));
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/configuration2/web/TestServletContextConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/web/TestServletContextConfiguration.java
index f62803e9..8cd6d4f9 100644
--- 
a/src/test/java/org/apache/commons/configuration2/web/TestServletContextConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/web/TestServletContextConfiguration.java
@@ -29,6 +29,7 @@ import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServlet;
 
 import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.configuration2.TestAbstractConfiguration;
 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
 import org.junit.jupiter.api.Test;
@@ -107,4 +108,10 @@ public class TestServletContextConfiguration extends 
TestAbstractConfiguration {
     public void testClearProperty() {
         assertThrows(UnsupportedOperationException.class, 
super::testClearProperty);
     }
+
+    @Test
+    public void testContainsValue() {
+        final Configuration config = getConfiguration();
+        assertThrows(NullPointerException.class, () -> 
config.containsValue(null));
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/configuration2/web/TestServletFilterConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/web/TestServletFilterConfiguration.java
index 7341e3bc..a48a65fb 100644
--- 
a/src/test/java/org/apache/commons/configuration2/web/TestServletFilterConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/web/TestServletFilterConfiguration.java
@@ -26,6 +26,7 @@ import javax.servlet.FilterConfig;
 import javax.servlet.ServletContext;
 
 import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.configuration2.TestAbstractConfiguration;
 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
 import org.junit.jupiter.api.Test;
@@ -91,4 +92,10 @@ public class TestServletFilterConfiguration extends 
TestAbstractConfiguration {
     public void testClearProperty() {
         assertThrows(UnsupportedOperationException.class, 
super::testClearProperty);
     }
+
+    @Test
+    public void testContainsValue() {
+        final Configuration config = getConfiguration();
+        assertThrows(NullPointerException.class, () -> 
config.containsValue(null));
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/configuration2/web/TestServletRequestConfiguration.java
 
b/src/test/java/org/apache/commons/configuration2/web/TestServletRequestConfiguration.java
index c8492ec4..dad94efe 100644
--- 
a/src/test/java/org/apache/commons/configuration2/web/TestServletRequestConfiguration.java
+++ 
b/src/test/java/org/apache/commons/configuration2/web/TestServletRequestConfiguration.java
@@ -115,4 +115,10 @@ public class TestServletRequestConfiguration extends 
TestAbstractConfiguration {
         }
         assertEquals(expected, v);
     }
+
+    @Test
+    public void testContainsValue() {
+        final Configuration config = getConfiguration();
+        assertThrows(NullPointerException.class, () -> 
config.containsValue(null));
+    }
 }


Reply via email to