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}