summaryrefslogtreecommitdiff
path: root/src/org/unitConverter/unit/Unit.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/unitConverter/unit/Unit.java')
-rw-r--r--src/org/unitConverter/unit/Unit.java113
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();
+ }
}