diff options
-rw-r--r-- | src/org/unitConverter/math/ObjectProduct.java | 4 | ||||
-rw-r--r-- | src/org/unitConverter/unit/LinearUnit.java | 26 | ||||
-rw-r--r-- | src/org/unitConverter/unit/NameSymbol.java | 277 | ||||
-rw-r--r-- | src/org/unitConverter/unit/SI.java | 1 | ||||
-rw-r--r-- | src/org/unitConverter/unit/Unit.java | 217 | ||||
-rw-r--r-- | src/org/unitConverter/unit/UnitDatabase.java | 3 | ||||
-rw-r--r-- | src/org/unitConverter/unit/UnitPrefix.java | 85 |
7 files changed, 388 insertions, 225 deletions
diff --git a/src/org/unitConverter/math/ObjectProduct.java b/src/org/unitConverter/math/ObjectProduct.java index 29d0f6e..bf00647 100644 --- a/src/org/unitConverter/math/ObjectProduct.java +++ b/src/org/unitConverter/math/ObjectProduct.java @@ -92,8 +92,8 @@ public final class ObjectProduct<T> { * @since 2019-10-16
*/
private ObjectProduct(final Map<T, Integer> exponents) {
- this.exponents = Collections.unmodifiableMap(ConditionalExistenceCollections
- .conditionalExistenceMap(new HashMap<>(exponents), e -> !Integer.valueOf(0).equals(e.getValue())));
+ this.exponents = Collections.unmodifiableMap(ConditionalExistenceCollections.conditionalExistenceMap(exponents,
+ e -> !Integer.valueOf(0).equals(e.getValue())));
}
/**
diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java index 1532fc4..1e5ae53 100644 --- a/src/org/unitConverter/unit/LinearUnit.java +++ b/src/org/unitConverter/unit/LinearUnit.java @@ -350,14 +350,38 @@ public final class LinearUnit extends Unit { /** * Returns the result of applying {@code prefix} to this unit. + * <p> + * If this unit and the provided prefix have a primary name, the returned unit will have a primary name (prefix's + * name + unit's name). <br> + * If this unit and the provided prefix have a symbol, the returned unit will have a symbol. <br> + * This method ignores alternate names of both this unit and the provided prefix. * * @param prefix * prefix to apply * @return unit with prefix * @since 2019-03-18 * @since v0.2.0 + * @throws NullPointerException + * if prefix is null */ public LinearUnit withPrefix(final UnitPrefix prefix) { - return this.times(prefix.getMultiplier()); + final LinearUnit unit = this.times(prefix.getMultiplier()); + + // create new name and symbol, if possible + final String name; + if (this.getPrimaryName().isPresent() && prefix.getPrimaryName().isPresent()) { + name = prefix.getPrimaryName().get() + this.getPrimaryName().get(); + } else { + name = null; + } + + final String symbol; + if (this.getSymbol().isPresent() && prefix.getSymbol().isPresent()) { + symbol = prefix.getSymbol().get() + this.getSymbol().get(); + } else { + symbol = null; + } + + return unit.withName(NameSymbol.ofNullable(name, symbol)); } } diff --git a/src/org/unitConverter/unit/NameSymbol.java b/src/org/unitConverter/unit/NameSymbol.java new file mode 100644 index 0000000..96fab45 --- /dev/null +++ b/src/org/unitConverter/unit/NameSymbol.java @@ -0,0 +1,277 @@ +/** + * 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 <https://www.gnu.org/licenses/>. + */ +package org.unitConverter.unit; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +/** + * A class that can be used to specify names and a symbol for a unit. + * + * @author Adrien Hopkins + * @since 2019-10-21 + */ +public final class NameSymbol { + public static final NameSymbol EMPTY = new NameSymbol(Optional.empty(), Optional.empty(), new HashSet<>()); + + /** + * Gets a {@code NameSymbol} with a primary name, a symbol and no other names. + * + * @param name + * name to use + * @param symbol + * symbol to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException + * if name or symbol is null + */ + public static final NameSymbol of(final String name, final String symbol) { + return new NameSymbol(Optional.of(name), Optional.of(symbol), new HashSet<>()); + } + + /** + * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. + * + * @param name + * name to use + * @param symbol + * symbol to use + * @param otherNames + * other names to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException + * if any argument is null + */ + public static final NameSymbol of(final String name, final String symbol, final Set<String> otherNames) { + return new NameSymbol(Optional.of(name), Optional.of(symbol), + new HashSet<>(Objects.requireNonNull(otherNames, "otherNames must not be null."))); + } + + /** + * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. + * + * @param name + * name to use + * @param symbol + * symbol to use + * @param otherNames + * other names to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException + * if any argument is null + */ + public static final NameSymbol of(final String name, final String symbol, final String... otherNames) { + return new NameSymbol(Optional.of(name), Optional.of(symbol), + new HashSet<>(Arrays.asList(Objects.requireNonNull(otherNames, "otherNames must not be null.")))); + } + + /** + * Gets a {@code NameSymbol} with a primary name, a symbol and an additional name. + * + * @param name + * name to use + * @param symbol + * symbol to use + * @param otherNames + * other names to use + * @param name2 + * alternate name + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException + * if any argument is null + */ + public static final NameSymbol of(final String name, final String symbol, final String name2) { + final Set<String> otherNames = new HashSet<>(); + otherNames.add(Objects.requireNonNull(name2, "name2 must not be null.")); + return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames); + } + + /** + * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. + * + * @param name + * name to use + * @param symbol + * symbol to use + * @param otherNames + * other names to use + * @param name2 + * alternate name + * @param name3 + * alternate name + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException + * if any argument is null + */ + public static final NameSymbol of(final String name, final String symbol, final String name2, final String name3) { + final Set<String> otherNames = new HashSet<>(); + otherNames.add(Objects.requireNonNull(name2, "name2 must not be null.")); + otherNames.add(Objects.requireNonNull(name3, "name3 must not be null.")); + return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames); + } + + /** + * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. + * + * @param name + * name to use + * @param symbol + * symbol to use + * @param otherNames + * other names to use + * @param name2 + * alternate name + * @param name3 + * alternate name + * @param name4 + * alternate name + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException + * if any argument is null + */ + public static final NameSymbol of(final String name, final String symbol, final String name2, final String name3, + final String name4) { + final Set<String> otherNames = new HashSet<>(); + otherNames.add(Objects.requireNonNull(name2, "name2 must not be null.")); + otherNames.add(Objects.requireNonNull(name3, "name3 must not be null.")); + otherNames.add(Objects.requireNonNull(name4, "name4 must not be null.")); + return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames); + } + + /** + * Gets a {@code NameSymbol} with a primary name, no symbol, and no other names. + * + * @param name + * name to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException + * if name is null + */ + public static final NameSymbol ofName(final String name) { + return new NameSymbol(Optional.of(name), Optional.empty(), new HashSet<>()); + } + + /** + * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. + * <p> + * If any argument is null, this static factory replaces it with an empty Optional or empty Set. + * + * @param name + * name to use + * @param symbol + * symbol to use + * @param otherNames + * other names to use + * @return NameSymbol instance + * @since 2019-11-26 + */ + public static final NameSymbol ofNullable(final String name, final String symbol, final Set<String> otherNames) { + return new NameSymbol(Optional.ofNullable(name), Optional.ofNullable(symbol), + otherNames == null ? new HashSet<>() : new HashSet<>(otherNames)); + } + + /** + * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. + * <p> + * If any argument is null, this static factory replaces it with an empty Optional or empty Set. + * + * @param name + * name to use + * @param symbol + * symbol to use + * @param otherNames + * other names to use + * @return NameSymbol instance + * @since 2019-11-26 + */ + public static final NameSymbol ofNullable(final String name, final String symbol, final String... otherNames) { + return new NameSymbol(Optional.ofNullable(name), Optional.ofNullable(symbol), + otherNames == null ? new HashSet<>() : new HashSet<>(Arrays.asList(otherNames))); + } + + /** + * Gets a {@code NameSymbol} with a symbol and no names. + * + * @param symbol + * symbol to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException + * if symbol is null + */ + public static final NameSymbol ofSymbol(final String symbol) { + return new NameSymbol(Optional.empty(), Optional.of(symbol), new HashSet<>()); + } + + private final Optional<String> primaryName; + private final Optional<String> symbol; + + private final Set<String> otherNames; + + /** + * Creates the {@code NameSymbol}. + * + * @param primaryName + * primary name of unit + * @param symbol + * symbol used to represent unit + * @param otherNames + * other names and/or spellings + * @since 2019-10-21 + */ + private NameSymbol(final Optional<String> primaryName, final Optional<String> symbol, + final Set<String> otherNames) { + this.primaryName = primaryName; + this.symbol = symbol; + this.otherNames = Collections.unmodifiableSet(otherNames); + } + + /** + * @return otherNames + * @since 2019-10-21 + */ + public final Set<String> getOtherNames() { + return this.otherNames; + } + + /** + * @return primaryName + * @since 2019-10-21 + */ + public final Optional<String> getPrimaryName() { + return this.primaryName; + } + + /** + * @return symbol + * @since 2019-10-21 + */ + public final Optional<String> getSymbol() { + return this.symbol; + } +}
\ No newline at end of file diff --git a/src/org/unitConverter/unit/SI.java b/src/org/unitConverter/unit/SI.java index 19d63e6..c8d228c 100644 --- a/src/org/unitConverter/unit/SI.java +++ b/src/org/unitConverter/unit/SI.java @@ -17,7 +17,6 @@ package org.unitConverter.unit;
import org.unitConverter.math.ObjectProduct;
-import org.unitConverter.unit.Unit.NameSymbol;
/**
* All of the units, prefixes and dimensions that are used by the SI, as well as some outside the SI.
diff --git a/src/org/unitConverter/unit/Unit.java b/src/org/unitConverter/unit/Unit.java index 737802a..35b32fc 100644 --- a/src/org/unitConverter/unit/Unit.java +++ b/src/org/unitConverter/unit/Unit.java @@ -16,7 +16,6 @@ */ package org.unitConverter.unit; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -36,222 +35,6 @@ import org.unitConverter.math.ObjectProduct; */ public abstract class Unit { /** - * A class that can be used to specify names and a symbol for a unit. - * - * @author Adrien Hopkins - * @since 2019-10-21 - */ - public static final class NameSymbol { - public static final NameSymbol EMPTY = new NameSymbol(Optional.empty(), Optional.empty(), new HashSet<>()); - - /** - * Gets a {@code NameSymbol} with a primary name, a symbol and no other names. - * - * @param name - * name to use - * @param symbol - * symbol to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException - * if name or symbol is null - */ - public static final NameSymbol of(final String name, final String symbol) { - return new NameSymbol(Optional.of(name), Optional.of(symbol), new HashSet<>()); - } - - /** - * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. - * - * @param name - * name to use - * @param symbol - * symbol to use - * @param otherNames - * other names to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException - * if any argument is null - */ - public static final NameSymbol of(final String name, final String symbol, final Set<String> otherNames) { - return new NameSymbol(Optional.of(name), Optional.of(symbol), - new HashSet<>(Objects.requireNonNull(otherNames, "otherNames must not be null."))); - } - - /** - * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. - * - * @param name - * name to use - * @param symbol - * symbol to use - * @param otherNames - * other names to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException - * if any argument is null - */ - public static final NameSymbol of(final String name, final String symbol, final String... otherNames) { - return new NameSymbol(Optional.of(name), Optional.of(symbol), - new HashSet<>(Arrays.asList(Objects.requireNonNull(otherNames, "otherNames must not be null.")))); - } - - /** - * Gets a {@code NameSymbol} with a primary name, a symbol and an additional name. - * - * @param name - * name to use - * @param symbol - * symbol to use - * @param otherNames - * other names to use - * @param name2 - * alternate name - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException - * if any argument is null - */ - public static final NameSymbol of(final String name, final String symbol, final String name2) { - final Set<String> otherNames = new HashSet<>(); - otherNames.add(Objects.requireNonNull(name2, "name2 must not be null.")); - return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames); - } - - /** - * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. - * - * @param name - * name to use - * @param symbol - * symbol to use - * @param otherNames - * other names to use - * @param name2 - * alternate name - * @param name3 - * alternate name - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException - * if any argument is null - */ - public static final NameSymbol of(final String name, final String symbol, final String name2, - final String name3) { - final Set<String> otherNames = new HashSet<>(); - otherNames.add(Objects.requireNonNull(name2, "name2 must not be null.")); - otherNames.add(Objects.requireNonNull(name3, "name3 must not be null.")); - return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames); - } - - /** - * Gets a {@code NameSymbol} with a primary name, a symbol and additional names. - * - * @param name - * name to use - * @param symbol - * symbol to use - * @param otherNames - * other names to use - * @param name2 - * alternate name - * @param name3 - * alternate name - * @param name4 - * alternate name - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException - * if any argument is null - */ - public static final NameSymbol of(final String name, final String symbol, final String name2, - final String name3, final String name4) { - final Set<String> otherNames = new HashSet<>(); - otherNames.add(Objects.requireNonNull(name2, "name2 must not be null.")); - otherNames.add(Objects.requireNonNull(name3, "name3 must not be null.")); - otherNames.add(Objects.requireNonNull(name4, "name4 must not be null.")); - return new NameSymbol(Optional.of(name), Optional.of(symbol), otherNames); - } - - /** - * Gets a {@code NameSymbol} with a primary name, no symbol, and no other names. - * - * @param name - * name to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException - * if name is null - */ - public static final NameSymbol ofName(final String name) { - return new NameSymbol(Optional.of(name), Optional.empty(), new HashSet<>()); - } - - /** - * Gets a {@code NameSymbol} with a symbol and no names. - * - * @param symbol - * symbol to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException - * if symbol is null - */ - public static final NameSymbol ofSymbol(final String symbol) { - return new NameSymbol(Optional.empty(), Optional.of(symbol), new HashSet<>()); - } - - private final Optional<String> primaryName; - private final Optional<String> symbol; - - private final Set<String> otherNames; - - /** - * Creates the {@code NameSymbol}. - * - * @param primaryName - * primary name of unit - * @param symbol - * symbol used to represent unit - * @param otherNames - * other names and/or spellings - * @since 2019-10-21 - */ - private NameSymbol(final Optional<String> primaryName, final Optional<String> symbol, - final Set<String> otherNames) { - this.primaryName = primaryName; - this.symbol = symbol; - this.otherNames = Collections.unmodifiableSet(otherNames); - } - - /** - * @return otherNames - * @since 2019-10-21 - */ - public final Set<String> getOtherNames() { - return this.otherNames; - } - - /** - * @return primaryName - * @since 2019-10-21 - */ - public final Optional<String> getPrimaryName() { - return this.primaryName; - } - - /** - * @return symbol - * @since 2019-10-21 - */ - public final Optional<String> getSymbol() { - return this.symbol; - } - } - - /** * Returns a unit from its base and the functions it uses to convert to and from its base. * * <p> diff --git a/src/org/unitConverter/unit/UnitDatabase.java b/src/org/unitConverter/unit/UnitDatabase.java index 6a89b67..9df34a7 100644 --- a/src/org/unitConverter/unit/UnitDatabase.java +++ b/src/org/unitConverter/unit/UnitDatabase.java @@ -974,12 +974,13 @@ public final class UnitDatabase { */ private static final Map<Pattern, String> EXPRESSION_REPLACEMENTS = new HashMap<>(); + // add data to expression replacements static { // place brackets around any expression of the form "number unit", with or without the space EXPRESSION_REPLACEMENTS.put(Pattern.compile("((?:-?[1-9]\\d*|0)" // integer + "(?:\\.\\d+)?)" // optional decimal point with numbers after it + "\\s*" // optional space(s) - + "([a-zA-Z]+)" // unit name + + "([a-zA-Z]+)" // any string of letters + "(?!-?\\d)" // no number directly afterwards (avoids matching "1e3") ), "\\($1 $2\\)"); } diff --git a/src/org/unitConverter/unit/UnitPrefix.java b/src/org/unitConverter/unit/UnitPrefix.java index 360b0c1..31cc0b3 100644 --- a/src/org/unitConverter/unit/UnitPrefix.java +++ b/src/org/unitConverter/unit/UnitPrefix.java @@ -16,6 +16,10 @@ */ package org.unitConverter.unit; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + import org.unitConverter.math.DecimalComparison; /** @@ -34,10 +38,41 @@ public final class UnitPrefix { * @since 2019-10-16 */ public static UnitPrefix valueOf(final double multiplier) { - return new UnitPrefix(multiplier); + return new UnitPrefix(multiplier, NameSymbol.EMPTY); + } + + /** + * Gets a {@code UnitPrefix} from a multiplier and a name + * + * @param multiplier + * multiplier of prefix + * @param ns + * name(s) and symbol of prefix + * @return prefix + * @since 2019-10-16 + * @throws NullPointerException + * if ns is null + */ + public static UnitPrefix valueOf(final double multiplier, final NameSymbol ns) { + return new UnitPrefix(multiplier, Objects.requireNonNull(ns, "ns must not be null.")); } /** + * This prefix's primary name + */ + private final Optional<String> primaryName; + + /** + * This prefix's symbol + */ + private final Optional<String> symbol; + + /** + * Other names and symbols used by this prefix + */ + private final Set<String> otherNames; + + /** * The number that this prefix multiplies units by * * @since 2019-10-16 @@ -51,8 +86,11 @@ public final class UnitPrefix { * @since 2019-01-14 * @since v0.2.0 */ - private UnitPrefix(final double multiplier) { + private UnitPrefix(final double multiplier, final NameSymbol ns) { this.multiplier = multiplier; + this.primaryName = ns.getPrimaryName(); + this.symbol = ns.getSymbol(); + this.otherNames = ns.getOtherNames(); } /** @@ -106,6 +144,30 @@ public final class UnitPrefix { } /** + * @return other names + * @since 2019-11-26 + */ + public final Set<String> getOtherNames() { + return this.otherNames; + } + + /** + * @return primary name + * @since 2019-11-26 + */ + public final Optional<String> getPrimaryName() { + return this.primaryName; + } + + /** + * @return symbol + * @since 2019-11-26 + */ + public final Optional<String> getSymbol() { + return this.symbol; + } + + /** * {@inheritDoc} * * Uses the prefix's multiplier to determine a hash code. @@ -158,6 +220,23 @@ public final class UnitPrefix { */ @Override public String toString() { - return String.format("Unit prefix with multiplier %s", this.multiplier); + if (this.primaryName.isPresent()) + return String.format("%s (\u00D7 %s)", this.primaryName.get(), this.multiplier); + else if (this.symbol.isPresent()) + return String.format("%s (\u00D7 %s)", this.symbol.get(), this.multiplier); + else + return String.format("Unit Prefix (\u00D7 %s)", this.multiplier); + } + + /** + * @param ns + * name(s) and symbol to use + * @return copy of this prefix with provided name(s) and symbol + * @since 2019-11-26 + * @throws NullPointerException + * if ns is null + */ + public UnitPrefix withName(final NameSymbol ns) { + return valueOf(this.multiplier, ns); } } |