/** * 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 org.unitConverter.dimension.UnitDimension; /** * A unit that is the base for its dimension. It does not have to be for a base dimension, so units like the Newton and * Joule are still base units. * * @author Adrien Hopkins * @since 2018-12-23 * @since v0.1.0 */ public final class BaseUnit extends AbstractUnit implements OperatableUnit { /** * Is this unit a full base (i.e. m, s, ... but not N, J, ...) * * @since 2019-01-15 * @since v0.1.0 */ private final boolean isFullBase; /** * Creates the {@code BaseUnit}. * * @param dimension * dimension measured by unit * @param system * system that unit is a part of * @param name * name of unit * @param symbol * symbol of unit * @since 2018-12-23 * @since v0.1.0 */ BaseUnit(final UnitDimension dimension, final UnitSystem system) { super(dimension, system); this.isFullBase = dimension.isBase(); } /** * @return this unit as a {@code LinearUnit} * @since 2019-01-25 * @since v0.1.0 */ public LinearUnit asLinearUnit() { return this.times(1); } @Override public double convertFromBase(final double value) { return value; } @Override public double convertToBase(final double value) { return value; } /** * Divides this unit by another unit. * * @param other * unit to divide by * @return quotient of two units * @throws IllegalArgumentException * if this unit's system is not other's system * @throws NullPointerException * if other is null * @since 2018-12-22 * @since v0.1.0 */ public BaseUnit dividedBy(final BaseUnit other) { Objects.requireNonNull(other, "other must not be null."); if (!this.getSystem().equals(other.getSystem())) throw new IllegalArgumentException("Incompatible base units for division."); return new BaseUnit(this.getDimension().dividedBy(other.getDimension()), this.getSystem()); } /** * Divides this unit by a divisor * * @param divisor * amount to divide by * @return quotient * @since 2018-12-23 * @since v0.1.0 */ public LinearUnit dividedBy(final double divisor) { return new LinearUnit(this, 1 / divisor); } @Override public boolean equals(final Object obj) { if (!(obj instanceof BaseUnit)) return false; final BaseUnit other = (BaseUnit) obj; return Objects.equals(this.getSystem(), other.getSystem()) && Objects.equals(this.getDimension(), other.getDimension()); } @Override public int hashCode() { final int prime = 31; int result = 1; result = result * prime + this.getSystem().hashCode(); result = result * prime + this.getDimension().hashCode(); return result; } @Override public LinearUnit negated() { return this.times(-1); } @Override public OperatableUnit plus(final OperatableUnit addend) { Objects.requireNonNull(addend, "addend must not be null."); // reject addends that cannot be added to this unit if (!this.getSystem().equals(addend.getSystem())) throw new IllegalArgumentException( String.format("Incompatible units for addition or subtraction \"%s\" and \"%s\".", this, addend)); if (!this.getDimension().equals(addend.getDimension())) throw new IllegalArgumentException( String.format("Incompatible units for addition or subtraction \"%s\" and \"%s\".", this, addend)); // add them together if (addend instanceof BaseUnit) return this.times(2); else return addend.plus(this); } @Override public BaseUnit reciprocal() { return this.toExponent(-1); } /** * Multiplies this unit by another unit. * * @param other * unit to multiply by * @return product of two units * @throws IllegalArgumentException * if this unit's system is not other's system * @throws NullPointerException * if other is null * @since 2018-12-22 * @since v0.1.0 */ public BaseUnit times(final BaseUnit other) { Objects.requireNonNull(other, "other must not be null."); if (!this.getSystem().equals(other.getSystem())) throw new IllegalArgumentException("Incompatible base units for multiplication."); return new BaseUnit(this.getDimension().times(other.getDimension()), this.getSystem()); } /** * Multiplies this unit by a multiplier. * * @param multiplier * amount to multiply by * @return product * @since 2018-12-23 * @since v0.1.0 */ public LinearUnit times(final double multiplier) { return new LinearUnit(this, multiplier); } @Override public OperatableUnit times(final OperatableUnit multiplier) { Objects.requireNonNull(multiplier, "multiplier must not be null."); // reject multipliers that cannot be muliplied by this unit if (!this.getSystem().equals(multiplier.getSystem())) throw new IllegalArgumentException(String .format("Incompatible units for multiplication or division \"%s\" and \"%s\".", this, multiplier)); // multiply the units if (multiplier instanceof BaseUnit) return new BaseUnit(this.getDimension().times(multiplier.getDimension()), this.getSystem()); else return multiplier.times(this); } /** * Returns this unit, but to an exponent. * * @param exponent * exponent * @return result of exponentiation * @since 2019-01-15 * @since v0.1.0 */ @Override public BaseUnit toExponent(final int exponent) { return this.getSystem().getBaseUnit(this.getDimension().toExponent(exponent)); } @Override public String toString() { return String.format("%s base unit of%s dimension %s", this.getSystem(), this.isFullBase ? " base" : "", this.getDimension()); } }