Adyen / Adyen/adyen-java-api-library
Approach for centralizing unknown enum handling
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 148
- Forks
- 158
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 10
Description
Approach for centralizing unknown enum handling
The handling of enums can be improved by centralizing the fromValue logic.
1. New EnumUtils utility (hand-written, non-generated)
src/main/java/com/adyen/util/EnumUtils.java
public final class EnumUtils {
private static final Logger LOG = Logger.getLogger(EnumUtils.class.getName());
private EnumUtils() {}
public static <T extends Enum<T>> T fromValue(
Class<T> enumClass, String value, Function<T, String> getValue) {
for (T b : enumClass.getEnumConstants()) {
if (getValue.apply(b).equals(value)) return b;
}
LOG.warning(String.format("%s: unexpected enum value '%s' - Supported values are %s",
enumClass.getSimpleName(), value, Arrays.toString(enumClass.getEnumConstants())));
return null;
}
}
2. Template changes (modelEnum.mustache + modelInnerEnum.mustache)
Gated behind a useEnumUtils flag — same pattern as useReflectionEqualsHashCode, handleNullableProperties, and useNullForUnknownEnumValue already in the templates.
Imports — drop Logger when flag is on:
{{^useEnumUtils}}
import java.util.logging.Logger;
{{/useEnumUtils}}
Enum body — drop the LOG field when flag is on:
{{^useEnumUtils}}
private static final Logger LOG = Logger.getLogger({{{datatypeWithEnum}}}.class.getName());
{{/useEnumUtils}}
fromValue — delegate to the utility:
public static {{{datatypeWithEnum}}} fromValue({{{dataType}}} value) {
{{#useEnumUtils}}
return com.adyen.util.EnumUtils.fromValue(
{{{datatypeWithEnum}}}.class, value, {{{datatypeWithEnum}}}::getValue);
{{/useEnumUtils}}
{{^useEnumUtils}}
for ({{{datatypeWithEnum}}} b : {{{datatypeWithEnum}}}.values()) {
if (b.value.equals(value)) return b;
}
LOG.warning(String.format(
"{{{datatypeWithEnum}}}: unexpected enum value '%s' - Supported values are %s",
value, Arrays.toString({{{datatypeWithEnum}}}.values())));
return null;
{{/useEnumUtils}}
}
3. Scope — TAPI-only vs global
Both options are feasible:
- TAPI-only: Set
useEnumUtils: trueonly in the TAPI config inadyen-sdk-automation. Safe and scoped to this PR, but leaves an inconsistency: TAPI enums useEnumUtils, all other services keep the per-enumLogger. - Global (recommended): Set the flag across all service configs in
adyen-sdk-automation, re-generate all services. EliminatesLoggerfrom every generated enum consistently — which seems to be the intent of the original suggestion.
TAPI-only is a one-liner per config file in the automation repo and easy to do now; globally applying it later is equally straightforward since it's just a flag flip.
Also: the String.format() suggestion applies to the fallback (non-useEnumUtils) path in the template as well — worth fixing there too regardless of which direction we go.
Originally posted by @thomasc-adyen in https://github.com/Adyen/adyen-java-api-library/issues/1906#issuecomment-4238296755
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src/main/java/com/adyen/util/EnumUtils.java, modelEnum.mustache, and modelInnerEnum.mustache, then inspect the existing flag patterns and service configuration files in adyen-sdk-automation. Determine whether the flag is applied to TAPI only or globally; done means the selected generated enums use the centralized handling consistently and the fallback template path includes the noted String.format change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, backend
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100