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 f9e8b41  [CONFIGURATION-731] Allow user to specify the comments & 
separator chars.
f9e8b41 is described below

commit f9e8b415cf9d3cf34cd911eac9d89c955fdd2785
Author: Gary Gregory <ggreg...@rocketsoftware.com>
AuthorDate: Thu Feb 28 10:01:50 2019 -0500

    [CONFIGURATION-731] Allow user to specify the comments & separator
    chars.
    
    Apply a different version of the patch that does not break compatibility
    by using Java 8 default methods.
---
 src/changes/changes.xml                            |   6 ++
 .../commons/configuration2/INIConfiguration.java   | 118 ++++++++++++++++++---
 .../builder/INIBuilderParametersImpl.java          |  18 ++++
 .../builder/INIBuilderProperties.java              |  34 +++++-
 .../configuration2/TestINIConfiguration.java       |  52 +++++++++
 5 files changed, 212 insertions(+), 16 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 1cad9bd..ffe6c27 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -25,6 +25,12 @@
   </properties>
 
   <body>
+    <release version="2.5" date="2019-MM-DD"
+             description="Minor release with new features and updated 
dependencies.">
+      <action dev="ggregory" type="fix" issue="CONFIGURATION-731" 
due-to="Shuai Zhang, Gary Gregory">
+        Allow user to specify the comments & separator chars.
+      </action>
+    </release>
     <release version="2.4" date="2018-10-23"
              description="Minor release with new features and updated 
dependencies.">
       <action dev="oheger" type="fix" issue="CONFIGURATION-710" 
due-to="thc202">
diff --git 
a/src/main/java/org/apache/commons/configuration2/INIConfiguration.java 
b/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
index c343245..af62d66 100644
--- a/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
@@ -227,12 +227,12 @@ public class INIConfiguration extends 
BaseHierarchicalConfiguration implements
         FileBasedConfiguration
 {
     /**
-     * The characters that signal the start of a comment line.
+     * The default characters that signal the start of a comment line.
      */
     protected static final String COMMENT_CHARS = "#;";
 
     /**
-     * The characters used to separate keys from values.
+     * The default characters used to separate keys from values.
      */
     protected static final String SEPARATOR_CHARS = "=:";
 
@@ -257,6 +257,17 @@ public class INIConfiguration extends 
BaseHierarchicalConfiguration implements
     private String separatorUsedInOutput = " = ";
 
     /**
+     * The separator used when reading an INI file.
+     */
+    private String separatorUsedInInput = SEPARATOR_CHARS;
+
+    /**
+     * The characters used to separate keys from values
+     * when reading an INI file.
+     */
+    private String commentCharsUsedInInput = COMMENT_CHARS;
+
+    /**
      * Create a new empty INI Configuration.
      */
     public INIConfiguration()
@@ -317,6 +328,86 @@ public class INIConfiguration extends 
BaseHierarchicalConfiguration implements
     }
 
     /**
+     * Get separator used in INI reading. see {@code setSeparatorUsedInInput}
+     * for further explanation
+     *
+     * @return the current separator for reading the INI input
+     * @since 2.5
+     */
+    public String getSeparatorUsedInInput()
+    {
+        beginRead(false);
+        try
+        {
+            return separatorUsedInInput;
+        }
+        finally
+        {
+            endRead();
+        }
+    }
+
+    /**
+     * Allows setting the key and value separator which is used in reading
+     * an INI file
+     *
+     * @param separator String of the new separator for INI reading
+     * @since 2.5
+     */
+    public void setSeparatorUsedInInput(final String separator)
+    {
+        beginRead(false);
+        try
+        {
+            this.separatorUsedInInput = separator;
+        }
+        finally
+        {
+            endRead();
+        }
+    }
+
+    /**
+     * Get comment leading separator used in INI reading.
+     * see {@code setCommentLeadingCharsUsedInInput} for further explanation
+     *
+     * @return the current separator for reading the INI input
+     * @since 2.5
+     */
+    public String getCommentLeadingCharsUsedInInput()
+    {
+        beginRead(false);
+        try
+        {
+            return commentCharsUsedInInput;
+        }
+        finally
+        {
+            endRead();
+        }
+    }
+
+    /**
+     * Allows setting the leading comment separator which is used in reading
+     * an INI file
+     *
+     * @param separator String of the new separator for INI reading
+     * @since 2.5
+     */
+    public void setCommentLeadingCharsUsedInInput(final String separator)
+    {
+        beginRead(false);
+        try
+        {
+            this.commentCharsUsedInInput = separator;
+        }
+        finally
+        {
+            endRead();
+        }
+    }
+
+    /**
      * Save the configuration to the specified writer.
      *
      * @param writer - The writer to save the configuration to.
@@ -530,7 +621,8 @@ public class INIConfiguration extends 
BaseHierarchicalConfiguration implements
      * @param reader the reader (needed if multiple lines have to be read)
      * @throws IOException if an IO error occurs
      */
-    private static String parseValue(final String val, final BufferedReader 
reader) throws IOException
+    private String parseValue(final String val, final BufferedReader reader)
+        throws IOException
     {
         final StringBuilder propertyValue = new StringBuilder();
         boolean lineContinues;
@@ -645,7 +737,7 @@ public class INIConfiguration extends 
BaseHierarchicalConfiguration implements
      * @param pos the start position
      * @return a flag whether this line continues
      */
-    private static boolean lineContinues(final String line, final int pos)
+    private boolean lineContinues(final String line, final int pos)
     {
         String s;
 
@@ -672,9 +764,9 @@ public class INIConfiguration extends 
BaseHierarchicalConfiguration implements
      * @param c the character
      * @return a flag whether this character starts a comment
      */
-    private static boolean isCommentChar(final char c)
+    private boolean isCommentChar(final char c)
     {
-        return COMMENT_CHARS.indexOf(c) >= 0;
+        return getCommentLeadingCharsUsedInInput().indexOf(c) >= 0;
     }
 
     /**
@@ -687,14 +779,14 @@ public class INIConfiguration extends 
BaseHierarchicalConfiguration implements
      * @param line the line to be checked
      * @return the index of the separator character or -1 if none is found
      */
-    private static int findSeparator(final String line)
+    private int findSeparator(final String line)
     {
         int index =
                 findSeparatorBeforeQuote(line,
                         findFirstOccurrence(line, QUOTE_CHARACTERS));
         if (index < 0)
         {
-            index = findFirstOccurrence(line, SEPARATOR_CHARS);
+            index = findFirstOccurrence(line, getSeparatorUsedInInput());
         }
         return index;
     }
@@ -774,13 +866,14 @@ public class INIConfiguration extends 
BaseHierarchicalConfiguration implements
      * @param value the value to be escaped
      * @return the value with comment characters escaped
      */
-    private static String escapeComments(final String value)
+    private String escapeComments(final String value)
     {
+        final String commentChars = getCommentLeadingCharsUsedInInput();
         boolean quoted = false;
 
-        for (int i = 0; i < COMMENT_CHARS.length() && !quoted; i++)
+        for (int i = 0; i < commentChars.length() && !quoted; i++)
         {
-            final char c = COMMENT_CHARS.charAt(i);
+            final char c = commentChars.charAt(i);
             if (value.indexOf(c) != -1)
             {
                 quoted = true;
@@ -808,7 +901,8 @@ public class INIConfiguration extends 
BaseHierarchicalConfiguration implements
             return false;
         }
         // blank lines are also treated as comment lines
-        return line.length() < 1 || COMMENT_CHARS.indexOf(line.charAt(0)) >= 0;
+        return line.length() < 1
+            || getCommentLeadingCharsUsedInInput().indexOf(line.charAt(0)) >= 
0;
     }
 
     /**
diff --git 
a/src/main/java/org/apache/commons/configuration2/builder/INIBuilderParametersImpl.java
 
b/src/main/java/org/apache/commons/configuration2/builder/INIBuilderParametersImpl.java
index fef9cfe..43c6481 100644
--- 
a/src/main/java/org/apache/commons/configuration2/builder/INIBuilderParametersImpl.java
+++ 
b/src/main/java/org/apache/commons/configuration2/builder/INIBuilderParametersImpl.java
@@ -40,12 +40,18 @@ public class INIBuilderParametersImpl extends 
HierarchicalBuilderParametersImpl
     /** The key for the separatorUsedInINIOutput property. */
     private static final String PROP_SEPARATOR_USED_IN_INI_OUTPUT
         = "separatorUsedInOutput";
+    private static final String PROP_SEPARATOR_USED_IN_INI_INPUT
+        = "separatorUsedInInput";
+    private static final String 
PROP_COMMENT_LEADING_SEPARATOR_USED_IN_INI_INPUT
+        = "commentLeadingCharsUsedInInput";
 
     @Override
     public void inheritFrom(final Map<String, ?> source)
     {
         super.inheritFrom(source);
         copyPropertiesFrom(source, PROP_SEPARATOR_USED_IN_INI_OUTPUT);
+        copyPropertiesFrom(source, PROP_SEPARATOR_USED_IN_INI_INPUT);
+        copyPropertiesFrom(source, 
PROP_COMMENT_LEADING_SEPARATOR_USED_IN_INI_INPUT);
     }
 
     @Override
@@ -54,4 +60,16 @@ public class INIBuilderParametersImpl extends 
HierarchicalBuilderParametersImpl
         storeProperty(PROP_SEPARATOR_USED_IN_INI_OUTPUT, separator);
         return this;
     }
+
+    @Override
+    public INIBuilderParametersImpl setSeparatorUsedInInput(String separator) {
+        storeProperty(PROP_SEPARATOR_USED_IN_INI_INPUT, separator);
+        return this;
+    }
+
+    @Override
+    public INIBuilderParametersImpl setCommentLeadingCharsUsedInInput(String 
separator) {
+        storeProperty(PROP_COMMENT_LEADING_SEPARATOR_USED_IN_INI_INPUT, 
separator);
+        return this;
+    }
 }
diff --git 
a/src/main/java/org/apache/commons/configuration2/builder/INIBuilderProperties.java
 
b/src/main/java/org/apache/commons/configuration2/builder/INIBuilderProperties.java
index 6c58a92..6b2a86c 100644
--- 
a/src/main/java/org/apache/commons/configuration2/builder/INIBuilderProperties.java
+++ 
b/src/main/java/org/apache/commons/configuration2/builder/INIBuilderProperties.java
@@ -33,11 +33,37 @@ package org.apache.commons.configuration2.builder;
  * @since 2.2
  * @param <T> the type of the result of all set methods for method chaining
  */
-public interface INIBuilderProperties<T>
-{
+public interface INIBuilderProperties<T> {
+    
     /**
-     * Allows setting the separator between key and value to be used when
-     * writing an INI file.
+     * Allows setting the leading comment separator which is used in reading 
an INI
+     * file
+     *
+     * @param separator String of the new separator for INI reading
+     * @return a reference to this object for method chaining
+     * @since 2.5
+     */
+    default T setCommentLeadingCharsUsedInInput(String separator) {
+        // NoOp
+        return (T) this;
+    }
+
+    /**
+     * Allows setting the key and value separator which is used in reading an 
INI
+     * file
+     *
+     * @param separator String of the new separator for INI reading
+     * @return a reference to this object for method chaining
+     * @since 2.5
+     */
+    default T setSeparatorUsedInInput(String separator) {
+        // NoOp
+        return (T) this;
+    }
+
+    /**
+     * Allows setting the separator between key and value to be used when 
writing an
+     * INI file.
      *
      * @param separator the new separator for INI output
      * @return a reference to this object for method chaining
diff --git 
a/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java 
b/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
index 92a1ca4..2d1263d 100644
--- a/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
+++ b/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
@@ -20,6 +20,7 @@ package org.apache.commons.configuration2;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -254,6 +255,57 @@ public class TestINIConfiguration
     }
 
     /**
+     * Test of read method with changed separator.
+     */
+    @Test
+    public void testSeparatorUsedInINIInput() throws Exception
+    {
+        final String inputSeparator = "=";
+        final String input = "[section]" + LINE_SEPARATOR
+            + "k1:v1$key1=value1" + LINE_SEPARATOR
+            + "k1:v1,k2:v2$key2=value2" + LINE_SEPARATOR
+            + "key3:value3" + LINE_SEPARATOR
+            + "key4 = value4" + LINE_SEPARATOR;
+
+        final INIConfiguration instance = new FileBasedConfigurationBuilder<>(
+            INIConfiguration.class)
+            .configure(new 
Parameters().ini().setSeparatorUsedInInput(inputSeparator))
+            .getConfiguration();
+        load(instance, input);
+
+        assertEquals("value1", instance.getString("section.k1:v1$key1"));
+        assertEquals("value2", instance.getString("section.k1:v1,k2:v2$key2"));
+        assertEquals("", instance.getString("section.key3:value3"));
+        assertEquals("value4", instance.getString("section.key4").trim());
+    }
+
+    /**
+     * Test of read method with changed comment leading separator
+     */
+    @Test
+    public void testCommentLeadingSeparatorUsedInINIInput() throws Exception
+    {
+        final String inputCommentLeadingSeparator = ";";
+        final String input = "[section]" + LINE_SEPARATOR
+            + "key1=a;b;c" + LINE_SEPARATOR
+            + "key2=a#b#c" + LINE_SEPARATOR
+            + ";key3=value3" + LINE_SEPARATOR
+            + "#key4=value4" + LINE_SEPARATOR;
+
+        final INIConfiguration instance = new FileBasedConfigurationBuilder<>(
+            INIConfiguration.class)
+            .configure(new Parameters().ini()
+                
.setCommentLeadingCharsUsedInInput(inputCommentLeadingSeparator))
+            .getConfiguration();
+        load(instance, input);
+
+        assertEquals("a;b;c", instance.getString("section.key1"));
+        assertEquals("a#b#c", instance.getString("section.key2"));
+        assertNull("", instance.getString("section.;key3"));
+        assertEquals("value4", instance.getString("section.#key4"));
+    }
+
+    /**
      * Helper method for testing a save operation. This method constructs a
      * configuration from the specified content string. Then it saves this
      * configuration and checks whether the result matches the original 
content.

Reply via email to