0

I have an enum like below. Until recently, all variables were single-valued. However, now TYPE4 can have one of three acceptable values. I was hoping to simply modify this enum to accommodate for TYPE4, but thinking perhaps having only one type that is multi-valued means I need to use an object for mapping rather than an enum. I would be grateful for any insights. Thank you.

public enum Record {
    TYPE1("TYPE1"),
    TYPE2("TYPE2"),
    TYPE3("TYPE3"),
    TYPE4_MULTI(TYPE_A or TYPE_B or TYPE_C); 

    private final String value;
    public static final Map<Record, String> enumMap = new EnumMap<Record, String>(
        Record.class);

    static {
        for (Record e : Record.values())
            enumMap.put(e, e.getValue());
    }

    Record(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

Operationally, I use this enum in a factory class to determine which of 4 types of subclasses I should instantiate. I do this by have each of the subclasses know its own type like this:

@Override
public String getType() {
    return Record.TYPE1.getValue();
}

,and then the factory class pre-builds a set of the subclasses like this:

@Component
public class RecordProcessorFactory {

    @Autowired
    public RecordProcessorFactory(List<RecordProcessor> processors) {
        for (RecordProcessor recordProcessor : processors) {
            processorCache.put(recordProcessor.getType(), recordProcessor);
        }
    }

    private static final Map<String, RecordProcessor> processorCache = new HashMap<String, RecordProcessor>();

    public RecordProcessor getSyncProcessor(String type) {
        RecordProcessor service = processorCache.get(type);
        if(service == null) throw new RuntimeException("Unknown service type: " + type);
        return service;
    }
}
4
  • question: what is the function of enumMap? (enumMap.get(rec) is basically the same result as rec.getValue() [ignoring the rec==null] case) || If you need multi-values, then maybe value should be a List, or some other Collection. Commented Jan 11, 2023 at 12:57
  • What is the datatype of TYPE_A, TYPE_B and TYPE_C? Are they Strings? Commented Jan 11, 2023 at 12:58
  • I would suggest hiding enumMap and providing just a method like static Record map(String) that does the lookup. You wouldn't want to allow tampering with the map from the outside. Commented Jan 11, 2023 at 13:03
  • What you're asking doesn't make sense.. When you have a variable of type Record, what do you want to assign it to when it's "TYPE4_MULTI"? It can't be of 3 types at the same time, right? Otherwise it's a one-to-many relationship and you'd have to store a collection of Records Commented Jan 11, 2023 at 13:05

2 Answers 2

1

You could use a String array to store multiple values, note that your logic may change with enumMap that way.

public enum Record {
    TYPE1("TYPE1"),
    TYPE2("TYPE2"),
    TYPE3("TYPE3"),
    TYPE4_MULTI("TYPE_A", "TYPE_B", "TYPE_C");

    private final String[] values;
    public static final Map<Record, String[]> enumMap = new EnumMap<Record, String[]>(Record.class);

    static {
        for (Record e : Record.values())
            enumMap.put(e, e.getValues());
    }


    Record(String... values) {
        this.values = values;
    }

    public String[] getValues() {
        return values;
    }
}

In case you need to get the Enum from a String value, you could add this static method:

public static Optional<Record> optionalValueOf(final String value) {
    for (Record record : values()) {
        for (String recordValue : record.values) {
            if (null == value && null == recordValue || value.equals(recordValue)) {
                return Optional.of(record);
            }
        }
    }
    return Optional.empty();
}
Sign up to request clarification or add additional context in comments.

11 Comments

but enumMap is a Map from Record to String - optionalValueOf is more like the reverse (from String to Record, which is reasonable)... (reason why I asked what is the intended function of enumMap )
You're right, I modify my answer, thanks.
@Alexis, I am unfamiliar with "String...". What is this? When was this introduced to java? Thanks
@Timothy Clotworthy This is called varargs, it is similar to String[] but does not require an array parameter, you can pass any number of String parameters. So instead of writing function(new String[] {"foo", "bar"}) you can directly write function("foo", "bar").
@Alexis, ok, thanks for clarification. So, your solution acommodates the situation where I simply need to know whether a value (yes a String) presented is within the total values array and thus I can use your optionalValueOf method. However, the 4 types are used in a factory class to determine which of 4 subclasses I should instantiate, and I think your solution as presented prevents me from saying if String is TYPE_A or TYPE_B or TYPE_C, instatiate TYPE4_MULTI subclass. Perhaps another static public method could be added to perform this task? I'll update post to clarify.
|
0

I think it's better to encapsulate values in the enum. It should be immutable (array is not immutable data storage).

@lombok.Getter
public enum Record {
    TYPE1("TYPE1"),
    TYPE2("TYPE2"),
    TYPE3("TYPE3"),
    TYPE4_MULTI("TYPE_A", "TYPE_B", "TYPE_C");

    // immutable list
    private final List<String> values;

    Record(String... values) {
        this.values = Arrays.stream(values)
                            .collect(Collectors.toList());
    }

}

P.S. Map<Record, String> enumMap I think is useless, because you have a Record already and all you need just call record.getValues() instead of Record.enumMaps.get(record). Also, this is breakes OOP encapsulation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.