1 /* 2 * $RCSfile: NegotiableCapability.java,v $ 3 * 4 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 5 * 6 * Use is subject to license terms. 7 * 8 * $Revision: 1.1 $ 9 * $Date: 2005/02/11 04:57:51 $ 10 * $State: Exp $ 11 */package com.lightcrafts.mediax.jai.remote; 12 13 import java.io.Serializable; 14 import java.util.ArrayList; 15 import java.util.Enumeration; 16 import java.util.List; 17 import java.util.Hashtable; 18 import java.util.Vector; 19 20 import com.lightcrafts.mediax.jai.ParameterList; 21 import com.lightcrafts.mediax.jai.ParameterListImpl; 22 import com.lightcrafts.mediax.jai.ParameterListDescriptor; 23 import com.lightcrafts.mediax.jai.ParameterListDescriptorImpl; 24 import com.lightcrafts.mediax.jai.util.CaselessStringKey; 25 26 /** 27 * A <code>NegotiableCapability</code> represents the capabilities of an 28 * object. These capabilities can be used to negotiate with the capabilities 29 * of a similar object. Each <code>NegotiableCapability</code> is 30 * characterized by the category it belongs to, as returned by the 31 * <code>getCategory()</code> method, by the actual name of the capability 32 * it represents, as returned by the <code>getCapabilityName()</code> method 33 * and by a list of parameter name-value pairs that define the 34 * <code>NegotiableCapability</code>. Every <code>NegotiableCapability</code> 35 * object also holds references to a representation of the objects that 36 * generated it. These can be accessed via the <code>getGenerators()</code> 37 * method. The creator or generator of a <code>NegotiableCapability</code> 38 * can supply any representation of itself while constructing the 39 * <code>NegotiableCapability</code>. No interpretation is forced by this 40 * class, that is left upto the generating class and to the class that 41 * utilizes the <code>NegotiableCapability</code> to get the negotiated 42 * results. The negotiation is performed by the 43 * <code>negotiate()</code> method. Since this method returns a 44 * <code>NegotiableCapability</code>, this method can be used repeatedly to 45 * perform multiple negotiations. If the negotiation fails, null will be 46 * returned from the <code>negotiate()</code> method. Every successful 47 * negotiation will add the generator of the <code>NegotiableCapability</code> 48 * negotiated with, to the set of generators of the resultant 49 * <code>NegotiableCapability</code>. The generators are intended to help 50 * the user of <code>NegotiableCapability</code> identify the object that 51 * created the <code>NegotiableCapability</code> and therefore the object 52 * that can be relied on to be able to handle the parameters agreed on during 53 * negotiation. For example, if the negotiation is to be performed to choose 54 * a compatible <code>TileEncoder</code>, <code>TileDecoder</code> pair 55 * for data compression/decompression, the category would be "tileCodec", 56 * the capabilityName would be a specific tile encoding format, say "jpeg" 57 * and the generator for the <code>NegotiableCapability</code> could be the 58 * <code>TileDecoderFactory</code>/<code>TileEncoderFactory</code> object 59 * that generated that <code>NegotiableCapability</code>. After a 60 * successful negotiation, the <code>NegotiableCapability</code> that is 61 * the result of the negotiation will contain a 62 * <code>TileEncoderFactory</code> and a <code>TileDecoderFactory</code> 63 * object as the generators for that <code>NegotiableCapability</code>. 64 * These two objects can then be retrieved using the 65 * <code>getGenerators</code> method and used to do the encoding and 66 * decoding and can be relied to be compatible, since the negotiation 67 * was successful between their respective 68 * <code>NegotiableCapability</code> objects. 69 * 70 * <p> The number, name, Class type and default values for the parameters in 71 * this class is specified by the <code>ParameterListDescriptor</code> 72 * returned from <code>getParameterListDescriptor</code> method. Each 73 * parameter value in this class must be a class that implements the 74 * <code>Negotiable</code> interface. It is for this reason that all of 75 * the <code>ParameterList</code> set methods that take primitive data 76 * types as arguments and all the <code>ParameterList</code> get methods 77 * that return primitive data types are overridden in this class 78 * to throw an IllegalArgumentException, as this class only accepts 79 * <code>Negotiable</code>'s as parameter values in order to facilitate 80 * negotiation on parameters. It may be noted that the implementation of 81 * the version of <code>ParameterList.setParameter</code> that takes 82 * an <code>Object</code> as the parameter value, in this class 83 * throws an <code>IllegalArgumentException</code> if the supplied 84 * <code>Object</code> to be set does not implement the 85 * <code>Negotiable</code> interface. If no <code>Negotiable</code> value is 86 * available as the value for a particular parameter, <code>null</code> 87 * should be set as the value. A null value returned from the 88 * <code>getNegotiatedValue(String)</code> method is however valid, since 89 * the single value result of the negotiation can be null. 90 * Similarly the <code>Object</code> returned from the 91 * <code>ParameterList.getObjectParameter</code> implementation in this class 92 * is always a class that implements the <code>Negotiable</code> interface, 93 * and not a wrapper class of a primitive data type, as documented for this 94 * method in <code>ParameterList</code>. The 95 * <code>getParamValueRange(String parameterName)</code> and the 96 * <code>getEnumeratedParameterValues(String parameterName)</code> methods 97 * of the <code>ParameterListDescriptor</code> returned from 98 * <code>getParameterListDescriptor</code> method of this class should be 99 * implemented to return null, since these methods are not meaningful when 100 * the parameter values are <code>Negotiable</code>. 101 * 102 * <p>In order for the negotiation to be successful, the category and the 103 * capabilityName of the two <code>NegotiableCapability</code> objects must be 104 * the same. In addition, negotiation on each of the parameters must be 105 * successful. Since each parameter is represented as a 106 * <code>Negotiable</code>, negotiation on it can be performed using the 107 * <code>Negotiable.negotiate(Negotiable negotiable)</code> method. The 108 * <code>NegotiableCapability</code> returned from the 109 * <code>negotiate(NegotiableCapability capability)</code> method 110 * contains the same category and capabilityName as that of the 111 * <code>NegotiableCapability</code> objects being negotiated as well as 112 * including the negotiated values for each parameter. If the negotiation fails 113 * for any one parameter, the negotiation for the 114 * <code>NegotiableCapability</code>s as a whole is said to fail (unless 115 * preference <code>NegotiableCapability</code> objects are involved in 116 * the negotiation, as described below) and a null is returned. 117 * 118 * <p> In order to get a single negotiated value from the set of valid 119 * values represented as the <code>Negotiable</code> value for a parameter, 120 * the <code>getNegotiatedValue(String parameterName)</code> method can be 121 * called. If the negotiation was successful, an <code>Object</code> which 122 * is the negotiated result will be returned, otherwise a 123 * <code>null</code> (signifying that the negotiation failed) will be 124 * returned. 125 * 126 * <p> <code>NegotiableCapability</code> objects can be classified as being 127 * either preferences or non-preferences. A non-preference describes the 128 * capabilities of an object completely by specifying <code>Negotiable</code> 129 * values for each and every parameter defined in the 130 * <code>ParameterListDescriptor</code> returned from 131 * <code>getParameterListDescriptor</code> method. A non-preference is allowed 132 * to not specify the value of a particular parameter, if a default value 133 * for that parameter exists (i.e. the default value is not 134 * <code>null</code>). When a non-preference is created, all parameter 135 * values are initialized to their default values, and therefore if any 136 * parameter value is left unset at the time of the negotiation, the 137 * default value that was set at time of initialization will be used for 138 * the negotiation. If the default value happened to be <code>null</code>, 139 * the negotiation in this case would fail. Note that all references to 140 * values in this paragraph, whether default or not, refered to the 141 * objects implementing the <code>Negotiable</code> interface that are 142 * the values set for a particular parameter name. 143 * 144 * A preference on the other hand specifies preferences for the selection of 145 * a prefered set of (maybe even a single) parameter value from the set of 146 * valid ones at negotiation time. 147 * A preference is allowed to specify <code>Negotiable</code> parameter 148 * values for a subset of parameters, if it so wishes. For those parameters 149 * for whom the preference does not specify values, the preference is 150 * indicating a don't-care attitude, and the result of the negotiation for 151 * such a parameter will be the <code>Negotiable</code> value from the 152 * non-preference object the preference is negotiating with. Note that the 153 * default value is not substituted for a parameter whose value has not been 154 * specified in a preference. A <code>NegotiableCapability</code> which is 155 * a preference should return true from the <code>isPreference</code> method, 156 * a non-preference object that defines values for all the parameters (or 157 * relies on defaults) should return false from this method. As a rule, the 158 * result of negotiation between one non-preference and another is a 159 * non-preference, between a preference and a non-preference is a 160 * non-preference and that between two preferences is a preference, if 161 * the negotiation is successful. It may be noted that preferences are 162 * not expected to specify their generators, since in general, preferences 163 * don't come from objects that can support them. However if generators are 164 * specified within a preference, they will be added to the set of generators 165 * of the resultant <code>NegotiableCapability</code> in the event of a 166 * successful negotiation. 167 * 168 * <p> Negotiation between a preference and a non-preference 169 * <code>NegotiableCapability</code> results in a non-preference 170 * <code>NegotiableCapability</code>. For each parameter, if a value is 171 * specified (i.e the value is not <code>null</code>) 172 * in both the preference and the non-preference, then if these values 173 * have a common subset, the negotiation will succeed on this parameter, 174 * if there is no commonality, then the negotiation will fail on this 175 * parameter and thus also fail as a whole. If the preference doesn't 176 * specify a value for a parameter (i.e the value is <code>null</code>), 177 * then the value specified by the non-preference for that same parameter 178 * is chosen as a result of the successful negotiation on that parameter. 179 * 180 * <p> Negotiation between two preference <code>NegotiableCapability</code> 181 * objects results in a preference <code>NegotiableCapability</code>. For 182 * each parameter, if a value is specified (i.e the value is not 183 * <code>null</code>) in both the preference objects, the negotiation on 184 * that parameter will have a value which is the portion that is common 185 * to both. If there is no commonality, negotiation will fail on this 186 * parameter (<code>null</code> will be returned) and thus also fail as 187 * a whole. If the value for a particular parameter is specified in one 188 * preference and not in the other, the negotiated value will be the one 189 * specified. If for a particular parameter, no value is specified in 190 * either preference, the negotiated value for that parameter will be 191 * <code>null</code>, and the negotiation as a whole on the 192 * <code>NegotiableCapability</code> will not fail. 193 * 194 * <p> When a preference <code>NegotiableCapability</code> is constructed, 195 * the values of all the parameters defined in the 196 * <code>ParameterListDescriptor</code> returned from 197 * <code>getParameterListDescriptor</code> method, are initialized to 198 * <code>null</code>. <code>null</code> within this class represents a 199 * value that has not been specified. Such values are only allowed on 200 * a preference <code>NegotiableCapability</code>. On the other hand when 201 * a non-preference <code>NegotiableCapability</code> is 202 * constructed, all the values are initialized to their default values. 203 * 204 * <p>All names are treated in a case-retentive and case-insensitive manner. 205 * 206 * @since JAI 1.1 207 */ 208 public class NegotiableCapability extends ParameterListImpl implements Serializable { 209 210 private String category; 211 private String capabilityName; 212 private List generators; 213 private boolean isPreference = false; 214 215 /** 216 * Creates a <code>NegotiableCapability</code> with the specified 217 * <code>category</code> and <code>capabilityName</code>. 218 * 219 * @param category The category this capability belongs to. 220 * @param capabilityName The name of this capability. 221 * @param generators A <code>List</code> containing representations 222 * of the objects that generated this 223 * <code>NegotiableCapability</code> or null, if 224 * there are none. 225 * @param descriptor The descriptor that describes the parameters for 226 * this class. 227 * @param isPreference Boolean specifying whether this class represents 228 * a preference or a non-preference. 229 * 230 * @throws IllegalArgumentException if category is null. 231 * @throws IllegalArgumentException if capabilityName is null. 232 * @throws IllegalArgumentException if descriptor is null. 233 * @throws IllegalArgumentException if any of the default values returned 234 * from the supplied descriptor's getParamDefaults() method is 235 * ParameterListDescriptor.NO_PARAMETER_DEFAULT. null should be used to 236 * represent the absence of a default. 237 * @throws IllegalArgumentException if any of the <code>Class</code> 238 * types returned from the supplied descriptor's getParamClasses() method 239 * does not implement <code>Negotiable</code>. 240 */ NegotiableCapability(String category, String capabilityName, List generators, ParameterListDescriptor descriptor, boolean isPreference)241 public NegotiableCapability(String category, 242 String capabilityName, 243 List generators, 244 ParameterListDescriptor descriptor, 245 boolean isPreference) { 246 super(descriptor); 247 248 if (category == null) { 249 throw new IllegalArgumentException( 250 JaiI18N.getString("NegotiableCapability0")); 251 } 252 253 if (capabilityName == null) { 254 throw new IllegalArgumentException( 255 JaiI18N.getString("NegotiableCapability1")); 256 } 257 258 ParameterListDescriptor desc = getParameterListDescriptor(); 259 int numParams = desc.getNumParameters(); 260 String names[] = desc.getParamNames(); 261 Class classes[] = desc.getParamClasses(); 262 Object defaults[] = desc.getParamDefaults(); 263 264 for (int i=0; i<numParams; i++) { 265 266 // Check that all paramClasses implement Negotiable. 267 if (Negotiable.class.isAssignableFrom(classes[i]) == false) { 268 throw new IllegalArgumentException( 269 JaiI18N.getString("NegotiableCapability4")); 270 } 271 272 if (defaults[i] == ParameterListDescriptor.NO_PARAMETER_DEFAULT) { 273 throw new IllegalArgumentException( 274 JaiI18N.getString("NegotiableCapability5")); 275 } 276 } 277 278 this.category = category; 279 this.capabilityName = capabilityName; 280 this.generators = generators; 281 this.isPreference = isPreference; 282 } 283 284 /** 285 * Returns the category of this <code>NegotiableCapability</code>. 286 */ getCategory()287 public String getCategory() { 288 return category; 289 } 290 291 /** 292 * Returns the name of this <code>NegotiableCapability</code>. 293 */ getCapabilityName()294 public String getCapabilityName() { 295 return capabilityName; 296 } 297 298 /** 299 * Returns the <code>List</code> containing representations of the 300 * objects that generated this <code>NegotiableCapability</code>. This 301 * method will return null, if there are no generators for this 302 * <code>NegotiableCapability</code>. 303 */ getGenerators()304 public List getGenerators() { 305 return generators; 306 } 307 308 /** 309 * Set the specified <code>List</code> as the generators for this 310 * <code>NegotiableCapability</code>. A generator is a representation 311 * of the object that generated this <code>NegotiableCapability</code>. 312 * 313 * @param generators The <code>List</code> of generators. 314 */ setGenerators(List generators)315 public void setGenerators(List generators) { 316 this.generators = generators; 317 } 318 319 /** 320 * Returns true if this <code>NegotiableCapability</code> is a 321 * preference, false otherwise. 322 */ isPreference()323 public boolean isPreference() { 324 return isPreference; 325 } 326 327 /** 328 * Returns a single negotiated value from the <code>Negotiable</code> that 329 * represents the set of valid values for the given parameter. This 330 * method uses the <code>Negotiable.getNegotiatedValue</code> to get 331 * the negotiated value for the <code>Negotiable</code> value of the 332 * parameter specified by <code>parameterName</code>. If this 333 * <code>NegotiableCapability</code> is a non-preference, then a valid 334 * <code>Negotiable</code> must be present as the value of the specified 335 * parameter, and a single value from that <code>Negotiable</code> will 336 * be returned. If this <code>NegotiableCapability</code> is a preference 337 * the specified parameter may have a <code>null</code> as its value. 338 * In this case, this <code>null</code> will be returned as the 339 * negotiated value. 340 * 341 * @param parameterName The name of parameter to return the negotiated 342 * value for. 343 * @throws IllegalArgumentException if the parameterName is not one of 344 * those described by the associated <code>ParameterListDescriptor</code>. 345 */ getNegotiatedValue(String parameterName)346 public Object getNegotiatedValue(String parameterName) { 347 Negotiable value = (Negotiable)getObjectParameter(parameterName); 348 if (value == null) 349 return null; 350 return value.getNegotiatedValue(); 351 } 352 353 /** 354 * Performs negotiation between this <code>NegotiableCapability</code> 355 * and the given <code>NegotiableCapability</code>. Returns the common 356 * subset supported by this <code>NegotiableCapability</code> and the given 357 * <code>NegotiableCapability</code> if the negotiation is successful, 358 * null otherwise. 359 * 360 * <p>In order for the negotiation to be successful, the category and the 361 * capabilityName of the supplied <code>NegotiableCapability</code> object 362 * must be the same as of this class. In addition, negotiation on each of 363 * the parameters must be successful. Since each parameter is represented 364 * as a <code>Negotiable</code>, negotiation on it can be performed using 365 * the <code>Negotiable.negotiate()</code> method. The 366 * <code>NegotiableCapability</code> returned contains the same category, 367 * capabilityName as that of this class and also includes the negotiated 368 * values for each parameter. If the negotiation fails for any one 369 * parameter, the negotiation for the <code>NegotiableCapability</code>s 370 * as a whole is said to fail and a null is returned. The result of 371 * negotiation between one non-preference and another is a non-preference, 372 * between a preference and a non-preference is a non-preference and 373 * that between two preferences is a preference, if the negotiation is 374 * successful. 375 * 376 * If this <code>NegotiableCapability</code> is a non-preference, i.e 377 * the <code>isPreference()</code> method returns false, and the 378 * supplied <code>NegotiableCapability</code> argument is also a 379 * non-preference, then the negotiation will fail if the number and 380 * <code>Class</code> of parameters in both the 381 * <code>NegotiableCapability</code> objects is not the same. 382 * If either one of the <code>NegotiableCapability</code> objects is 383 * a preference and the other is a non-preference, the number of 384 * parameters are not required to match. For those parameters whose names 385 * are the same in both the <code>NegotiableCapability</code> objects, 386 * the <code>Class</code> types have to match, otherwise the negotiation 387 * will fail. Those parameters that exist in the non-preference 388 * <code>NegotiableCapability</code> object but not in the preference 389 * <code>NegotiableCapability</code> object do not take part in the 390 * negotiation, but are directly set on the resultant 391 * <code>NegotiableCapability</code> object if the negotiation 392 * is successful on the common parameters. Those parameters that 393 * exist in the preference <code>NegotiableCapability</code> object but 394 * not in the non-preference <code>NegotiableCapability</code> object 395 * are ignored, do not take part in the negotiation and are not 396 * reflected in the resultant <code>NegotiableCapability</code> in the 397 * event of a successful negotiation. If both the 398 * <code>NegotiableCapability</code> objects are preferences, then 399 * only the common parameters take part in the negotiation and the 400 * ones that aren't present in both the <code>NegotiableCapability</code>s 401 * are directly set on the resultant <code>NegotiableCapability</code> 402 * object if the negotiation is successful on the common parameters. 403 * For the common parameters, the <code>Class</code> types have to match, 404 * otherwise the negotiation will fail. The check for the compatibility 405 * of the <code>ParameterListDescriptor</code> of the supplied 406 * <code>NegotiableCapability</code> with the current 407 * <code>NegotiableCapability</code>'s <code>ParameterListDescriptor</code> 408 * is done using the <code>areParameterListDescriptorsCompatible()</code> 409 * method. 410 411 * It may be noted that the <code>ParameterListDescriptor</code> of 412 * the <code>NegotiableCapability</code> returned as a result of a 413 * successful negotiation will implement the getParamDefaults() and 414 * the getParamValueRange() methods in terms of the values returned 415 * from the same methods on the <code>ParameterListDescriptor</code> 416 * associated with this class, if the negotiation took place between 417 * two preferences, or from the same methods on the 418 * <code>ParameterListDescriptor</code> associated with the 419 * non-preference otherwise. 420 * 421 * <p> If the supplied <code>NegotiableCapability</code> is null, then 422 * the negotiation will fail and null will be returned. 423 * 424 * @param capability The <code>NegotiableCapability</code> to negotiate 425 * with. 426 * @returns the <code>NegotiableCapability</code> that is the result of a 427 * successful negotiation, null if the negotiation failed. 428 */ negotiate(NegotiableCapability capability)429 public NegotiableCapability negotiate(NegotiableCapability capability) { 430 431 if (capability == null) { 432 return null; 433 } 434 435 if (capability.getCategory().equalsIgnoreCase(category) == false || 436 capability.getCapabilityName().equalsIgnoreCase(capabilityName) 437 == false) { 438 // Negotiation failed 439 return null; 440 } 441 442 // If the PLD's are not compatible for negotiation, fail the 443 // negotiation 444 if (areParameterListDescriptorsCompatible(capability) == false) { 445 return null; 446 } 447 448 int negStatus; 449 if (capability.isPreference() == true) { 450 if (isPreference == true) { 451 negStatus = 0; 452 } else { 453 negStatus = 1; 454 } 455 } else { 456 if (isPreference == true) { 457 negStatus = 2; 458 } else { 459 negStatus = 3; 460 } 461 } 462 463 ParameterListDescriptor pld = getParameterListDescriptor(); 464 ParameterListDescriptor otherPld = 465 capability.getParameterListDescriptor(); 466 String thisNames[] = pld.getParamNames(); 467 if (thisNames == null) 468 thisNames = new String[0]; 469 String otherNames[] = otherPld.getParamNames(); 470 if (otherNames == null) 471 otherNames = new String[0]; 472 Hashtable thisHash = hashNames(thisNames); 473 Hashtable otherHash = hashNames(otherNames); 474 475 Class thisClasses[] = pld.getParamClasses(); 476 Class otherClasses[] = otherPld.getParamClasses(); 477 Object thisDefaults[] = pld.getParamDefaults(); 478 Object otherDefaults[] = otherPld.getParamDefaults(); 479 480 NegotiableCapability result = null; 481 String currParam; 482 Negotiable thisValue, otherValue, resultValue; 483 ArrayList resultGenerators = new ArrayList(); 484 if (generators != null) 485 resultGenerators.addAll(generators); 486 if (capability.getGenerators() != null) 487 resultGenerators.addAll(capability.getGenerators()); 488 489 switch (negStatus) { 490 491 case 0: 492 493 Vector commonNames = commonElements(thisHash, otherHash); 494 Hashtable commonHash = hashNames(commonNames); 495 Vector thisExtras = removeAll(thisHash, commonHash); 496 Vector otherExtras = removeAll(otherHash, commonHash); 497 498 int thisExtraLength = thisExtras.size(); 499 int otherExtraLength = otherExtras.size(); 500 501 // Create a new PLD which is the amalgamation of the two 502 // NC's PLD's 503 Vector resultParams = new Vector(commonNames); 504 resultParams.addAll(thisExtras); 505 resultParams.addAll(otherExtras); 506 int resultLength = resultParams.size(); 507 String resultNames[] = new String[resultLength]; 508 for (int i=0; i<resultLength; i++) { 509 resultNames[i] = (String)resultParams.elementAt(i); 510 } 511 512 Class resultClasses[] = new Class[resultLength]; 513 Object resultDefaults[] = new Object[resultLength]; 514 Object resultValidValues[] = new Object[resultLength]; 515 String name; 516 int count; 517 for (count=0; count<commonNames.size(); count++) { 518 name = (String)commonNames.elementAt(count); 519 resultClasses[count] = thisClasses[getIndex(thisHash, name)]; 520 resultDefaults[count] = thisDefaults[getIndex(thisHash, name)]; 521 resultValidValues[count] = pld.getParamValueRange(name); 522 } 523 for (int i=0; i<thisExtraLength; i++) { 524 name = (String)thisExtras.elementAt(i); 525 resultClasses[count+i] = thisClasses[getIndex(thisHash, name)]; 526 resultDefaults[count+i] = thisDefaults[getIndex(thisHash, 527 name)]; 528 resultValidValues[count+i] = pld.getParamValueRange(name); 529 } 530 count += thisExtraLength; 531 for (int i=0; i<otherExtraLength; i++) { 532 name = (String)otherExtras.elementAt(i); 533 resultClasses[i+count] = otherClasses[getIndex(otherHash, 534 name)]; 535 resultDefaults[i+count] = otherDefaults[getIndex(otherHash, 536 name)]; 537 resultValidValues[i+count] = otherPld.getParamValueRange(name); 538 } 539 540 ParameterListDescriptorImpl resultPLD = 541 new ParameterListDescriptorImpl(null, 542 resultNames, 543 resultClasses, 544 resultDefaults, 545 resultValidValues); 546 547 // Both NC's are preferences 548 result = new NegotiableCapability(category, 549 capabilityName, 550 resultGenerators, 551 resultPLD, 552 true); 553 554 for (int i=0; i<commonNames.size(); i++) { 555 currParam = (String)commonNames.elementAt(i); 556 thisValue = (Negotiable)getObjectParameter(currParam); 557 otherValue = 558 (Negotiable)capability.getObjectParameter(currParam); 559 560 // If one of the values is null, select the other one, and 561 // negotiation succeeds. Note that this also takes care 562 // of the scenario when both are null, therefore the result 563 // is null, and on a non-pref, this would have failed the 564 // negotiation, but on a pref, it doesn't, so we just set 565 // null (otherValue) as the result and allow negotiation to 566 // succeed. 567 if (thisValue == null) { 568 result.setParameter(currParam, otherValue); 569 continue; 570 } 571 572 if (otherValue == null) { 573 result.setParameter(currParam, thisValue); 574 continue; 575 } 576 577 // Following only gets executed if neither of the two is 578 // a null, and therefore both have set values. If negotiation 579 // fails, the negotiation as a whole is failed, otherwise 580 // set the result on the resultant NC. 581 resultValue = thisValue.negotiate(otherValue); 582 if (resultValue == null) { 583 return null; 584 } 585 586 result.setParameter(currParam, resultValue); 587 } 588 589 // Copy the extra ones directly into the result 590 for (int i=0; i<thisExtraLength; i++) { 591 currParam = (String)thisExtras.elementAt(i); 592 result.setParameter(currParam, 593 (Negotiable)getObjectParameter(currParam)); 594 } 595 596 for (int i=0; i<otherExtraLength; i++) { 597 currParam = (String)otherExtras.elementAt(i); 598 result.setParameter(currParam, 599 (Negotiable)capability.getObjectParameter(currParam)); 600 } 601 602 break; 603 604 case 1: 605 606 // The given capability is a pref, while this is a non-pref 607 commonNames = commonElements(thisHash, otherHash); 608 commonHash = hashNames(commonNames); 609 thisExtras = removeAll(thisHash, commonHash); 610 611 // Create a new PLD which is the amalgamation of the two 612 // NC's PLD's 613 resultParams = new Vector(commonNames); 614 resultParams.addAll(thisExtras); 615 resultLength = resultParams.size(); 616 resultNames = new String[resultLength]; 617 for (int i=0; i<resultLength; i++) { 618 resultNames[i] = (String)resultParams.elementAt(i); 619 } 620 621 resultClasses = new Class[resultLength]; 622 resultDefaults = new Object[resultLength]; 623 resultValidValues = new Object[resultLength]; 624 625 count = 0; 626 for (count=0; count<commonNames.size(); count++) { 627 name = (String)commonNames.elementAt(count); 628 resultClasses[count] = thisClasses[getIndex(thisHash, name)]; 629 resultDefaults[count] = thisDefaults[getIndex(thisHash, name)]; 630 resultValidValues[count] = pld.getParamValueRange(name); 631 } 632 for (int i=0; i<thisExtras.size(); i++) { 633 name = (String)thisExtras.elementAt(i); 634 resultClasses[i+count] = thisClasses[getIndex(thisHash, name)]; 635 resultDefaults[i+count] = thisDefaults[getIndex(thisHash, 636 name)]; 637 resultValidValues[i+count] = pld.getParamValueRange(name); 638 } 639 640 resultPLD = new ParameterListDescriptorImpl(null, 641 resultNames, 642 resultClasses, 643 resultDefaults, 644 resultValidValues); 645 646 result = new NegotiableCapability(category, 647 capabilityName, 648 resultGenerators, 649 resultPLD, 650 false); 651 652 for (int i=0; i<commonNames.size(); i++) { 653 currParam = (String)commonNames.elementAt(i); 654 thisValue = (Negotiable)getObjectParameter(currParam); 655 otherValue = 656 (Negotiable)capability.getObjectParameter(currParam); 657 658 if (thisValue == null) { 659 // If non-pref doesn't have value, negotiation fails right 660 // away 661 return null; 662 } 663 664 if (otherValue == null) { 665 // If pref value is null, then non-pref's value wins. 666 // This needs to be done separately, since 667 // non-null.negotiate(null) returns null, which is *not* 668 // what we want. 669 result.setParameter(currParam, thisValue); 670 } else { 671 // Do the negotiation. 672 resultValue = thisValue.negotiate(otherValue); 673 674 if (resultValue == null) { 675 // Negotiation on one parameter failed, so negotiation 676 // on the entire NC has also failed, return null to 677 // signify this 678 return null; 679 } else { 680 result.setParameter(currParam, resultValue); 681 } 682 } 683 } 684 685 // Copy the extra ones directly into the result 686 for (int i=0; i<thisExtras.size(); i++) { 687 currParam = (String)thisExtras.elementAt(i); 688 resultValue = (Negotiable)getObjectParameter(currParam); 689 if (resultValue == null) 690 return null; 691 result.setParameter(currParam, resultValue); 692 } 693 694 break; 695 696 case 2: 697 698 // The given capability is a non-pref, while this is a pref 699 commonNames = commonElements(thisHash, otherHash); 700 commonHash = hashNames(commonNames); 701 otherExtras = removeAll(otherHash, commonHash); 702 703 // Create a new PLD which is the amalgamation of the two 704 // NC's PLD's 705 resultParams = new Vector(commonNames); 706 resultParams.addAll(otherExtras); 707 resultLength = resultParams.size(); 708 resultNames = new String[resultLength]; 709 for (int i=0; i<resultLength; i++) { 710 resultNames[i] = (String)resultParams.elementAt(i); 711 } 712 713 resultClasses = new Class[resultLength]; 714 resultDefaults = new Object[resultLength]; 715 resultValidValues = new Object[resultLength]; 716 count = 0; 717 for (count=0; count<commonNames.size(); count++) { 718 name = (String)commonNames.elementAt(count); 719 resultClasses[count] = thisClasses[getIndex(thisHash, name)]; 720 resultDefaults[count] = thisDefaults[getIndex(thisHash, name)]; 721 resultValidValues[count] = pld.getParamValueRange(name); 722 } 723 724 for (int i=0; i<otherExtras.size(); i++) { 725 name = (String)otherExtras.elementAt(i); 726 resultClasses[i+count] = otherClasses[getIndex(otherHash, 727 name)]; 728 resultDefaults[i+count] = otherDefaults[getIndex(otherHash, 729 name)]; 730 resultValidValues[i+count] = otherPld.getParamValueRange(name); 731 } 732 733 resultPLD = new ParameterListDescriptorImpl(null, 734 resultNames, 735 resultClasses, 736 resultDefaults, 737 resultValidValues); 738 739 result = new NegotiableCapability(category, 740 capabilityName, 741 resultGenerators, 742 resultPLD, 743 false); 744 745 for (int i=0; i<commonNames.size(); i++) { 746 currParam = (String)commonNames.elementAt(i); 747 thisValue = (Negotiable)getObjectParameter(currParam); 748 otherValue = 749 (Negotiable)capability.getObjectParameter(currParam); 750 751 // If non-pref doesn't have value, negotiation fails right 752 // away 753 if (otherValue == null) { 754 return null; 755 } 756 757 if (thisValue == null) { 758 // If pref value is null, then non-pref's value wins. 759 // This needs to be done separately, since 760 // non-null.negotiate(null) returns null, which is *not* 761 // what we want. 762 result.setParameter(currParam, otherValue); 763 } else { 764 // Do the negotiation. 765 resultValue = otherValue.negotiate(thisValue); 766 767 if (resultValue == null) { 768 // Negotiation on one parameter failed, so negotiation 769 // on the entire NC has also failed, return null to 770 // signify this 771 return null; 772 } else { 773 result.setParameter(currParam, resultValue); 774 } 775 } 776 } 777 778 for (int i=0; i<otherExtras.size(); i++) { 779 currParam = (String)otherExtras.elementAt(i); 780 resultValue = 781 (Negotiable)capability.getObjectParameter(currParam); 782 if (resultValue == null) 783 return null; 784 result.setParameter(currParam, resultValue); 785 } 786 787 break; 788 789 case 3: 790 791 // Both are non-prefs 792 result = new NegotiableCapability(category, capabilityName, 793 resultGenerators, pld, false); 794 795 for (int i=0; i<thisNames.length; i++) { 796 currParam = thisNames[i]; 797 thisValue = (Negotiable)getObjectParameter(currParam); 798 otherValue = 799 (Negotiable)capability.getObjectParameter(currParam); 800 801 // failed since in nonpref-nonpref negotiation, both 802 // Negotiables must have a non-null value 803 if (thisValue == null || 804 otherValue == null) { 805 return null; 806 } 807 808 resultValue = thisValue.negotiate(otherValue); 809 810 if (resultValue == null) { 811 // Negotiation on one parameter failed, so negotiation 812 // on the entire NC has also failed, return null to 813 // signify this 814 return null; 815 } else { 816 result.setParameter(currParam, resultValue); 817 } 818 } 819 820 break; 821 } 822 823 return result; 824 } 825 826 /** 827 * Returns true if the <code>ParameterListDescriptor</code> of the 828 * supplied <code>NegotiableCapability</code> is compatible with the 829 * <code>ParameterListDescriptor</code> of this class for negotiation 830 * purposes. If both the <code>NegotiableCapability</code> objects are 831 * non-preferences, both the number of parameters as well as the 832 * <code>Class</code> type of the parameters has to match for this 833 * method to return true. If either one or both of the 834 * <code>NegotiableCapability</code> objects is a preference, then 835 * the <code>Class</code> type of the same named parameters in both 836 * the <code>NegotiableCapability</code> object's 837 * <code>ParameterListDescriptor</code>s has to match for this 838 * method to return true. 839 * 840 * @param other The <code>NegotiableCapability</code> to check 841 * compatibility for negotiation purposes for. 842 * @throws IllegalArgumentException if other is null. 843 */ areParameterListDescriptorsCompatible(NegotiableCapability other)844 public boolean areParameterListDescriptorsCompatible(NegotiableCapability 845 other) { 846 847 if (other == null) { 848 throw new IllegalArgumentException( 849 JaiI18N.getString("NegotiableCapability6")); 850 } 851 852 ParameterListDescriptor thisDesc = getParameterListDescriptor(); 853 ParameterListDescriptor otherDesc = other.getParameterListDescriptor(); 854 855 String thisNames[] = thisDesc.getParamNames(); 856 if (thisNames == null) 857 thisNames = new String[0]; 858 String otherNames[] = otherDesc.getParamNames(); 859 if (otherNames == null) 860 otherNames = new String[0]; 861 Hashtable thisHash = hashNames(thisNames); 862 Hashtable otherHash = hashNames(otherNames); 863 864 if (isPreference == false && other.isPreference() == false) { 865 866 // The number of parameters must be the same. 867 if (thisDesc.getNumParameters() != otherDesc.getNumParameters()) 868 return false; 869 870 // The same names should be present in both in the same order. 871 if (containsAll(thisHash, otherHash) == false) 872 return false; 873 874 Class thisParamClasses[] = thisDesc.getParamClasses(); 875 Class otherParamClasses[] = otherDesc.getParamClasses(); 876 for (int i=0; i<thisNames.length; i++) { 877 if (thisParamClasses[i] != 878 otherParamClasses[getIndex(otherHash, thisNames[i])]) 879 return false; 880 } 881 882 return true; 883 884 } else { 885 886 Vector commonNames = commonElements(thisHash, otherHash); 887 888 Class thisParamClasses[] = thisDesc.getParamClasses(); 889 Class otherParamClasses[] = otherDesc.getParamClasses(); 890 String currName; 891 for (int i=0; i<commonNames.size(); i++) { 892 currName = (String)commonNames.elementAt(i); 893 if (thisParamClasses[getIndex(thisHash, currName)] != 894 otherParamClasses[getIndex(otherHash, currName)]) 895 return false; 896 } 897 898 return true; 899 } 900 } 901 902 // A case insensitive containsAll for Hashtables containing Strings containsAll(Hashtable thisHash, Hashtable otherHash)903 private boolean containsAll(Hashtable thisHash, Hashtable otherHash) { 904 905 CaselessStringKey thisNameKey; 906 for (Enumeration i=thisHash.keys(); i.hasMoreElements(); ) { 907 thisNameKey = (CaselessStringKey)i.nextElement(); 908 if (otherHash.containsKey(thisNameKey) == false) 909 return false; 910 } 911 912 return true; 913 } 914 915 // Return only those names which exist in thisNames but not in otherNames removeAll(Hashtable thisHash, Hashtable otherHash)916 private Vector removeAll(Hashtable thisHash, Hashtable otherHash) { 917 918 Vector v = new Vector(); 919 CaselessStringKey thisNameKey; 920 for (Enumeration i=thisHash.keys(); i.hasMoreElements(); ) { 921 thisNameKey = (CaselessStringKey)i.nextElement(); 922 if (otherHash.containsKey(thisNameKey)) 923 continue; 924 else 925 v.add(thisNameKey.toString()); 926 } 927 928 return v; 929 } 930 getIndex(Hashtable h, String s)931 private int getIndex(Hashtable h, String s) { 932 return ((Integer)h.get(new CaselessStringKey(s))).intValue(); 933 } 934 commonElements(Hashtable thisHash, Hashtable otherHash)935 private Vector commonElements(Hashtable thisHash, 936 Hashtable otherHash) { 937 938 Vector v = new Vector(); 939 CaselessStringKey thisNameKey; 940 for (Enumeration i=thisHash.keys(); i.hasMoreElements(); ) { 941 thisNameKey = (CaselessStringKey)i.nextElement(); 942 if (otherHash.containsKey(thisNameKey)) 943 v.add(thisNameKey.toString()); 944 } 945 946 return v; 947 } 948 hashNames(String paramNames[])949 private Hashtable hashNames(String paramNames[]) { 950 951 Hashtable h = new Hashtable(); 952 if (paramNames != null) { 953 for (int i=0; i<paramNames.length; i++) { 954 h.put(new CaselessStringKey(paramNames[i]), new Integer(i)); 955 } 956 } 957 958 return h; 959 } 960 hashNames(Vector paramNames)961 private Hashtable hashNames(Vector paramNames) { 962 963 Hashtable h = new Hashtable(); 964 if (paramNames != null) { 965 for (int i=0; i<paramNames.size(); i++) { 966 h.put(new CaselessStringKey((String)(paramNames.elementAt(i))), 967 new Integer(i)); 968 } 969 } 970 971 return h; 972 } 973 974 /***************** Overridden methods from ParameterList *****************/ 975 976 /** 977 * Overrides the method in <code>ParameterListImpl</code> to throw 978 * an IllegalArgumentException since parameter values set on this class 979 * must be a <code>Negotiable</code>. 980 * 981 * @param paramName a <code>String</code> naming a parameter. 982 * @param b a <code>byte</code> value for the parameter. 983 * 984 * @throws IllegalArgumentException since the value being set is not a 985 * <code>Negotiable</code>. 986 */ setParameter(String paramName, byte b)987 public ParameterList setParameter(String paramName, byte b) { 988 throw new IllegalArgumentException( 989 JaiI18N.getString("NegotiableCapability2")); 990 } 991 992 /** 993 * Overrides the method in <code>ParameterListImpl</code> to throw 994 * an IllegalArgumentException since parameter values set on this class 995 * must be a <code>Negotiable</code>. 996 * 997 * @param paramName a <code>String</code> naming a parameter. 998 * @param b a <code>boolean</code> value for the parameter. 999 * 1000 * @throws IllegalArgumentException since the value being set is not a 1001 * <code>Negotiable</code>. 1002 */ setParameter(String paramName, boolean b)1003 public ParameterList setParameter(String paramName, boolean b) { 1004 throw new IllegalArgumentException( 1005 JaiI18N.getString("NegotiableCapability2")); 1006 } 1007 1008 /** 1009 * Overrides the method in <code>ParameterListImpl</code> to throw 1010 * an IllegalArgumentException since parameter values set on this class 1011 * must be a <code>Negotiable</code>. 1012 * 1013 * @param paramName a <code>String</code> naming a parameter. 1014 * @param c a <code>char</code> value for the parameter. 1015 * 1016 * @throws IllegalArgumentException since the value being set is not a 1017 * <code>Negotiable</code>. 1018 */ setParameter(String paramName, char c)1019 public ParameterList setParameter(String paramName, char c) { 1020 throw new IllegalArgumentException( 1021 JaiI18N.getString("NegotiableCapability2")); 1022 } 1023 1024 /** 1025 * Overrides the method in <code>ParameterListImpl</code> to throw 1026 * an IllegalArgumentException since parameter values set on this class 1027 * must be a <code>Negotiable</code>. 1028 * 1029 * @param paramName a <code>String</code> naming a parameter. 1030 * @param s a short value for the parameter. 1031 * 1032 * @throws IllegalArgumentException since the value being set is not a 1033 * <code>Negotiable</code>. 1034 */ setParameter(String paramName, short s)1035 public ParameterList setParameter(String paramName, short s) { 1036 throw new IllegalArgumentException( 1037 JaiI18N.getString("NegotiableCapability2")); 1038 } 1039 1040 /** 1041 * Overrides the method in <code>ParameterListImpl</code> to throw 1042 * an IllegalArgumentException since parameter values set on this class 1043 * must be a <code>Negotiable</code>. 1044 * 1045 * @param paramName a <code>String</code> naming a parameter. 1046 * @param i an <code>int</code> value for the parameter. 1047 * 1048 * @throws IllegalArgumentException since the value being set is not a 1049 * <code>Negotiable</code>. 1050 */ setParameter(String paramName, int i)1051 public ParameterList setParameter(String paramName, int i) { 1052 throw new IllegalArgumentException( 1053 JaiI18N.getString("NegotiableCapability2")); 1054 } 1055 1056 /** 1057 * Overrides the method in <code>ParameterListImpl</code> to throw 1058 * an IllegalArgumentException since parameter values set on this class 1059 * must be a <code>Negotiable</code>. 1060 * 1061 * @param paramName a <code>String</code> naming a parameter. 1062 * @param l a <code>long</code> value for the parameter. 1063 * 1064 * @throws IllegalArgumentException since the value being set is not a 1065 * <code>Negotiable</code>. 1066 */ setParameter(String paramName, long l)1067 public ParameterList setParameter(String paramName, long l) { 1068 throw new IllegalArgumentException( 1069 JaiI18N.getString("NegotiableCapability2")); 1070 } 1071 1072 /** 1073 * Overrides the method in <code>ParameterListImpl</code> to throw 1074 * an IllegalArgumentException since parameter values set on this class 1075 * must be a <code>Negotiable</code>. 1076 * 1077 * @param paramName a <code>String</code> naming a parameter. 1078 * @param f a <code>float</code> value for the parameter. 1079 * 1080 * @throws IllegalArgumentException since the value being set is not a 1081 * <code>Negotiable</code>. 1082 */ setParameter(String paramName, float f)1083 public ParameterList setParameter(String paramName, float f) { 1084 throw new IllegalArgumentException( 1085 JaiI18N.getString("NegotiableCapability2")); 1086 } 1087 1088 /** 1089 * Overrides the method in <code>ParameterListImpl</code> to throw 1090 * an IllegalArgumentException since parameter values set on this class 1091 * must be a <code>Negotiable</code>. 1092 * 1093 * @param paramName a <code>String</code> naming a parameter. 1094 * @param d a <code>double</code> value for the parameter. 1095 * 1096 * @throws IllegalArgumentException since the value being set is not a 1097 * <code>Negotiable</code>. 1098 */ setParameter(String paramName, double d)1099 public ParameterList setParameter(String paramName, double d) { 1100 throw new IllegalArgumentException( 1101 JaiI18N.getString("NegotiableCapability2")); 1102 } 1103 1104 /** 1105 * Overrides the superclass method to ensure only a <code>Negotiable</code> 1106 * object can be added as the value of the parameter. 1107 * 1108 * @param paramName A <code>String</code> naming a parameter. 1109 * @param obj An Object value for the parameter. 1110 * 1111 * @throws IllegalArgumentException if obj is not an instance of 1112 * <code>Negotiable</code>. 1113 */ setParameter(String paramName, Object obj)1114 public ParameterList setParameter(String paramName, Object obj) { 1115 1116 if (obj != null && !(obj instanceof Negotiable)) { 1117 throw new IllegalArgumentException( 1118 JaiI18N.getString("NegotiableCapability2")); 1119 } 1120 1121 super.setParameter(paramName, obj); 1122 return this; 1123 } 1124 1125 // getObjectParameter method doesn't need to be overridden since it 1126 // is implemented in ParameterListImpl and can return a Negotiable as 1127 // an Object 1128 1129 /** 1130 * Overrides the method in <code>ParameterListImpl</code> to throw 1131 * an IllegalArgumentException since parameter values in this class 1132 * are <code>Negotiable</code> and therefore cannot be returned as 1133 * a primitive data type. 1134 * 1135 * @param paramName the name of the parameter to be returned. 1136 * @throws IllegalArgumentException since a <code>Negotiable</code> value 1137 * cannot be returned as a primitive data type. 1138 */ getByteParameter(String paramName)1139 public byte getByteParameter(String paramName) { 1140 throw new IllegalArgumentException( 1141 JaiI18N.getString("NegotiableCapability3")); 1142 } 1143 1144 /** 1145 * Overrides the method in <code>ParameterListImpl</code> to throw 1146 * an IllegalArgumentException since parameter values in this class 1147 * are <code>Negotiable</code> and therefore cannot be returned as 1148 * a primitive data type. 1149 * 1150 * @param paramName the name of the parameter to be returned. 1151 * @throws IllegalArgumentException since a <code>Negotiable</code> value 1152 * cannot be returned as a primitive data type. 1153 */ getBooleanParameter(String paramName)1154 public boolean getBooleanParameter(String paramName) { 1155 throw new IllegalArgumentException( 1156 JaiI18N.getString("NegotiableCapability3")); 1157 } 1158 1159 /** 1160 * Overrides the method in <code>ParameterListImpl</code> to throw 1161 * an IllegalArgumentException since parameter values in this class 1162 * are <code>Negotiable</code> and therefore cannot be returned as 1163 * a primitive data type. 1164 * 1165 * @param paramName the name of the parameter to be returned. 1166 * @throws IllegalArgumentException since a <code>Negotiable</code> value 1167 * cannot be returned as a primitive data type. 1168 */ getCharParameter(String paramName)1169 public char getCharParameter(String paramName) { 1170 throw new IllegalArgumentException( 1171 JaiI18N.getString("NegotiableCapability3")); 1172 } 1173 1174 /** 1175 * Overrides the method in <code>ParameterListImpl</code> to throw 1176 * an IllegalArgumentException since parameter values in this class 1177 * are <code>Negotiable</code> and therefore cannot be returned as 1178 * a primitive data type. 1179 * 1180 * @param paramName the name of the parameter to be returned. 1181 * @throws IllegalArgumentException since a <code>Negotiable</code> value 1182 * cannot be returned as a primitive data type. 1183 */ getShortParameter(String paramName)1184 public short getShortParameter(String paramName) { 1185 throw new IllegalArgumentException( 1186 JaiI18N.getString("NegotiableCapability3")); 1187 } 1188 1189 /** 1190 * Overrides the method in <code>ParameterListImpl</code> to throw 1191 * an IllegalArgumentException since parameter values in this class 1192 * are <code>Negotiable</code> and therefore cannot be returned as 1193 * a primitive data type. 1194 * 1195 * @param paramName the name of the parameter to be returned. 1196 * @throws IllegalArgumentException since a <code>Negotiable</code> value 1197 * cannot be returned as a primitive data type. 1198 */ getIntParameter(String paramName)1199 public int getIntParameter(String paramName) { 1200 throw new IllegalArgumentException( 1201 JaiI18N.getString("NegotiableCapability3")); 1202 } 1203 1204 /** 1205 * Overrides the method in <code>ParameterListImpl</code> to throw 1206 * an IllegalArgumentException since parameter values in this class 1207 * are <code>Negotiable</code> and therefore cannot be returned as 1208 * a primitive data type. 1209 * 1210 * @param paramName the name of the parameter to be returned. 1211 * @throws IllegalArgumentException since a <code>Negotiable</code> value 1212 * cannot be returned as a primitive data type. 1213 */ getLongParameter(String paramName)1214 public long getLongParameter(String paramName) { 1215 throw new IllegalArgumentException( 1216 JaiI18N.getString("NegotiableCapability3")); 1217 } 1218 1219 /** 1220 * Overrides the method in <code>ParameterListImpl</code> to throw 1221 * an IllegalArgumentException since parameter values in this class 1222 * are <code>Negotiable</code> and therefore cannot be returned as 1223 * a primitive data type. 1224 * 1225 * @param paramName the name of the parameter to be returned. 1226 * @throws IllegalArgumentException since a <code>Negotiable</code> value 1227 * cannot be returned as a primitive data type. 1228 */ getFloatParameter(String paramName)1229 public float getFloatParameter(String paramName) { 1230 throw new IllegalArgumentException( 1231 JaiI18N.getString("NegotiableCapability3")); 1232 } 1233 1234 /** 1235 * Overrides the method in <code>ParameterListImpl</code> to throw 1236 * an IllegalArgumentException since parameter values in this class 1237 * are <code>Negotiable</code> and therefore cannot be returned as 1238 * a primitive data type. 1239 * 1240 * @param paramName the name of the parameter to be returned. 1241 * @throws IllegalArgumentException since a <code>Negotiable</code> value 1242 * cannot be returned as a primitive data type. 1243 */ getDoubleParameter(String paramName)1244 public double getDoubleParameter(String paramName) { 1245 throw new IllegalArgumentException( 1246 JaiI18N.getString("NegotiableCapability3")); 1247 } 1248 } 1249