/** * Copyright (C) 2018 Adrien Hopkins * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package org.unitConverter.unit; import java.util.Objects; import java.util.function.DoubleUnaryOperator; import org.unitConverter.dimension.UnitDimension; /** * A unit that has an associated base unit, and can convert a value expressed in it to and from that base. * * @author Adrien Hopkins * @since 2018-12-22 * @since v0.1.0 */ public interface Unit { /** * Returns a unit from its base and the functions it uses to convert to and from its base. * *

* For example, to get a unit representing the degree Celsius, the following code can be used: * * {@code Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15);} *

* * @param base * unit's base * @param converterFrom * function that accepts a value expressed in the unit's base and returns that value expressed in this * unit. * @param converterTo * function that accepts a value expressed in the unit and returns that value expressed in the unit's * base. * @return a unit that uses the provided functions to convert. * @since 2019-05-22 */ public static Unit fromConversionFunctions(final BaseUnit base, final DoubleUnaryOperator converterFrom, final DoubleUnaryOperator converterTo) { return FunctionalUnit.valueOf(base, converterFrom, converterTo); } /** * Checks if a value expressed in this unit can be converted to a value expressed in {@code other} * * @param other * unit to test with * @return true if the units are compatible * @since 2019-01-13 * @since v0.1.0 */ default boolean canConvertTo(final Unit other) { return Objects.equals(this.getBase(), other.getBase()); } /** * Converts from a value expressed in this unit's base unit to a value expressed in this unit. *

* This must be the inverse of {@code convertToBase}, so {@code convertFromBase(convertToBase(value))} must be equal * to {@code value} for any value, ignoring precision loss by roundoff error. *

*

* If this unit is a base unit, this method should return {@code value}. *

* * @param value * value expressed in base unit * @return value expressed in this unit * @since 2018-12-22 * @since v0.1.0 */ double convertFromBase(double value); /** * Converts a value expressed in this unit to a value expressed in {@code other}. * * @param other * unit to convert to * @param value * value to convert * @return converted value * @since 2019-05-22 * @throws IllegalArgumentException * if {@code other} is incompatible for conversion with this unit (as tested by * {@link Unit#canConvertTo}). */ default double convertTo(final Unit other, final double value) { if (this.canConvertTo(other)) return other.convertFromBase(this.convertToBase(value)); else throw new IllegalArgumentException(String.format("Cannot convert from %s to %s.", this, other)); } /** * Converts from a value expressed in this unit to a value expressed in this unit's base unit. *

* This must be the inverse of {@code convertFromBase}, so {@code convertToBase(convertFromBase(value))} must be * equal to {@code value} for any value, ignoring precision loss by roundoff error. *

*

* If this unit is a base unit, this method should return {@code value}. *

* * @param value * value expressed in this unit * @return value expressed in base unit * @since 2018-12-22 * @since v0.1.0 */ double convertToBase(double value); /** *

* Returns the base unit associated with this unit. *

*

* The dimension of this unit must be equal to the dimension of the returned unit. *

*

* If this unit is a base unit, this method should return this unit.\ *

* * @return base unit associated with this unit * @since 2018-12-22 * @since v0.1.0 */ BaseUnit getBase(); /** * @return dimension measured by this unit * @since 2018-12-22 * @since v0.1.0 */ UnitDimension getDimension(); /** * @return system that this unit is a part of * @since 2018-12-23 * @since v0.1.0 */ UnitSystem getSystem(); }