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}