Nrj
Nrj

Reputation: 6831

Design Issue | Enum to represent combo box options

I need to use an Enum with a combobox (values shown below).

YES (shown as YES on UI, stored in DB as Y)
NO (shown as NO on UI, stored in DB as N)
DEFAULT (shown as "" on UI, stored in DB as null)

The Enum has methods to perform the following -

  1. toString() - to provide the custom String for UI. (showing the combo options)
  2. OptionToDB (static) - Convert a selected option to db value (on save / update)
  3. DBToOption (static)- Convert a DB value to selcted option (while loading the screen)

    static enum EnumOption{
        YES,NO,DEFAULT;
        ....
        public static EnumOption DBToOption(String val){
            if("Y".equals(val)){
                return YES;
            } else if("N".equals(val)){
                return NO;
            }else {
                return DEFAULT;
            }
        }
        ....
    }
    

It works pretty well, but the issue with above methods is that it uses if/else comparison to deduce which option / db value to be returned.

I thought of storing the dbValue as a field in enum but I was not able to reduce the if/else from DBToOption.

Can this if/else be avoided in any way using a better design??

Upvotes: 2

Views: 572

Answers (3)

DaveFar
DaveFar

Reputation: 7457

So you want to get rid of the remaining if/else ...Are you doing Object Calisthenics?

You could do the following, if you do not have compatibility issues:

public enum EnumOption {

   Y("Y", "YES"), 
   N("N", "NO"), 
   D("D", "");

   private final String dbValue;
   private final String uiValue;

   private EnumOption(String dbValue, String uiValue) {
          this.dbValue = dbValue;
          this.uiValue = uiValue;
   }

   public String getDbValue() {
     return this.dbValue;
   }

   public String uiValue() {
      return this.uiValue;
   }

   public static EnumOption getFromDb(String dbValue) {
        return EnumOption.valueOf(dbValue);
   }
}

Since each enum value can only occur once, this has at least the same performance as all the other implementations.

For details about the automatically generated valueOf(String) method in enum types, and James DW's solution, you can read up in Josh Bloch's Effective Java Item 30 (Use enums instead of int constants), page 154.

Upvotes: 0

James DW
James DW

Reputation: 1815

public enum EnumOption {

   YES("Y"), NO("N"), DEFAULT("");

   private final String value;

   private final static Map<String, EnumOption> options;

   static {
          options = new HashMap<String, EnumOption>();
          for (EnumOption opt : EnumOption.values()) {
                 options.put(opt.value, opt);
          }
   }

   private EnumOption(String value) {
          this.value = value;
   }

   public static EnumOption DBToOption(String val) {
          return options.get(val) != null ? options.get(val) : DEFAULT;
   }
}

And here is the test that proves it works.

public void testDBToOption() {      
    assertEquals(EnumOption.NO, EnumOption.DBToOption("N"));
    assertEquals(EnumOption.YES, EnumOption.DBToOption("Y"));
    assertEquals(EnumOption.DEFAULT, EnumOption.DBToOption(""));
    assertEquals(EnumOption.DEFAULT, EnumOption.DBToOption(null));
    assertEquals(EnumOption.DEFAULT, EnumOption.DBToOption("R"));
}

Upvotes: 3

Jo&#227;o Silva
Jo&#227;o Silva

Reputation: 91329

If you store the dbValue as a field in the enum, you can remove the if/else and replace it with a for-loop, although I don't see anything wrong with those if/elses for this particular case:

static enum EnumOption {
  YES("Y"),
  NO("N"),
  DEFAULT("");

  private final String value;

  private EnumOption(String value) {
    this.value = value;
  }

  public static EnumOption DBToOption(String val) {
    for (EnumOption opt : EnumOption.values()) {
      if (opt.value.equals(val)) {
        return opt;
      }
    }
    return DEFAULT;
  }
}

Upvotes: 4

Related Questions