package org.unitConverter.unit; import java.util.Objects; import java.util.Optional; /** * A value expressed in a unit. * * Unless otherwise indicated, all methods in this class throw a * {@code NullPointerException} when an argument is null. * * @author Adrien Hopkins * @since 2020-07-26 */ public final class UnitValue { /** * @param unit unit to use * @param value value to use * @return {@code UnitValue} instance */ public static UnitValue of(Unit unit, double value) { return new UnitValue(Objects.requireNonNull(unit, "unit must not be null"), value); } private final Unit unit; private final double value; /** * @param unit the unit being used * @param value the value being represented */ private UnitValue(Unit unit, double value) { this.unit = unit; this.value = value; } /** * @return the unit */ public final Unit getUnit() { return unit; } /** * @return the value */ public final double getValue() { return value; } /** * Converts this {@code UnitValue} into an equivalent {@code LinearUnitValue} by * using this unit's base unit. * * @param newName A new name for the base unit. Use {@link NameSymbol#EMPTY} if * you don't want one. */ public final LinearUnitValue asLinearUnitValue(NameSymbol newName) { LinearUnit base = LinearUnit.valueOf(unit.getBase(), 1, newName); return LinearUnitValue.getExact(base, base.convertToBase(value)); } /** * @param other a {@code Unit} * @return true iff this value can be represented with {@code other}. */ public final boolean canConvertTo(Unit other) { return this.unit.canConvertTo(other); } /** * Returns a UnitValue that represents the same value expressed in a * different unit * * @param other new unit to express value in * @return value expressed in {@code other} */ public final UnitValue convertTo(Unit other) { return UnitValue.of(other, this.getUnit().convertTo(other, this.getValue())); } /** * Returns true if this and obj represent the same value, regardless of whether * or not they are expressed in the same unit. So (1000 m).equals(1 km) returns * true. */ @Override public boolean equals(Object obj) { if (!(obj instanceof UnitValue)) return false; final UnitValue other = (UnitValue) obj; return Objects.equals(this.unit.getBase(), other.unit.getBase()) && Double.doubleToLongBits(this.unit.convertToBase(this.getValue())) == Double .doubleToLongBits(other.unit.convertToBase(other.getValue())); } @Override public int hashCode() { return Objects.hash(this.unit.getBase(), this.unit.convertFromBase(this.getValue())); } @Override public String toString() { Optional primaryName = this.getUnit().getPrimaryName(); Optional symbol = this.getUnit().getSymbol(); if (primaryName.isEmpty() && symbol.isEmpty()) { double baseValue = this.getUnit().convertToBase(this.getValue()); return String.format("%s unnamed unit (= %s %s)", this.getValue(), baseValue, this.getUnit().getBase()); } else { String unitName = symbol.orElse(primaryName.get()); return this.getValue() + " " + unitName; } } }