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());
+ }
}