001/* A token that contains a boolean variable.
002
003 Copyright (c) 1998-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 */
027package ptolemy.data;
028
029import java.util.Locale;
030
031import ptolemy.data.type.BaseType;
032import ptolemy.data.type.Type;
033import ptolemy.data.type.TypeLattice;
034import ptolemy.graph.CPO;
035import ptolemy.kernel.util.IllegalActionException;
036
037///////////////////////////////////////////////////////////////////
038//// BooleanToken
039
040/**
041 A token that contains a boolean variable. Arithmetic on booleans is
042 that of a two-element Galois field (modulo two arithmetic). Thus,
043 add() is logical xor, multiply() is logical and, zero() is false,
044 one() is true.
045 <p>
046 In order to reduce the number of instances of this object that are created,
047 it is highly recommended that the getInstance() method be used, instead of
048 the constructor that takes a boolean argument.
049
050 @author Neil Smyth, Yuhong Xiong, Edward A. Lee, Steve Neuendorffer, Christopher Brooks
051 @version $Id$
052 @since Ptolemy II 0.2
053 @Pt.ProposedRating Yellow (cxh) nil token
054 @Pt.AcceptedRating Red (cxh)
055 */
056public class BooleanToken extends ScalarToken {
057    /** Construct a token with value false.
058     */
059    public BooleanToken() {
060        _value = false;
061    }
062
063    /** Construct a token with the specified value.
064     *  @param b The boolean value.
065     */
066    public BooleanToken(boolean b) {
067        _value = b;
068    }
069
070    /** Construct a token with the specified string.  The initialization
071     *  string is converted to lower case and compared to the string
072     *  "true".
073     *  @param init The initialization string.
074     *  @exception IllegalActionException If the token could not
075     *   be created with the given String.
076     */
077    public BooleanToken(String init) throws IllegalActionException {
078        if (init == null || init.equals("nil")) {
079            throw new IllegalActionException(
080                    notSupportedNullNilStringMessage("BooleanToken", init));
081        }
082        _value = init.toLowerCase(Locale.getDefault()).equals("true");
083    }
084
085    ///////////////////////////////////////////////////////////////////
086    ////                         public methods                    ////
087
088    /** Return a new token whose value is the logical AND of the value
089     *  of this token and the the value of the argument token.
090     *  If this token is nil, or the argument is nil,
091     *  then {@link #NIL} is returned.
092     *  @param rightArgument The BooleanToken to OR with this one.
093     *  @return A new BooleanToken containing the result.
094     */
095    public BooleanToken and(BooleanToken rightArgument) {
096        if (isNil() || rightArgument.isNil()) {
097            return BooleanToken.NIL;
098        }
099        if (_value && rightArgument.booleanValue()) {
100            return TRUE;
101        } else {
102            return FALSE;
103        }
104    }
105
106    /** Return the value as a boolean.
107     *  @return The value.
108     */
109    public boolean booleanValue() {
110        return _value;
111    }
112
113    /** Convert the specified token into an instance of BooleanToken.
114     *  This method does lossless conversion, which in the case of
115     *  booleans, means that the argument can only be already an
116     *  instance of BooleanToken.  It is returned unchanged.  If the
117     *  argument is a nil token, then {@link #NIL} is
118     *  returned.
119     *  @param token The token to be converted to a BooleanToken.
120     *  @return A BooleanToken.
121     *  @exception IllegalActionException If the argument is not
122     *   a BooleanToken.
123     */
124    public static BooleanToken convert(Token token)
125            throws IllegalActionException {
126        if (token instanceof BooleanToken) {
127            return (BooleanToken) token;
128        }
129        if (token.isNil()) {
130            return BooleanToken.NIL;
131        }
132
133        int compare = TypeLattice.compare(BaseType.BOOLEAN, token);
134
135        if (compare == CPO.LOWER || compare == CPO.INCOMPARABLE) {
136            throw new IllegalActionException(
137                    notSupportedIncomparableConversionMessage(token,
138                            "boolean"));
139        }
140
141        throw new IllegalActionException(
142                notSupportedConversionMessage(token, "boolean"));
143    }
144
145    /** Return true if the argument's class is BooleanToken and it has the
146     *  same values as this token.
147     *  @param object An instance of Object.
148     *  @return True if the argument is a BooleanToken with the same
149     *  value. If either this object or the argument is a nil Token,
150     *  return false.
151     */
152    @Override
153    public boolean equals(Object object) {
154        if (object == null) {
155            return false;
156        }
157        // This test rules out subclasses.
158        if (object.getClass() != getClass()) {
159            return false;
160        }
161
162        if (isNil() || ((BooleanToken) object).isNil()) {
163            return false;
164        }
165
166        if (((BooleanToken) object).booleanValue() == _value) {
167            return true;
168        }
169
170        return false;
171    }
172
173    /** Return the instance of this class corresponding to the given
174     *  boolean value.
175     *  @param value The given value.
176     *  @return BooleanToken.TRUE if the argument is true, or
177     *  BooleanToken.FALSE otherwise.
178     */
179    public static BooleanToken getInstance(boolean value) {
180        if (value) {
181            return BooleanToken.TRUE;
182        } else {
183            return BooleanToken.FALSE;
184        }
185    }
186
187    /** Return the type of this token.
188     *  @return BaseType.BOOLEAN
189     */
190    @Override
191    public Type getType() {
192        return BaseType.BOOLEAN;
193    }
194
195    /** Return a hash code value for this token. This method returns 1
196     *  if this token has value true, and 0 if this token has value
197     *  false.
198     *  @return A hash code value for this token.
199     */
200    @Override
201    public int hashCode() {
202        if (_value) {
203            return 1;
204        }
205
206        return 0;
207    }
208
209    /** Return true if the token is nil, (aka null or missing).
210     *  Nil or missing tokens occur when a data source is sparsely populated.
211     *  @return True if the token is the {@link #NIL} token.
212     */
213    @Override
214    public boolean isNil() {
215        // We use a method here so that we can easily change how
216        // we determine if a token is nil without modify lots of classes.
217        // Can't use equals() here, or we'll go into an infinite loop.
218        return this == BooleanToken.NIL;
219    }
220
221    /** Return a new BooleanToken with the logical not of the value
222     *  stored in this token.
223     *  @return The logical converse of this token.
224     */
225    public BooleanToken not() {
226        if (isNil()) {
227            return BooleanToken.NIL;
228        }
229        if (booleanValue()) {
230            return FALSE;
231        } else {
232            return TRUE;
233        }
234    }
235
236    /** Returns a token representing the multiplicative identity.
237     *  @return TRUE.
238     */
239    @Override
240    public Token one() {
241        return TRUE;
242    }
243
244    /** Return a new token whose value is the logical OR of the value
245     *  of this token and the the value of the argument token.
246     *  If this token is nil, or the argument is nil,
247     *  then {@link #NIL} is returned.
248     *  @param rightArgument The BooleanToken to OR with this one.
249     *  @return A new BooleanToken containing the result.
250     */
251    public BooleanToken or(BooleanToken rightArgument) {
252        if (isNil() || rightArgument.isNil()) {
253            return BooleanToken.NIL;
254        }
255        if (_value || rightArgument.booleanValue()) {
256            return TRUE;
257        } else {
258            return FALSE;
259        }
260    }
261
262    /** Return the value of this token as a string that can be parsed
263     *  by the expression language to recover a token with the same value.
264     *  @return The string "true" if this token represents true, or the
265     *  string "false" if it represents false.
266     */
267    @Override
268    public String toString() {
269        if (isNil()) {
270            return super.toString();
271        }
272        if (booleanValue()) {
273            return "true";
274        } else {
275            return "false";
276        }
277    }
278
279    /** Return a new token whose value is the logical XOR of the value
280     *  of this token and the the value of the argument token.
281     *  If this token is nil, or the argument is nil,
282     *  then {@link #NIL} is returned.
283     *  @param rightArgument The BooleanToken to XOR with this one.
284     *  @return A new BooleanToken containing the result.
285     */
286    public BooleanToken xor(BooleanToken rightArgument) {
287        if (isNil() || rightArgument.isNil()) {
288            return BooleanToken.NIL;
289        }
290        if (_value ^ rightArgument.booleanValue()) {
291            return TRUE;
292        } else {
293            return FALSE;
294        }
295    }
296
297    /** Returns a token representing the additive identity.
298     *  @return FALSE.
299     */
300    @Override
301    public Token zero() {
302        return FALSE;
303    }
304
305    ///////////////////////////////////////////////////////////////////
306    ////                         public variables                  ////
307
308    /** True-valued token. */
309    public static final BooleanToken TRUE = new BooleanToken(true);
310
311    /** A token that represents a missing value.
312     *  Null or missing tokens are common in analytical systems
313     *  like R and SAS where they are used to handle sparsely populated data
314     *  sources.  In database parlance, missing tokens are sometimes called
315     *  null tokens.  Since null is a Java keyword, we use the term "nil".
316     *  The toString() method on a nil token returns the string "nil".
317     */
318    public static final BooleanToken NIL = new BooleanToken(false);
319
320    /** False-valued token. */
321    public static final BooleanToken FALSE = new BooleanToken(false);
322
323    ///////////////////////////////////////////////////////////////////
324    ////                         protected methods                 ////
325
326    /** Return this token.
327     *  @return This token.
328     */
329    @Override
330    protected ScalarToken _absolute() {
331        return this;
332    }
333
334    /** Return a new token whose value is the value of the
335     *  argument Token added to the value of this Token.  It is assumed
336     *  that the type of the argument is an BooleanToken.
337     *  @param rightArgument The token to add to this token.
338     *  @return A new BooleanToken containing the result.
339     */
340    @Override
341    protected ScalarToken _add(ScalarToken rightArgument) {
342        return this.or((BooleanToken) rightArgument);
343    }
344
345    /** Returns a token representing the bitwise AND of this token and
346     *  the given token. This is the same as and().
347     *  @param rightArgument The DoubleToken to bitwise AND with this one.
348     *  @return The bitwise AND.
349     *  @exception IllegalActionException Always thrown by this base class.
350     */
351    @Override
352    protected ScalarToken _bitwiseAnd(ScalarToken rightArgument)
353            throws IllegalActionException {
354        return and((BooleanToken) rightArgument);
355    }
356
357    /** Returns a token representing the bitwise NOT of this token.
358     *  This is the same as not().
359     *  @return The bitwise NOT of this token.
360     *  @exception IllegalActionException Always thrown by this base class.
361     */
362    @Override
363    protected ScalarToken _bitwiseNot() throws IllegalActionException {
364        return not();
365    }
366
367    /** Returns a token representing the bitwise OR of this token and
368     *  the given token. This is the same as or().
369     *  @param rightArgument The DoubleToken to bitwise OR with this one.
370     *  @return The bitwise OR.
371     *  @exception IllegalActionException Always thrown by this base class.
372     */
373    @Override
374    protected ScalarToken _bitwiseOr(ScalarToken rightArgument)
375            throws IllegalActionException {
376        return or((BooleanToken) rightArgument);
377    }
378
379    /** Returns a token representing the bitwise XOR of this token and
380     *  the given token. This is the same as xor().
381     *  @param rightArgument The DoubleToken to bitwise XOR with this one.
382     *  @return The bitwise XOR.
383     *  @exception IllegalActionException Always thrown by this base class.
384     */
385    @Override
386    protected ScalarToken _bitwiseXor(ScalarToken rightArgument)
387            throws IllegalActionException {
388        return xor((BooleanToken) rightArgument);
389    }
390
391    /** Return a new token whose value is the value of this token
392     *  divided by the value of this Token.  It is assumed that
393     *  the type of the argument is an BooleanToken.  For booleans,
394     *  division is defined by multiplication (which is logical and).
395     *  Thus, if <i>c</i> = <i>a</i>/<i>b</i> then <i>c</i> is defined
396     *  so that <i>c</i><i>b</i> = <i>a</i>.  If <i>b</i> is
397     *  <i>false</i> then this result is not well defined, so this
398     *  method will throw an exception.  Specifically, if the argument
399     *  is <i>true</i>, then this method returns this token.
400     *  Otherwise it throws an exception.
401     *  @param rightArgument The token to divide this token by
402     *  @return A new BooleanToken containing the result.
403     *  @exception IllegalActionException If the argument token is
404     *  FALSE.
405     */
406    @Override
407    protected ScalarToken _divide(ScalarToken rightArgument)
408            throws IllegalActionException {
409        if (isNil() || ((BooleanToken) rightArgument).isNil()) {
410            return BooleanToken.NIL;
411        }
412        boolean denomValue = ((BooleanToken) rightArgument).booleanValue();
413
414        if (denomValue) {
415            return this;
416        } else {
417            throw new IllegalActionException("BooleanToken: division "
418                    + "by false-valued token (analogous to division by "
419                    + "zero).");
420        }
421    }
422
423    /** Return a true-valued token if the first argument is close to this
424     *  token, where in this class, "close" means "identical to."
425     *  It is assumed that the type of the argument is BooleanToken.
426     *  @param token The token to compare to this token.
427     *  @param epsilon Ignored in this method.
428     *  @return A token containing the result.
429     */
430    @Override
431    protected BooleanToken _isCloseTo(ScalarToken token, double epsilon) {
432        return _isEqualTo(token);
433    }
434
435    /** Test for equality of the values of this token and the argument.
436     *  This is the same as equals(), except that it returns a BooleanToken
437     *  instead of a boolean.
438     *  @param token The token to compare to this token.
439     *  @return A token containing the result.
440     *  If either this object or the argument is a nil Token, return
441     *  false.
442     */
443    @Override
444    protected BooleanToken _isEqualTo(ScalarToken token) {
445        if (equals(token)) {
446            return TRUE;
447        } else {
448            return FALSE;
449        }
450    }
451
452    /** Throw an exception.
453     *  @param rightArgument The token to compare to this token.
454     *  @exception IllegalActionException Always.
455     *  @return Does not return.
456     */
457    @Override
458    protected BooleanToken _isLessThan(ScalarToken rightArgument)
459            throws IllegalActionException {
460        throw new IllegalActionException(
461                notSupportedMessage("isLessThan", this, rightArgument));
462    }
463
464    /** Throw an exception. This method is not supported.
465     *  @param rightArgument The token to modulo this token by.
466     *  @exception IllegalActionException Always.
467     *  @return Does not return.
468     */
469    @Override
470    protected ScalarToken _modulo(ScalarToken rightArgument)
471            throws IllegalActionException {
472        throw new IllegalActionException(
473                notSupportedMessage("modulo", this, rightArgument));
474    }
475
476    /** Return a new token whose value is the value of this token
477     *  multiplied by the value of the argument token.  It is assumed
478     *  that the type of the argument is an BooleanToken.  For booleans,
479     *  this corresponds to the logical AND.
480     *  @param rightArgument The token to multiply this token by.
481     *  @return A new BooleanToken containing the result.
482     *  @exception IllegalActionException If ANDing the argument
483     *  and the token throws it.
484     */
485    @Override
486    protected ScalarToken _multiply(ScalarToken rightArgument)
487            throws IllegalActionException {
488        return this.and((BooleanToken) rightArgument);
489    }
490
491    /** Subtraction is not supported in Boolean algebras.
492     */
493    @Override
494    protected ScalarToken _subtract(ScalarToken rightArgument)
495            throws IllegalActionException {
496        throw new IllegalActionException(
497                notSupportedMessage("subtract", this, rightArgument));
498    }
499
500    ///////////////////////////////////////////////////////////////////
501    ////                         private variables                 ////
502    private boolean _value;
503}