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

szetszwo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new dd36de294 RATIS-599. Support underscores in numeric literals in 
RaftProperties. (#974)
dd36de294 is described below

commit dd36de2941925b1f490a5ef8403a1a0c7f6b186a
Author: Tsz-Wo Nicholas Sze <[email protected]>
AuthorDate: Wed Nov 29 10:59:18 2023 -0800

    RATIS-599. Support underscores in numeric literals in RaftProperties. (#974)
---
 .../java/org/apache/ratis/conf/RaftProperties.java |  98 +++++++-------------
 .../java/org/apache/ratis/util/StringUtils.java    |   6 +-
 .../java/org/apache/ratis/util/TimeDuration.java   |   7 +-
 .../apache/ratis/util/TraditionalBinaryPrefix.java |   8 +-
 .../org/apache/ratis/conf/TestRaftProperties.java  | 100 +++++++++++++++++++++
 .../ratis/util/TestTraditionalBinaryPrefix.java    |  14 ++-
 6 files changed, 157 insertions(+), 76 deletions(-)

diff --git 
a/ratis-common/src/main/java/org/apache/ratis/conf/RaftProperties.java 
b/ratis-common/src/main/java/org/apache/ratis/conf/RaftProperties.java
index f51bc731f..206ca11a8 100644
--- a/ratis-common/src/main/java/org/apache/ratis/conf/RaftProperties.java
+++ b/ratis-common/src/main/java/org/apache/ratis/conf/RaftProperties.java
@@ -246,22 +246,34 @@ public class RaftProperties {
    * <code>null</code> if no such property exists.
    * If the key is deprecated, it returns the value of
    * the first key which replaces the deprecated key and is not null
-   *
+   * <p>
    * Values are processed for <a href="#VariableExpansion">variable 
expansion</a>
    * before being returned.
+   * <p>
+   * Underscores can be optionally removed.
    *
    * @param name the property name.
+   * @param removeUnderscores should the underscores be removed?
+   *
    * @return the value of the <code>name</code> or its replacing property,
    *         or null if no such property exists.
    */
-  public String getTrimmed(String name) {
+  public String getTrimmed(String name, boolean removeUnderscores) {
     String value = get(name);
 
     if (null == value) {
       return null;
-    } else {
-      return value.trim();
     }
+    value = value.trim();
+    if (removeUnderscores) {
+      value = value.replace("_", "");
+    }
+    return value;
+  }
+
+  /** The same as getTrimmed(name, false). */
+  public String getTrimmed(String name) {
+    return getTrimmed(name, false);
   }
 
   /**
@@ -341,8 +353,8 @@ public class RaftProperties {
    * @return property value as an <code>int</code>,
    *         or <code>defaultValue</code>.
    */
-  public int getInt(String name, int defaultValue) {
-    String valueString = getTrimmed(name);
+  public Integer getInt(String name, Integer defaultValue) {
+    final String valueString = getTrimmed(name, true);
     if (valueString == null) {
       return defaultValue;
     }
@@ -376,8 +388,8 @@ public class RaftProperties {
    * @return property value as a <code>long</code>,
    *         or <code>defaultValue</code>.
    */
-  public long getLong(String name, long defaultValue) {
-    String valueString = getTrimmed(name);
+  public Long getLong(String name, Long defaultValue) {
+    final String valueString = getTrimmed(name, true);
     if (valueString == null) {
       return defaultValue;
     }
@@ -410,7 +422,7 @@ public class RaftProperties {
     if (null == valueString) {
       return defaultValue;
     }
-    String[] paths = getTrimmedStrings(name);
+    final String[] paths = StringUtils.getTrimmedStrings(get(name));
     return Arrays.stream(paths).map(File::new).collect(Collectors.toList());
   }
 
@@ -476,7 +488,7 @@ public class RaftProperties {
    *         or <code>defaultValue</code>.
    */
   public double getDouble(String name, double defaultValue) {
-    String valueString = getTrimmed(name);
+    final String valueString = getTrimmed(name, true);
     if (valueString == null) {
       return defaultValue;
     }
@@ -503,7 +515,7 @@ public class RaftProperties {
    * @return property value as a <code>boolean</code>,
    *         or <code>defaultValue</code>.
    */
-  public boolean getBoolean(String name, boolean defaultValue) {
+  public Boolean getBoolean(String name, Boolean defaultValue) {
     String valueString = getTrimmed(name);
     return StringUtils.string2boolean(valueString, defaultValue);
   }
@@ -529,18 +541,21 @@ public class RaftProperties {
   }
 
   /**
-   * Return value matching this enumerated type.
-   * Note that the returned value is trimmed by this method.
+   * Get the enum value mapped the given property name.
+   *
    * @param name Property name
+   * @param enumClass the {@link Class} of the enum
    * @param defaultValue Value returned if no mapping exists
-   * @throws IllegalArgumentException If mapping is illegal for the type
-   * provided
    */
-  public <T extends Enum<T>> T getEnum(String name, T defaultValue) {
+  public <T extends Enum<T>> T getEnum(String name, Class<T> enumClass, T 
defaultValue) {
     final String val = getTrimmed(name);
-    return null == val
-      ? defaultValue
-      : Enum.valueOf(defaultValue.getDeclaringClass(), val);
+    return null == val? defaultValue : Enum.valueOf(enumClass, val);
+  }
+
+  /** The same as getEnum(name, defaultValue.getDeclaringClass(), 
defaultValue). */
+  public <T extends Enum<T>> T getEnum(String name, T defaultValue) {
+    Objects.requireNonNull(defaultValue, "defaultValue == null");
+    return getEnum(name, defaultValue.getDeclaringClass(), defaultValue);
   }
 
   /**
@@ -579,51 +594,6 @@ public class RaftProperties {
     return (key, defaultValue) -> getTimeDuration(key, defaultValue, 
defaultUnit);
   }
 
-  /**
-   * Get the comma delimited values of the <code>name</code> property as
-   * an array of <code>String</code>s, trimmed of the leading and trailing 
whitespace.
-   * If no such property is specified then an empty array is returned.
-   *
-   * @param name property name.
-   * @return property value as an array of trimmed <code>String</code>s,
-   *         or empty array.
-   */
-  public String[] getTrimmedStrings(String name) {
-    String valueString = get(name);
-    return StringUtils.getTrimmedStrings(valueString);
-  }
-
-
-
-  /**
-   * Get the value of the <code>name</code> property
-   * as an array of <code>Class</code>.
-   * The value of the property specifies a list of comma separated class names.
-   * If no such property is specified, then <code>defaultValue</code> is
-   * returned.
-   *
-   * @param name the property name.
-   * @param defaultValue default value.
-   * @return property value as a <code>Class[]</code>,
-   *         or <code>defaultValue</code>.
-   */
-  public Class<?>[] getClasses(String name, Class<?> ... defaultValue) {
-    String valueString = getRaw(name);
-    if (null == valueString) {
-      return defaultValue;
-    }
-    String[] classnames = getTrimmedStrings(name);
-    try {
-      Class<?>[] classes = new Class<?>[classnames.length];
-      for(int i = 0; i < classnames.length; i++) {
-        classes[i] = ReflectionUtils.getClassByName(classnames[i]);
-      }
-      return classes;
-    } catch (ClassNotFoundException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
   /**
    * Get the value of the <code>name</code> property as a <code>Class</code>.
    * If no such property is specified, then <code>defaultValue</code> is
diff --git a/ratis-common/src/main/java/org/apache/ratis/util/StringUtils.java 
b/ratis-common/src/main/java/org/apache/ratis/util/StringUtils.java
index 68c76ba99..e1dae790c 100644
--- a/ratis-common/src/main/java/org/apache/ratis/util/StringUtils.java
+++ b/ratis-common/src/main/java/org/apache/ratis/util/StringUtils.java
@@ -117,15 +117,19 @@ public final class StringUtils {
     return s.toString();
   }
 
-  public static boolean string2boolean(String s, boolean defaultValue) {
+  public static Boolean string2boolean(String s, Boolean defaultValue) {
     if (s == null || s.isEmpty()) {
       return defaultValue;
     }
 
     if ("true".equalsIgnoreCase(s)) {
       return true;
+    } else if ("t".equalsIgnoreCase(s)) {
+      return true;
     } else if ("false".equalsIgnoreCase(s)) {
       return false;
+    } else if ("f".equalsIgnoreCase(s)) {
+      return false;
     } else {
       return defaultValue;
     }
diff --git a/ratis-common/src/main/java/org/apache/ratis/util/TimeDuration.java 
b/ratis-common/src/main/java/org/apache/ratis/util/TimeDuration.java
index 4d1fe4ef0..2abdfdfac 100644
--- a/ratis-common/src/main/java/org/apache/ratis/util/TimeDuration.java
+++ b/ratis-common/src/main/java/org/apache/ratis/util/TimeDuration.java
@@ -137,10 +137,10 @@ public final class TimeDuration implements 
Comparable<TimeDuration> {
   }
 
   /**
-   * Parse the given time duration string.
-   * If no unit is specified, use the default unit.
-   * This method support underscores in Numeric Literals as in Java 8.
+   * Parse the given string.
+   * The string is first be trimmed and underscore removed.
    *
+   * @param defaultUnit Use it if no unit is specified.
    * @return a {@link TimeDuration} in the target unit.
    */
   public static TimeDuration valueOf(String timeString, TimeUnit defaultUnit) {
@@ -158,6 +158,7 @@ public final class TimeDuration implements 
Comparable<TimeDuration> {
         }
       }
     }
+    Objects.requireNonNull(defaultUnit, "defaultUnit == null");
     return valueOf(Long.parseLong(lower), defaultUnit);
   }
 
diff --git 
a/ratis-common/src/main/java/org/apache/ratis/util/TraditionalBinaryPrefix.java 
b/ratis-common/src/main/java/org/apache/ratis/util/TraditionalBinaryPrefix.java
index b1902cfad..a6c9f0687 100644
--- 
a/ratis-common/src/main/java/org/apache/ratis/util/TraditionalBinaryPrefix.java
+++ 
b/ratis-common/src/main/java/org/apache/ratis/util/TraditionalBinaryPrefix.java
@@ -78,18 +78,18 @@ public enum TraditionalBinaryPrefix {
 
   /**
    * Convert a string to long.
-   * The input string is first be trimmed
+   * The input string is first be trimmed and underscore removed,
    * and then it is parsed with traditional binary prefix.
-   *
+   * <p>
    * For example,
-   * "-1230k" will be converted to -1230 * 1024 = -1259520;
+   * "-1_230k" will be converted to -1230 * 1024 = -1259520;
    * "891g" will be converted to 891 * 1024^3 = 956703965184;
    *
    * @param s input string
    * @return a long value represented by the input string.
    */
   public static long string2long(String s) {
-    s = s.trim();
+    s = s.trim().replace("_", "");
     final int lastpos = s.length() - 1;
     final char lastchar = s.charAt(lastpos);
     if (Character.isDigit(lastchar)) {
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/conf/TestRaftProperties.java 
b/ratis-test/src/test/java/org/apache/ratis/conf/TestRaftProperties.java
new file mode 100644
index 000000000..c65d00f43
--- /dev/null
+++ b/ratis-test/src/test/java/org/apache/ratis/conf/TestRaftProperties.java
@@ -0,0 +1,100 @@
+/*
+ * 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.ratis.conf;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestRaftProperties {
+  enum Type {APPEND_ENTRIES}
+
+  static class Request_Vote {
+  }
+
+  static final String KEY = "key";
+
+  static void setUnderscoreValue(RaftProperties p, String valueWithUnderscore) 
{
+    Assert.assertTrue(valueWithUnderscore.contains("_"));
+    p.set(KEY, valueWithUnderscore);
+  }
+
+  static void setNonUnderscoreValue(RaftProperties p, String 
valueWithoutUnderscore) {
+    Assert.assertFalse(valueWithoutUnderscore.contains("_"));
+    p.set(KEY, valueWithoutUnderscore);
+  }
+
+  @Test(timeout = 1000)
+  public void testUnderscore() {
+    final RaftProperties p = new RaftProperties();
+
+    { // boolean
+      Assert.assertNull(p.getBoolean(KEY, null));
+      setNonUnderscoreValue(p, "true");
+      Assert.assertTrue(p.getBoolean(KEY, null));
+      setNonUnderscoreValue(p, "false");
+      Assert.assertFalse(p.getBoolean(KEY, null));
+      setUnderscoreValue(p, "fa_lse");
+      Assert.assertNull(p.getBoolean(KEY, null));
+      p.unset(KEY);
+    }
+
+    { //int
+      final Integer expected = 1000000;
+      Assert.assertNull(p.getInt(KEY, null));
+      setUnderscoreValue(p, "1_000_000");
+      Assert.assertEquals(expected, p.getInt(KEY, null));
+      setNonUnderscoreValue(p, "1000000");
+      Assert.assertEquals(expected, p.getInt(KEY, null));
+      p.unset(KEY);
+    }
+
+    { // long
+      final Long expected = 1_000_000_000_000L;
+      Assert.assertNull(p.getLong(KEY, null));
+      setUnderscoreValue(p, "1_000_000_000_000");
+      Assert.assertEquals(expected, p.getLong(KEY, null));
+      setNonUnderscoreValue(p, "1000000000000");
+      Assert.assertEquals(expected, p.getLong(KEY, null));
+      p.unset(KEY);
+    }
+
+    { // File
+      final String expected = "1_000_000";
+      Assert.assertNull(p.getFile(KEY, null));
+      setUnderscoreValue(p, expected);
+      Assert.assertEquals(expected, p.getFile(KEY, null).getName());
+      p.unset(KEY);
+    }
+
+    { // class
+      final Type expected = Type.APPEND_ENTRIES;
+      Assert.assertNull(p.getEnum(KEY, Type.class, null));
+      setUnderscoreValue(p, expected.name());
+      Assert.assertEquals(expected, p.getEnum(KEY, Type.class, null));
+      p.unset(KEY);
+    }
+
+    { // enum
+      final Class<Request_Vote> expected = Request_Vote.class;
+      Assert.assertNull(p.getClass(KEY, null));
+      setUnderscoreValue(p, expected.getName());
+      Assert.assertEquals(expected, p.getClass(KEY, null));
+      p.unset(KEY);
+    }
+  }
+}
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/util/TestTraditionalBinaryPrefix.java
 
b/ratis-test/src/test/java/org/apache/ratis/util/TestTraditionalBinaryPrefix.java
index 26a62dae0..8b6b7a378 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/util/TestTraditionalBinaryPrefix.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/util/TestTraditionalBinaryPrefix.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -26,7 +26,7 @@ import static org.junit.Assert.fail;
 
 public class TestTraditionalBinaryPrefix {
   @Test(timeout = 1000)
-  public void testTraditionalBinaryPrefix() throws Exception {
+  public void testTraditionalBinaryPrefix() {
     //test string2long(..)
     String[] symbol = {"k", "m", "g", "t", "p", "e"};
     long m = 1024;
@@ -39,8 +39,8 @@ public class TestTraditionalBinaryPrefix {
     assertEquals(0L, string2long("0"));
     assertEquals(1024L, string2long("1k"));
     assertEquals(-1024L, string2long("-1k"));
-    assertEquals(1259520L, string2long("1230K"));
-    assertEquals(-1259520L, string2long("-1230K"));
+    assertEquals(1259520L, string2long("1_230K"));
+    assertEquals(-1259520L, string2long("-1_230K"));
     assertEquals(104857600L, string2long("100m"));
     assertEquals(-104857600L, string2long("-100M"));
     assertEquals(956703965184L, string2long("891g"));
@@ -142,4 +142,10 @@ public class TestTraditionalBinaryPrefix {
   private static String byteDescription(long len) {
     return long2String(len, "B", 2);
   }
+
+  @Test(timeout = 1000)
+  public void testUnderscore() {
+    final SizeInBytes value = SizeInBytes.valueOf("1_000_000_000_000_000");
+    assertEquals(1_000_000_000_000_000L, value.getSize());
+  }
 }

Reply via email to