From 145f524f19b3d61cd12441c2f1a8de05d7dcfe60 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Wed, 16 Oct 2019 12:31:09 -0400 Subject: Created the new BaseUnit, Unit and AbstractUnit implementations. --- src/org/unitConverter/newUnits/AbstractUnit.java | 76 +++++++++++ src/org/unitConverter/newUnits/BaseUnit.java | 102 +++++++++++++++ src/org/unitConverter/newUnits/FunctionalUnit.java | 98 ++++++++++++++ src/org/unitConverter/newUnits/Unit.java | 145 +++++++++++++++++++++ src/org/unitConverter/newUnits/package-info.java | 23 ++++ 5 files changed, 444 insertions(+) create mode 100644 src/org/unitConverter/newUnits/AbstractUnit.java create mode 100644 src/org/unitConverter/newUnits/BaseUnit.java create mode 100644 src/org/unitConverter/newUnits/FunctionalUnit.java create mode 100644 src/org/unitConverter/newUnits/Unit.java create mode 100644 src/org/unitConverter/newUnits/package-info.java (limited to 'src/org/unitConverter/newUnits') diff --git a/src/org/unitConverter/newUnits/AbstractUnit.java b/src/org/unitConverter/newUnits/AbstractUnit.java new file mode 100644 index 0000000..909ea8b --- /dev/null +++ b/src/org/unitConverter/newUnits/AbstractUnit.java @@ -0,0 +1,76 @@ +/** + * 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 + * 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.newUnits; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import org.unitConverter.dimension.BaseDimension; +import org.unitConverter.math.ObjectProduct; + +/** + * @author Adrien Hopkins + * @since 2019-10-16 + */ +public abstract class AbstractUnit implements Unit { + /** + * The combination of units that this unit is based on. + */ + private final ObjectProduct unitBase; + + /** + * Cache storing the result of getDimension() + */ + private transient ObjectProduct dimension = null; + + /** + * Creates the {@code AbstractUnit}. + * + * @param unitBase + * @since 2019-10-16 + * @throws NullPointerException + * if unitBase is null + */ + public AbstractUnit(final ObjectProduct unitBase) { + this.unitBase = Objects.requireNonNull(unitBase, "unitBase must not be null."); + } + + /** + * @return unitBase + * @since 2019-10-16 + */ + @Override + public final ObjectProduct getBase() { + return this.unitBase; + } + + @Override + public ObjectProduct getDimension() { + if (this.dimension == null) { + final Map mapping = this.unitBase.exponentMap(); + final Map dimensionMap = new HashMap<>(); + + for (final BaseUnit key : mapping.keySet()) { + dimensionMap.put(key.getBaseDimension(), mapping.get(key)); + } + + this.dimension = ObjectProduct.fromExponentMapping(dimensionMap); + } + return this.dimension; + } +} diff --git a/src/org/unitConverter/newUnits/BaseUnit.java b/src/org/unitConverter/newUnits/BaseUnit.java new file mode 100644 index 0000000..69e8b8b --- /dev/null +++ b/src/org/unitConverter/newUnits/BaseUnit.java @@ -0,0 +1,102 @@ +/** + * 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 + * 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.newUnits; + +import java.util.Objects; + +import org.unitConverter.dimension.BaseDimension; +import org.unitConverter.math.ObjectProduct; + +/** + * A unit that other units are defined by. + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +public final class BaseUnit implements Unit { + private final BaseDimension dimension; + private final String name; + private final String symbol; + + /** + * Creates the {@code BaseUnit}. + * + * @param dimension + * dimension of unit + * @param name + * name of unit + * @param symbol + * symbol of unit + * @throws NullPointerException + * if any argument is null + * @since 2019-10-16 + */ + private BaseUnit(final BaseDimension dimension, final String name, final String symbol) { + this.dimension = Objects.requireNonNull(dimension, "dimension must not be null."); + this.name = Objects.requireNonNull(name, "name must not be null."); + this.symbol = Objects.requireNonNull(symbol, "symbol must not be null."); + } + + @Override + public double convertFromBase(final double value) { + return value; + } + + @Override + public double convertToBase(final double value) { + return value; + } + + @Override + public ObjectProduct getBase() { + return ObjectProduct.oneOf(this); + } + + /** + * @return dimension + * @since 2019-10-16 + */ + public final BaseDimension getBaseDimension() { + return this.dimension; + } + + @Override + public ObjectProduct getDimension() { + return ObjectProduct.oneOf(this.getBaseDimension()); + } + + /** + * @return name + * @since 2019-10-16 + */ + public final String getName() { + return this.name; + } + + /** + * @return symbol + * @since 2019-10-16 + */ + public final String getSymbol() { + return this.symbol; + } + + @Override + public String toString() { + return String.format("%s (%s)", this.getName(), this.getSymbol()); + } +} diff --git a/src/org/unitConverter/newUnits/FunctionalUnit.java b/src/org/unitConverter/newUnits/FunctionalUnit.java new file mode 100644 index 0000000..99ff833 --- /dev/null +++ b/src/org/unitConverter/newUnits/FunctionalUnit.java @@ -0,0 +1,98 @@ +/** + * 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 + * 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.newUnits; + +import java.util.Objects; +import java.util.function.DoubleUnaryOperator; + +import org.unitConverter.math.ObjectProduct; + +/** + * A unit that uses functional objects to convert to and from its base. + * + * @author Adrien Hopkins + * @since 2019-05-22 + */ +final class FunctionalUnit extends AbstractUnit { + /** + * Returns a unit from its base and the functions it uses to convert to and from its base. + * + * @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 + * @throws NullPointerException + * if any argument is null + */ + public static FunctionalUnit valueOf(final ObjectProduct base, final DoubleUnaryOperator converterFrom, + final DoubleUnaryOperator converterTo) { + return new FunctionalUnit(base, converterFrom, converterTo); + } + + /** + * A function that accepts a value expressed in the unit's base and returns that value expressed in this unit. + * + * @since 2019-05-22 + */ + private final DoubleUnaryOperator converterFrom; + + /** + * A function that accepts a value expressed in the unit and returns that value expressed in the unit's base. + * + * @since 2019-05-22 + */ + private final DoubleUnaryOperator converterTo; + + /** + * Creates the {@code FunctionalUnit}. + * + * @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. + * @throws NullPointerException + * if any argument is null + * @since 2019-05-22 + */ + private FunctionalUnit(final ObjectProduct base, final DoubleUnaryOperator converterFrom, + final DoubleUnaryOperator converterTo) { + super(base); + this.converterFrom = Objects.requireNonNull(converterFrom, "converterFrom must not be null."); + this.converterTo = Objects.requireNonNull(converterTo, "converterTo must not be null."); + } + + @Override + public double convertFromBase(final double value) { + return this.converterFrom.applyAsDouble(value); + } + + @Override + public double convertToBase(final double value) { + return this.converterTo.applyAsDouble(value); + } + +} diff --git a/src/org/unitConverter/newUnits/Unit.java b/src/org/unitConverter/newUnits/Unit.java new file mode 100644 index 0000000..339afde --- /dev/null +++ b/src/org/unitConverter/newUnits/Unit.java @@ -0,0 +1,145 @@ +/** + * 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 + * 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.newUnits; + +import java.util.Objects; +import java.util.function.DoubleUnaryOperator; + +import org.unitConverter.dimension.BaseDimension; +import org.unitConverter.math.ObjectProduct; + +/** + * @author Adrien Hopkins + * @since 2019-10-16 + */ +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 + * @throws NullPointerException + * if any argument is null + */ + public static Unit fromConversionFunctions(final ObjectProduct 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 + * @throws NullPointerException + * if other is null + */ + default boolean canConvertTo(final Unit other) { + Objects.requireNonNull(other, "other must not be null."); + 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}). + * @throws NullPointerException + * if other is null + */ + default 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)); + 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); + + /** + * @return combination of units that this unit is based on + * @since 2018-12-22 + * @since v0.1.0 + */ + ObjectProduct getBase(); + + /** + * @return dimension measured by this unit + * @since 2018-12-22 + * @since v0.1.0 + */ + ObjectProduct getDimension(); +} \ No newline at end of file diff --git a/src/org/unitConverter/newUnits/package-info.java b/src/org/unitConverter/newUnits/package-info.java new file mode 100644 index 0000000..9cd0d1a --- /dev/null +++ b/src/org/unitConverter/newUnits/package-info.java @@ -0,0 +1,23 @@ +/** + * 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 + * 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 . + */ +/** + * The new definition for units. + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +package org.unitConverter.newUnits; \ No newline at end of file -- cgit v1.2.3