Peter Penzov
Peter Penzov

Reputation: 1588

Compare String in ENUM

I want to implement storing of enabled or disabled features into database row. When some String value is received from them the network I would like to compare it into ENUM.

ENUM:

public enum TerminalConfigurationFeatureBitString {
    Authorize("authorize", 0), // index 0 in bit string
    Authorize3d("authorize3d", 1), // index 1 in bit String
    Sale("sale", 2), // index 2 in bit String
    Sale3d("sale3d", 3), // index 3 in bit String
}

Map<TerminalConfigurationFeatureBitString, Boolean> featureMaps =
    config.initFromDatabaseValue(optsFromDatabase);

featureMaps.get(transaction.transactionType);

The best way is to use featureMaps.get(TerminalConfigurationFeatureBitString.Sale);

But I don't know the incoming string what would be.

Now I get warning Unlikely argument type String for get(Object) on a Map<TerminalConfigurationFeatureBitString,Boolean>

Is there any other way to make a query into the ENUM without knowing the key?

Upvotes: 0

Views: 586

Answers (3)

Michał Ziober
Michał Ziober

Reputation: 38655

You can extend your enum with extra static method which will try to convert given String on enum item:

enum TerminalConfigurationFeatureBitString {
    Authorize("authorize", 0), // index 0 in bit string
    Authorize3d("authorize3d", 1), // index 1 in bit String
    Sale("sale", 2), // index 2 in bit String
    Sale3d("sale3d", 3); // index 3 in bit String

    private final String value;
    private final int index;

    TerminalConfigurationFeatureBitString(String value, int index) {
        this.value = value;
        this.index = index;
    }

    public String getValue() {
        return value;
    }

    public int getIndex() {
        return index;
    }

    public static Optional<TerminalConfigurationFeatureBitString> fromValue(String value) {
        for (TerminalConfigurationFeatureBitString item : values()) {
            if (item.value.equals(value)) {
                return Optional.of(item);
            }
        }

        return Optional.empty();
    }
}

In case option is not found, return Optional.empty(). If feature is not present it means String representation does not represent any feature. Usage:

public void test() {
    EnumMap<TerminalConfigurationFeatureBitString, Boolean> featureMaps = new EnumMap<>(
        TerminalConfigurationFeatureBitString.class);

    Optional<TerminalConfigurationFeatureBitString> feature = TerminalConfigurationFeatureBitString.fromValue("authorize");
    if (!feature.isPresent()) {
        System.out.println("Feature is not foudn!");
    } else {
        Boolean authorize = featureMaps.get(feature.get());
        if (authorize != null && authorize) {
            System.out.println("Feature is enabled!");
        } else {
            System.out.println("Feature is disabled!");
        }
    }
}

Upvotes: 2

Michael
Michael

Reputation: 44150

In cases like these, I often find myself adding a static method getByX which does a lookup based upon a property of the enum:

public enum BitString {
    //...

    public static Optional<BitString> getByTransactionType(String transactionType)
    {
        return Arrays.stream(values())
            .filter(x -> x.transactionType.equals(transactionType))
            .findFirst();
    }
}

Usage:

enum TransactionStatus
{
    ENABLED, NOT_ENABLED, NOT_SUPPORTED
}

TransactionStatus status = BitString.getBygetByTransactionType(transaction.transactionType)
    .map(bitString -> featureMaps.get(bitString))
    .map(enabled -> enabled ? TransactionStatus.ENABLED : TransactionStatus.NOT_ENABLED)
    .orElse(TransactionStatus.NOT_SUPPORTED);

Upvotes: 2

Lino
Lino

Reputation: 19926

Similar to @Michael's answer, you can just generate a static lookup map inside your enum which maps an enums transaction type to the actual enum:

private static final Map<String, TerminalConfigurationFeatureBitString> TRANSACTION_TYPE_TO_ENUM = 
   Arrays.stream(values()).collect(Collectors.toMap(
       TerminalConfigurationFeatureBitString::getTransactionType, 
       Function.identity()
   );

And then have a lookup method, also inside the enum:

public static TerminalConfigurationFeatureBitString getByTransactionType(String transactionType) {
    TerminalConfigurationFeatureBitString bitString = TRANSACTION_TYPE_TO_ENUM.get(transactionType);
    if(bitString == null) throw new NoSuchElementException(transactionType);
    return bitString;
}

This in a way more performant than the mentioned answer, because the Map is created the first time the enum is loaded (So when it is the first time referenced). And thus the iteration happens only once. Also Maps have a rather fast lookup time so you could say that getting an enum this way works O(1) (when ignoring the initial computation time of O(n))

Upvotes: 2

Related Questions