1 /*
2 * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3 * the spring framework, http://el4j.sf.net
4 * Copyright (C) 2005 by ELCA Informatique SA, Av. de la Harpe 22-24,
5 * 1000 Lausanne, Switzerland, http://www.elca.ch
6 *
7 * EL4J is published under the GNU Lesser General Public License (LGPL)
8 * Version 2.1. See http://www.gnu.org/licenses/
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * For alternative licensing, please contact info@elca.ch
16 */
17 package ch.elca.el4j.util.codingsupport;
18
19 import java.io.ObjectStreamException;
20 import java.io.Serializable;
21 import java.util.Hashtable;
22
23
24 /**
25 * The parent class for enums using the typesafe enum pattern (these enums are
26 * not comparable). Use the AbstractComparableEnum class as a parent if you need
27 * comparable enums. The pattern ensures that enums are correctly serialized and
28 * that there are some common accessor methods.
29 * <p>
30 *
31 * <h2>Concepts</h2>
32 * <ul>
33 * <li><b>Enumerations</b> are programming language types. Elements of an
34 * enumeration are one of a fixed (small) number of enumerable elements. For
35 * example, a simple enumeration for a program for playing cards could be
36 * {Spade, Heart, Diamonds, Club}. An element of this enumeration would then be
37 * any one of the four types of cards.
38 * </ul>
39 *
40 * <h2>How to Use</h2>
41 *
42 * <H3> Usage example</H3>
43 *
44 * The following code shows how to write an enumeration with the three possible
45 * values <BR>
46 * <code>{ASSERT, REQUIRE, ENSURE}</code>:
47 * <code> <pre>
48 * package ch.elca.el4j.codingsupport;
49 *
50 * import java.io.ObjectStreamException;
51 * // only needed due to a IBM JDK 1.2.2 bug
52 *
53 * /**
54 * * Represents the type of an assertion.
55 * * It uses the typesafe enum pattern for <BR>
56 * * <code> enum AssertType { ASSERT, REQUIRE, ENSURE }; </code>
57 * * <p>
58 * *
59 * * The code for class is potentially generated.
60 * *
61 * * /
62 * public class AssertType extends AbstractDefaultEnum {
63 *
64 * // define a private constructor with the two arguments
65 * // and delegate construction
66 * // to the parent class's constructor:
67 * private AssertType(String name, int code) {
68 * super(name, code);
69 * }
70 *
71 * // now define the elements:
72 *
73 * public static final AssertType ASSERT =
74 * new AssertType("ASSERT",1);
75 *
76 * public static final AssertType REQUIRE =
77 * new AssertType("REQUIRE",2);
78 *
79 * public static final AssertType ENSURE =
80 * new AssertType("ENSURE",3);
81 * }
82 *
83 * // Customize the get(String) method
84 * public static AssertType get(String name) {
85 * return (AssertType) AbstractDefaultEnum.get(AssertType.class, name);
86 * }
87 * }
88 * </pre> </code>
89 *
90 * <H2>Deployment Environment</H2>
91 * The duplication of <code>readResolve</code> method in each enumeration is
92 * not needed because JDK 1.2.2 is no longer supported by EL4J.
93 *
94 * See also AbstractComparableEnum for a variant of this class that allow
95 * comparisons (i.e. it implements Comparable). <br/>
96 * The pattern for the implementation of this class was inspired by the book
97 * "Effective Java" by Joshua Bloch.
98 *
99 * @svnLink $Revision: 3873 $;$Date: 2009-08-04 13:59:45 +0200 (Di, 04. Aug 2009) $;$Author: swismer $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/core/src/main/java/ch/elca/el4j/util/codingsupport/AbstractDefaultEnum.java $
100 *
101 * @see <a href="http://www.javaworld.com/javaworld/javatips/jw-javatip122.html">
102 * Typesafe Enum Pattern Pitfalls</a>
103 *
104 * @author Raphael Boog (RBO)
105 */
106 public abstract class AbstractDefaultEnum implements Serializable {
107 /**
108 * A hastable containing all instances of this class.
109 */
110 protected static final Hashtable<String,Object> s_singletons =
111 new Hashtable<String,Object>();
112
113 /**
114 * The name of this enum element.
115 */
116 protected String m_name;
117
118 /**
119 * The integer code for this enum element.
120 */
121 protected int m_code;
122
123 /**
124 * Constructor that initializes the name and and adds this instance into
125 * the signletons list along with its key. The key is comprised of the class
126 * name and the name of this enum
127 *
128 * @param name Is the name of this instance.
129 * @param code Is the code.
130 */
131 protected AbstractDefaultEnum(String name, int code) {
132 m_name = name;
133 m_code = code;
134 // First parameter is a unique key.
135 // Second parameter is a unique value.
136 s_singletons.put((this.getClass()).getName() + "." + m_name, this);
137 }
138
139 /**
140 * Return the named enum (names are case sensitive!).
141 *
142 * @param myClass Is the type to get.
143 * @param name Is the name of the instantiated class.
144 * @return the named enum or null in case it is not found.
145 */
146 protected static Object get(Class<?> myClass, String name) {
147 return s_singletons.get(myClass.getName() + "." + name);
148 }
149
150 /**
151 * Return the enum's name.
152 * @return the enum's name.
153 */
154 public String toString() {
155 return m_name;
156 }
157
158 /**
159 * @return Return the enum's code.
160 */
161 public int toInt() {
162 return m_code;
163 }
164
165 /**
166 * Return true if and only if that object is equivalent to the object this
167 * operation is invoked upon. Remark: due to the fact that there is only one
168 * Object for each element of an enumeration, the == operator has the same
169 * semantics (but more efficient).
170 *
171 * {@inheritDoc}
172 */
173 public final boolean equals(Object that) {
174 return super.equals(that);
175 }
176
177 /**
178 * Retruns the hash code of this instance.
179 *
180 * {@inheritDoc}
181 */
182 public final int hashCode() {
183 return super.hashCode();
184 }
185
186 /**
187 * Performs an unique return of this instance after deserialzation.<br>
188 *
189 * This method has no effect with the JDK 1.2.2 of IBM. If you use the JDK
190 * version, this <code>readResolve</code> method must be duplicated in each
191 * enum subclass. EL4J does not support it any longer.
192 *
193 * @return readResolve
194 * @throws ObjectStreamException On reading error.
195 */
196 public Object readResolve() throws ObjectStreamException {
197 return s_singletons.get((this.getClass()).getName() + "." + m_name);
198 }
199 }