diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/library/scala/Enumeration.scala | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index 2feb892421..647bd35d31 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -74,7 +74,7 @@ abstract class Enumeration(initial: Int, names: String*) { string } - /** The mapping from the integer used to identifying values to the actual + /** The mapping from the integer used to identify values to the actual * values. */ private val vmap: Map[Int, Value] = new HashMap @@ -82,6 +82,10 @@ abstract class Enumeration(initial: Int, names: String*) { @transient private var vset: ValueSet = null @transient private var vsetDefined = false + /** The mapping from the integer used to identify values to their + * names. */ + private val nmap: Map[Int, String] = new HashMap + /** The values of this enumeration as a set. */ def values: ValueSet = { @@ -112,14 +116,16 @@ abstract class Enumeration(initial: Int, names: String*) { /** Returns a Value from this Enumeration whose name matches * the argument <var>s</var>. - * You must pass a String* set of names to the constructor, - * or initialize each Enumeration with Value(String), - * for valueOf to work. + * + * You can pass a String* set of names to the constructor, or + * initialize each Enumeration with Value(String). Otherwise, the + * names are determined automatically through reflection. + * * @param s an enumeration name - * Note the change here wrt 2.7 is intentional. You should know whether - * a name is in an Enumeration beforehand. If not, just use find on values. + * @return <tt>Some(Value)</tt> if an enumeration's name matches <var>s</var>, + * else <tt>None</tt> */ - def withName(s: String): Value = values.find(_.toString == s).get + final def withName(s: String): Value = values.find(_.toString == s).get /** Creates a fresh value, part of this enumeration. */ protected final def Value: Value = Value(nextId) @@ -150,6 +156,27 @@ abstract class Enumeration(initial: Int, names: String*) { */ protected final def Value(i: Int, name: String): Value = new Val(i, name) + /* Obtains the name for the value with id `i`. If no name is cached + * in `nmap`, it populates `nmap` using reflection. + */ + private def nameOf(i: Int): String = nmap.get(i) match { + case Some(name) => name + case None => + val methods = getClass.getMethods + for (m <- methods + if classOf[Value].isAssignableFrom(m.getReturnType) && + !java.lang.reflect.Modifier.isFinal(m.getModifiers)) { + val name = m.getName + // invoke method to obtain actual `Value` instance + val value = m.invoke(this) + // invoke `id` method + val idMeth = classOf[Val].getMethod("id") + val id: Int = idMeth.invoke(value).asInstanceOf[Integer].intValue() + nmap += (id -> name) + } + nmap(i) + } + /** The type of the enumerated values. */ @serializable @SerialVersionUID(7091335633555234129L) @@ -202,7 +229,7 @@ abstract class Enumeration(initial: Int, names: String*) { if (nextId > topId) topId = nextId def id = i override def toString() = - if (name eq null) Enumeration.this + "(" + i + ")" + if (name eq null) Enumeration.this.nameOf(i) else name private def readResolve(): AnyRef = if (vmap ne null) vmap(i) |