# Class TraitConstraint

java.lang.Object
com.codename1.home.TraitConstraint

public final class TraitConstraint extends Object

What one particular accessory will actually accept for one particular `Trait`: whether it can be read or written, the range it works over, the step it moves in, and for an enum trait, which constants it can produce.

`Trait` documents the nominal range -- brightness is a percentage, so it is 0 to 100. This carries the real one, from HomeKit's `HMCharacteristicMetadata` or the Matter attribute's own min and max attributes. A dimmer whose floor is 10 percent and that steps in fives says so here, and a slider built from these numbers will not offer the user a value the accessory is going to reject.

##### Writes are refused, not clamped

A write outside `getMinimum()` to `getMaximum()` fails with `HomeError.VALUE_OUT_OF_RANGE`. Clamping was the obvious alternative and it is worse: an app that asked for 40 degrees and silently got 38 never learns it was wrong, so the bug reaches the user as a thermostat that "does not go high enough" rather than as a failure at the call site where it can be fixed.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `boolean`
  `accepts(TraitValue value)`
  Whether a value falls inside what this accessory will accept.
  `static TraitConstraint`
  `choices(Trait trait, boolean readable, boolean writable, boolean notifies, int[] validOrdinals)`
  A constraint for an enum trait whose accessory declared which values it can produce.
  `double`
  `getMaximum()`
  The largest value this accessory accepts, in `Trait.getUnit()`.
  `double`
  `getMinimum()`
  The smallest value this accessory accepts, in `Trait.getUnit()`.
  `double`
  `getStep()`
  The increment this accessory moves in, in `Trait.getUnit()`.
  `Trait`
  `getTrait()`
  The trait this describes.
  `List<Integer>`
  `getValidOrdinals()`
  The ordinals of the domain-enum constants this accessory can produce or accept.
  `boolean`
  `hasRange()`
  Whether `getMinimum()`, `getMaximum()` and `getStep()` mean anything.
  `boolean`
  `isReadable()`
  Whether this accessory will answer a read of this trait.
  `boolean`
  `isWritable()`
  Whether this accessory will accept a write of this trait.
  `boolean`
  `notifiesOnChange()`
  Whether this accessory pushes changes to this trait.
  `static TraitConstraint`
  `of(Trait trait, boolean readable, boolean writable, boolean notifies)`
  A constraint for a trait whose accessory declared no range -- a boolean, or a numeric trait the platform did not describe.
  `static TraitConstraint`
  `ranged(Trait trait, boolean readable, boolean writable, boolean notifies, double minimum, double maximum, double step)`
  A constraint for a numeric trait whose accessory declared its range.
  `String`
  `toString()`
  Returns a string representation of the object.

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- ## Method Details

  - ### of

    public static TraitConstraint of(Trait trait, boolean readable, boolean writable, boolean notifies)

    A constraint for a trait whose accessory declared no range -- a boolean, or a numeric trait the platform did not describe.

    ###### Parameters

    - `trait`: the trait this describes

    - `readable`: whether the accessory will answer a read

    - `writable`: whether the accessory will accept a write

    - `notifies`: whether the accessory pushes changes, so a subscription on it can do better than polling

    ###### Returns

    the constraint

    ###### Throws

    - `IllegalArgumentException`: when `trait` is `null`

  - ### ranged

    public static TraitConstraint ranged(Trait trait, boolean readable, boolean writable, boolean notifies, double minimum, double maximum, double step)

    A constraint for a numeric trait whose accessory declared its range.

    ###### Parameters

    - `trait`: the trait this describes

    - `readable`: whether the accessory will answer a read

    - `writable`: whether the accessory will accept a write

    - `notifies`: whether the accessory pushes changes

    - `minimum`: the smallest accepted value, in `Trait.getUnit()`

    - `maximum`: the largest accepted value, in `Trait.getUnit()`

    - `step`: the increment the accessory moves in, or zero when it did not say

    ###### Returns

    the constraint

    ###### Throws

    - `IllegalArgumentException`: when `trait` is `null`, or `maximum` is below `minimum`

  - ### choices

    public static TraitConstraint choices(Trait trait, boolean readable, boolean writable, boolean notifies, int[] validOrdinals)

    A constraint for an enum trait whose accessory declared which values it can produce.

    ###### Parameters

    - `trait`: the trait this describes

    - `readable`: whether the accessory will answer a read

    - `writable`: whether the accessory will accept a write

    - `notifies`: whether the accessory pushes changes

    - `validOrdinals`: the ordinals of the constants this accessory can produce or accept, in the domain enum for this trait; `null` or empty means it did not say, which is not the same as "none"

    ###### Returns

    the constraint

    ###### Throws

    - `IllegalArgumentException`: when `trait` is `null`

  - ### getTrait

    public Trait getTrait()

    The trait this describes.

    ###### Returns

    the trait, never `null`

  - ### isReadable

    public boolean isReadable()

    Whether this accessory will answer a read of this trait.

    ###### Returns

    `true` when the trait is readable here

  - ### isWritable

    public boolean isWritable()

    Whether this accessory will accept a write of this trait.

    Narrower than `Trait.isReadOnly()`, which says whether writing the trait could ever mean anything at all. A writable trait can still be read-only on a particular accessory -- a thermostat you have been given view-only access to, a covering with its motor disabled.

    ###### Returns

    `true` when the trait is writable here

  - ### notifiesOnChange

    public boolean notifiesOnChange()

    Whether this accessory pushes changes to this trait.

    Where this is `false`, a subscription still works but has nothing better than polling behind it, so changes arrive late or only when you call `SmartHome.drainChanges()`. Independent of `TraitSubscription.isPushDelivery()`, which is about whether the platform can deliver at all; this is about whether the accessory bothers to say.

    ###### Returns

    `true` when the accessory reports changes on its own

  - ### hasRange

    public boolean hasRange()

    Whether `getMinimum()`, `getMaximum()` and `getStep()` mean anything.

    ###### Returns

    `true` when the accessory declared a range

  - ### getMinimum

    public double getMinimum()

    The smallest value this accessory accepts, in `Trait.getUnit()`.

    ###### Returns

    the minimum, or zero when `hasRange()` is `false`

  - ### getMaximum

    public double getMaximum()

    The largest value this accessory accepts, in `Trait.getUnit()`.

    ###### Returns

    the maximum, or zero when `hasRange()` is `false`

  - ### getStep

    public double getStep()

    The increment this accessory moves in, in `Trait.getUnit()`.

    Zero means it did not say, which is not the same as continuous -- treat it as unknown rather than as a step of nothing.

    ###### Returns

    the step, or zero

  - ### getValidOrdinals

    public List<Integer> getValidOrdinals()

    The ordinals of the domain-enum constants this accessory can produce or accept.

    An empty list means the accessory did not say, not that it accepts nothing. Most do not say.

    ###### Returns

    an immutable list of ordinals, possibly empty

  - ### accepts

    public boolean accepts(TraitValue value)

    Whether a value falls inside what this accessory will accept.

    Checks the range for a numeric trait and the ordinal list for an enum one, and answers `true` for anything the accessory did not constrain -- this is what the write path tests, and refusing values on the strength of information an accessory never gave would fail writes that work.

    The step is deliberately not enforced. Accessories declare steps they then round to happily, and refusing 33 percent on a dimmer that declares fives would reject a value the hardware accepts.

    ###### Parameters

    - `value`: the value to test, or `null`

    ###### Returns

    `true` when the value is acceptable, or when the accessory declared no constraint to test it against; `false` for a `null` value or one whose kind does not match the trait

  - ### 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`