Proposal: Negotiation API
~~~~~~~~~~~~~~~~~~~~~~~~~
Aastha Bhardwaj
Created: 07/24/2000
Revised: 09/25/2000
1. Motivation
Network Imaging makes communication between machines of widely varying
capabilities possible. In order to make this communication as efficient
as possible and to make the best use of these capabilities, it is
necessary that a mechanism to negotiate and agree on the most suitable
capability supported by both ends of the network connection be
available. The Negotiation API is designed to fulfill this need.
The API is designed to be generic enough to allow negotiation to take
place on any capability. The goal here is to define the negotiation
mechanism, but not to specify or restrict the list of capabilities or
objects which can be negotiated upon.
2. API
All classes and interfaces in the Negotiation API are listed below.
2.1 Interface Negotiable
This interface is the cornerstone of the Negotiation API. The Negotiable
interface represents an Object that can be negotiated upon. Negotiation
is performed by retrieving the subset that is common to both the objects
that are to be negotiated upon. This represents the set of capabilities
that are common to both and thus supported by both objects. This is
performed by using the negotiate() method. Note that this method returns
a new Negotiable which can be used again for further negotiation with
yet other Negotiable. Thus the negotiate() method can be used repeatedly
to perform multiple negotiations.
An object that can be negotiated upon must also be able to provide a
single value agreed upon in the negotiation. This is performed using the
getNegotiatedValue() method which returns a single value as the result
of the negotiation from the set of values that are common to and thus
supported by the both negotiating Negotiable Objects.
Here is the API specification for this class:
package javax.media.jai.remote;
/**
* An interface that defines objects that can be negotiated upon.
* Negotiation amongst objects is performed using the
* negotiate()
method. This method can be used to
* perform a chaining of successful negotiations, i.e., the results
* of one successful negotiation can be used to negotiate with another
* Negotiable
and so on. In order to retrieve a single
* negotiated value out of the Negotiable
, the
* getNegotiatedValue()
method can be used at any point
* during this series of negotiations.
*
* @since 1.1
*/
public interface Negotiable extends Serializable {
/**
* Returns a Negotiable
object that represents the
* set intersection of this Negotiable
with the
* given Negotiable
. The returned Negotiable
* represents the support that is common to both the
* Negotiable
s. If the negotiation fails, i.e there is
* no common subset, null is returned.
*
*
If the supplied argument is null, negotiation will fail and
* null will be returned, as it is not possible to negotiate with a
* null value. It may, however, be noted that it is valid for
* getNegotiatedValue()
to return null, i.e the single
* value result of the negotiation can be null.
*
* @param other The Negotiable
object to negotiate with.
* @returns The Negotiable
that represents the subset
* common to this and the given Negotiable
.
* null
is returned if there is no common subset.
*/
Negotiable negotiate(Negotiable other);
/**
* Returns a value that is valid for this Negotiable
.
* If more than one value is valid for this Negotiable
,
* this method can choose one arbitrarily, e.g. picking the first one
* or by having static preferences amongst the valid values. Which of the
* many valid values is returned is upto the particular implementation
* of this method.
*
* @returns The negotiated value.
*/
Object getNegotiatedValue();
/**
* Returns the Class
of the object that would be returned
* from the getNegotiatedValue
method on a successful
* negotiation. This method can be used to learn what the
* Class
of the negotiated value will be if the negotiation
* is successful. Implementing classes are encouraged to return an
* accurate Class
from this method if at all possible.
* However it is permissible to return null, if the Class
* of the negotiated value is indeterminate for any reason.
*
* @returns the Class
of the negotiated value.
*/
Class getNegotiatedValueClass();
}
2.2 Class NegotiableCapability
This is a class that represents the capabilities of an object. These
capabilities can be negotiated upon with the capabilities of another
similar object. This class expects its parameters to be classes that
implement the Negotiable interface. It is similar to the Negotiable
interface in that it provides a negotiate() method that returns a
NegotiableCapability allowing for the method to be called repeatedly for
multiple negotiations.
To retrieve the single value that is the result of the negotiation for a
particular parameter, this class has a getNegotiatedValue() method that
takes the parameter name of the parameter whose negotiated value is to
be determined as an argument.
Here is the API specification for this class :
package javax.media.jai.remote;
/**
* A NegotiableCapability
represents the capabilities of an
* object. These capabilities can be used to negotiate with the capabilities
* of a similar object. Each NegotiableCapability
is
* characterized by the category it belongs to, as returned by the
* getCategory()
method, by the actual name of the capability
* it represents, as returned by the getCapabilityName()
method
* and by a list of parameter name-value pairs that define the
* NegotiableCapability
. Every NegotiableCapability
* object also holds references to a representation of the objects that
* generated it. These can be accessed via the getGenerators()
* method. The creator or generator of a NegotiableCapability
* can supply any representation of itself while constructing the
* NegotiableCapability
. No interpretation is forced by this
* class, that is left upto the generating class and to the class that
* utilizes the NegotiableCapability
to get the negotiated
* results. The negotiation is performed by the
* negotiate()
method. Since this method returns a
* NegotiableCapability
, this method can be used repeatedly to
* perform multiple negotiations. If the negotiation fails, null will be
* returned from the negotiate()
method. Every successful
* negotiation will add the generator of the NegotiableCapability
* negotiated with, to the set of generators of the resultant
* NegotiableCapability
. The generators are intended to help
* the user of NegotiableCapability
identify the object that
* created the NegotiableCapability
and therefore the object
* that can be relied on to be able to handle the parameters agreed on during
* negotiation. For example, if the negotiation is to be performed to choose
* a compatible TileEncoder
, TileDecoder
pair
* for data compression/decompression, the category would be "tileCodec",
* the capabilityName would be a specific tile encoding format, say "jpeg"
* and the generator for the NegotiableCapability
could be the
* TileDecoderFactory
/TileEncoderFactory
object
* that generated that NegotiableCapability
. After a
* successful negotiation, the NegotiableCapability
that is
* the result of the negotiation will contain a
* TileEncoderFactory
and a TileDecoderFactory
* object as the generators for that NegotiableCapability
.
* These two objects can then be retrieved using the
* getGenerators
method and used to do the encoding and
* decoding and can be relied to be compatible, since the negotiation
* was successful between their respective
* NegotiableCapability
objects.
*
*
The number, name, Class type and default values for the parameters in
* this class is specified by the ParameterListDescriptor
* returned from getParameterListDescriptor
method. Each
* parameter value in this class must be a class that implements the
* Negotiable
interface. It is for this reason that all of
* the ParameterList
set methods that take primitive data
* types as arguments and all the ParameterList
get methods
* that return primitive data types are overridden in this class
* to throw an IllegalArgumentException, as this class only accepts
* Negotiable
's as parameter values in order to facilitate
* negotiation on parameters. It may be noted that the implementation of
* the version of ParameterList.setParameter
that takes
* an Object
as the parameter value, in this class
* throws an IllegalArgumentException
if the supplied
* Object
to be set does not implement the
* Negotiable
interface. If no Negotiable
value is
* available as the value for a particular parameter, null
* should be set as the value. A null value returned from the
* getNegotiatedValue(String)
method is however valid, since
* the single value result of the negotiation can be null.
* Similarly the Object
returned from the
* ParameterList.getObjectParameter
implementation in this class
* is always a class that implements the Negotiable
interface,
* and not a wrapper class of a primitive data type, as documented for this
* method in ParameterList
. The
* getParamValueRange(String parameterName)
and the
* getEnumeratedParameterValues(String parameterName)
methods
* of the ParameterListDescriptor
returned from
* getParameterListDescriptor
method of this class should be
* implemented to return null, since these methods are not meaningful when
* the parameter values are Negotiable
.
*
*
In order for the negotiation to be successful, the category and the
* capabilityName of the two NegotiableCapability
objects must be
* the same. In addition, negotiation on each of the parameters must be
* successful. Since each parameter is represented as a
* Negotiable
, negotiation on it can be performed using the
* Negotiable.negotiate(Negotiable negotiable)
method. The
* NegotiableCapability
returned from the
* negotiate(NegotiableCapability capability)
method
* contains the same category and capabilityName as that of the
* NegotiableCapability
objects being negotiated as well as
* including the negotiated values for each parameter. If the negotiation fails
* for any one parameter, the negotiation for the
* NegotiableCapability
s as a whole is said to fail (unless
* preference NegotiableCapability
objects are involved in
* the negotiation, as described below) and a null is returned.
*
*
In order to get a single negotiated value from the set of valid
* values represented as the Negotiable
value for a parameter,
* the getNegotiatedValue(String parameterName)
method can be
* called. If the negotiation was successful, an Object
which
* is the negotiated result will be returned, otherwise a
* null
(signifying that the negotiation failed) will be
* returned.
*
*
NegotiableCapability
objects can be classified as being
* either preferences or non-preferences. A non-preference describes the
* capabilities of an object completely by specifying Negotiable
* values for each and every parameter defined in the
* ParameterListDescriptor
returned from
* getParameterListDescriptor
method. A non-preference is allowed
* to not specify the value of a particular parameter, if a default value
* for that parameter exists (i.e. the default value is not
* null
). When a non-preference is created, all parameter
* values are initialized to their default values, and therefore if any
* parameter value is left unset at the time of the negotiation, the
* default value that was set at time of initialization will be used for
* the negotiation. If the default value happened to be null
,
* the negotiation in this case would fail. Note that all references to
* values in this paragraph, whether default or not, refered to the
* objects implementing the Negotiable
interface that are
* the values set for a particular parameter name.
*
* A preference on the other hand specifies preferences for the selection of
* a prefered set of (maybe even a single) parameter value from the set of
* valid ones at negotiation time.
* A preference is allowed to specify Negotiable
parameter
* values for a subset of parameters, if it so wishes. For those parameters
* for whom the preference does not specify values, the preference is
* indicating a don't-care attitude, and the result of the negotiation for
* such a parameter will be the Negotiable
value from the
* non-preference object the preference is negotiating with. Note that the
* default value is not substituted for a parameter whose value has not been
* specified in a preference. A NegotiableCapability
which is
* a preference should return true from the isPreference
method,
* a non-preference object that defines values for all the parameters (or
* relies on defaults) should return false from this method. As a rule, the
* result of negotiation between one non-preference and another is a
* non-preference, between a preference and a non-preference is a
* non-preference and that between two preferences is a preference, if
* the negotiation is successful. It may be noted that preferences are
* not expected to specify their generators, since in general, preferences
* don't come from objects that can support them. However if generators are
* specified within a preference, they will be added to the set of generators
* of the resultant NegotiableCapability
in the event of a
* successful negotiation.
*
*
Negotiation between a preference and a non-preference
* NegotiableCapability
results in a non-preference
* NegotiableCapability
. For each parameter, if a value is
* specified (i.e the value is not null
)
* in both the preference and the non-preference, then if these values
* have a common subset, the negotiation will succeed on this parameter,
* if there is no commonality, then the negotiation will fail on this
* parameter and thus also fail as a whole. If the preference doesn't
* specify a value for a parameter (i.e the value is null
),
* then the value specified by the non-preference for that same parameter
* is chosen as a result of the successful negotiation on that parameter.
*
*
Negotiation between two preference NegotiableCapability
* objects results in a preference NegotiableCapability
. For
* each parameter, if a value is specified (i.e the value is not
* null
) in both the preference objects, the negotiation on
* that parameter will have a value which is the portion that is common
* to both. If there is no commonality, negotiation will fail on this
* parameter (null
will be returned) and thus also fail as
* a whole. If the value for a particular parameter is specified in one
* preference and not in the other, the negotiated value will be the one
* specified. If for a particular parameter, no value is specified in
* either preference, the negotiated value for that parameter will be
* null
, and the negotiation as a whole on the
* NegotiableCapability
will not fail.
*
*
When a preference NegotiableCapability
is constructed,
* the values of all the parameters defined in the
* ParameterListDescriptor
returned from
* getParameterListDescriptor
method, are initialized to
* null
. null
within this class represents a
* value that has not been specified. Such values are only allowed on
* a preference NegotiableCapability
. On the other hand when
* a non-preference NegotiableCapability
is
* constructed, all the values are initialized to their default values.
*
*
All names are treated in a case-retentive and case-insensitive manner.
*
* @since 1.1
*/
public class NegotiableCapability extends ParameterListImpl implements Serializable {
/**
* Creates a NegotiableCapability
with the specified
* category
and capabilityName
.
*
* @param category The category this capability belongs to.
* @param capabilityName The name of this capability.
* @param generators A List
containing representations
* of the objects that generated this
* NegotiableCapability
or null, if
* there are none.
* @param descriptor The descriptor that describes the parameters for
* this class.
* @param isPreference Boolean specifying whether this class represents
* a preference or a non-preference.
*
* @throws IllegalArgumentException if category is null.
* @throws IllegalArgumentException if capabilityName is null.
* @throws IllegalArgumentException if descriptor is null.
* @throws IllegalArgumentException if any of the default values returned
* from the supplied descriptor's getParamDefaults() method is
* ParameterListDescriptor.NO_PARAMETER_DEFAULT. null should be used to
* represent the absence of a default.
* @throws IllegalArgumentException if any of the Class
* types returned from the supplied descriptor's getParamClasses() method
* does not implement Negotiable
.
*/
public NegotiableCapability(String category,
String capabilityName,
List generators,
ParameterListDescriptor descriptor,
boolean isPreference) {}
/**
* Returns the category of this NegotiableCapability
.
*/
public String getCategory() {}
/**
* Returns the name of this NegotiableCapability
.
*/
public String getCapabilityName() {}
/**
* Returns the List
containing representations of the
* objects that generated this NegotiableCapability
. This
* method will return null, if there are no generators for this
* NegotiableCapability
.
*/
public List getGenerators() {}
/**
* Set the specified List
as the generators for this
* NegotiableCapability
. A generator is a representation
* of the object that generated this NegotiableCapability
.
*
* @param generators The List
of generators.
*/
public void setGenerators(List generators) {}
/**
* Returns true if this NegotiableCapability
is a
* preference, false otherwise.
*/
public boolean isPreference() {}
/**
* Returns a single negotiated value from the Negotiable
that
* represents the set of valid values for the given parameter. This
* method uses the Negotiable.getNegotiatedValue
to get
* the negotiated value for the Negotiable
value of the
* parameter specified by parameterName
. If this
* NegotiableCapability
is a non-preference, then a valid
* Negotiable
must be present as the value of the specified
* parameter, and a single value from that Negotiable
will
* be returned. If this NegotiableCapability
is a preference
* the specified parameter may have a null
as its value.
* In this case, this null
will be returned as the
* negotiated value.
*
* @param parameterName The name of parameter to return the negotiated
* value for.
* @throws IllegalArgumentException if the parameterName is not one of
* those described by the associated ParameterListDescriptor
.
*/
public Object getNegotiatedValue(String parameterName) {}
/**
* Performs negotiation between this NegotiableCapability
* and the given NegotiableCapability
. Returns the common
* subset supported by this NegotiableCapability
and the given
* NegotiableCapability
if the negotiation is successful,
* null otherwise.
*
*
In order for the negotiation to be successful, the category and the
* capabilityName of the supplied NegotiableCapability
object
* must be the same as of this class. In addition, negotiation on each of
* the parameters must be successful. Since each parameter is represented
* as a Negotiable
, negotiation on it can be performed using
* the Negotiable.negotiate()
method. The
* NegotiableCapability
returned contains the same category,
* capabilityName as that of this class and also includes the negotiated
* values for each parameter. If the negotiation fails for any one
* parameter, the negotiation for the NegotiableCapability
s
* as a whole is said to fail and a null is returned. The result of
* negotiation between one non-preference and another is a non-preference,
* between a preference and a non-preference is a non-preference and
* that between two preferences is a preference, if the negotiation is
* successful.
*
* If this NegotiableCapability
is a non-preference, i.e
* the isPreference()
method returns false, and the
* supplied NegotiableCapability
argument is also a
* non-preference, then the negotiation will fail if the number and
* Class
of parameters in both the
* NegotiableCapability
objects is not the same.
* If either one of the NegotiableCapability
objects is
* a preference and the other is a non-preference, the number of
* parameters are not required to match. For those parameters whose names
* are the same in both the NegotiableCapability
objects,
* the Class
types have to match, otherwise the negotiation
* will fail. Those parameters that exist in the non-preference
* NegotiableCapability
object but not in the preference
* NegotiableCapability
object do not take part in the
* negotiation, but are directly set on the resultant
* NegotiableCapability
object if the negotiation
* is successful on the common parameters. Those parameters that
* exist in the preference NegotiableCapability
object but
* not in the non-preference NegotiableCapability
object
* are ignored, do not take part in the negotiation and are not
* reflected in the resultant NegotiableCapability
in the
* event of a successful negotiation. If both the
* NegotiableCapability
objects are preferences, then
* only the common parameters take part in the negotiation and the
* ones that aren't present in both the NegotiableCapability
s
* are directly set on the resultant NegotiableCapability
* object if the negotiation is successful on the common parameters.
* For the common parameters, the Class
types have to match,
* otherwise the negotiation will fail. The check for the compatibility
* of the ParameterListDescriptor
of the supplied
* NegotiableCapability
with the current
* NegotiableCapability
's ParameterListDescriptor
* is done using the areParameterListDescriptorsCompatible()
* method.
* It may be noted that the ParameterListDescriptor
of
* the NegotiableCapability
returned as a result of a
* successful negotiation will implement the getParamDefaults() and
* the getParamValueRange() methods in terms of the values returned
* from the same methods on the ParameterListDescriptor
* associated with this class, if the negotiation took place between
* two preferences, or from the same methods on the
* ParameterListDescriptor
associated with the
* non-preference otherwise.
*
*
If the supplied NegotiableCapability
is null, then
* the negotiation will fail and null will be returned.
*
* @param capability The NegotiableCapability
to negotiate
* with.
* @returns the NegotiableCapability
that is the result of a
* successful negotiation, null if the negotiation failed.
*/
public NegotiableCapability negotiate(NegotiableCapability capability) {}
/**
* Returns true if the ParameterListDescriptor
of the
* supplied NegotiableCapability
is compatible with the
* ParameterListDescriptor
of this class for negotiation
* purposes. If both the NegotiableCapability
objects are
* non-preferences, both the number of parameters as well as the
* Class
type of the parameters has to match for this
* method to return true. If either one or both of the
* NegotiableCapability
objects is a preference, then
* the Class
type of the same named parameters in both
* the NegotiableCapability
object's
* ParameterListDescriptor
s has to match for this
* method to return true.
*
* @param other The NegotiableCapability
to check
* compatibility for negotiation purposes for.
* @throws IllegalArgumentException if other is null.
*/
public boolean areParameterListDescriptorsCompatible(NegotiableCapability
other) {}
/***************** Overridden methods from ParameterList *****************/
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values set on this class
* must be a Negotiable
.
*
* @param paramName a String
naming a parameter.
* @param b a byte
value for the parameter.
*
* @throws IllegalArgumentException since the value being set is not a
* Negotiable
.
*/
public ParameterList setParameter(String paramName, byte b) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values set on this class
* must be a Negotiable
.
*
* @param paramName a String
naming a parameter.
* @param b a boolean
value for the parameter.
*
* @throws IllegalArgumentException since the value being set is not a
* Negotiable
.
*/
public ParameterList setParameter(String paramName, boolean b) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values set on this class
* must be a Negotiable
.
*
* @param paramName a String
naming a parameter.
* @param c a char
value for the parameter.
*
* @throws IllegalArgumentException since the value being set is not a
* Negotiable
.
*/
public ParameterList setParameter(String paramName, char c) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values set on this class
* must be a Negotiable
.
*
* @param paramName a String
naming a parameter.
* @param s a short value for the parameter.
*
* @throws IllegalArgumentException since the value being set is not a
* Negotiable
.
*/
public ParameterList setParameter(String paramName, short s) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values set on this class
* must be a Negotiable
.
*
* @param paramName a String
naming a parameter.
* @param i an int
value for the parameter.
*
* @throws IllegalArgumentException since the value being set is not a
* Negotiable
.
*/
public ParameterList setParameter(String paramName, int i) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values set on this class
* must be a Negotiable
.
*
* @param paramName a String
naming a parameter.
* @param l a long
value for the parameter.
*
* @throws IllegalArgumentException since the value being set is not a
* Negotiable
.
*/
public ParameterList setParameter(String paramName, long l) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values set on this class
* must be a Negotiable
.
*
* @param paramName a String
naming a parameter.
* @param f a float
value for the parameter.
*
* @throws IllegalArgumentException since the value being set is not a
* Negotiable
.
*/
public ParameterList setParameter(String paramName, float f) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values set on this class
* must be a Negotiable
.
*
* @param paramName a String
naming a parameter.
* @param d a double
value for the parameter.
*
* @throws IllegalArgumentException since the value being set is not a
* Negotiable
.
*/
public ParameterList setParameter(String paramName, double d) {}
/**
* Overrides the superclass method to ensure only a Negotiable
* object can be added as the value of the parameter.
*
* @param paramName A String
naming a parameter.
* @param obj An Object value for the parameter.
*
* @throws IllegalArgumentException if obj is not an instance of
* Negotiable
.
*/
public ParameterList setParameter(String paramName, Object obj) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values in this class
* are Negotiable
and therefore cannot be returned as
* a primitive data type.
*
* @param paramName the name of the parameter to be returned.
* @throws IllegalArgumentException since a Negotiable
value
* cannot be returned as a primitive data type.
*/
public byte getByteParameter(String paramName) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values in this class
* are Negotiable
and therefore cannot be returned as
* a primitive data type.
*
* @param paramName the name of the parameter to be returned.
* @throws IllegalArgumentException since a Negotiable
value
* cannot be returned as a primitive data type.
*/
public boolean getBooleanParameter(String paramName) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values in this class
* are Negotiable
and therefore cannot be returned as
* a primitive data type.
*
* @param paramName the name of the parameter to be returned.
* @throws IllegalArgumentException since a Negotiable
value
* cannot be returned as a primitive data type.
*/
public char getCharParameter(String paramName) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values in this class
* are Negotiable
and therefore cannot be returned as
* a primitive data type.
*
* @param paramName the name of the parameter to be returned.
* @throws IllegalArgumentException since a Negotiable
value
* cannot be returned as a primitive data type.
*/
public short getShortParameter(String paramName) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values in this class
* are Negotiable
and therefore cannot be returned as
* a primitive data type.
*
* @param paramName the name of the parameter to be returned.
* @throws IllegalArgumentException since a Negotiable
value
* cannot be returned as a primitive data type.
*/
public int getIntParameter(String paramName) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values in this class
* are Negotiable
and therefore cannot be returned as
* a primitive data type.
*
* @param paramName the name of the parameter to be returned.
* @throws IllegalArgumentException since a Negotiable
value
* cannot be returned as a primitive data type.
*/
public long getLongParameter(String paramName) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values in this class
* are Negotiable
and therefore cannot be returned as
* a primitive data type.
*
* @param paramName the name of the parameter to be returned.
* @throws IllegalArgumentException since a Negotiable
value
* cannot be returned as a primitive data type.
*/
public float getFloatParameter(String paramName) {}
/**
* Overrides the method in ParameterListImpl
to throw
* an IllegalArgumentException since parameter values in this class
* are Negotiable
and therefore cannot be returned as
* a primitive data type.
*
* @param paramName the name of the parameter to be returned.
* @throws IllegalArgumentException since a Negotiable
value
* cannot be returned as a primitive data type.
*/
public double getDoubleParameter(String paramName) {}
}
2.3 Class NegotiationCapabilitySet
This class serves as an aggregation of NegotiableCapability objects. It
allows multiple NegotiableCapability objects to be added to it. This
would be the class that would need to be created to represent the
capabilities of the server and the client machine. The preferences
specified by the user for the negotiation process will also be specified
using this class. This class allows for the specification of the entire
set of a machine's capabilities in one object. So if this object had to
be retrieved from the server, it could be done by a single connection to
the server, multiple requests to the server would not have to be made
for Capabilities of different types, all could be transmitted at one go.
This class allows for multiple NegotiableCapability objects with the
same category and same capabilityName to be added to it.
This class also allows for itself to be classified as either a
preference or a non-preference. For a non-preference
NegotiationCapabilitySet, only non-preference NegotiableCapability
objects can be added to it, otherwise an IllegalArgumentException is
thrown from the add method. Similarly a preference
NegotiationCapabilitySet allows only preference NegotiableCapability
objects to be added to it.
Here is the API specification for this class:
package javax.media.jai.remote;
/**
* This class is an aggregation of NegotiableCapability
objects.
* This class can be used to represent all the capabilities of a machine.
*
*
This class can be classified as either a preference or a non-preference.
* For an explanation of the concept of preference, refer to the class
* comments on javax.media.jai.remote.NegotiableCapability
.
*
*
If multiple NegotiableCapability
objects with the
* same category and capability name are added to this class, the
* NegotiableCapability
added earliest has the highest
* preference.
*
*
All names are treated in a case-retentive and case-insensitive manner.
*
* @since 1.1
*/
public class NegotiableCapabilitySet implements Serializable {
/**
* Creates a NegotiableCapabilitySet
. The
* isPreference
argument specifies whether this
* NegotiableCapabilitySet
should be treated as a preference
* or non-preference. If this NegotiableCapabilitySet
is
* specified to be a non-preference, only non-preference
* NegotiableCapability
's will be allowed to be added to it,
* otherwise an IllegalArgumentException
will be thrown
* at the time of addition. Similarly only preference
* NegotiableCapability
objects can be added to this
* NegotiableCapabilitySet
if isPreference
* is true.
*
* @param isPreference a boolean that specifies whether the component
* NegotiableCapability
's are preferences.
*/
public NegotiableCapabilitySet(boolean isPreference) {}
/**
* Returns true if this NegotiableCapabilitySet
is an
* aggregation of preference NegotiableCapability
's,
* false otherwise.
*/
public boolean isPreference() {}
/**
* Adds a new NegotiableCapability
to this
* NegotiableCapabilitySet
. If a
* NegotiableCapability
with the same category and same
* capability name as the one currently being added has been added
* previously, the previous one will have a higher preference.
*
* @param capability The NegotiableCapability
to be added.
* @throws IllegalArgumentException if capability is null.
* @throws IllegalArgumentException if isPreference()
* returns false, and capability is a preference
* NegotiableCapability
.
* @throws IllegalArgumentException if isPreference()
* returns true, and capability is a non-preference
* NegotiableCapability
.
*/
public void add(NegotiableCapability capability) {}
/**
* Removes the specified NegotiableCapability
from this
* NegotiableCapabilitySet
. If the specified
* NegotiableCapability
was not added previously, an
* IllegalArgumentException
will be thrown.
*
* @param capability The NegotiableCapability
to be removed.
* @throws IllegalArgumentException if capability is null.
* @throws IllegalArgumentException if the specified
* NegotiableCapabilitySet
was not added previously.
*/
public void remove(NegotiableCapability capability) {}
/**
* Returns all the NegotiableCapability
s with the given
* category and capability name added previously, as a List
.
* If none were added, returns an empty List
.
*
* @param category The category of the NegotiableCapability
.
* @param capabilityName The name of the NegotiableCapability
.
*
* @throws IllegalArgumentException if category is null.
* @throws IllegalArgumentException if capabilityName is null.
*/
public List get(String category, String capabilityName) {}
/**
* Returns all the NegotiableCapability
s with the given
* category as a List
. Returns an empty List
* if no such NegotiableCapability
s were added.
*
* @param category The category of the NegotiableCapability
s
* to return.
* @throws IllegalArgumentException if category is null.
*/
public List get(String category) {}
/**
* Returns the category of all the NegotiableCapability
* objects that have been added previously, as a List
.
* Returns an empty List
, if no
* NegotiableCapability
objects have been added.
*
*
The returned List
does not contain any
* duplicates.
*/
public List getCategories() {}
/**
* Returns the capability names of all the
* NegotiableCapability
objects that have been added
* previously, as a List
. Returns an empty
* List
if no such NegotiableCapability
* objects have been added.
*
*
The returned List
does not contain any
* duplicates.
*
* @param category The category of the NegotiableCapability
.
* @throws IllegalArgumentException if category is null.
*/
public List getCapabilityNames(String category) {}
/**
* Returns the common subset supported by this
* NegotiableCapabilitySet
and the given
* NegotiableCapabilitySet
, if the negotiation succeeds.
* This method returns null if negotiation fails for all categories.
*
*
For those categories that are common to both the
* NegotiableCapabilitySet
objects, negotiation is
* performed on a per category basis. Within each category, negotiation
* is performed on a per capabilityName basis. The categories which exist
* only in one or the other NegotiableCapabilitySet
are
* not negotiated upon and do not show up in the resultant
* NegotiableCapabilitySet
, if the negotiation is successful.
* If this class contains 'm' NegotiableCapability
objects
* for the same category and capabilityName for which the
* NegotiableCapabilitySet
being negotiated with contains
* 'n' NegotiableCapability
objects, then the negotiation
* for this category and capabilityName will require m x n number of
* negotiations between two NegotiableCapability
objects.
* The ones that succeed will produce new NegotiableCapability
* objects which will be added to the returned
* NegotiableCapabilitySet
.
*
*
If the supplied NegotiableCapabilitySet
is null,
* then the negotiation will fail, and null will be returned.
*
* @param other The NegotiableCapabilitySet
to negotiate with.
*/
public NegotiableCapabilitySet negotiate(NegotiableCapabilitySet other) {}
/**
* Returns the single NegotiableCapability
that is the
* negotiated result for the given category from the current class.
* Returns null if negotiation for this category failed. If the
* negotiation is successful, then this method will return the most
* prefered (the one that was added first i.e. the one that is first
* in the list) NegotiableCapability
from the list of
* NegotiableCapability
that are valid for this category.
*
* @param category The category to find the negotiated result for.
* @throws IllegalArgumentException if category is null.
*/
public NegotiableCapability getNegotiatedValue(String category) {}
/**
* Performs negotiation with the given NegotiableCapabilitySet
* for the specified category and returns the single
* NegotiableCapability
that is the negotiated result for
* the given category, if the negotiation succeeds, null
* otherwise.
*
*
Negotiation is only performed for the specified category. For
* the specified category, if there are 'm'
* NegotiableCapability
objects for which the
* NegotiableCapabilitySet
being negotiated with contains
* 'n' NegotiableCapability
objects, then the negotiation
* for this category may require m x n number of negotiations at a
* maximum and one negotiation at a minimum as the negotiation process
* stops as soon as a negotiation is successful. The results of this
* successful negotiation are then returned. If all the m x n
* negotiations fail, null is returned.
*
*
If the supplied NegotiableCapabilitySet
is null,
* then the negotiation will fail and null will be returned.
*
* @param other The NegotiableCapabilitySet
to negotiate with.
* @param category The category to negotiate for.
* @throws IllegalArgumentException if category is null.
*/
public NegotiableCapability getNegotiatedValue(NegotiableCapabilitySet
other, String category) {}
/**
* Returns true if no NegotiableCapability
objects have been
* added.
*/
public boolean isEmpty() {}
}
2.4 RemoteJAI.negotiate method
Finally we have the two methods that will be most often used in JAI
Network Imaging for performing negotiation amongst the client and server
capabilities according to user specified preferences. Here are the
signatures for these methods:
/**
* This method negotiates the capabilities to be used in the remote
* communication. Upon completion of the negotiation process,
* this method returns a NegotiableCapabilitySet
which
* contains an aggregation of the NegotiableCapability
* objects that represent the results of negotiation. If the negotiation
* fails, null will be returned.
*
*
The negotiation process treats the serverCapabilities and the
* clientCapabilities as non-preferences and will throw an
* IllegalArgumentException
if the
* isPreference
method for either of these returns
* true. The preferences NegotiableCapabilitySet
should
* return true from its isPreference
method, otherwise an
* IllegalArgumentException
will be thrown. The negotiation
* is done in accordance with the rules described in the class comments
* for NegotiableCapability
.
*
*
If either the serverCapabilities or the clientCapabilities
* is null, then the negotiation will fail, and null will be returned.
* If preferences is null, the negotiation will become a two-way
* negotiation between the two non-null
* NegotiableCapabilitySet
s.
*
* @param preferences The user preferences for the negotiation.
* @param serverCapabilities The capabilities of the server.
* @param clientCapabilities The capabilities of the client.
*
* @throws IllegalArgumentException if serverCapabilities is a
* preference, i.e., if it's isPreference()
method
* returns true.
* @throws IllegalArgumentException if clientCapabilities is a
* preference, i.e., if it's isPreference()
method
* returns true.
* @throws IllegalArgumentException if preferences is a
* non-preference, i.e., if it's isPreference()
method
* returns false.
*/
public static NegotiableCapabilitySet negotiate(
NegotiableCapabilitySet preferences,
NegotiableCapabilitySet serverCapabilities,
NegotiableCapabilitySet clientCapabilities) {}
/**
* This method negotiates the capabilities to be used in the remote
* communication for the given category. Upon completion of the
* negotiation process, this method returns a
* NegotiableCapability
object, that represents the result
* of the negotiation for the given category. If the negotiation fails,
* null will be returned.
*
*
The negotiation process treats the serverCapabilities and the
* clientCapabilities as non-preferences and will throw an
* IllegalArgumentException
if the
* isPreference
method for either of these returns
* true. The preferences NegotiableCapabilitySet
should
* return true from its isPreference
method or an
* IllegalArgumentException
will be thrown. The negotiation
* is done in accordance with the rules described in the class comments
* for NegotiableCapability
.
*
*
If either the serverCapabilities or the clientCapabilities
* is null, then the negotiation will fail, and null will be returned.
* If preferences is null, the negotiation will become a two-way
* negotiation between the two non-null
* NegotiableCapabilitySet
s.
*
* @param preferences The user preferences for the negotiation.
* @param serverCapabilities The capabilities of the server.
* @param clientCapabilities The capabilities of the client.
* @param category The category to perform the negotiation on.
*
* @throws IllegalArgumentException if preferences is a
* non-preference, i.e., if it's isPreference()
method
* returns false.
* @throws IllegalArgumentException if serverCapabilities is a
* preference, i.e., if it's isPreference()
method
* returns true.
* @throws IllegalArgumentException if clientCapabilities is a
* preference, i.e., if it's isPreference()
method
* returns true.
* @throws IllegalArgumentException if category is null.
*/
public static NegotiableCapability negotiate(
NegotiableCapabilitySet preferences,
NegotiableCapabilitySet serverCapabilities,
NegotiableCapabilitySet clientCapabilities,
String category) {}
3. Utility classes
It is felt that some convenience classes are needed that make the job of
converting a data type often used as a parameter value into an Object
implementing the Negotiable interface easier. Therefore the following
three classes are being proposed:
3.1 Class NegotiableNumericRange
package javax.media.jai.remote;
/**
* A class that wraps a Range
which contains numeric elements,
* to implement the Negotiable
interface.
* NegotiableNumericRange
is a convenience class to specify a
* Negotiable
parameter whose valid numeric values are
* specified by a Range
.
*
* @since 1.1
*/
public class NegotiableNumericRange implements Negotiable {
/**
* Creates a NegotiableNumericRange
given an
* Range
containing elements of a subclass of
* Number
.
*
* @throws IllegalArgumentException if range is null.
* @throws IllegalArgumentException if the elements of the supplied range
* are not a Number
subclass.
*/
public NegotiableNumericRange(Range range) {}
/**
* Returns the Range
of values which are currently valid
* for this class, null if there are no valid values.
*/
public Range getRange() {}
/**
* Returns a NegotiableNumericRange
that contains the range
* of values that are common to this NegotiableNumericRange
* and the one supplied. If the supplied Negotiable
is not
* a NegotiableNumericRange
with its elements being of the
* same Class
as this class', or if there is no common
* range of values, the negotiation will fail and
* null
will be returned.
*
* @param other The Negotiable
to negotiate with.
*/
public Negotiable negotiate(Negotiable other) {}
/**
* Returns a single value that is valid for this
* NegotiableNumericRange
. The returned value is the lowest
* value contained in this NegotiableNumericRange
if the
* range is not unbounded on the minimum end, or the highest value
* in the range, if the range is unbounded on the minimum end. If both
* ends are unbounded, 0 will be returned wrapped in the appropriate
* Number
wrapper. Returns null
if there
* are no valid elements in this NegotiableNumericRange
.
*/
public Object getNegotiatedValue() {}
/**
* Returns the Class
of the Object returned as the result
* of the negotiation. This will be a subclass of Number
.
*/
public Class getNegotiatedValueClass() {}
}
3.2 Class NegotiableCollection
package javax.media.jai.remote;
/**
* A class that wraps an Collection
to implement the
* Negotiable
interface. NegotiableCollection
* is a convenience class to specify a Negotiable
value for
* a parameter whose valid values are contained in an Collection
.
*
* @since 1.1
*/
public class NegotiableCollection implements Negotiable {
/**
* Creates a NegotiableCollection
given an
* Collection
.
*
* @throws IllegalArgumentException if collection is null.
* @throws IllegalArgumentException if all the elements of collection
* are not of the same Class
type.
*/
public NegotiableCollection(Collection collection) {}
/**
* Creates a NegotiableCollection
given an array of
* Object
s. The elements of the Object
* array are treated as being the elements of an Collection
.
*
* @throws IllegalArgumentException if objects is null.
* @throws IllegalArgumentException if all the elements of objects are not
* of the same Class
type.
*/
public NegotiableCollection(Object objects[]) {}
/**
* Returns the Collection
of values which are currently
* valid for this class, null if there are no valid values.
*/
public Collection getCollection() {}
/**
* Returns a NegotiableCollection
that contains those
* elements that are common to this NegotiableCollection
* and the one supplied. If the supplied Negotiable
is not
* a NegotiableCollection
with its elements being of the
* same Class
as this class', or if there are no common
* elements, the negotiation will fail and null
(signifying
* the failure of the negotiation) will be returned.
*
* @param other The Negotiable
to negotiate with.
*/
public Negotiable negotiate(Negotiable other) {}
/**
* Returns a single value that is valid for this
* NegotiableCollection
. The returned value is the first
* element contained in this NegotiableCollection
. Returns
* null
if there are no valid elements in this
* NegotiableCollection
.
*/
public Object getNegotiatedValue() {}
/**
* Returns the Class
of the Object returned as the result
* of the negotiation. If the Collection
used to construct
* this NegotiableCollection
was empty, i.e. had no
* elements, the Class
of the elements is indeterminate,
* therefore null will be returned from this method in such a case.
*/
public Class getNegotiatedValueClass() {}
}
3.3 Class NegotiableNumeric
package javax.media.jai.remote;
/**
* A class that wraps a numeric primitive data type or a subclass of
* Number
to implement the Negotiable
interface.
* NegotiableNumeric
is a convenience class to specify a
* Negotiable
value for a parameter which has a single
* valid numeric value.
*
* @since 1.1
*/
public class NegotiableNumeric implements Negotiable {
/**
* Creates a NegotiableNumeric
given a byte
.
*
* @param b The byte
to be wrapped to implement
* Negotiable
.
*/
public NegotiableNumeric(byte b) {}
/**
* Creates a NegotiableNumeric
given a short
.
*
* @param s The short
to be wrapped to implement
* Negotiable
.
*/
public NegotiableNumeric(short s) {}
/**
* Creates a NegotiableNumeric
given an int
.
*
* @param i The int
to be wrapped to implement
* Negotiable
.
*/
public NegotiableNumeric(int i) {}
/**
* Creates a NegotiableNumeric
given a long
.
*
* @param l The long
to be wrapped to implement
* Negotiable
.
*/
public NegotiableNumeric(long l) {}
/**
* Creates a NegotiableNumeric
given a float
.
*
* @param f The float
to be wrapped to implement
* Negotiable
.
*/
public NegotiableNumeric(float f) {}
/**
* Creates a NegotiableNumeric
given a double
.
*
* @param d The double
to be wrapped to implement
* Negotiable
.
*/
public NegotiableNumeric(double d) {}
/**
* Creates a NegotiableNumeric
given a Number
.
*
* @param n The Number
to be wrapped to implement
* Negotiable
.
*
* @throws IllegalArgumentException if n is null.
*/
public NegotiableNumeric(Number n) {}
/**
* Returns the Number
that is currently the valid value
* for this class. A valid primitive data type value, such as int,
* will be returned as a member of the corresponding wrapper class,
* such as Integer
.
*/
public Number getNumber() {}
/**
* Returns a NegotiableNumeric
that contains the value
* that is common to this NegotiableNumeric
* and the one supplied, i.e the Number
encapsulated in
* both the NegotiableNumeric
are equal. If the supplied
* Negotiable
is not a NegotiableNumeric
with
* its element being of the same Class
as this class', or
* if there is no common value (i.e the values are not equal), the
* negotiation will fail and null
will be returned.
*
* @param other The Negotiable
to negotiate with.
*/
public Negotiable negotiate(Negotiable other) {}
/**
* Returns the result of the negotiation as a Number
* subclass. Values belonging to a base type, such as int
,
* will be returned as a member of the corresponding Number
* subclass, such as Integer
.
*/
public Object getNegotiatedValue() {}
/**
* Returns the Class
of the negotiated value. Values
* belonging to a base type, such as int
, will be returned
* as a member of the corresponding Number
subclass, such as
* Integer
. The Class
returned similarly will be
* a Number
subclass.
*/
public Class getNegotiatedValueClass() {}
/**
* A convenience method to return the single negotiated value as a
* byte
.
*
* @throws ClassCastException if the value is of a different Class type.
*/
public byte getNegotiatedValueAsByte() {}
/**
* A convenience method to return the single negotiated value as a
* short
.
*
* @throws ClassCastException if the value is of a different Class type.
*/
public short getNegotiatedValueAsShort() {}
/**
* A convenience method to return the single negotiated value as a
* int
.
*
* @throws ClassCastException if the value is of a different Class type.
*/
public int getNegotiatedValueAsInt() {}
/**
* A convenience method to return the single negotiated value as a
* long
.
*
* @throws ClassCastException if the value is of a different Class type.
*/
public long getNegotiatedValueAsLong() {}
/**
* A convenience method to return the single negotiated value as a
* float
.
*
* @throws ClassCastException if the value is of a different Class type.
*/
public float getNegotiatedValueAsFloat() {}
/**
* A convenience method to return the single negotiated value as a
* double
.
*
* @throws ClassCastException if the value is of a different Class type.
*/
public double getNegotiatedValueAsDouble() {}
}