From 3a08cbbb97df78b056db97ab0898114d52ef2ead Mon Sep 17 00:00:00 2001 From: Philipp Haller Date: Tue, 27 Oct 2009 18:10:35 +0000 Subject: Improves Enumeration to obtain names of values ... Improves Enumeration to obtain names of values through reflection. This addresses those parts of #2111 that we agreed on in the Scala meeting. --- src/library/scala/Enumeration.scala | 43 ++++++++++++++++++++++++++++++------- test/files/run/t2111.check | 6 ++++++ test/files/run/t2111.scala | 20 +++++++++++++++++ 3 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 test/files/run/t2111.check create mode 100644 test/files/run/t2111.scala 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 s. - * 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 Some(Value) if an enumeration's name matches s, + * else None */ - 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) diff --git a/test/files/run/t2111.check b/test/files/run/t2111.check new file mode 100644 index 0000000000..0fc64f38ed --- /dev/null +++ b/test/files/run/t2111.check @@ -0,0 +1,6 @@ +Red +Green +Blue +Blue +Green +Red diff --git a/test/files/run/t2111.scala b/test/files/run/t2111.scala new file mode 100644 index 0000000000..3c6c5b8e8f --- /dev/null +++ b/test/files/run/t2111.scala @@ -0,0 +1,20 @@ + +object Test extends Application { + + object Color extends Enumeration { + val Red, Green, Blue = Value + } + + class MyColor extends Enumeration { + val Red, Green, Blue = Value + } + + println(Color.Red) + println(Color.Green) + println(Color.Blue) + val col = new MyColor + println(col.Blue) + println(col.Green) + println(col.Red) + +} -- cgit v1.2.3