summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Haller <hallerp@gmail.com>2009-10-27 18:10:35 +0000
committerPhilipp Haller <hallerp@gmail.com>2009-10-27 18:10:35 +0000
commit3a08cbbb97df78b056db97ab0898114d52ef2ead (patch)
tree458638d05a61fd3ec7ffba344d05a9c8a59c3f8f
parent727490ab53bdda68b36a9e38a729471094c4e6b5 (diff)
downloadscala-3a08cbbb97df78b056db97ab0898114d52ef2ead.tar.gz
scala-3a08cbbb97df78b056db97ab0898114d52ef2ead.tar.bz2
scala-3a08cbbb97df78b056db97ab0898114d52ef2ead.zip
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.
-rw-r--r--src/library/scala/Enumeration.scala43
-rw-r--r--test/files/run/t2111.check6
-rw-r--r--test/files/run/t2111.scala20
3 files changed, 61 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)
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)
+
+}