package edu.stanford.nlp.util; import java.io.Serializable; /** * A boolean, but for three-valued logics (true / false / unknown). * For most use cases, you can probably use the static values for TRUE, FALSE, and UNKNOWN. * * @author Gabor Angeli */ @SuppressWarnings("UnusedDeclaration") public class Trilean implements Serializable { private static final long serialVersionUID = 42L; /** * 0 = false * 1 = true * 2 = unknown */ private final byte value; /** * Construct a new Trilean value. * @param isTrue Set to true if the value is true. Set to false if the value is false or unknown. * @param isFalse Set to true if the value is false. Set to false if the value is true or unknown. */ public Trilean(boolean isTrue, boolean isFalse) { if (isTrue && isFalse) { throw new IllegalArgumentException("Value cannot be both true and false."); } if (isTrue) { value = 1; } else if (isFalse) { value = 0; } else { value = 2; } } /** * The copy constructor. * @param other The value to copy from. */ public Trilean(Trilean other) { this.value = other.value; } /** * Returns true if this Trilean is true, and false if it is false or unknown. */ public boolean isTrue() { return value == 1; } /** * Returns true if this Trilean is false, and false if it is true or unknown. */ public boolean isFalse() { return value == 0; } /** * Returns true if this Trilean is either true or false, and false if it is unknown. */ public boolean isKnown() { return value != 2; } /** * Returns true if this Trilean is neither true or false, and false if it is either true or false. */ public boolean isUnknown() { return value == 2; } /** * Convert this Trilean to a boolean, with a specified default value if the truth value is unknown. * @param valueForUnknown The default value to use if the value of this Trilean is unknown. * @return The boolean value of this Trilean. */ public boolean toBoolean(boolean valueForUnknown) { switch (value) { case 1: return true; case 0: return false; case 2: return valueForUnknown; default: throw new IllegalStateException("Something went very very wrong."); } } /** * Convert this Trilean to a Boolean, or null if the value is not known. * @return Either True, False, or null. */ public Boolean toBooleanOrNull() { switch (value) { case 1: return true; case 0: return false; case 2: return null; default: throw new IllegalStateException("Something went very very wrong."); } } /** * Returns the logical and of this and the other value. * @param other The value to and this value with. */ public Trilean and(Trilean other) { if (this.value == 0 || other.value == 0) { return FALSE; } else if (this.value == 2 || other.value == 2) { return UNKNOWN; } else { return TRUE; } } /** * Returns the logical or of this and the other value. * @param other The value to or this value with. */ public Trilean or(Trilean other) { if (this.value == 1 || other.value == 1) { return TRUE; } else if (this.value == 2 || other.value == 2) { return UNKNOWN; } else { return FALSE; } } /** * Returns the logical not of this value. */ public Trilean not() { switch (value) { case 0: return TRUE; case 1: return FALSE; case 2: return UNKNOWN; default: throw new IllegalStateException("Something went very very wrong."); } } /** * Returns whether this Trilean is equal either to the given Trilean, or the given Boolean. */ @SuppressWarnings("SimplifiableIfStatement") @Override public boolean equals(Object other) { if (other instanceof Trilean) { return ((Trilean) other).value == this.value; } else if (other instanceof Boolean) { return from(((Boolean) other)).value == this.value; } else { return false; } } /** * {@inheritDoc} * <p> * Implementation note: this hash code should be consistent with {@link Boolean#hashCode}. * </p> */ public int hashCode() { if (this.isTrue()) { return Boolean.hashCode(true); } else if (this.isFalse()) { return Boolean.hashCode(false); } else { return Byte.hashCode(value); } } /** * Returns a String representation of this Trilean: either "true", "false", or "unknown". */ public String toString() { if (isTrue()) { return "true"; } else if (isFalse()) { return "false"; } else { return "unknown"; } } /** * Create the Trilean value for the given Boolean * @param bool The boolean to parse, into either {@link Trilean#TRUE} or {@link Trilean#FALSE}. * @return One of {@link Trilean#TRUE} or {@link Trilean#FALSE}. */ public static Trilean from(boolean bool) { if (bool) { return TRUE; } else { return FALSE; } } public static Trilean fromString(String value) { switch(value.toLowerCase()) { case "true": case "t": return TRUE; case "false": case "f": return FALSE; case "unknown": case "unk": case "u": return UNKNOWN; default: throw new IllegalArgumentException("Cannot parse Trilean from string: " + value); } } /** The static value for True */ public static Trilean TRUE = new Trilean(true, false); /** The static value for False */ public static Trilean FALSE = new Trilean(false, true); /** The static value for Unknown (neither true or false) */ public static Trilean UNKNOWN = new Trilean(false, false); }