Home > front end >  Call specific method on object depending on selected enum value
Call specific method on object depending on selected enum value

Time:02-07

Let's assume we have an enum, that represents searchable fields:

enum SearchableFields {
    ALL,
    FIELD1,
    FIELD2,
    FIELD3;
}

This enum is displayed via a (combobox) selection inside a GUI. At runtime, I want to evaluate the selection of this combobox and search accordingly.

Depending on the selection, I need to retrieve the fields to search from a POJO (example below) via a getter.

class FieldPojo {
    private String field1;
    private String field2;
    private String field3;
    ...
    public String getField1() {
        return field1;
    }
    ...
}

I currently use a switch statement to evaluate the selection of SelectableFields and to then retrieve the correct field(s) to search:

private String retrieveField(FieldPojo f) {
    switch (selectedField) {
    case ALL:
        return retrieveAll(); // method that retrieves all available fields
    case FIELD1:
        return f.getField1();
    ...
}

This does work, however I feel like it's clunky.

Question:

Is there a more concise way to do this without evaluating the enum via a switch? (Java 8)

CodePudding user response:

You could store a reference to the getter in your enum constants:

enum SearchableFields {
    ALL(FieldPojo::retrieveAll),
    FIELD1(FieldPojo::getField1)

    private final Function<FieldPojo, String> accessor;
    SearchableFields(Function<FieldPojo, String> acccessor) {
        this.accessor = accessor;
    }

    public String get(FieldPojo fp) {
        return accessor.apply(fp);
    }
}

CodePudding user response:

Enums can contain method definitions, so one way is to define the method that retrieves the field name based on the enum value. I assume you have the actual field name stored as a member field also. Then you can override the method for the special ALL value:

enum SearchableFields {
    ALL("all") { // all is just a placeholder in this case
        @Override
        String retrieveField(FieldPojo f) {
            // logic for all fields
        }
    },
    FIELD1("field1"),
    FIELD2("field2"),
    FIELD3("field3");
    
    SearchableFields(String fieldName) {
        this.fieldName = Optional.of(fieldName);
    }
    SearchableFields() {
        fieldName = Optional.empty();
    }
    private final Optional<String> fieldName;

    String retrieveField(FieldPojo f) {
        if (fieldName.isPresent()) {
            return (String) f.getClass().getField(fieldName.get()).get(f);
        } else {
           // ...
        }
    }
}

CodePudding user response:

You can create a static map instead of the switch-case.

private static final Map<SearchableFields,Supplier<String>> searchableFieldsToFieldPojo = Map.of(
    ALL, this::retrieveAll,
    FIELD1, FieldPojo::retrieveAll
    );

And then you can access via:

searchableFieldsToFieldPojo.get(selectedField).get();

CodePudding user response:

Given that you can modify all parts of the code, you have several options:

  • Put the retrieveField into the class FieldPojo and modify it's parameter so it takes the enum SearchableFields as parameter.
  • Put the fields of FieldPojo as values into a map with a key of type SearchableFields. You can then decide whether you want to have "ALL" as an extra entry of the map or handle it as special case in a method similar to retrieveField. You could use this to have a "default" handling if you want to update the enum but not the FieldPojo class.
  • You put retrieveField into the class FieldPojo together with the SearchableFields enum - since only FieldPojo knows, which fields it actually provides as searchable fields.
  • You use introspection to gather the list of possible searchable fields and also access their contents.

Depending on your real requirements (you only showed a very abstract and specific version of them) one or the other method might be "the right one" for you. I would actually prefer the "everything into FieldPojo" as the most robust one, but on the other hand if you are not able to change FieldPojo and have to handle many different classes like it, the introspection variant might be the right one. (Be aware that it is fragile in terms of security and also probably very slow.)

  •  Tags:  
  • Related