blob: 765761aa7fc393990d00909c2e0f3f8f51ff20dc [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27package javax.print.attribute;
28
29import java.io.InvalidObjectException;
30import java.io.ObjectStreamException;
31import java.io.Serializable;
32
33/**
34 * Class EnumSyntax is an abstract base class providing the common
35 * implementation of all "type safe enumeration" objects. An enumeration class
36 * (which extends class EnumSyntax) provides a group of enumeration values
37 * (objects) that are singleton instances of the enumeration class; for example:
38 * <PRE>
39 * public class Bach extends EnumSyntax {
40 * public static final Bach JOHANN_SEBASTIAN = new Bach(0);
41 * public static final Bach WILHELM_FRIEDEMANN = new Bach(1);
42 * public static final Bach CARL_PHILIP_EMMANUEL = new Bach(2);
43 * public static final Bach JOHANN_CHRISTIAN = new Bach(3);
44 * public static final Bach P_D_Q = new Bach(4);
45 *
46 * private static final String[] stringTable = {
47 * "Johann Sebastian Bach",
48 * "Wilhelm Friedemann Bach",
49 * "Carl Philip Emmanuel Bach",
50 * "Johann Christian Bach",
51 * "P.D.Q. Bach"
52 * };
53 *
54 * protected String[] getStringTable() {
55 * return stringTable;
56 * }
57 *
58 * private static final Bach[] enumValueTable = {
59 * JOHANN_SEBASTIAN,
60 * WILHELM_FRIEDEMANN,
61 * CARL_PHILIP_EMMANUEL,
62 * JOHANN_CHRISTIAN,
63 * P_D_Q
64 * };
65 *
66 * protected EnumSyntax[] getEnumValueTable() {
67 * return enumValueTable;
68 * }
69 * }
70 * </PRE>
71 * You can then write code that uses the <CODE>==</CODE> and <CODE>!=</CODE>
72 * operators to test enumeration values; for example:
73 * <PRE>
74 * Bach theComposer;
75 * . . .
76 * if (theComposer == Bach.JOHANN_SEBASTIAN) {
77 * System.out.println ("The greatest composer of all time!");
78 * }
79 * </PRE>
80 * The <CODE>equals()</CODE> method for an enumeration class just does a test
81 * for identical objects (<CODE>==</CODE>).
82 * <P>
83 * You can convert an enumeration value to a string by calling {@link
84 * #toString() <CODE>toString()</CODE>}. The string is obtained from a table
85 * supplied by the enumeration class.
86 * <P>
87 * Under the hood, an enumeration value is just an integer, a different integer
88 * for each enumeration value within an enumeration class. You can get an
89 * enumeration value's integer value by calling {@link #getValue()
90 * <CODE>getValue()</CODE>}. An enumeration value's integer value is established
91 * when it is constructed (see {@link #EnumSyntax(int)
92 * <CODE>EnumSyntax(int)</CODE>}). Since the constructor is protected, the only
93 * possible enumeration values are the singleton objects declared in the
94 * enumeration class; additional enumeration values cannot be created at run
95 * time.
96 * <P>
97 * You can define a subclass of an enumeration class that extends it with
98 * additional enumeration values. The subclass's enumeration values' integer
99 * values need not be distinct from the superclass's enumeration values' integer
100 * values; the <CODE>==</CODE>, <CODE>!=</CODE>, <CODE>equals()</CODE>, and
101 * <CODE>toString()</CODE> methods will still work properly even if the subclass
102 * uses some of the same integer values as the superclass. However, the
103 * application in which the enumeration class and subclass are used may need to
104 * have distinct integer values in the superclass and subclass.
105 * <P>
106 *
107 * @author David Mendenhall
108 * @author Alan Kaminsky
109 */
110public abstract class EnumSyntax implements Serializable, Cloneable {
111
112 private static final long serialVersionUID = -2739521845085831642L;
113
114 /**
115 * This enumeration value's integer value.
116 * @serial
117 */
118 private int value;
119
120 /**
121 * Construct a new enumeration value with the given integer value.
122 *
123 * @param value Integer value.
124 */
125 protected EnumSyntax(int value) {
126 this.value = value;
127 }
128
129 /**
130 * Returns this enumeration value's integer value.
131 * @return the value
132 */
133 public int getValue() {
134 return value;
135 }
136
137 /**
138 * Returns a clone of this enumeration value, which to preserve the
139 * semantics of enumeration values is the same object as this enumeration
140 * value.
141 */
142 public Object clone() {
143 return this;
144 }
145
146 /**
147 * Returns a hash code value for this enumeration value. The hash code is
148 * just this enumeration value's integer value.
149 */
150 public int hashCode() {
151 return value;
152 }
153
154 /**
155 * Returns a string value corresponding to this enumeration value.
156 */
157 public String toString() {
158
159 String[] theTable = getStringTable();
160 int theIndex = value - getOffset();
161 return
162 theTable != null && theIndex >= 0 && theIndex < theTable.length ?
163 theTable[theIndex] :
164 Integer.toString (value);
165 }
166
167 /**
168 * During object input, convert this deserialized enumeration instance to
169 * the proper enumeration value defined in the enumeration attribute class.
170 *
171 * @return The enumeration singleton value stored at index
172 * <I>i</I>-<I>L</I> in the enumeration value table returned by
173 * {@link #getEnumValueTable() <CODE>getEnumValueTable()</CODE>},
174 * where <I>i</I> is this enumeration value's integer value and
175 * <I>L</I> is the value returned by {@link #getOffset()
176 * <CODE>getOffset()</CODE>}.
177 *
178 * @throws ObjectStreamException if the stream can't be deserialised
179 * @throws InvalidObjectException
180 * Thrown if the enumeration value table is null, this enumeration
181 * value's integer value does not correspond to an element in the
182 * enumeration value table, or the corresponding element in the
183 * enumeration value table is null. (Note: {@link
184 * java.io.InvalidObjectException InvalidObjectException} is a subclass
185 * of {@link java.io.ObjectStreamException ObjectStreamException}, which
186 * <CODE>readResolve()</CODE> is declared to throw.)
187 */
188 protected Object readResolve() throws ObjectStreamException {
189
190 EnumSyntax[] theTable = getEnumValueTable();
191
192 if (theTable == null) {
193 throw new InvalidObjectException(
194 "Null enumeration value table for class " +
195 getClass());
196 }
197
198 int theOffset = getOffset();
199 int theIndex = value - theOffset;
200
201 if (0 > theIndex || theIndex >= theTable.length) {
202 throw new InvalidObjectException
203 ("Integer value = " + value + " not in valid range " +
204 theOffset + ".." + (theOffset + theTable.length - 1) +
205 "for class " + getClass());
206 }
207
208 EnumSyntax result = theTable[theIndex];
209 if (result == null) {
210 throw new InvalidObjectException
211 ("No enumeration value for integer value = " +
212 value + "for class " + getClass());
213 }
214 return result;
215 }
216
217 // Hidden operations to be implemented in a subclass.
218
219 /**
220 * Returns the string table for this enumeration value's enumeration class.
221 * The enumeration class's integer values are assumed to lie in the range
222 * <I>L</I>..<I>L</I>+<I>N</I>-1, where <I>L</I> is the value returned by
223 * {@link #getOffset() <CODE>getOffset()</CODE>} and <I>N</I> is the length
224 * of the string table. The element in the string table at index
225 * <I>i</I>-<I>L</I> is the value returned by {@link #toString()
226 * <CODE>toString()</CODE>} for the enumeration value whose integer value
227 * is <I>i</I>. If an integer within the above range is not used by any
228 * enumeration value, leave the corresponding table element null.
229 * <P>
230 * The default implementation returns null. If the enumeration class (a
231 * subclass of class EnumSyntax) does not override this method to return a
232 * non-null string table, and the subclass does not override the {@link
233 * #toString() <CODE>toString()</CODE>} method, the base class {@link
234 * #toString() <CODE>toString()</CODE>} method will return just a string
235 * representation of this enumeration value's integer value.
236 * @return the string table
237 */
238 protected String[] getStringTable() {
239 return null;
240 }
241
242 /**
243 * Returns the enumeration value table for this enumeration value's
244 * enumeration class. The enumeration class's integer values are assumed to
245 * lie in the range <I>L</I>..<I>L</I>+<I>N</I>-1, where <I>L</I> is the
246 * value returned by {@link #getOffset() <CODE>getOffset()</CODE>} and
247 * <I>N</I> is the length of the enumeration value table. The element in the
248 * enumeration value table at index <I>i</I>-<I>L</I> is the enumeration
249 * value object whose integer value is <I>i</I>; the {@link #readResolve()
250 * <CODE>readResolve()</CODE>} method needs this to preserve singleton
251 * semantics during deserialization of an enumeration instance. If an
252 * integer within the above range is not used by any enumeration value,
253 * leave the corresponding table element null.
254 * <P>
255 * The default implementation returns null. If the enumeration class (a
256 * subclass of class EnumSyntax) does not override this method to return
257 * a non-null enumeration value table, and the subclass does not override
258 * the {@link #readResolve() <CODE>readResolve()</CODE>} method, the base
259 * class {@link #readResolve() <CODE>readResolve()</CODE>} method will throw
260 * an exception whenever an enumeration instance is deserialized from an
261 * object input stream.
262 * @return the value table
263 */
264 protected EnumSyntax[] getEnumValueTable() {
265 return null;
266 }
267
268 /**
269 * Returns the lowest integer value used by this enumeration value's
270 * enumeration class.
271 * <P>
272 * The default implementation returns 0. If the enumeration class (a
273 * subclass of class EnumSyntax) uses integer values starting at other than
274 * 0, override this method in the subclass.
275 * @return the offset of the lowest enumeration value.
276 */
277 protected int getOffset() {
278 return 0;
279 }
280
281}