@(#)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 Classes 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 Strings 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: * *

* * With respect to 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.