001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.units;
006
007import java.util.Objects;
008
009/**
010 * A measure holds the magnitude and unit of some dimension, such as distance, time, or speed. An
011 * immutable measure is <i>immutable</i> and <i>type safe</i>, making it easy to use in concurrent
012 * situations and gives compile-time safety. Two measures with the same <i>unit</i> and
013 * <i>magnitude</i> are effectively equivalent objects.
014 *
015 * @param <U> the unit type of the measure
016 */
017public class ImmutableMeasure<U extends Unit<U>> implements Measure<U> {
018  private final double m_magnitude;
019  private final double m_baseUnitMagnitude;
020  private final U m_unit;
021
022  /**
023   * Creates a new immutable measure instance. This shouldn't be used directly; prefer one of the
024   * factory methods instead.
025   *
026   * @param magnitude the magnitude of this measure
027   * @param unit the unit of this measure.
028   */
029  @SuppressWarnings("unchecked")
030  ImmutableMeasure(double magnitude, double baseUnitMagnitude, Unit<U> unit) {
031    Objects.requireNonNull(unit, "Unit cannot be null");
032    m_magnitude = magnitude;
033    m_baseUnitMagnitude = baseUnitMagnitude;
034    m_unit = (U) unit;
035  }
036
037  /**
038   * Creates a new measure in the given unit with a magnitude equal to the given one in base units.
039   *
040   * @param <U> the type of the units of measure
041   * @param baseUnitMagnitude the magnitude of the measure, in terms of the base unit of measure
042   * @param unit the unit of measure
043   * @return a new measure
044   */
045  public static <U extends Unit<U>> ImmutableMeasure<U> ofBaseUnits(
046      double baseUnitMagnitude, Unit<U> unit) {
047    return new ImmutableMeasure<>(unit.fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, unit);
048  }
049
050  /**
051   * Creates a new measure in the given unit with a magnitude in terms of that unit.
052   *
053   * @param <U> the type of the units of measure
054   * @param relativeMagnitude the magnitude of the measure
055   * @param unit the unit of measure
056   * @return a new measure
057   */
058  public static <U extends Unit<U>> ImmutableMeasure<U> ofRelativeUnits(
059      double relativeMagnitude, Unit<U> unit) {
060    return new ImmutableMeasure<>(relativeMagnitude, unit.toBaseUnits(relativeMagnitude), unit);
061  }
062
063  /** Gets the unitless magnitude of this measure. */
064  @Override
065  public double magnitude() {
066    return m_magnitude;
067  }
068
069  @Override
070  public double baseUnitMagnitude() {
071    return m_baseUnitMagnitude;
072  }
073
074  /** Gets the units of this measure. */
075  @Override
076  public U unit() {
077    return m_unit;
078  }
079
080  /**
081   * Checks for <i>object equality</i>. To check if two measures are <i>equivalent</i>, use {@link
082   * #isEquivalent(Measure) isEquivalent}.
083   */
084  @Override
085  public boolean equals(Object o) {
086    if (this == o) {
087      return true;
088    }
089    if (!(o instanceof Measure)) {
090      return false;
091    }
092    Measure<?> that = (Measure<?>) o;
093    return Objects.equals(m_unit, that.unit()) && m_baseUnitMagnitude == that.baseUnitMagnitude();
094  }
095
096  @Override
097  public int hashCode() {
098    return Objects.hash(m_magnitude, m_unit);
099  }
100
101  @Override
102  public Measure<U> copy() {
103    return this; // already immutable, no need to allocate a new object
104  }
105
106  @Override
107  public String toString() {
108    return toShortString();
109  }
110}