summaryrefslogtreecommitdiff
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-rw-r--r--src/library/scala/Enumeration.scala43
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)