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