ford prefect
ford prefect

Reputation: 7388

Multiple Values for one enum

So I am creating a parser to parse some configuration files made by our client engineers. I don't particularly trust our client engineers. They can usually spell things right but they can never remember what to capitalize. This makes Enum classes kind of noisome in that they go and break the program cause the Enum fails if they don't type in the exact right string.

Here is my Enum Class:

object EnumLayoutAlignment extends Enumeration
{
     type Alignment = Value
     val Vertical = Value("Vertical")
     val Horizontal = Value("Horizontal")
}

Is there a way I could make it so that "Vertical", "vertical", and "VERTICAL" all mapped to the same enum value?

EDIT: @Radai brought up a good point of just .upper() on the input but I would also like to include "vert" and other similar inputs

I used this as an example

Upvotes: 1

Views: 2121

Answers (2)

wingedsubmariner
wingedsubmariner

Reputation: 13667

You can add a method like this to your Enumeration:

def tryAsHardAsPossibleToFindMatch(s: String) = {
  val ls = s.toLowerCase
  val fv = values.filter(_.toString.toLowerCase.startsWith(ls))
  fv.size match {
    case 1 => fv.head
    case 0 => sys.error("No matching value for " + s)
    case _ => sys.error("Ambiguous values for " + s)
  }
}

This will allow you to use any string, regardless of case, that is part of the beginning of a Value. So Vertical can be obtained with "VERT", "vErTi", "vERTICAL", "VerticaL", etc.

Upvotes: 0

Sean Vieira
Sean Vieira

Reputation: 159915

One way to handle this is to provide a method for deserialization:

def fromString(s: String) = s.upper() match {
  case "VERTICAL" | "VERT" | "V" => Some(Vertical)
  case "HORIZONTAL" | "HORIZ" | "H" => Some(Horizontal)
  case => None
}

Then using it is as simple as:

EnumLayoutAlignment.fromString(someInput).map(doThingWithValidEnum)

Upvotes: 3

Related Questions