From 85a5cc1de18993b98d20ad154b449b5c420959a4 Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Thu, 4 Sep 2008 01:22:14 +0000 Subject: [PATCH] Enum base class that does most of the right things. (The beginning.) git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5351 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- src/as/com/threerings/util/Enum.as | 165 +++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/as/com/threerings/util/Enum.as diff --git a/src/as/com/threerings/util/Enum.as b/src/as/com/threerings/util/Enum.as new file mode 100644 index 000000000..86465ea7c --- /dev/null +++ b/src/as/com/threerings/util/Enum.as @@ -0,0 +1,165 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.util { + +import flash.utils.Dictionary; + +/** + * Base enum class for actionscript. Works pretty much like enums in Java, only you've got + * to do one or two things + * + * To use, you'll want to subclass and have something like the following: + * + * public final class Foo extends Enum + * { + * public static const ONE = new Foo("ONE"); + * public static const TWO = new Foo("TWO"); + * finishedEnumerating(Foo); + * + * // {at}private + * public function Foo (name :String) + * { + * super(name); + * } + * + * public static function values () :Array + * { + * return Enum.values(Foo); + * } + * } + */ +public class Enum + implements Hashable, Comparable +{ + /** + * Call this constructor in your enum subclass constructor. + */ + public function Enum (name :String) + { + const clazz :Class = ClassUtil.getClass(this); + if (Boolean(_blocked[clazz])) { + throw new Error("You may not just construct an enum!"); + } + + var list :Array = _enums[clazz] as Array; + if (list == null) { + list = []; + _enums[clazz] = list; + } + list.push(this); + + // now, actually construct + _name = name; + } + + /** + * Get the name of this enum. + */ + public function name () :String + { + return _name; + } + + /** + * Get the ordinal of this enum. + */ + public function ordinal () :int + { + return (_enums[ClassUtil.getClass(this)] as Array).indexOf(this); + } + + // from Hashable + public function equals (other :Object) :Boolean + { + // enums are singleton + return (other === this); + } + + // from Hashable + public function hashCode () :int + { + return ordinal(); + } + + /** + * Return the String representation of this enum. + */ + public function toString () :String + { + return _name; + } + + // from Comparable + public function compareTo (other :Object) :int + { + if (!ClassUtil.isSameClass(this, other)) { + throw new ArgumentError("Not same class"); + } + return Integer.compare(this.ordinal(), Enum(other).ordinal()); + } + + /** + * Turn a String name into an Enum constant. + */ + public static function valueOf (clazz :Class, name :String) :Enum + { + for each (var enum :Enum in values(clazz)) { + if (enum.name() === name) { + return enum; + } + } + throw new ArgumentError("No such enum [class=" + clazz + ", name=" + name + "]."); + } + + /** + * Get all the enums of the specified class, or null if it's not an enum. + */ + public static function values (clazz :Class) :Array + { + var arr :Array = _enums[clazz] as Array; + if (arr == null) { + throw new ArgumentError("Not an enum [class=" + clazz + "]."); + } + return arr; + } + + /** + * This should be called by your enum subclass after you've finished enumating the enum + * constants. See the example in the class header documentation. + */ + protected static function finishedEnumerating (clazz :Class) :void + { + _blocked[clazz] = true; + } + + /** The String name of this enum value. */ + protected var _name :String; + + /** An array of enums for each enum class. */ + protected static const _enums :Dictionary = new Dictionary(true); + + /** Is further instantiation of enum constants for a class allowed? */ + protected static const _blocked :Dictionary = new Dictionary(true); + + finishedEnumerating(Enum); // do not allow any enums in this base class +} +}