Skip to content

Commit

Permalink
Add EnumUtils.getFirstEnum(Class<E>, int, ToIntFunction<E>, E)
Browse files Browse the repository at this point in the history
  • Loading branch information
garydgregory committed Feb 22, 2025
1 parent 03e181b commit b2e66fe
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ The <action> type attribute can be add,update,fix,remove.
<action type="add" dev="ggregory" due-to="Gary Gregory">Add IterableStringTokenizer.</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add FailableIntToFloatFunction.</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add Validate.isTrue(boolean, Supplier&lt;String&gt;).</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add EnumUtils.getFirstEnum(Class&lt;E&gt;, int, ToIntFunction&lt;E&gt;, E).</action>
<!-- UPDATE -->
<action type="update" dev="ggregory" due-to="Gary Gregory, Dependabot">Bump org.apache.commons:commons-parent from 73 to 81 #1267, #1277, #1283, #1288, #1302.</action>
<action type="update" dev="ggregory" due-to="Gary Gregory, Dependabot">[site] Bump org.codehaus.mojo:taglist-maven-plugin from 3.1.0 to 3.2.1 #1300.</action>
Expand Down
39 changes: 33 additions & 6 deletions src/main/java/org/apache/commons/lang3/EnumUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -69,7 +70,6 @@ private static <E extends Enum<E>> Class<E> checkBitVectorable(final Class<E> en
final E[] constants = asEnum(enumClass).getEnumConstants();
Validate.isTrue(constants.length <= Long.SIZE, CANNOT_STORE_S_S_VALUES_IN_S_BITS,
Integer.valueOf(constants.length), enumClass.getSimpleName(), Integer.valueOf(Long.SIZE));

return enumClass;
}

Expand Down Expand Up @@ -321,6 +321,29 @@ public static <E extends Enum<E>> E getEnumSystemProperty(final Class<E> enumCla
: getEnum(enumClass, System.getProperty(propName), defaultEnum);
}

/**
* Gets the enum for the class and value, returning {@code defaultEnum} if not found.
*
* <p>
* This method differs from {@link Enum#valueOf} in that it does not throw an exception for an invalid enum name and performs case insensitive matching of
* the name.
* </p>
*
* @param <E> the type of the enumeration.
* @param enumClass the class of the enum to query, not null.
* @param value the enum name, null returns default enum.
* @param toIntFunction the function that gets an int for an enum for comparison to {@code value}.
* @param defaultEnum the default enum.
* @return an enum, default enum if not found.
* @since 3.18.0
*/
public static <E extends Enum<E>> E getFirstEnum(final Class<E> enumClass, final int value, final ToIntFunction<E> toIntFunction, final E defaultEnum) {
if (isEnum(enumClass)) {
return defaultEnum;
}
return Stream.of(enumClass.getEnumConstants()).filter(e -> value == toIntFunction.applyAsInt(e)).findFirst().orElse(defaultEnum);
}

/**
* Gets the enum for the class, returning {@code defaultEnum} if not found.
*
Expand All @@ -332,15 +355,19 @@ public static <E extends Enum<E>> E getEnumSystemProperty(final Class<E> enumCla
* @param enumName the enum name, null returns default enum
* @param stringFunction the function that gets the string for an enum for comparison to {@code enumName}.
* @param defaultEnum the default enum
* @return the enum, default enum if not found
* @return an enum, default enum if not found
* @since 3.13.0
*/
public static <E extends Enum<E>> E getFirstEnumIgnoreCase(final Class<E> enumClass, final String enumName, final Function<E, String> stringFunction,
final E defaultEnum) {
if (enumName == null || !enumClass.isEnum()) {
return defaultEnum;
final E defaultEnum) {
if (enumName == null || !enumClass.isEnum()) {
return defaultEnum;
}
return Stream.of(enumClass.getEnumConstants()).filter(e -> enumName.equalsIgnoreCase(stringFunction.apply(e))).findFirst().orElse(defaultEnum);
}
return Stream.of(enumClass.getEnumConstants()).filter(e -> enumName.equalsIgnoreCase(stringFunction.apply(e))).findFirst().orElse(defaultEnum);

private static <E extends Enum<E>> boolean isEnum(final Class<E> enumClass) {
return enumClass != null && !enumClass.isEnum();
}

/**
Expand Down
38 changes: 30 additions & 8 deletions src/test/java/org/apache/commons/lang3/EnumUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,11 @@
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.ToIntFunction;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

enum Enum64 {
A00, A01, A02, A03, A04, A05, A06, A07, A08, A09, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22,
A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45,
A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63
}

/**
*/
public class EnumUtilsTest extends AbstractLangTest {
Expand Down Expand Up @@ -438,6 +433,21 @@ public void testGetFirstEnumIgnoreCase_defaultEnum() {
assertNull(EnumUtils.getFirstEnumIgnoreCase(Traffic2.class, "PURPLE", f, null));
}

@Test
public void testGetFirstEnumToIntFunction() {
final ToIntFunction<Traffic2> f = Traffic2::getValue;
assertEquals(Traffic2.RED, EnumUtils.getFirstEnum(Traffic2.class, 1, f, Traffic2.AMBER));
assertEquals(Traffic2.AMBER, EnumUtils.getFirstEnum(Traffic2.class, 2, f, Traffic2.GREEN));
assertEquals(Traffic2.GREEN, EnumUtils.getFirstEnum(Traffic2.class, 3, f, Traffic2.RED));
assertEquals(Traffic2.AMBER, EnumUtils.getFirstEnum(Traffic2.class, 4, f, Traffic2.AMBER));
assertEquals(Traffic2.GREEN, EnumUtils.getFirstEnum(Traffic2.class, 5, f, Traffic2.GREEN));
assertEquals(Traffic2.RED, EnumUtils.getFirstEnum(Traffic2.class, 6, f, Traffic2.RED));
assertEquals(Traffic2.AMBER, EnumUtils.getFirstEnum(Traffic2.class, 0, f, Traffic2.AMBER));
assertEquals(Traffic2.GREEN, EnumUtils.getFirstEnum(Traffic2.class, -1, f, Traffic2.GREEN));
assertEquals(Traffic2.RED, EnumUtils.getFirstEnum(Traffic2.class, 0, f, Traffic2.RED));
assertNull(EnumUtils.getFirstEnum(Traffic2.class, 7, f, null));
}

@Test
public void testIsValidEnum() {
assertTrue(EnumUtils.isValidEnum(Traffic.class, "RED"));
Expand Down Expand Up @@ -591,6 +601,12 @@ public void testProcessBitVectors_nullClass() {

}

enum Enum64 {
A00, A01, A02, A03, A04, A05, A06, A07, A08, A09, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22,
A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45,
A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63
}

enum Month {
JAN(1), FEB(2), MAR(3), APR(4), MAY(5), JUN(6), JUL(7), AUG(8), SEP(9), OCT(10), NOV(11), DEC(12);

Expand All @@ -617,15 +633,21 @@ enum Traffic {

enum Traffic2 {

RED("***Red***"), AMBER("**Amber**"), GREEN("*green*");
RED("***Red***", 1), AMBER("**Amber**", 2), GREEN("*green*", 3);

final String label;
final int value;

Traffic2(final String label) {
Traffic2(final String label, final int value) {
this.label = label;
this.value = value;
}

public String getLabel() {
return label;
}

public int getValue() {
return value;
}
}

0 comments on commit b2e66fe

Please sign in to comment.