diff options
Diffstat (limited to 'src/org/unitConverter/unit/Unit.java')
-rw-r--r-- | src/org/unitConverter/unit/Unit.java | 113 |
1 files changed, 82 insertions, 31 deletions
diff --git a/src/org/unitConverter/unit/Unit.java b/src/org/unitConverter/unit/Unit.java index 54f0ab5..7971a41 100644 --- a/src/org/unitConverter/unit/Unit.java +++ b/src/org/unitConverter/unit/Unit.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2018 Adrien Hopkins + * Copyright (C) 2019 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 @@ -16,19 +16,20 @@ */ package org.unitConverter.unit; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.function.DoubleUnaryOperator; -import org.unitConverter.dimension.UnitDimension; +import org.unitConverter.math.ObjectProduct; /** - * A unit that has an associated base unit, and can convert a value expressed in it to and from that base. + * A unit that is composed of base units. * * @author Adrien Hopkins - * @since 2018-12-22 - * @since v0.1.0 + * @since 2019-10-16 */ -public interface Unit { +public abstract class Unit { /** * Returns a unit from its base and the functions it uses to convert to and from its base. * @@ -51,12 +52,50 @@ public interface Unit { * @throws NullPointerException * if any argument is null */ - public static Unit fromConversionFunctions(final BaseUnit base, final DoubleUnaryOperator converterFrom, - final DoubleUnaryOperator converterTo) { + public static final Unit fromConversionFunctions(final ObjectProduct<BaseUnit> base, + final DoubleUnaryOperator converterFrom, final DoubleUnaryOperator converterTo) { return FunctionalUnit.valueOf(base, converterFrom, converterTo); } /** + * The combination of units that this unit is based on. + * + * @since 2019-10-16 + */ + private final ObjectProduct<BaseUnit> unitBase; + + /** + * Cache storing the result of getDimension() + * + * @since 2019-10-16 + */ + private transient ObjectProduct<BaseDimension> dimension = null; + + /** + * A constructor that constructs {@code BaseUnit} instances. + * + * @since 2019-10-16 + */ + Unit() { + if (this instanceof BaseUnit) { + this.unitBase = ObjectProduct.oneOf((BaseUnit) this); + } else + throw new AssertionError(); + } + + /** + * Creates the {@code AbstractUnit}. + * + * @param unitBase + * @since 2019-10-16 + * @throws NullPointerException + * if unitBase is null + */ + protected Unit(final ObjectProduct<BaseUnit> unitBase) { + this.unitBase = Objects.requireNonNull(unitBase, "unitBase must not be null."); + } + + /** * Checks if a value expressed in this unit can be converted to a value expressed in {@code other} * * @param other @@ -67,7 +106,7 @@ public interface Unit { * @throws NullPointerException * if other is null */ - default boolean canConvertTo(final Unit other) { + public final boolean canConvertTo(final Unit other) { Objects.requireNonNull(other, "other must not be null."); return Objects.equals(this.getBase(), other.getBase()); } @@ -82,17 +121,24 @@ public interface Unit { * If this unit <i>is</i> a base unit, this method should return {@code value}. * </p> * + * @implSpec This method is used by {@link #convertTo}, and its behaviour affects the behaviour of + * {@code convertTo}. + * * @param value * value expressed in <b>base</b> unit * @return value expressed in <b>this</b> unit * @since 2018-12-22 * @since v0.1.0 */ - double convertFromBase(double value); + protected abstract double convertFromBase(double value); /** * Converts a value expressed in this unit to a value expressed in {@code other}. * + * @implSpec If unit conversion is possible, this implementation returns + * {@code other.convertFromBase(this.convertToBase(value))}. Therefore, overriding either of those methods + * will change the output of this method. + * * @param other * unit to convert to * @param value @@ -105,7 +151,7 @@ public interface Unit { * @throws NullPointerException * if other is null */ - default double convertTo(final Unit other, final double value) { + public final double convertTo(final Unit other, final double value) { Objects.requireNonNull(other, "other must not be null."); if (this.canConvertTo(other)) return other.convertFromBase(this.convertToBase(value)); @@ -123,42 +169,47 @@ public interface Unit { * If this unit <i>is</i> a base unit, this method should return {@code value}. * </p> * + * @implSpec This method is used by {@link #convertTo}, and its behaviour affects the behaviour of + * {@code convertTo}. + * * @param value * value expressed in <b>this</b> unit * @return value expressed in <b>base</b> unit * @since 2018-12-22 * @since v0.1.0 */ - double convertToBase(double value); + protected abstract double convertToBase(double value); /** - * <p> - * Returns the base unit associated with this unit. - * </p> - * <p> - * The dimension of this unit must be equal to the dimension of the returned unit. - * </p> - * <p> - * If this unit <i>is</i> a base unit, this method should return this unit.\ - * </p> - * - * @return base unit associated with this unit + * @return combination of units that this unit is based on * @since 2018-12-22 * @since v0.1.0 */ - BaseUnit getBase(); + public final ObjectProduct<BaseUnit> getBase() { + return this.unitBase; + } /** * @return dimension measured by this unit * @since 2018-12-22 * @since v0.1.0 */ - UnitDimension getDimension(); + public final ObjectProduct<BaseDimension> getDimension() { + if (this.dimension == null) { + final Map<BaseUnit, Integer> mapping = this.unitBase.exponentMap(); + final Map<BaseDimension, Integer> dimensionMap = new HashMap<>(); - /** - * @return system that this unit is a part of - * @since 2018-12-23 - * @since v0.1.0 - */ - UnitSystem getSystem(); + for (final BaseUnit key : mapping.keySet()) { + dimensionMap.put(key.getBaseDimension(), mapping.get(key)); + } + + this.dimension = ObjectProduct.fromExponentMapping(dimensionMap); + } + return this.dimension; + } + + @Override + public String toString() { + return "Unit derived from base " + this.getBase().toString(); + } } |