# Class TraitValue

java.lang.Object
com.codename1.home.TraitValue

public final class TraitValue extends Object

One value of one `Trait`: immutable, typed, and carrying its unit.

    TraitValue on = TraitValue.of(true);
    TraitValue dim = TraitValue.of(40, TraitUnit.PERCENT);
    TraitValue warm = TraitValue.of(370, TraitUnit.MIRED);

##### A tagged union, not forty subclasses

Home values are genuinely heterogeneous -- a switch is a boolean, a dimmer is a percentage, a lock is one of a fixed set -- and both native layers hand them over as raw numbers. Something has to give them types back.

A class per trait would mean a cast at every read site, and this codebase has a hard rule against a cast whose failure you expect to handle: ParparVM does not check `CHECKCAST`, so on iOS a wrong cast does not throw, it hands the wrong object to the next instruction and reads the target type's fields out of it. One class with kind-checked getters turns the same mistake into an `IllegalStateException` naming both kinds, on every platform.

##### There is no zero-argument getDouble

`getDouble(TraitUnit)` makes you name the unit you expect and converts, or throws if the dimensions disagree. That is inherited straight from `com.codename1.health.HealthQuantity`, and the reason is the same: a bare `getDouble()` is how a Celsius setpoint gets rendered as Fahrenheit and how a colour temperature in mireds gets treated as Kelvin. Neither mistake raises anything at the time.

`getRawDouble()` is the escape hatch, named to be awkward enough that it is not reached for by habit.

##### The raw platform value

Some mappings in this API are judgment calls -- HomeKit has six air-quality levels and Matter has seven, and Matter has five thermostat modes HomeKit cannot express. Where the canonical answer is lossy, `getRawPlatformValue()` carries the platform's own ordinal alongside it. Without it every lossy mapping decision would be a permanent lie; with it, an app that must be exact can be.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `boolean`
  `equals(Object o)`
  Indicates whether some other object is "equal to" this one.
  `boolean`
  `getBoolean()`
  The boolean.
  `double`
  `getColorTemperatureKelvin()`
  A colour temperature in Kelvin.
  `double`
  `getDouble(TraitUnit in)`
  The quantity, converted into the unit you name.
  `String`
  `getEnumName()`
  The name of the enum constant this value was built from.
  `int`
  `getEnumOrdinal()`
  The ordinal of an enum value, for the codec and for `LockState.of(TraitValue)` and its siblings.
  `int`
  `getInt()`
  The whole number.
  `TraitValueKind`
  `getKind()`
  What sort of value this is, and therefore which getter works.
  `double`
  `getRawDouble()`
  The quantity in whatever unit it happens to be in, with no conversion and no check.
  `int`
  `getRawPlatformValue()`
  The backend's own numeric value, where the canonical mapping was lossy.
  `String`
  `getString()`
  The text.
  `TraitUnit`
  `getUnit()`
  The unit a `TraitValueKind.DOUBLE` value is expressed in.
  `int`
  `hashCode()`
  Returns a hash code value for the object.
  `boolean`
  `hasRawPlatformValue()`
  Whether the backend's own numeric value is available alongside the canonical one.
  `static TraitValue`
  `of(boolean value)`
  A boolean value -- a switch, a motion flag, a mute.
  `static TraitValue`
  `of(double value, TraitUnit unit)`
  A measured quantity.
  `static TraitValue`
  `of(int value)`
  A unitless whole number.
  `static TraitValue`
  `of(String value)`
  Free text.
  `static TraitValue`
  `ofEnum(Enum<?> value)`
  One of a fixed set, from one of this package's domain enums.
  `static TraitValue`
  `ofEnumOrdinal(int ordinal)`
  Builds an enum value straight from an ordinal, for the codec.
  `String`
  `toString()`
  Returns a string representation of the object.
  `TraitValue`
  `withRawPlatformValue(int raw)`
  This value with the platform's own ordinal attached.

  ### Methods inherited from class Object

  `clone, getClass, notify, notifyAll, wait, wait, wait`

- ## Method Details

  - ### of

    public static TraitValue of(boolean value)

    A boolean value -- a switch, a motion flag, a mute.

    ###### Parameters

    - `value`: the boolean

    ###### Returns

    a value of kind `TraitValueKind.BOOLEAN`

  - ### of

    public static TraitValue of(int value)

    A unitless whole number.

    ###### Parameters

    - `value`: the number

    ###### Returns

    a value of kind `TraitValueKind.INT`

  - ### of

    public static TraitValue of(double value, TraitUnit unit)

    A measured quantity.

    ###### Parameters

    - `value`: the quantity

    - `unit`: the unit it is expressed in

    ###### Returns

    a value of kind `TraitValueKind.DOUBLE`

    ###### Throws

    - `IllegalArgumentException`: when `unit` is `null`. A quantity with no unit is the bug this class exists to prevent, so it is refused at construction rather than defaulted to something plausible.

    - `IllegalArgumentException`: when `value` is NaN or an infinity. Nothing downstream can carry one: the wire encodes a number as text and its decoder refuses these as INVALID_DATA, so a write that got this far was accepted, stored by the local backend, and then read back as a failure -- and on a device it would be a number no accessory could act on.

  - ### of

    public static TraitValue of(String value)

    Free text.

    ###### Parameters

    - `value`: the text; `null` becomes the empty string

    ###### Returns

    a value of kind `TraitValueKind.STRING`

  - ### ofEnum

    public static TraitValue ofEnum(Enum<?> value)

    One of a fixed set, from one of this package's domain enums.

    ###### Parameters

    - `value`: the constant

    ###### Returns

    a value of kind `TraitValueKind.ENUM`

    ###### Throws

    - `IllegalArgumentException`: when `value` is `null`

  - ### ofEnumOrdinal

    public static TraitValue ofEnumOrdinal(int ordinal)

    Builds an enum value straight from an ordinal, for the codec.

    Application code should use `ofEnum(java.lang.Enum)`; this exists because the wire carries an ordinal and the decoder has no constant to hand.

    ###### Parameters

    - `ordinal`: the ordinal of a constant in this package's domain enum for the trait in question

    ###### Returns

    a value of kind `TraitValueKind.ENUM`

  - ### withRawPlatformValue

    public TraitValue withRawPlatformValue(int raw)

    This value with the platform's own ordinal attached.

    Used by the ports where the canonical mapping is lossy, so an app can see what the accessory actually said. See `getRawPlatformValue()`.

    ###### Parameters

    - `raw`: the backend's own numeric value

    ###### Returns

    a copy carrying the raw value; this instance is unchanged

  - ### getKind

    public TraitValueKind getKind()

    What sort of value this is, and therefore which getter works.

    ###### Returns

    the kind, never `null`

  - ### getUnit

    public TraitUnit getUnit()

    The unit a `TraitValueKind.DOUBLE` value is expressed in. `TraitUnit.NONE` for every other kind.

    ###### Returns

    the unit, never `null`

  - ### getBoolean

    public boolean getBoolean()

    The boolean.

    ###### Returns

    the value

    ###### Throws

    - `IllegalStateException`: when this is not a `TraitValueKind.BOOLEAN`

  - ### getInt

    public int getInt()

    The whole number.

    ###### Returns

    the value

    ###### Throws

    - `IllegalStateException`: when this is not an `TraitValueKind.INT`

  - ### getString

    public String getString()

    The text.

    ###### Returns

    the value, never `null`

    ###### Throws

    - `IllegalStateException`: when this is not a `TraitValueKind.STRING`

  - ### getEnumOrdinal

    public int getEnumOrdinal()

    The ordinal of an enum value, for the codec and for `LockState.of(TraitValue)` and its siblings.

    Application code should go through those lookups rather than reading the ordinal: they are total, they name the constant, and they document which ones a given backend can never produce.

    ###### Returns

    the ordinal

    ###### Throws

    - `IllegalStateException`: when this is not an `TraitValueKind.ENUM`

  - ### getEnumName

    public String getEnumName()

    The name of the enum constant this value was built from.

    `null` only for a value built straight from an ordinal with `ofEnumOrdinal(int)` and never resolved against a trait. Present for every value an application builds and for every reading the codec decodes -- the trait names the ordinal there -- which is what lets `Trait.acceptsEnumValue(TraitValue)` tell one domain enum from another -- ParparVM's `Enum.getDeclaringClass()` returns `null`, so the type itself is not available to check.

    ###### Returns

    the constant's name, or `null`

    ###### Throws

    - `IllegalStateException`: when this is not an `TraitValueKind.ENUM`

  - ### getDouble

    public double getDouble(TraitUnit in)

    The quantity, converted into the unit you name.

    ###### Parameters

    - `in`: the unit you want the answer in

    ###### Returns

    the quantity expressed in `in`

    ###### Throws

    - `IllegalStateException`: when this is not a `TraitValueKind.DOUBLE`

    - `IllegalArgumentException`: when `in` measures a different dimension than this value

  - ### getRawDouble

    public double getRawDouble()

    The quantity in whatever unit it happens to be in, with no conversion and no check.

    Deliberately awkward. Reach for `getDouble(TraitUnit)` unless you have already read `getUnit()` and are doing something with both.

    ###### Returns

    the raw numeric component

    ###### Throws

    - `IllegalStateException`: when this is not a `TraitValueKind.DOUBLE`

  - ### getColorTemperatureKelvin

    public double getColorTemperatureKelvin()

    A colour temperature in Kelvin.

    Separate from `getDouble(TraitUnit)` because mireds and Kelvin are reciprocal rather than affine and so cannot be a `TraitUnit` pair; see `TraitUnit.miredToKelvin(double)`.

    ###### Returns

    the colour temperature in Kelvin

    ###### Throws

    - `IllegalStateException`: when this is not a `TraitValueKind.DOUBLE`

    - `IllegalArgumentException`: when this value is not a colour temperature, or is not positive

  - ### hasRawPlatformValue

    public boolean hasRawPlatformValue()

    Whether the backend's own numeric value is available alongside the canonical one.

    ###### Returns

    `true` when `getRawPlatformValue()` is meaningful

  - ### getRawPlatformValue

    public int getRawPlatformValue()

    The backend's own numeric value, where the canonical mapping was lossy.

    Meaningful only when `hasRawPlatformValue()` answers `true`, and meaningful only in terms of the backend that produced it -- read `SmartHome.getBackend()` before interpreting it. Zero otherwise.

    Deliberately outside `equals(java.lang.Object)`: it is metadata about where a value came from, not part of the value. Two readings that are equal can carry different raw ordinals, which is exactly the lossiness this exists to expose -- compare these explicitly when that matters.

    ###### Returns

    the platform's own ordinal, or zero

  - ### equals

    public boolean equals(Object o)
    Description copied from class: `Object`
    Indicates whether some other object is "equal to" this one. The equals method implements an equivalence relation: It is reflexive: for any reference value x, x.equals(x) should return true. It is symmetric: for any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true. It is transitive: for any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified. For any non-null reference value x, x.equals(null) should return false. The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any reference values x and y, this method returns true if and only if x and y refer to the same object (x==y has the value true).
    Overrides:
      `equals` in class `Object`

  - ### hashCode

    public int hashCode()
    Description copied from class: `Object`
    Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable. The general contract of hashCode is: Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application. If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables. As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)
    Overrides:
      `hashCode` in class `Object`

  - ### toString

    public String toString()
    Description copied from class: `Object`
    Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method. The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of: getClass().getName() + '@' + Integer.toHexString(hashCode())
    Overrides:
      `toString` in class `Object`