J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 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 | |
| 27 | package javax.print.attribute; |
| 28 | |
| 29 | import java.io.InvalidObjectException; |
| 30 | import java.io.ObjectStreamException; |
| 31 | import 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 | */ |
| 110 | public 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 | } |