From 6bc32ce379ff6e085339b27a33eed03b46dc4a70 Mon Sep 17 00:00:00 2001 From: ZhouXY108 Date: Thu, 26 Dec 2024 11:42:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=20EnumTools=20=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ProgressOfTesting.txt | 6 +- .../plusone/commons/util/EnumTools.java | 54 ++++- .../plusone/commons/util/EnumToolsTests.java | 209 ++++++++++++++++++ 3 files changed, 260 insertions(+), 9 deletions(-) create mode 100644 src/test/java/xyz/zhouxy/plusone/commons/util/EnumToolsTests.java diff --git a/ProgressOfTesting.txt b/ProgressOfTesting.txt index 96b03ac..2f81ee2 100644 --- a/ProgressOfTesting.txt +++ b/ProgressOfTesting.txt @@ -1,6 +1,6 @@ [ ] 未开始测试 - 15 (21.43%) -[-] 测试未完成 - 12 (17.14%) -[Y] 测试完成 - 22 (31.43%) +[-] 测试未完成 - 11 (15.71%) +[Y] 测试完成 - 23 (32.86%) [x] 无需测试 - 21 (30.00%) xyz.zhouxy.plusone.commons @@ -89,7 +89,7 @@ xyz.zhouxy.plusone.commons ConcurrentHashMapTools.java [-] DateTimeTools.java [-] Enumeration.java [Y] - EnumTools.java [-] + EnumTools.java [Y] IdGenerator.java [ ] IdWorker.java [ ] Numbers.java [Y] diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/EnumTools.java b/src/main/java/xyz/zhouxy/plusone/commons/util/EnumTools.java index 37b53a1..ba1f76a 100644 --- a/src/main/java/xyz/zhouxy/plusone/commons/util/EnumTools.java +++ b/src/main/java/xyz/zhouxy/plusone/commons/util/EnumTools.java @@ -18,6 +18,7 @@ package xyz.zhouxy.plusone.commons.util; import java.util.function.Supplier; +import javax.annotation.Nonnull; import javax.annotation.Nullable; /** @@ -41,14 +42,28 @@ public final class EnumTools { * @deprecated 不推荐使用枚举的 ordinal。 */ @Deprecated - public static > E valueOf(Class enumType, int ordinal) { // NOSONAR 该方法弃用,但不删掉 - AssertTools.checkNotNull(enumType, "Enum type must not be null."); + private static > E valueOfInternal(@Nonnull Class enumType, int ordinal) { // NOSONAR 该方法弃用,但不删掉 E[] values = enumType.getEnumConstants(); AssertTools.checkCondition((ordinal >= 0 && ordinal < values.length), () -> new EnumConstantNotPresentException(enumType, Integer.toString(ordinal))); return values[ordinal]; } + /** + * 通过 ordinal 获取枚举实例 + * + * @param 枚举的类型 + * @param enumType 枚举的类型信息 + * @param ordinal 序号 + * @return 枚举对象 + * @deprecated 不推荐使用枚举的 ordinal。 + */ + @Deprecated + public static > E valueOf(Class enumType, int ordinal) { // NOSONAR 该方法弃用,但不删掉 + AssertTools.checkNotNull(enumType, "Enum type must not be null."); + return valueOfInternal(enumType, ordinal); + } + /** * 通过 ordinal 获取枚举实例 * @@ -62,7 +77,8 @@ public final class EnumTools { @Deprecated public static > E valueOf(Class enumType, // NOSONAR 该方法弃用,但不删掉 @Nullable Integer ordinal, E defaultValue) { - return null == ordinal ? defaultValue : valueOf(enumType, ordinal); + AssertTools.checkNotNull(enumType); + return null == ordinal ? defaultValue : valueOfInternal(enumType, ordinal); } /** @@ -80,7 +96,9 @@ public final class EnumTools { Class enumType, @Nullable Integer ordinal, Supplier defaultValue) { - return null == ordinal ? defaultValue.get() : valueOf(enumType, ordinal); + AssertTools.checkNotNull(enumType); + AssertTools.checkNotNull(defaultValue); + return null == ordinal ? defaultValue.get() : valueOfInternal(enumType, ordinal); } /** @@ -134,7 +152,7 @@ public final class EnumTools { */ @Nullable public static > Integer checkOrdinalNullable(Class enumType, @Nullable Integer ordinal) { - return checkOrdinalOrDefault(enumType, ordinal, null); + return checkOrdinalOrDefault(enumType, ordinal, (Integer) null); } /** @@ -163,6 +181,30 @@ public final class EnumTools { Class enumType, @Nullable Integer ordinal, @Nullable Integer defaultValue) { - return ordinal != null ? checkOrdinal(enumType, ordinal) : defaultValue; + AssertTools.checkNotNull(enumType); + return checkOrdinalOrGetInternal(enumType, ordinal, () -> checkOrdinalOrDefaultInternal(enumType, defaultValue, null)); + } + + /** + * 仅对 {@code ordinal} 进行判断,不对 {@code defaultValue} 进行判断 + */ + @Nullable + private static > Integer checkOrdinalOrDefaultInternal( + @Nonnull Class enumType, + @Nullable Integer ordinal, + @Nullable Integer defaultValue) { + return ordinal != null + ? checkOrdinal(enumType, ordinal) + : defaultValue; + } + + @Nullable + private static > Integer checkOrdinalOrGetInternal( + @Nonnull Class enumType, + @Nullable Integer ordinal, + @Nonnull Supplier defaultValueSupplier) { + return ordinal != null + ? checkOrdinal(enumType, ordinal) + : defaultValueSupplier.get(); } } diff --git a/src/test/java/xyz/zhouxy/plusone/commons/util/EnumToolsTests.java b/src/test/java/xyz/zhouxy/plusone/commons/util/EnumToolsTests.java new file mode 100644 index 0000000..a4c83fb --- /dev/null +++ b/src/test/java/xyz/zhouxy/plusone/commons/util/EnumToolsTests.java @@ -0,0 +1,209 @@ +package xyz.zhouxy.plusone.commons.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@SuppressWarnings("deprecation") +public +class EnumToolsTests { + + private enum MyEnum { + VALUE_0, + VALUE_1, + VALUE_2, + VALUE_3, + } + + @ParameterizedTest + @ValueSource(ints = { 0, 1, 2, 3 }) + void testCheckOrdinal_success(int ordinal) { + assertEquals(ordinal, EnumTools.checkOrdinal(MyEnum.class, ordinal)); + } + + @ParameterizedTest + @ValueSource(ints = { -1, 4 }) + void testCheckOrdinal_EnumConstantNotPresentException(int ordinal) { + assertThrows(EnumConstantNotPresentException.class, + () -> EnumTools.checkOrdinal(MyEnum.class, ordinal)); + } + + @Test + void testCheckOrdinal_null() { + assertThrows(NullPointerException.class, + () -> EnumTools.checkOrdinal(MyEnum.class, null)); + assertThrows(NullPointerException.class, + () -> EnumTools.checkOrdinal(null, 0)); + assertThrows(NullPointerException.class, + () -> EnumTools.checkOrdinal(null, null)); + } + + @ParameterizedTest + @ValueSource(ints = { 0, 1, 2, 3 }) + void testCheckOrdinalNullable_success(int ordinal) { + assertEquals(ordinal, EnumTools.checkOrdinalNullable(MyEnum.class, ordinal)); + } + + @ParameterizedTest + @ValueSource(ints = { -1, 4 }) + void testCheckOrdinalNullable_EnumConstantNotPresentException(int ordinal) { + assertThrows(EnumConstantNotPresentException.class, () -> { + EnumTools.checkOrdinalNullable(MyEnum.class, ordinal); + }); + } + + @Test + void testCheckOrdinalNullable_null() { + assertNull(EnumTools.checkOrdinalNullable(MyEnum.class, null)); + + assertThrows(NullPointerException.class, () -> { + EnumTools.checkOrdinalNullable(null, 0); + }); + + assertThrows(NullPointerException.class, () -> { + EnumTools.checkOrdinalNullable(null, null); + }); + } + + @ParameterizedTest + @ValueSource(ints = { 0, 1, 2, 3 }) + void testCheckOrdinalOrDefault_0To3(int ordinal) { + assertEquals(ordinal, EnumTools.checkOrdinalOrDefault(MyEnum.class, ordinal)); + } + + @ParameterizedTest + @ValueSource(ints = { -1, 4 }) + void testCheckOrdinalOrDefault_EnumConstantNotPresentException(int ordinal) { + assertThrows(EnumConstantNotPresentException.class, () -> { + EnumTools.checkOrdinalOrDefault(MyEnum.class, ordinal); + }); + assertThrows(EnumConstantNotPresentException.class, () -> { + EnumTools.checkOrdinalOrDefault(MyEnum.class, null, ordinal); + }); + } + + @Test + void testCheckOrdinalOrDefault_null() { + assertEquals(0, EnumTools.checkOrdinalOrDefault(MyEnum.class, null)); + assertEquals(1, EnumTools.checkOrdinalOrDefault(MyEnum.class, null, 1)); + assertNull(EnumTools.checkOrdinalOrDefault(MyEnum.class, null, null)); + } + + @Test + void testGetValueNullable_0To3() { + assertSame(MyEnum.VALUE_0, EnumTools.getValueNullable(MyEnum.class, 0)); + assertSame(MyEnum.VALUE_1, EnumTools.getValueNullable(MyEnum.class, 1)); + assertSame(MyEnum.VALUE_2, EnumTools.getValueNullable(MyEnum.class, 2)); + assertSame(MyEnum.VALUE_3, EnumTools.getValueNullable(MyEnum.class, 3)); + } + + @ParameterizedTest + @ValueSource(ints = { -1, 4 }) + void testGetValueNullable_EnumConstantNotPresentException(int ordinal) { + assertThrows(EnumConstantNotPresentException.class, () -> { + EnumTools.getValueNullable(MyEnum.class, ordinal); + }); + } + + @Test + void testGetValueNullable_null() { + assertNull(EnumTools.getValueNullable(MyEnum.class, null)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueNullable(null, 0)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueNullable(null, null)); + } + + @Test + void testGetValueOrDefault_0To3() { + assertSame(MyEnum.VALUE_0, EnumTools.getValueOrDefault(MyEnum.class, 0)); + assertSame(MyEnum.VALUE_1, EnumTools.getValueOrDefault(MyEnum.class, 1)); + assertSame(MyEnum.VALUE_2, EnumTools.getValueOrDefault(MyEnum.class, 2)); + assertSame(MyEnum.VALUE_3, EnumTools.getValueOrDefault(MyEnum.class, 3)); + + assertSame(MyEnum.VALUE_0, EnumTools.getValueOrDefault(MyEnum.class, 0, () -> MyEnum.VALUE_1)); + assertSame(MyEnum.VALUE_1, EnumTools.getValueOrDefault(MyEnum.class, 1, () -> MyEnum.VALUE_0)); + assertSame(MyEnum.VALUE_2, EnumTools.getValueOrDefault(MyEnum.class, 2, () -> MyEnum.VALUE_0)); + assertSame(MyEnum.VALUE_3, EnumTools.getValueOrDefault(MyEnum.class, 3, () -> MyEnum.VALUE_0)); + + assertSame(MyEnum.VALUE_0, EnumTools.getValueOrDefault(MyEnum.class, 0, () -> null)); + assertSame(MyEnum.VALUE_1, EnumTools.getValueOrDefault(MyEnum.class, 1, () -> null)); + assertSame(MyEnum.VALUE_2, EnumTools.getValueOrDefault(MyEnum.class, 2, () -> null)); + assertSame(MyEnum.VALUE_3, EnumTools.getValueOrDefault(MyEnum.class, 3, () -> null)); + } + + @ParameterizedTest + @ValueSource(ints = { -1, 4 }) + void testGetValueOrDefault_EnumConstantNotPresentException(int ordinal) { + assertThrows(EnumConstantNotPresentException.class, () -> { + EnumTools.getValueOrDefault(MyEnum.class, ordinal); + }); + assertThrows(EnumConstantNotPresentException.class, () -> { + EnumTools.getValueOrDefault(MyEnum.class, ordinal, () -> MyEnum.VALUE_0); + }); + } + + @Test + void testGetValueOrDefault_null() { + assertSame(MyEnum.VALUE_0, EnumTools.getValueOrDefault(MyEnum.class, null)); + assertSame(MyEnum.VALUE_0, EnumTools.getValueOrDefault(MyEnum.class, null, () -> MyEnum.VALUE_0)); + assertNull(EnumTools.getValueOrDefault(MyEnum.class, null, () -> null)); + + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, null)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, -1)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, 0)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, 4)); + + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, null, () -> MyEnum.VALUE_0)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, -1, () -> MyEnum.VALUE_1)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, 0, () -> MyEnum.VALUE_1)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, 4, () -> MyEnum.VALUE_0)); + + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(MyEnum.class, null, null)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(MyEnum.class, -1, null)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(MyEnum.class, 0, null)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(MyEnum.class, 4, null)); + + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, null, null)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, -1, null)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, 0, null)); + assertThrows(NullPointerException.class, () -> EnumTools.getValueOrDefault(null, 4, null)); + + } + + @Test + void testValueOf_0To3() { + assertSame(MyEnum.VALUE_0, EnumTools.valueOf(MyEnum.class, 0)); + assertSame(MyEnum.VALUE_1, EnumTools.valueOf(MyEnum.class, 1)); + assertSame(MyEnum.VALUE_2, EnumTools.valueOf(MyEnum.class, 2)); + assertSame(MyEnum.VALUE_3, EnumTools.valueOf(MyEnum.class, 3)); + + assertSame(MyEnum.VALUE_0, EnumTools.valueOf(MyEnum.class, 0, MyEnum.VALUE_1)); + assertSame(MyEnum.VALUE_1, EnumTools.valueOf(MyEnum.class, 1, MyEnum.VALUE_0)); + assertSame(MyEnum.VALUE_2, EnumTools.valueOf(MyEnum.class, 2, MyEnum.VALUE_0)); + assertSame(MyEnum.VALUE_3, EnumTools.valueOf(MyEnum.class, 3, MyEnum.VALUE_0)); + + assertSame(MyEnum.VALUE_0, EnumTools.valueOf(MyEnum.class, 0, null)); + assertSame(MyEnum.VALUE_1, EnumTools.valueOf(MyEnum.class, 1, null)); + assertSame(MyEnum.VALUE_2, EnumTools.valueOf(MyEnum.class, 2, null)); + assertSame(MyEnum.VALUE_3, EnumTools.valueOf(MyEnum.class, 3, null)); + } + + @ParameterizedTest + @ValueSource(ints = { -1, 4 }) + void testValueOf_EnumConstantNotPresentException(int ordinal) { + assertThrows(EnumConstantNotPresentException.class, () -> EnumTools.valueOf(MyEnum.class, ordinal)); + assertThrows(EnumConstantNotPresentException.class, () -> EnumTools.valueOf(MyEnum.class, ordinal, MyEnum.VALUE_0)); + assertThrows(EnumConstantNotPresentException.class, () -> EnumTools.valueOf(MyEnum.class, ordinal, null)); + } + + @Test + void testValueOf_null() { + assertThrows(NullPointerException.class, () -> EnumTools.valueOf(null, 0)); + assertSame(MyEnum.VALUE_0, EnumTools.valueOf(MyEnum.class, null, MyEnum.VALUE_0)); + assertNull(EnumTools.valueOf(MyEnum.class, null, null)); + } +}