1 /*
2 * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package eu.simuline.util;
27
28 import java.io.Serializable;
29 import java.io.IOException;
30 import java.io.InvalidObjectException;
31 import java.io.ObjectInputStream;
32 import java.io.ObjectStreamException;
33
34 /**
35 * This class is inspired by {@link java.lang.Enum}
36 * and is intended as common base class of classes we shall call 'soft enums'.
37 * While soft enums are ordinary classes and lack all support
38 * special to enumeration types,
39 * they are also not subject to the restrictions that come with them.
40 * <p>
41 * It is the programmer who is responsible for implementing soft enums
42 * in a proper way.
43 * <p>
44 * As enumeration types
45 * are implicitely final subclasses of {@link java.lang.Enum},
46 * 'soft enums' are derived from {@link SoftEnum}
47 * and shall be final except if constants overwrite methods.
48 * A 'soft enum' shall have no instances
49 * other than those defined by its enum constants.
50
51 *
52 * More information about enums, including descriptions of the
53 * implicitly declared methods synthesized by the compiler, can be
54 * found in section 8.9 of
55 * <cite>The Java™ Language Specification</cite>.
56 *
57 * <p> Note that when using an enumeration type as the type of a set
58 * or as the type of the keys in a map, specialized and efficient
59 * {@linkplain java.util.EnumSet set} and {@linkplain
60 * java.util.EnumMap map} implementations are available.
61 *
62 * @param <E> The enum type subclass
63 * @author Josh Bloch
64 * @author Neal Gafter
65 * @see Class#getEnumConstants()
66 * @see java.util.EnumSet
67 * @see java.util.EnumMap
68 * @since 1.5
69 */
70 public abstract class SoftEnum<E extends SoftEnum<E>>
71 implements Comparable<E>, Serializable {
72
73 private static final long serialVersionUID = -2479143000061671589L;
74
75 /**
76 * The name of this enum constant, as declared in the enum declaration.
77 * Most programmers should use the {@link #toString} method rather than
78 * accessing this field.
79 */
80 private final String name;
81
82 /**
83 * Returns the name of this enum constant, exactly as declared in its
84 * enum declaration.
85 *
86 * <b>Most programmers should use the {@link #toString} method in
87 * preference to this one, as the toString method may return
88 * a more user-friendly name.</b> This method is designed primarily for
89 * use in specialized situations where correctness depends on getting the
90 * exact name, which will not vary from release to release.
91 *
92 * @return the name of this enum constant
93 */
94 public final String name() {
95 return name;
96 }
97
98 /**
99 * The ordinal of this enumeration constant (its position
100 * in the enum declaration, where the initial constant is assigned
101 * an ordinal of zero).
102 *
103 * Most programmers will have no use for this field. It is designed
104 * for use by sophisticated enum-based data structures, such as
105 * {@link java.util.EnumSet} and {@link java.util.EnumMap}.
106 */
107 private final int ordinal;
108
109 /**
110 * Returns the ordinal of this enumeration constant (its position
111 * in its enum declaration, where the initial constant is assigned
112 * an ordinal of zero).
113 *
114 * Most programmers will have no use for this method. It is
115 * designed for use by sophisticated enum-based data structures, such
116 * as {@link java.util.EnumSet} and {@link java.util.EnumMap}.
117 *
118 * @return the ordinal of this enumeration constant
119 */
120 public final int ordinal() {
121 return ordinal;
122 }
123
124 /**
125 * Sole constructor. Programmers cannot invoke this constructor.
126 * It is for use by code emitted by the compiler in response to
127 * enum type declarations.
128 *
129 * @param name - The name of this enum constant, which is the identifier
130 * used to declare it.
131 * @param ordinal - The ordinal of this enumeration constant (its position
132 * in the enum declaration, where the initial constant is assigned
133 * an ordinal of zero).
134 */
135 protected SoftEnum(String name, int ordinal) {
136 this.name = name;
137 this.ordinal = ordinal;
138 }
139
140 /**
141 * Returns the name of this enum constant, as contained in the
142 * declaration. This method may be overridden, though it typically
143 * isn't necessary or desirable. An enum type should override this
144 * method when a more "programmer-friendly" string form exists.
145 *
146 * @return the name of this enum constant
147 */
148 public final String toString() {
149 return name;
150 }
151
152 /**
153 * Returns true if the specified object is equal to this
154 * enum constant.
155 *
156 * @param other the object to be compared for equality with this object.
157 * @return true if the specified object is equal to this
158 * enum constant.
159 */
160 public final boolean equals(Object other) {
161 return this == other;
162 }
163
164 /**
165 * Returns a hash code for this enum constant.
166 *
167 * @return a hash code for this enum constant.
168 */
169 public final int hashCode() {
170 return super.hashCode();
171 }
172
173 /**
174 * Throws CloneNotSupportedException. This guarantees that enums
175 * are never cloned, which is necessary to preserve their "singleton"
176 * status.
177 *
178 * @return (never returns)
179 */
180 public final SoftEnum<E> clone() throws CloneNotSupportedException {
181 throw new CloneNotSupportedException();
182 }
183
184 /**
185 * Compares this enum with the specified object for order. Returns a
186 * negative integer, zero, or a positive integer as this object is less
187 * than, equal to, or greater than the specified object.
188 *
189 * Enum constants are only comparable to other enum constants of the
190 * same enum type. The natural order implemented by this
191 * method is the order in which the constants are declared.
192 */
193 public final int compareTo(E obj) {
194 SoftEnum<E> other = obj;
195 SoftEnum<E> self = this;
196 if (self.getClass() != other.getClass() && // optimization
197 self.getDeclaringClass() != other.getDeclaringClass()) {
198 throw new ClassCastException();
199 }
200 return self.ordinal - other.ordinal;
201 }
202
203 /**
204 * Returns the Class object corresponding to this enum constant's
205 * enum type. Two enum constants e1 and e2 are of the
206 * same enum type if and only if
207 * e1.getDeclaringClass() == e2.getDeclaringClass().
208 * (The value returned by this method may differ from the one returned
209 * by the {@link Object#getClass} method for enum constants with
210 * constant-specific class bodies.)
211 *
212 * @return the Class object corresponding to this enum constant's
213 * enum type
214 */
215 public final Class<?> getDeclaringClass() {
216 Class<?> clazz = getClass();
217 Class<?> zuper = clazz.getSuperclass();
218 return (zuper == Enum.class) ? clazz : zuper;
219 }
220
221 /*
222 * Returns the enum constant of the specified enum type with the
223 * specified name. The name must match exactly an identifier used
224 * to declare an enum constant in this type. (Extraneous whitespace
225 * characters are not permitted.)
226 *
227 * <p>Note that for a particular enum type {@code T}, the
228 * implicitly declared {@code public static T valueOf(String)}
229 * method on that enum may be used instead of this method to map
230 * from a name to the corresponding enum constant. All the
231 * constants of an enum type can be obtained by calling the
232 * implicit {@code public static T[] values()} method of that
233 * type.
234 *
235 * @param <T> The enum type whose constant is to be returned
236 * @param enumType the {@code Class} object of the enum type from which
237 * to return a constant
238 * @param name the name of the constant to return
239 * @return the enum constant of the specified enum type with the
240 * specified name
241 * @throws IllegalArgumentException if the specified enum type has
242 * no constant with the specified name, or the specified
243 * class object does not represent an enum type
244 * @throws NullPointerException if {@code enumType} or {@code name}
245 * is null
246 * @since 1.5
247 */
248 // public static <T extends Enum<T>> T valueOf(Class<T> enumType,
249 // String name) {
250 // T result = enumType.enumConstantDirectory().get(name);
251 // if (result != null)
252 // return result;
253 // if (name == null)
254 // throw new NullPointerException("Name is null");
255 // throw new IllegalArgumentException(
256 // "No enum constant " + enumType.getCanonicalName() + "." + name);
257 // }
258
259 // /**
260 // * enum classes cannot have finalize methods.
261 // */
262 // protected final void finalize() { // NOPMD
263 // }
264
265 /**
266 * Prevent default deserialization.
267 */
268 @SuppressWarnings("PMD.UnusedFormalParameter")
269 private void readObject(ObjectInputStream stream)
270 throws IOException, ClassNotFoundException {
271 throw new InvalidObjectException("can't deserialize enum");
272 }
273
274 @SuppressWarnings("PMD.UnusedPrivateMethod")
275 private void readObjectNoData() throws ObjectStreamException {
276 throw new InvalidObjectException("can't deserialize enum");
277 }
278 }