001/* Base class for data capsules. 002 003 Copyright (c) 1997-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.data; 029 030import ptolemy.kernel.util.IllegalActionException; 031 032/////////////////////////////////////////////////////////////////// 033//// AbstractNotConvertibleToken 034 035/** 036 The Token base class provides a very general interface for building 037 new data types. However, in many ways, the interface is rather 038 complex in order to allow operations between tokens that are defined 039 in different classes. In particular, this requires the duplicate 040 operation() and operationReverse() methods. 041 042 <p> This base class is intended to make it easy to implement tokens 043 where operations are only defined for other tokens that are defined in 044 the same class. In these cases, the operation() and 045 operationReverse() method can share the same code. This class 046 implements these methods to ensure that the argument of each operation 047 is actually an instance of the correct class. The implementation then 048 defers to a protected _operation() method. These protected methods 049 should be overridden in derived classes to provide type-specific 050 operations. 051 052 <p> This class is used a base class for ArrayToken and RecordToken. 053 Note that these classes actually represent tokens having different 054 types in the type lattice. 055 056 @author Steve Neuendorffer 057 @version $Id$ 058 @since Ptolemy II 2.1 059 @Pt.ProposedRating Green (neuendor) 060 @Pt.AcceptedRating Green (cxh) 061 */ 062public abstract class AbstractNotConvertibleToken extends Token { 063 /////////////////////////////////////////////////////////////////// 064 //// public methods //// 065 066 /** Return a new token whose value is the sum of this token and 067 * the argument. This base class ensures that the 068 * arguments are implemented in the same class, and then defers 069 * to the _add() method. Subclasses should override that method to 070 * perform type-specific operation 071 * @param rightArgument The token to add to this token. 072 * @return A new token containing the result. 073 * @exception IllegalActionException If the argument token and 074 * this token are implemented in different classes, or the 075 * operation does not make sense for the given types. 076 */ 077 @Override 078 public Token add(Token rightArgument) throws IllegalActionException { 079 if (getClass() != rightArgument.getClass()) { 080 throw new IllegalActionException( 081 notSupportedDifferentClassesMessage("add", this, 082 rightArgument)); 083 } 084 085 try { 086 return _add(rightArgument); 087 } catch (IllegalActionException ex) { 088 // If the type-specific operation fails, then create a 089 // better error message that has the types of the 090 // arguments that were passed in. 091 throw new IllegalActionException(null, ex, 092 notSupportedMessage("add", this, rightArgument)); 093 } 094 } 095 096 /** Return a new token whose value is the sum of this token and 097 * the argument. This base class ensures that the 098 * arguments are implemented in the same class, and then defers 099 * to the _add() method. Subclasses should override that method to 100 * perform type-specific operation. 101 * @param leftArgument The token to add this token to. 102 * @return A new token containing the result. 103 * @exception IllegalActionException If the argument token and 104 * this token are implemented in different classes, or the 105 * operation does not make sense for the given types. 106 */ 107 @Override 108 public Token addReverse(ptolemy.data.Token leftArgument) 109 throws IllegalActionException { 110 if (getClass() != leftArgument.getClass()) { 111 throw new IllegalActionException( 112 notSupportedDifferentClassesMessage("addReverse", this, 113 leftArgument)); 114 } 115 116 try { 117 return ((AbstractNotConvertibleToken) leftArgument)._add(this); 118 } catch (IllegalActionException ex) { 119 // If the type-specific operation fails, then create a 120 // better error message that has the types of the 121 // arguments that were passed in. 122 throw new IllegalActionException(null, ex, 123 notSupportedMessage("addReverse", this, leftArgument)); 124 } 125 } 126 127 /** Return a new token whose value is the value of this token 128 * divided by the value of the argument token. This base class 129 * ensures that the arguments are implemented in the same class, 130 * and then defers to the _divide() method. Subclasses should 131 * override that method to perform type-specific operation. 132 * @param rightArgument The token to divide into this token. 133 * @return A new token containing the result. 134 * @exception IllegalActionException If the argument token and 135 * this token are implemented in different classes, or the 136 * operation does not make sense for the given types. 137 */ 138 @Override 139 public Token divide(Token rightArgument) throws IllegalActionException { 140 if (getClass() != rightArgument.getClass()) { 141 throw new IllegalActionException( 142 notSupportedDifferentClassesMessage("divide", this, 143 rightArgument)); 144 } 145 146 try { 147 return _divide(rightArgument); 148 } catch (IllegalActionException ex) { 149 // If the type-specific operation fails, then create a 150 // better error message that has the types of the 151 // arguments that were passed in. 152 throw new IllegalActionException(null, ex, 153 notSupportedMessage("divide", this, rightArgument)); 154 } 155 } 156 157 /** Return a new token whose value is the value of the argument 158 * token divided by the value of this token. This base class 159 * ensures that the arguments are implemented in the same class, 160 * and then defers to the _divide() method. Subclasses should 161 * override that method to perform type-specific operation. 162 * @param leftArgument The token to be divided by the value of 163 * this token. 164 * @return A new token containing the result. 165 * @exception IllegalActionException If the argument token and 166 * this token are implemented in different classes, or the 167 * operation does not make sense for the given types. 168 */ 169 @Override 170 public Token divideReverse(Token leftArgument) 171 throws IllegalActionException { 172 if (getClass() != leftArgument.getClass()) { 173 throw new IllegalActionException( 174 notSupportedDifferentClassesMessage("divideReverse", this, 175 leftArgument)); 176 } 177 178 try { 179 return ((AbstractNotConvertibleToken) leftArgument)._divide(this); 180 } catch (IllegalActionException ex) { 181 // If the type-specific operation fails, then create a 182 // better error message that has the types of the 183 // arguments that were passed in. 184 throw new IllegalActionException(null, ex, 185 notSupportedMessage("divideReverse", this, leftArgument)); 186 } 187 } 188 189 /** Test that the value of this token is close to the first argument, 190 * where "close" means that the distance between them is less than 191 * or equal to the second argument. This method only makes sense 192 * for tokens where the distance between them is reasonably 193 * represented as a double. This base class ensures that the arguments are 194 * implemented in the same class, and then defers to the 195 * _isCloseTo() method. Subclasses should override that method to 196 * perform type-specific operation. 197 * @param token The token to test closeness of this token with. 198 * @param epsilon The value that we use to determine whether two 199 * tokens are close. 200 * @return A boolean token that contains the value true if the 201 * value of this token is close to that of the argument token. 202 * @exception IllegalActionException If the argument token and 203 * this token are implemented in different classes. 204 */ 205 @Override 206 public BooleanToken isCloseTo(Token token, double epsilon) 207 throws IllegalActionException { 208 if (getClass() != token.getClass()) { 209 throw new IllegalActionException( 210 notSupportedDifferentClassesMessage("isCloseTo", this, 211 token)); 212 } 213 214 try { 215 return _isCloseTo(token, epsilon); 216 } catch (IllegalActionException ex) { 217 // If the type-specific operation fails, then create a 218 // better error message that has the types of the 219 // arguments that were passed in. 220 throw new IllegalActionException(null, ex, 221 notSupportedMessage("isCloseTo", this, token)); 222 } 223 } 224 225 /** Test for equality of the values of this token and the argument 226 * token. This base class ensures that the arguments are 227 * implemented in the same class, and then defers to the 228 * _isEqualTo() method. Subclasses should override that method to 229 * perform type-specific operation. 230 * 231 * @param rightArgument The token with which to test equality. 232 * @return A boolean token that contains the value true if the 233 * value of this token is equal to that of the argument token. 234 * @exception IllegalActionException If the argument token and 235 * this token are implemented in different classes. 236 */ 237 @Override 238 public BooleanToken isEqualTo(Token rightArgument) 239 throws IllegalActionException { 240 if (getClass() != rightArgument.getClass()) { 241 throw new IllegalActionException( 242 notSupportedDifferentClassesMessage("isEqualTo", this, 243 rightArgument)); 244 } 245 246 return _isEqualTo(rightArgument); 247 } 248 249 /** Return a new token whose value is the value of this token 250 * modulo the value of the argument token. This base class 251 * ensures that the arguments are implemented in the same class, 252 * and then defers to the _modulo() method. Subclasses should 253 * override that method to perform type-specific operation. 254 * @param rightArgument The token to divide into this token. 255 * @return A new token containing the result. 256 * @exception IllegalActionException If the argument token and 257 * this token are implemented in different classes, or the 258 * operation does not make sense for the given types. 259 */ 260 @Override 261 public Token modulo(Token rightArgument) throws IllegalActionException { 262 if (getClass() != rightArgument.getClass()) { 263 throw new IllegalActionException( 264 notSupportedDifferentClassesMessage("modulo", this, 265 rightArgument)); 266 } 267 268 try { 269 return _modulo(rightArgument); 270 } catch (IllegalActionException ex) { 271 // If the type-specific operation fails, then create a 272 // better error message that has the types of the 273 // arguments that were passed in. 274 throw new IllegalActionException(null, ex, 275 notSupportedMessage("modulo", this, rightArgument)); 276 } 277 } 278 279 /** Return a new token whose value is the value of the argument token 280 * modulo the value of this token. This base class 281 * ensures that the arguments are implemented in the same class, 282 * and then defers to the _modulo() method. Subclasses should 283 * override that method to perform type-specific operation. 284 * @param leftArgument The token to apply modulo to by the value 285 * of this token. 286 * @return A new token containing the result. 287 * @exception IllegalActionException If the argument token and 288 * this token are implemented in different classes, or the 289 * operation does not make sense for the given types. 290 */ 291 @Override 292 public Token moduloReverse(Token leftArgument) 293 throws IllegalActionException { 294 if (getClass() != leftArgument.getClass()) { 295 throw new IllegalActionException( 296 notSupportedDifferentClassesMessage("moduloReverse", this, 297 leftArgument)); 298 } 299 300 try { 301 return ((AbstractNotConvertibleToken) leftArgument)._modulo(this); 302 } catch (IllegalActionException ex) { 303 // If the type-specific operation fails, then create a 304 // better error message that has the types of the 305 // arguments that were passed in. 306 throw new IllegalActionException(null, ex, 307 notSupportedMessage("moduloReverse", this, leftArgument)); 308 } 309 } 310 311 /** Return a new token whose value is the value of this token 312 * multiplied by the value of the argument token. This base class 313 * ensures that the arguments are implemented in the same class, 314 * and then defers to the _multiply() method. Subclasses should 315 * override that method to perform type-specific operation. 316 * @param rightArgument The token to multiply this token by. 317 * @return A new token containing the result. 318 * @exception IllegalActionException If the argument token and 319 * this token are implemented in different classes, or the 320 * operation does not make sense for the given types. 321 */ 322 @Override 323 public Token multiply(Token rightArgument) throws IllegalActionException { 324 if (getClass() != rightArgument.getClass()) { 325 throw new IllegalActionException( 326 notSupportedDifferentClassesMessage("multiply", this, 327 rightArgument)); 328 } 329 330 try { 331 return _multiply(rightArgument); 332 } catch (IllegalActionException ex) { 333 // If the type-specific operation fails, then create a 334 // better error message that has the types of the 335 // arguments that were passed in. 336 throw new IllegalActionException(null, ex, 337 notSupportedMessage("multiply", this, rightArgument)); 338 } 339 } 340 341 /** Return a new token whose value is the value of the argument token 342 * multiplied by the value of this token. This base class 343 * ensures that the arguments are implemented in the same class, 344 * and then defers to the _multiply() method. Subclasses should 345 * override that method to perform type-specific operation. 346 * @param leftArgument The token to be multiplied by the value of 347 * this token. 348 * @return A new token containing the result. 349 * @exception IllegalActionException If the argument token and 350 * this token are implemented in different classes, or the 351 * operation does not make sense for the given types. 352 */ 353 @Override 354 public Token multiplyReverse(Token leftArgument) 355 throws IllegalActionException { 356 if (getClass() != leftArgument.getClass()) { 357 throw new IllegalActionException( 358 notSupportedDifferentClassesMessage("multiplyReverse", this, 359 leftArgument)); 360 } 361 362 try { 363 return ((AbstractNotConvertibleToken) leftArgument)._multiply(this); 364 } catch (IllegalActionException ex) { 365 // If the type-specific operation fails, then create a 366 // better error message that has the types of the 367 // arguments that were passed in. 368 throw new IllegalActionException(null, ex, 369 notSupportedMessage("multiplyReverse", this, leftArgument)); 370 } 371 } 372 373 /** Return a string with an error message that states that the 374 * given operation is not supported between two tokens, because 375 * they have incomparable types and cannot be converted to the 376 * same type. 377 * @param operation A string naming the unsupported token 378 * operation. 379 * @param firstToken The first token in the message. 380 * @param secondToken The second token in the message. 381 * @return A string error message. 382 */ 383 public static String notSupportedDifferentClassesMessage(String operation, 384 Token firstToken, Token secondToken) { 385 // We use this method to factor out a very common message 386 return operation + " method not supported between " 387 + firstToken.getClass().getName() + " '" + firstToken.toString() 388 + "' and " + secondToken.getClass().getName() + " '" 389 + secondToken.toString() 390 + "' because the tokens have different classes."; 391 } 392 393 /** Return a new token whose value is the value of the argument token 394 * subtracted from the value of this token. This base class 395 * ensures that the arguments are implemented in the same class, 396 * and then defers to the _subtract() method. Subclasses should 397 * override that method to perform type-specific operation. 398 * @param rightArgument The token to subtract from this token. 399 * @return A new token containing the result. 400 * @exception IllegalActionException If the argument token and 401 * this token are implemented in different classes, or the 402 * operation does not make sense for the given types. 403 */ 404 @Override 405 public Token subtract(Token rightArgument) throws IllegalActionException { 406 if (getClass() != rightArgument.getClass()) { 407 throw new IllegalActionException( 408 notSupportedDifferentClassesMessage("subtract", this, 409 rightArgument)); 410 } 411 412 try { 413 return _subtract(rightArgument); 414 } catch (IllegalActionException ex) { 415 // If the type-specific operation fails, then create a 416 // better error message that has the types of the 417 // arguments that were passed in. 418 throw new IllegalActionException(null, ex, 419 notSupportedMessage("subtract", this, rightArgument)); 420 } 421 } 422 423 /** Return a new token whose value is the value of this token 424 * subtracted from the value of the argument token. This base class 425 * ensures that the arguments are implemented in the same class, 426 * and then defers to the _subtract() method. Subclasses should 427 * override that method to perform type-specific operation. 428 * @param leftArgument The token to subtract this token from. 429 * @return A new token containing the result. 430 * @exception IllegalActionException If the argument token and 431 * this token are implemented in different classes, or the 432 * operation does not make sense for the given types. 433 */ 434 @Override 435 public Token subtractReverse(Token leftArgument) 436 throws IllegalActionException { 437 if (getClass() != leftArgument.getClass()) { 438 throw new IllegalActionException( 439 notSupportedDifferentClassesMessage("subtractReverse", this, 440 leftArgument)); 441 } 442 443 try { 444 return ((AbstractNotConvertibleToken) leftArgument)._subtract(this); 445 } catch (IllegalActionException ex) { 446 // If the type-specific operation fails, then create a 447 // better error message that has the types of the 448 // arguments that were passed in. 449 throw new IllegalActionException(null, ex, 450 notSupportedMessage("subtractReverse", this, leftArgument)); 451 } 452 } 453 454 /////////////////////////////////////////////////////////////////// 455 //// protected methods //// 456 457 /** Return a new token whose value is the value of the argument 458 * token added to the value of this token. It is guaranteed by 459 * the caller that the type of the argument is the same as the 460 * type of this class. This method should be overridden in 461 * derived classes to provide type specific actions for add. 462 * @param rightArgument The token whose value we add to the value 463 * of this token. 464 * @exception IllegalActionException If this method is not 465 * supported by the derived class. 466 * @return A new token containing the result that is of the same 467 * class as this token. 468 */ 469 protected abstract Token _add(Token rightArgument) 470 throws IllegalActionException; 471 472 /** Return a new token whose value is the value of this token 473 * divided by the value of the argument token. It is guaranteed 474 * by the caller that the type of the argument is the same as the 475 * type of this class. This method should be overridden in 476 * derived classes to provide type specific actions for divide. 477 * @param rightArgument The token to divide this token by. 478 * @exception IllegalActionException If this method is not 479 * supported by the derived class. 480 * @return A new token containing the result that is of the same 481 * class as this token. 482 */ 483 protected abstract Token _divide(Token rightArgument) 484 throws IllegalActionException; 485 486 /** Test that the value of this Token is close to the first argument, 487 * where "close" means that the distance between them is less than 488 * or equal to the second argument. 489 * It is guaranteed by the caller that the type 490 * of the argument is the same as the type of this class. This 491 * method should be overridden in derived classes to provide type 492 * specific actions for divide. 493 * @param rightArgument The token with which to test closeness. 494 * @param epsilon The value that we use to determine whether two 495 * tokens are close. 496 * @exception IllegalActionException If this method is not 497 * supported by the derived class. 498 * @return A token that contains the result of the test. 499 */ 500 protected abstract BooleanToken _isCloseTo(Token rightArgument, 501 double epsilon) throws IllegalActionException; 502 503 /** Test for equality of the values of this token and the argument. 504 * This base class delegates to the equals() method. 505 * @param token The token to compare to this token. 506 * @return A token containing true if the value element of the first 507 * argument is equal to the value of this token. 508 * @exception IllegalActionException Not thrown in this base class. 509 */ 510 protected BooleanToken _isEqualTo(Token token) 511 throws IllegalActionException { 512 return BooleanToken.getInstance(equals(token)); 513 } 514 515 /** Return a new token whose value is the value of this token 516 * modulo the value of the argument token. It is guaranteed by 517 * the caller that the type of the argument is the same as the 518 * type of this class. This method should be overridden in 519 * derived classes to provide type specific actions for modulo. 520 * @param rightArgument The token to modulo this token by. 521 * @exception IllegalActionException If this method is not 522 * supported by the derived class. 523 * @return A new token containing the result that is of the same 524 * class as this token. 525 */ 526 protected abstract Token _modulo(Token rightArgument) 527 throws IllegalActionException; 528 529 /** Return a new token whose value is the value of this token 530 * multiplied by the value of the argument token. It is 531 * guaranteed by the caller that the type of the argument is the 532 * same as the type of this class. This method should be 533 * overridden in derived classes to provide type specific actions 534 * for multiply. 535 * @param rightArgument The token to multiply this token by. 536 * @exception IllegalActionException If this method is not 537 * supported by the derived class. 538 * @return A new token containing the result that is of the same 539 * class as this token. 540 */ 541 protected abstract Token _multiply(Token rightArgument) 542 throws IllegalActionException; 543 544 /** Return a new token whose value is the value of the argument 545 * token subtracted from the value of this token. It is 546 * guaranteed by the caller that the type of the argument is the 547 * same as the type of this class. This method should be 548 * overridden in derived classes to provide type specific actions 549 * for subtract. 550 * @param rightArgument The token to subtract from this token. 551 * @exception IllegalActionException If this method is not 552 * supported by the derived class. 553 * @return A new token containing the result that is of the same 554 * class as this token. 555 */ 556 protected abstract Token _subtract(Token rightArgument) 557 throws IllegalActionException; 558}