@(#)EnumParam.txt 1.4
Proposal for EnumeratedParameter-related Modifications
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Brian Burkhalter
Created: 16 February 2000
Revised: 12/18/00
NOTE
----
This proposal was created before a number of concepts discussed in the
OperationRegistry proposal were developed. Therefore the exact specification
of some of the methods discussed herein as well as the implementation thereof
has changed; the ideas however remain the same. Please refer to the
OperationRegistry proposal for the current structure of OperationDescriptor.
PROPOSAL
--------
This proposal discusses some possible minor modifications to the
OperationDescriptor specification and implementation which would improve
the introspection capability of this portion of JAI.
1. Named Sources
While this capability might not be of any utility to most users it has been
requested that operation sources, like operation parameters, have names.
However, as it appears simple to implement this request we are proposing to
honor it.
1.1 OperationDescriptor
Add a method specification:
/**
* Returns an array of Class
es that describe the types
* of sources required by this operation for the specified mode.
* If this operation has no sources, this method returns null
.
*
* @param modeName the operation mode name
*
* @throws IllegalArgumentException if modeName is null
*
* @since Java Advanced Imaging 1.1
*/
Class[] getSourceClasses(String modeName);
1.2 OperationDescriptorImpl
1.2.1 Constructor
Modify the principal constructor (the one with six parameters): insert the
parameter "String[] sourceNames" before "Class[] paramClasses".
/**
[...]
* @param sourceNames The source names. It may be null
* if this operation has no sources or if the default source
* naming convention ("source0", "source1", etc.) is to be used.
[...]
* @throws IllegalArgumentException if sourceNames
* is non-null
and its length does not equal
* the number of sources of this operation.
[...]
*/
public OperationDescriptorImpl(String[][] resources,
String[] supportedModes,
String[] sourceNames,
Class [][] sourceClasses,
String[] paramNames,
Class [][] paramClasses,
Object[][] paramDefaults,
Object[][] validParamValues) {}
Note: The "supportedModes" and "validParamValues" are discussed in the
OperationRegsitry proposal.
1.2.2 Method
Add implementation of getSourceNames() specified in OperationDescriptor.
/**
* Returns an array of String
s that are the names
* of the sources of this operation. If this operation has no
* sources, this method returns null
. If this
* operation has sources but their names were not provided at
* construction time, then the returned names will be of the
* form "source0", "source1", etc.
*/
public String[] getSourceNames();
1.3 ParameterBlockJAI
Add a method:
/**
* Sets a named source to a given Object
value.
*
* @param sourceName a String
naming a source.
* @param source an Object
value for the source.
*
* @throws NullPointerException if source
is null.
* @throws NullPointerException if sourceName
is null.
* @throws IllegalArgumentException if source
is not
* an instance of (any of) the
* expected class(es).
* @throws IllegalArgumentException if the associated operation has
* no source with the supplied name.
*
* @since Java Advanced Imaging 1.1
*/
public ParameterBlockJAI setSource(String sourceName, Object source) {}
2. ParameterBlocks and Beans
2.1 ParameterBlocks as Beans
It was suggested during the expert group meetings that making ParameterBlockJAI
into a bean would be beneficial. This concept was investigated and the
conclusion was reached that there was no general way in which this could be
accomplished while adhering to the standard design patterns suggested by the
Java Beans API. Instead it seemed that it would be sufficient to enhance the
current definitions of OperationDescriptor[Impl] and ParameterBlockJAI such
that full introspection is possible. This objective should be achieved by
implementing the proposal of section 1 above and that of the following section.
If this is deemed insufficient, suggestions as to how a reasonable bean
architecture for operators might be designed (and implemented) would be
welcome.
2.2 Introspection of Enumerated Parameters
In the JAI 1.0 specification the OperationDescriptors of several operators
included definitions of constants which were to be used as the value of a
specific parameter of the operator. For example, TransposeDescriptor defined
seven constants (FLIP_* and ROTATE_*) to indicate the acceptable range of
values of the unique operator parameter which is named "type". The problem
with this approach is that unlike for other parameters there is no way to
determine automatically the accpeted range of values. The following proposal
is one suggestion for a means of removing this impediment. This implementation
has already been tested successfully.
2.2.1 Description of Proposed Implementation
. Create a class named EnumeratedParameter which has a single
instance variable "String name" and a public constructor which takes
the name. toString() would return the String:
package javax.media.jai;
import java.io.Serializable;
/**
* This class provides a mechanism by which enumerated parameters may be
* added to subclasses of OperationDescriptorImpl
while
* retaining the ability to perform introspection on the allowable range of
* values of the enumeration. An example of an enumerated parameter is the
* type parameter of the "Transpose" operation which is defined in
* TransposeDescriptor
to accept only the values defined by the
* FLIP_*
and ROTATE_*
fields of the descriptor.
*
*
This class may be used to create enumerated parameters in an
* OperationDescriptor
as follows:
*
*
EnumeratedParameter
. This class should consist of only a
* package private constructor with a single String
parameter
* called name and a single statement invoking the superclass
* constructor with name as the parameter.EnumeratedParameter
which was created for it in
* in the previous step.OperationDescriptor
of the operator a public static final
* field of type equal to the class defined in the first step. Each field
* should be assigned an instance of the subclass defined in the first step.
* The name and value
used for each of these
* EnumeratedParameter
subclass instances should be distinct
* for each distinct field or an error will occur.TransposeDescriptor
, the three steps above
* would be to 1) create a final class TransposeType
in the
* javax.media.jai.operator
package; 2) define the
* type of the "type" parameter as TransposeType.class
; and
* 3) define a static final field of class TransposeType
for
* each of the enumerated values with each field being initialized to an
* instance of TransposeType
with name equal to the name
* of the field and value to its integral (enumerated) value.
*
* @see OperationDescriptorImpl
* @see javax.media.jai.operator.TransposeDescriptor
*
* @since Java(tm) Advanced Imaging 1.1
*/
public class EnumeratedParameter implements Serializable {
/**
* Constructs an EnumeratedParameter
with the indicated name
* and value.
*/
public EnumeratedParameter(String name, int value) {}
/**
* Returns the name assigned to this EnumeratedParameter
* when it was constructed.
*/
public String getName() {}
/**
* Returns the value assigned to this EnumeratedParameter
* when it was constructed.
*/
public int getValue() {}
/**
* Returns true
if and only if the parameter is an instance
* of the class on which this method is invoked and has either the same
* name or the same value.
*/
public boolean equals(Object o) {}
/**
* Returns the name assigned to this EnumeratedParameter
* when it was constructed.
*/
public String toString() {}
}
. In each OperationDescriptor class containing enumerated parameter values,
a final package private class extending EnumeratedParameter would be defined
for each enumerated parameter.
. Each static final parameter value would be created as an instance of the
inner class corresponding to that parameter. The set of all such static
final parameters constitutes the data range of the corresponding parameter.
. OperationDescriptorImpl should create a Collection of EnumeratedParameter
objects for each parameter the type of which is EnumeratedParameter. The
Collection would be created using reflection.
. OperationDescriptorImpl should create a Map of all Collections of
EnumeratedParameter objects with the key being the name of the
associated parameter.
. Add two methods to OperationDescriptor:
/**
* Returns an array of the names of all parameters the type
* of which is EnumeratedParameter.
*/
String[] getEnumeratedParameterNames()
/**
* Returns an array of EnumeratedParameter objects corresponding to the
* operation parameter with the specified name.
*/
EnumeratedParameter[] getEnumeratedParameterValues(String parameterName)
Note: Due to issues raised in the OperationRegistry proposal, the above
methods are actually specified in the ParameterListDescriptor interface
returned by the getParameterListDescriptor() method of the
RegistryElementDescriptor superinterface of OperationDescriptor.
. Add an implementation of each of the above methods to
OperationDescriptorImpl.
Note: Per the preceding note this is no longer necessary.
2.2.2 Adding new operators
If a new operator were to be added which includes parameters which have values
constrained to a discrete set then the above construct may be utilized as
follows:
1. For each constrained-value parameter created a final package-private class
extending EnumeratedParameter. This class should consist of only a
constructor with a String parameter called "name" and which has a single
statement invoking the superclass constructor on "name".
2. Define the class of the parameter in question to be the package-private
subclass of EnumeratedParameter which was created for it in step 1.
3. For each possible value of the parameter define in the OperationDescriptor
of the operator a public static final field of type java.lang.Object to
which is assigned a distinct instance of the EnumeratedParameter subclass.
2.2.2.1 Example: "Zoom" Operator
A "Zoom" operator which supports 2X, 4X, and 8X zoom and has a
parameter called "type" used to specify the amount of zoom. The
OperationDescriptor is called ZoomDescriptor and extends
OperationDescriptorImpl.
Step 1: Define ZoomType (in ZoomDescriptor.java) as:
final class ZoomType extends EnumeratedParameter {
public ZoomType(String name) {
super(name);
}
}
Step 2: Set the class of the "type" parameter to ZoomType.class
Step 3: Define these constants:
public static final Object ZOOM_2 = new ZoomType("ZOOM_2");
public static final Object ZOOM_4 = new ZoomType("ZOOM_4");
public static final Object ZOOM_8 = new ZoomType("ZOOM_8");
The OperationDescriptorImpl detects the above by reflection so that
A) getEnumeratedParameterNames() returns {"type"}
and
B) getEnumeratedParameterValues("type") returns {"ZOOM_2", "ZOOM_4", "ZOOM_8"}.
It should be apparent that the above approach makes it easy to add parameters
constrained to a discrete set of values. Note also that it permits value
validation by simply checking the class of any value supplied for the
parameter and it permits retrieval of the names of the discrete values of the
parameter. The specific interpretation of the permissible values is left to
the implementation of the operator.