/*
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.print.attribute;
import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
import java.io.Serial;
import java.io.Serializable;
Class EnumSyntax
is an abstract base class providing the common implementation of all "type safe enumeration" objects. An enumeration class (which extends class EnumSyntax
) provides a group of enumeration values (objects) that are singleton instances of the enumeration class; for example: public class Bach extends EnumSyntax {
public static final Bach JOHANN_SEBASTIAN = new Bach(0);
public static final Bach WILHELM_FRIEDEMANN = new Bach(1);
public static final Bach CARL_PHILIP_EMMANUEL = new Bach(2);
public static final Bach JOHANN_CHRISTIAN = new Bach(3);
public static final Bach P_D_Q = new Bach(4);
private static final String[] stringTable = {
"Johann Sebastian Bach",
"Wilhelm Friedemann Bach",
"Carl Philip Emmanuel Bach",
"Johann Christian Bach",
"P.D.Q. Bach"
};
protected String[] getStringTable() {
return stringTable;
}
private static final Bach[] enumValueTable = {
JOHANN_SEBASTIAN,
WILHELM_FRIEDEMANN,
CARL_PHILIP_EMMANUEL,
JOHANN_CHRISTIAN,
P_D_Q
};
protected EnumSyntax[] getEnumValueTable() {
return enumValueTable;
}
}
You can then write code that uses the ==
and !=
operators to test enumeration values; for example: Bach theComposer;
. . .
if (theComposer == Bach.JOHANN_SEBASTIAN) {
System.out.println ("The greatest composer of all time!");
}
The equals()
method for an enumeration class just does a test for identical objects (==
). You can convert an enumeration value to a string by calling toString()
. The string is obtained from a table supplied by the enumeration class.
Under the hood, an enumeration value is just an integer, a different integer for each enumeration value within an enumeration class. You can get an enumeration value's integer value by calling getValue()
. An enumeration value's integer value is established when it is constructed (see EnumSyntax(int)
). Since the constructor is protected, the only possible enumeration values are the singleton objects declared in the enumeration class; additional enumeration values cannot be created at run time.
You can define a subclass of an enumeration class that extends it with additional enumeration values. The subclass's enumeration values' integer values need not be distinct from the superclass's enumeration values' integer values; the ==
, !=
, equals()
, and toString()
methods will still work properly even if the subclass uses some of the same integer values as the superclass. However, the application in which the enumeration class and subclass are used may need to have distinct integer values in the superclass and subclass.
Author: David Mendenhall, Alan Kaminsky
/**
* Class {@code EnumSyntax} is an abstract base class providing the common
* implementation of all "type safe enumeration" objects. An enumeration class
* (which extends class {@code EnumSyntax}) provides a group of enumeration
* values (objects) that are singleton instances of the enumeration class; for
* example:
*
* <pre>
* public class Bach extends EnumSyntax {
* public static final Bach JOHANN_SEBASTIAN = new Bach(0);
* public static final Bach WILHELM_FRIEDEMANN = new Bach(1);
* public static final Bach CARL_PHILIP_EMMANUEL = new Bach(2);
* public static final Bach JOHANN_CHRISTIAN = new Bach(3);
* public static final Bach P_D_Q = new Bach(4);
*
* private static final String[] stringTable = {
* "Johann Sebastian Bach",
* "Wilhelm Friedemann Bach",
* "Carl Philip Emmanuel Bach",
* "Johann Christian Bach",
* "P.D.Q. Bach"
* };
*
* protected String[] getStringTable() {
* return stringTable;
* }
*
* private static final Bach[] enumValueTable = {
* JOHANN_SEBASTIAN,
* WILHELM_FRIEDEMANN,
* CARL_PHILIP_EMMANUEL,
* JOHANN_CHRISTIAN,
* P_D_Q
* };
*
* protected EnumSyntax[] getEnumValueTable() {
* return enumValueTable;
* }
* }
* </pre>
* You can then write code that uses the {@code ==} and {@code !=} operators to
* test enumeration values; for example:
* <pre>
* Bach theComposer;
* . . .
* if (theComposer == Bach.JOHANN_SEBASTIAN) {
* System.out.println ("The greatest composer of all time!");
* }
* </pre>
* The {@code equals()} method for an enumeration class just does a test for
* identical objects ({@code ==}).
* <p>
* You can convert an enumeration value to a string by calling
* {@link #toString() toString()}. The string is obtained from a table supplied
* by the enumeration class.
* <p>
* Under the hood, an enumeration value is just an integer, a different integer
* for each enumeration value within an enumeration class. You can get an
* enumeration value's integer value by calling {@link #getValue() getValue()}.
* An enumeration value's integer value is established when it is constructed
* (see {@link #EnumSyntax(int) EnumSyntax(int)}). Since the constructor is
* protected, the only possible enumeration values are the singleton objects
* declared in the enumeration class; additional enumeration values cannot be
* created at run time.
* <p>
* You can define a subclass of an enumeration class that extends it with
* additional enumeration values. The subclass's enumeration values' integer
* values need not be distinct from the superclass's enumeration values' integer
* values; the {@code ==}, {@code !=}, {@code equals()}, and {@code toString()}
* methods will still work properly even if the subclass uses some of the same
* integer values as the superclass. However, the application in which the
* enumeration class and subclass are used may need to have distinct integer
* values in the superclass and subclass.
*
* @author David Mendenhall
* @author Alan Kaminsky
*/
public abstract class EnumSyntax implements Serializable, Cloneable {
Use serialVersionUID from JDK 1.4 for interoperability.
/**
* Use serialVersionUID from JDK 1.4 for interoperability.
*/
@Serial
private static final long serialVersionUID = -2739521845085831642L;
This enumeration value's integer value.
@serial
/**
* This enumeration value's integer value.
*
* @serial
*/
private int value;
Construct a new enumeration value with the given integer value.
Params: - value – Integer value
/**
* Construct a new enumeration value with the given integer value.
*
* @param value Integer value
*/
protected EnumSyntax(int value) {
this.value = value;
}
Returns this enumeration value's integer value.
Returns: the value
/**
* Returns this enumeration value's integer value.
*
* @return the value
*/
public int getValue() {
return value;
}
Returns a clone of this enumeration value, which to preserve the
semantics of enumeration values is the same object as this enumeration
value.
/**
* Returns a clone of this enumeration value, which to preserve the
* semantics of enumeration values is the same object as this enumeration
* value.
*/
public Object clone() {
return this;
}
Returns a hash code value for this enumeration value. The hash code is
just this enumeration value's integer value.
/**
* Returns a hash code value for this enumeration value. The hash code is
* just this enumeration value's integer value.
*/
public int hashCode() {
return value;
}
Returns a string value corresponding to this enumeration value.
/**
* Returns a string value corresponding to this enumeration value.
*/
public String toString() {
String[] theTable = getStringTable();
int theIndex = value - getOffset();
return
theTable != null && theIndex >= 0 && theIndex < theTable.length ?
theTable[theIndex] :
Integer.toString (value);
}
During object input, convert this deserialized enumeration instance to
the proper enumeration value defined in the enumeration attribute class.
Throws: - ObjectStreamException – if the stream can't be deserialised
- InvalidObjectException – if the enumeration value table is
null
, this enumeration value's integer value does not correspond to an element in the enumeration value table, or the corresponding element in the enumeration value table is null
. (Note: InvalidObjectException
is a subclass of ObjectStreamException
, which readResolve()
is declared to throw.)
Returns: The enumeration singleton value stored at index i-L in the enumeration value table returned by getEnumValueTable()
, where i
is this enumeration value's integer value and L is the value returned by getOffset()
/**
* During object input, convert this deserialized enumeration instance to
* the proper enumeration value defined in the enumeration attribute class.
*
* @return The enumeration singleton value stored at index <i>i</i>-<i>L</i>
* in the enumeration value table returned by
* {@link #getEnumValueTable() getEnumValueTable()}, where <i>i</i>
* is this enumeration value's integer value and <i>L</i> is the
* value returned by {@link #getOffset() getOffset()}
* @throws ObjectStreamException if the stream can't be deserialised
* @throws InvalidObjectException if the enumeration value table is
* {@code null}, this enumeration value's integer value does not
* correspond to an element in the enumeration value table, or the
* corresponding element in the enumeration value table is
* {@code null}. (Note:
* {@link InvalidObjectException InvalidObjectException} is a
* subclass of {@link ObjectStreamException ObjectStreamException},
* which {@code readResolve()} is declared to throw.)
*/
@Serial
protected Object readResolve() throws ObjectStreamException {
EnumSyntax[] theTable = getEnumValueTable();
if (theTable == null) {
throw new InvalidObjectException(
"Null enumeration value table for class " +
getClass());
}
int theOffset = getOffset();
int theIndex = value - theOffset;
if (0 > theIndex || theIndex >= theTable.length) {
throw new InvalidObjectException
("Integer value = " + value + " not in valid range " +
theOffset + ".." + (theOffset + theTable.length - 1) +
"for class " + getClass());
}
EnumSyntax result = theTable[theIndex];
if (result == null) {
throw new InvalidObjectException
("No enumeration value for integer value = " +
value + "for class " + getClass());
}
return result;
}
// Hidden operations to be implemented in a subclass.
Returns the string table for this enumeration value's enumeration class.
The enumeration class's integer values are assumed to lie in the range
L..L+N-1, where L is the value returned by getOffset()
and N is the length of the string
table. The element in the string table at index i-L is the value returned by toString()
for the enumeration value whose integer value is i. If an integer within the above range is not used by any enumeration value, leave the corresponding table element null
. The default implementation returns null
. If the enumeration class (a subclass of class EnumSyntax
) does not override this method to return a non-null
string table, and the subclass does not override the toString()
method, the base class toString()
method will return just a string representation of this enumeration value's integer value.
Returns: the string table
/**
* Returns the string table for this enumeration value's enumeration class.
* The enumeration class's integer values are assumed to lie in the range
* <i>L</i>..<i>L</i>+<i>N</i>-1, where <i>L</i> is the value returned by
* {@link #getOffset() getOffset()} and <i>N</i> is the length of the string
* table. The element in the string table at index <i>i</i>-<i>L</i> is the
* value returned by {@link #toString() toString()} for the enumeration
* value whose integer value is <i>i</i>. If an integer within the above
* range is not used by any enumeration value, leave the corresponding table
* element {@code null}.
* <p>
* The default implementation returns {@code null}. If the enumeration class
* (a subclass of class {@code EnumSyntax}) does not override this method to
* return a {@code non-null} string table, and the subclass does not
* override the {@link #toString() toString()} method, the base class
* {@link #toString() toString()} method will return just a string
* representation of this enumeration value's integer value.
*
* @return the string table
*/
protected String[] getStringTable() {
return null;
}
Returns the enumeration value table for this enumeration value's
enumeration class. The enumeration class's integer values are assumed to
lie in the range L..L+N-1, where L is the value returned by getOffset()
and N is the
length of the enumeration value table. The element in the enumeration
value table at index i-L is the enumeration value object
whose integer value is i; the readResolve()
method needs this to preserve singleton semantics during deserialization of an enumeration instance. If an integer within the above range is not used by any enumeration value, leave the corresponding table element null
. The default implementation returns null
. If the enumeration class (a subclass of class EnumSyntax) does not override this method to return a non-null
enumeration value table, and the subclass does not override the readResolve()
method, the base class readResolve()
method will throw an exception whenever an enumeration instance is deserialized from an object input stream.
Returns: the value table
/**
* Returns the enumeration value table for this enumeration value's
* enumeration class. The enumeration class's integer values are assumed to
* lie in the range <i>L</i>..<i>L</i>+<i>N</i>-1, where <i>L</i> is the
* value returned by {@link #getOffset() getOffset()} and <i>N</i> is the
* length of the enumeration value table. The element in the enumeration
* value table at index <i>i</i>-<i>L</i> is the enumeration value object
* whose integer value is <i>i</i>; the {@link #readResolve() readResolve()}
* method needs this to preserve singleton semantics during deserialization
* of an enumeration instance. If an integer within the above range is not
* used by any enumeration value, leave the corresponding table element
* {@code null}.
* <p>
* The default implementation returns {@code null}. If the enumeration class
* (a subclass of class EnumSyntax) does not override this method to return
* a {@code non-null} enumeration value table, and the subclass does not
* override the {@link #readResolve() readResolve()} method, the base class
* {@link #readResolve() readResolve()} method will throw an exception
* whenever an enumeration instance is deserialized from an object input
* stream.
*
* @return the value table
*/
protected EnumSyntax[] getEnumValueTable() {
return null;
}
Returns the lowest integer value used by this enumeration value's
enumeration class.
The default implementation returns 0. If the enumeration class (a subclass of class EnumSyntax
) uses integer values starting at other than 0, override this method in the subclass.
Returns: the offset of the lowest enumeration value
/**
* Returns the lowest integer value used by this enumeration value's
* enumeration class.
* <p>
* The default implementation returns 0. If the enumeration class (a
* subclass of class {@code EnumSyntax}) uses integer values starting at
* other than 0, override this method in the subclass.
*
* @return the offset of the lowest enumeration value
*/
protected int getOffset() {
return 0;
}
}