/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.common.util;
import com.facebook.infer.annotation.Functional;
/**
* Generic tri-state enum for boolean values that can also be unset.
*/
public enum TriState {
YES,
NO,
UNSET,
;
/** @return whether this value is set; that is, whether it is YES or NO. */
@Functional
public boolean isSet() {
return this != UNSET;
}
/**
* Returns the value of the {@link TriState} enum that corresponds to the specified
* {@code boolean}.
* <p>
* This method deliberately declares {@code boolean} as its param type rather than {@link Boolean}
* because:
* <ol>
* <li>Declaring {@link Boolean} would likely result in a bunch of unnecessary autoboxing.
* <li>Anyone who finds himself using a {@link Boolean} instead of a {@code boolean} for its
* nullability should replace the {@link Boolean} with a {@link TriState}, anyway.
* </ol>
*/
@Functional
public static TriState valueOf(boolean bool) {
return bool ? YES : NO;
}
@Functional
public static TriState valueOf(Boolean bool) {
return bool != null ? valueOf(bool.booleanValue()) : TriState.UNSET;
}
/**
* Returns the {@code boolean} value that corresponds to this {@link TriState}, if appropriate.
*
* @return {@code true} if {@code this} is {@link TriState#YES} or
* {@code false} if {@code this} is {@link TriState#NO}
* @throws IllegalStateException if {@code this} is {@link TriState#UNSET}.
*/
@Functional
public boolean asBoolean() {
switch (this) {
case YES:
return true;
case NO:
return false;
case UNSET:
throw new IllegalStateException("No boolean equivalent for UNSET");
default:
throw new IllegalStateException("Unrecognized TriState value: " + this);
}
}
/**
* Returns the {@code boolean} value that corresponds to this {@link TriState}, if appropriate.
*
* @param defaultValue default value to use if not set
* @return {@code true} if {@code this} is {@link TriState#YES} or
* {@code false} if {@code this} is {@link TriState#NO} or {@code defaultValue} if
* {@code this} is {@link TriState#UNSET}.
*/
@Functional
public boolean asBoolean(boolean defaultValue) {
switch (this) {
case YES:
return true;
case NO:
return false;
case UNSET:
return defaultValue;
default:
throw new IllegalStateException("Unrecognized TriState value: " + this);
}
}
/**
* Returns the {@code Boolean} value that corresponds to this {@link TriState}, if appropriate.
*
* @return {@link Boolean#TRUE} if {@code this} is {@link TriState#YES} or
* {@link Boolean#FALSE} if {@code this} is {@link TriState#NO} or {@code null} if
* {@code this} is {@link TriState#UNSET}.
*/
@Functional
public Boolean asBooleanObject() {
switch (this) {
case YES:
return Boolean.TRUE;
case NO:
return Boolean.FALSE;
case UNSET:
return null;
default:
throw new IllegalStateException("Unrecognized TriState value: " + this);
}
}
@Functional
public int getDbValue() {
switch (this) {
case YES:
return 1;
case NO:
return 2;
case UNSET:
default:
return 3;
}
}
@Functional
public static TriState fromDbValue(int value) {
switch (value) {
case 1:
return YES;
case 2:
return NO;
case 3:
default:
return UNSET;
}
}
}