units;
-
- /**
- * The rule that specifies when prefix repetition is allowed. It takes in one
- * argument: a list of the prefixes being applied to the unit
- *
- * The prefixes are inputted in application order. This means that
- * testing whether "kilomegagigametre" is a valid unit is equivalent to
- * running the following code (assuming all variables are defined correctly):
- *
- * {@code prefixRepetitionRule.test(Arrays.asList(giga, mega, kilo))}
- */
- private Predicate> prefixRepetitionRule;
-
- /**
- * A parser that can parse unit expressions.
- *
- * @since 2019-03-22
- * @since v0.2.0
- */
- private final ExpressionParser unitExpressionParser = new ExpressionParser.Builder<>(
- this::getLinearUnit).addBinaryOperator("+", (o1, o2) -> o1.plus(o2), 0)
- .addBinaryOperator("-", (o1, o2) -> o1.minus(o2), 0)
- .addBinaryOperator("*", (o1, o2) -> o1.times(o2), 1)
- .addSpaceFunction("*")
- .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1)
- .addBinaryOperator("^", UnitDatabase::exponentiateUnits, 2)
- .build();
-
- /**
- * A parser that can parse unit value expressions.
- *
- * @since 2020-08-04
- */
- private final ExpressionParser unitValueExpressionParser = new ExpressionParser.Builder<>(
- this::getLinearUnitValue)
- .addBinaryOperator("+", (o1, o2) -> o1.plus(o2), 0)
- .addBinaryOperator("-", (o1, o2) -> o1.minus(o2), 0)
- .addBinaryOperator("*", (o1, o2) -> o1.times(o2), 1)
- .addSpaceFunction("*")
- .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1)
- .addBinaryOperator("^", UnitDatabase::exponentiateUnitValues, 2)
- .build();
-
- /**
- * A parser that can parse unit prefix expressions
- *
- * @since 2019-04-13
- * @since v0.2.0
- */
- private final ExpressionParser prefixExpressionParser = new ExpressionParser.Builder<>(
- this::getPrefix).addBinaryOperator("*", (o1, o2) -> o1.times(o2), 0)
- .addSpaceFunction("*")
- .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 0)
- .addBinaryOperator("^",
- (o1, o2) -> o1.toExponent(o2.getMultiplier()), 1)
- .build();
-
- /**
- * A parser that can parse unit dimension expressions.
- *
- * @since 2019-04-13
- * @since v0.2.0
- */
- private final ExpressionParser> unitDimensionParser = new ExpressionParser.Builder<>(
- this::getDimension).addBinaryOperator("*", (o1, o2) -> o1.times(o2), 0)
- .addSpaceFunction("*")
- .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 0).build();
-
- /**
- * Creates the {@code UnitsDatabase}.
- *
- * @since 2019-01-10
- * @since v0.1.0
- */
- public UnitDatabase() {
- this(prefixes -> true);
- }
-
- /**
- * Creates the {@code UnitsDatabase}
- *
- * @param prefixRepetitionRule the rule that determines when prefix
- * repetition is allowed
- * @since 2020-08-26
- */
- public UnitDatabase(Predicate> prefixRepetitionRule) {
- this.prefixlessUnits = new HashMap<>();
- this.prefixes = new HashMap<>();
- this.dimensions = new HashMap<>();
- this.prefixRepetitionRule = prefixRepetitionRule;
- this.units = ConditionalExistenceCollections.conditionalExistenceMap(
- new PrefixedUnitMap(this.prefixlessUnits, this.prefixes),
- entry -> this.prefixRepetitionRule
- .test(this.getPrefixesFromName(entry.getKey())));
- }
-
- /**
- * Adds a unit dimension to the database.
- *
- * @param name dimension's name
- * @param dimension dimension to add
- * @throws NullPointerException if name or dimension is null
- * @since 2019-03-14
- * @since v0.2.0
- */
- public void addDimension(final String name,
- final ObjectProduct dimension) {
- this.dimensions.put(
- Objects.requireNonNull(name, "name must not be null."),
- Objects.requireNonNull(dimension, "dimension must not be null."));
- }
-
- /**
- * Adds to the list from a line in a unit dimension file.
- *
- * @param line line to look at
- * @param lineCounter number of line, for error messages
- * @since 2019-04-10
- * @since v0.2.0
- */
- private void addDimensionFromLine(final String line,
- final long lineCounter) {
- // ignore lines that start with a # sign - they're comments
- if (line.isEmpty())
- return;
- if (line.contains("#")) {
- this.addDimensionFromLine(line.substring(0, line.indexOf("#")),
- lineCounter);
- return;
- }
-
- // divide line into name and expression
- final Matcher lineMatcher = NAME_EXPRESSION.matcher(line);
- if (!lineMatcher.matches())
- throw new IllegalArgumentException(String.format(
- "Error at line %d: Lines of a dimension file must consist of a dimension name, then spaces or tabs, then a dimension expression.",
- lineCounter));
- final String name = lineMatcher.group(1);
- final String expression = lineMatcher.group(2);
-
- if (name.endsWith(" ")) {
- System.err.printf("Warning - line %d's dimension name ends in a space",
- lineCounter);
- }
-
- // if expression is "!", search for an existing dimension
- // if no unit found, throw an error
- if (expression.equals("!")) {
- if (!this.containsDimensionName(name))
- throw new IllegalArgumentException(String.format(
- "! used but no dimension found (line %d).", lineCounter));
- } else {
- // it's a unit, get the unit
- final ObjectProduct dimension;
- try {
- dimension = this.getDimensionFromExpression(expression);
- } catch (final IllegalArgumentException e) {
- System.err.printf("Parsing error on line %d:%n", lineCounter);
- throw e;
- }
-
- this.addDimension(name, dimension);
- }
- }
-
- /**
- * Adds a unit prefix to the database.
- *
- * @param name prefix's name
- * @param prefix prefix to add
- * @throws NullPointerException if name or prefix is null
- * @since 2019-01-14
- * @since v0.1.0
- */
- public void addPrefix(final String name, final UnitPrefix prefix) {
- this.prefixes.put(Objects.requireNonNull(name, "name must not be null."),
- Objects.requireNonNull(prefix, "prefix must not be null."));
- }
-
- /**
- * Adds a unit to the database.
- *
- * @param name unit's name
- * @param unit unit to add
- * @throws NullPointerException if unit is null
- * @since 2019-01-10
- * @since v0.1.0
- */
- public void addUnit(final String name, final Unit unit) {
- this.prefixlessUnits.put(
- Objects.requireNonNull(name, "name must not be null."),
- Objects.requireNonNull(unit, "unit must not be null."));
- }
-
- /**
- * Adds to the list from a line in a unit file.
- *
- * @param line line to look at
- * @param lineCounter number of line, for error messages
- * @since 2019-04-10
- * @since v0.2.0
- */
- private void addUnitOrPrefixFromLine(final String line,
- final long lineCounter) {
- // ignore lines that start with a # sign - they're comments
- if (line.isEmpty())
- return;
- if (line.contains("#")) {
- this.addUnitOrPrefixFromLine(line.substring(0, line.indexOf("#")),
- lineCounter);
- return;
- }
-
- // divide line into name and expression
- final Matcher lineMatcher = NAME_EXPRESSION.matcher(line);
- if (!lineMatcher.matches())
- throw new IllegalArgumentException(String.format(
- "Error at line %d: Lines of a unit file must consist of a unit name, then spaces or tabs, then a unit expression.",
- lineCounter));
- final String name = lineMatcher.group(1);
-
- final String expression = lineMatcher.group(2);
-
- if (name.endsWith(" ")) {
- System.err.printf("Warning - line %d's unit name ends in a space",
- lineCounter);
- }
-
- // if expression is "!", search for an existing unit
- // if no unit found, throw an error
- if (expression.equals("!")) {
- if (!this.containsUnitName(name))
- throw new IllegalArgumentException(String
- .format("! used but no unit found (line %d).", lineCounter));
- } else {
- if (name.endsWith("-")) {
- final UnitPrefix prefix;
- try {
- prefix = this.getPrefixFromExpression(expression);
- } catch (final IllegalArgumentException e) {
- System.err.printf("Parsing error on line %d:%n", lineCounter);
- throw e;
- }
- this.addPrefix(name.substring(0, name.length() - 1), prefix);
- } else {
- // it's a unit, get the unit
- final Unit unit;
- try {
- unit = this.getUnitFromExpression(expression);
- } catch (final IllegalArgumentException e) {
- System.err.printf("Parsing error on line %d:%n", lineCounter);
- throw e;
- }
-
- this.addUnit(name, unit);
- }
- }
- }
-
- /**
- * Tests if the database has a unit dimension with this name.
- *
- * @param name name to test
- * @return if database contains name
- * @since 2019-03-14
- * @since v0.2.0
- */
- public boolean containsDimensionName(final String name) {
- return this.dimensions.containsKey(name);
- }
-
- /**
- * Tests if the database has a unit prefix with this name.
- *
- * @param name name to test
- * @return if database contains name
- * @since 2019-01-13
- * @since v0.1.0
- */
- public boolean containsPrefixName(final String name) {
- return this.prefixes.containsKey(name);
- }
-
- /**
- * Tests if the database has a unit with this name, taking prefixes into
- * consideration
- *
- * @param name name to test
- * @return if database contains name
- * @since 2019-01-13
- * @since v0.1.0
- */
- public boolean containsUnitName(final String name) {
- return this.units.containsKey(name);
- }
-
- /**
- * @return a map mapping dimension names to dimensions
- * @since 2019-04-13
- * @since v0.2.0
- */
- public Map> dimensionMap() {
- return Collections.unmodifiableMap(this.dimensions);
- }
-
- /**
- * Evaluates a unit expression, following the same rules as
- * {@link #getUnitFromExpression}.
- *
- * @param expression expression to parse
- * @return {@code LinearUnitValue} representing value of expression
- * @since 2020-08-04
- */
- public LinearUnitValue evaluateUnitExpression(final String expression) {
- Objects.requireNonNull(expression, "expression must not be null.");
-
- // attempt to get a unit as an alias, or a number with precision first
- if (this.containsUnitName(expression))
- return this.getLinearUnitValue(expression);
-
- // force operators to have spaces
- String modifiedExpression = expression;
- modifiedExpression = modifiedExpression.replaceAll("\\+", " \\+ ");
- modifiedExpression = modifiedExpression.replaceAll("-", " - ");
-
- // format expression
- for (final Entry replacement : EXPRESSION_REPLACEMENTS
- .entrySet()) {
- modifiedExpression = replacement.getKey().matcher(modifiedExpression)
- .replaceAll(replacement.getValue());
- }
-
- // the previous operation breaks negative numbers, fix them!
- // (i.e. -2 becomes - 2)
- // FIXME the previous operaton also breaks stuff like "1e-5"
- for (int i = 0; i < modifiedExpression.length(); i++) {
- if (modifiedExpression.charAt(i) == '-'
- && (i < 2 || Arrays.asList('+', '-', '*', '/', '^')
- .contains(modifiedExpression.charAt(i - 2)))) {
- // found a broken negative number
- modifiedExpression = modifiedExpression.substring(0, i + 1)
- + modifiedExpression.substring(i + 2);
- }
- }
-
- return this.unitValueExpressionParser.parseExpression(modifiedExpression);
- }
-
- /**
- * Gets a unit dimension from the database using its name.
- *
- *
- * This method accepts exponents, like "L^3"
- *
- *
- * @param name dimension's name
- * @return dimension
- * @since 2019-03-14
- * @since v0.2.0
- */
- public ObjectProduct getDimension(final String name) {
- Objects.requireNonNull(name, "name must not be null.");
- if (name.contains("^")) {
- final String[] baseAndExponent = name.split("\\^");
-
- final ObjectProduct base = this
- .getDimension(baseAndExponent[0]);
-
- final int exponent;
- try {
- exponent = Integer
- .parseInt(baseAndExponent[baseAndExponent.length - 1]);
- } catch (final NumberFormatException e2) {
- throw new IllegalArgumentException("Exponent must be an integer.");
- }
-
- return base.toExponent(exponent);
- }
- return this.dimensions.get(name);
- }
-
- /**
- * Uses the database's data to parse an expression into a unit dimension
- *
- * The expression is a series of any of the following:
- *
- * - The name of a unit dimension, which multiplies or divides the result
- * based on preceding operators
- * - The operators '*' and '/', which multiply and divide (note that just
- * putting two unit dimensions next to each other is equivalent to
- * multiplication)
- * - The operator '^' which exponentiates. Exponents must be integers.
- *
- *
- * @param expression expression to parse
- * @throws IllegalArgumentException if the expression cannot be parsed
- * @throws NullPointerException if expression is null
- * @since 2019-04-13
- * @since v0.2.0
- */
- public ObjectProduct getDimensionFromExpression(
- final String expression) {
- Objects.requireNonNull(expression, "expression must not be null.");
-
- // attempt to get a dimension as an alias first
- if (this.containsDimensionName(expression))
- return this.getDimension(expression);
-
- // force operators to have spaces
- String modifiedExpression = expression;
-
- // format expression
- for (final Entry replacement : EXPRESSION_REPLACEMENTS
- .entrySet()) {
- modifiedExpression = replacement.getKey().matcher(modifiedExpression)
- .replaceAll(replacement.getValue());
- }
- modifiedExpression = modifiedExpression.replaceAll(" *\\^ *", "\\^");
-
- return this.unitDimensionParser.parseExpression(modifiedExpression);
- }
-
- /**
- * Gets a unit. If it is linear, cast it to a LinearUnit and return it.
- * Otherwise, throw an {@code IllegalArgumentException}.
- *
- * @param name unit's name
- * @return unit
- * @since 2019-03-22
- * @since v0.2.0
- */
- private LinearUnit getLinearUnit(final String name) {
- // see if I am using a function-unit like tempC(100)
- Objects.requireNonNull(name, "name may not be null");
- if (name.contains("(") && name.contains(")")) {
- // break it into function name and value
- final List parts = Arrays.asList(name.split("\\("));
- if (parts.size() != 2)
- throw new IllegalArgumentException(
- "Format nonlinear units like: unit(value).");
-
- // solve the function
- final Unit unit = this.getUnit(parts.get(0));
- final double value = Double.parseDouble(
- parts.get(1).substring(0, parts.get(1).length() - 1));
- return LinearUnit.fromUnitValue(unit, value);
- } else {
- // get a linear unit
- final Unit unit = this.getUnit(name);
-
- if (unit instanceof LinearUnit)
- return (LinearUnit) unit;
- else
- throw new IllegalArgumentException(
- String.format("%s is not a linear unit.", name));
- }
- }
-
- /**
- * Gets a {@code LinearUnitValue} from a unit name. Nonlinear units will be
- * converted to their base units.
- *
- * @param name name of unit
- * @return {@code LinearUnitValue} instance
- * @since 2020-08-04
- */
- private LinearUnitValue getLinearUnitValue(final String name) {
- try {
- // try to parse it as a number - otherwise it is not a number!
- final BigDecimal number = new BigDecimal(name);
-
- final double uncertainty = Math.pow(10, -number.scale());
- return LinearUnitValue.of(SI.ONE,
- UncertainDouble.of(number.doubleValue(), uncertainty));
- } catch (final NumberFormatException e) {
- return LinearUnitValue.getExact(this.getLinearUnit(name), 1);
- }
- }
-
- /**
- * Gets a unit prefix from the database from its name
- *
- * @param name prefix's name
- * @return prefix
- * @since 2019-01-10
- * @since v0.1.0
- */
- public UnitPrefix getPrefix(final String name) {
- try {
- return UnitPrefix.valueOf(Double.parseDouble(name));
- } catch (final NumberFormatException e) {
- return this.prefixes.get(name);
- }
- }
-
- /**
- * Gets all of the prefixes that are on a unit name, in application order.
- *
- * @param unitName name of unit
- * @return prefixes
- * @since 2020-08-26
- */
- List getPrefixesFromName(final String unitName) {
- final List prefixes = new ArrayList<>();
- String name = unitName;
-
- while (!this.prefixlessUnits.containsKey(name)) {
- // find the longest prefix
- String longestPrefixName = null;
- int longestLength = name.length();
-
- while (longestPrefixName == null) {
- longestLength--;
- if (longestLength <= 0)
- throw new AssertionError(
- "No prefix found in " + name + ", but it is not a unit!");
- if (this.prefixes.containsKey(name.substring(0, longestLength))) {
- longestPrefixName = name.substring(0, longestLength);
- }
- }
-
- // longest prefix found!
- final UnitPrefix prefix = this.getPrefix(longestPrefixName);
- prefixes.add(0, prefix);
- name = name.substring(longestLength);
- }
- return prefixes;
- }
-
- /**
- * Gets a unit prefix from a prefix expression
- *
- * Currently, prefix expressions are much simpler than unit expressions: They
- * are either a number or the name of another prefix
- *
- *
- * @param expression expression to input
- * @return prefix
- * @throws IllegalArgumentException if expression cannot be parsed
- * @throws NullPointerException if any argument is null
- * @since 2019-01-14
- * @since v0.1.0
- */
- public UnitPrefix getPrefixFromExpression(final String expression) {
- Objects.requireNonNull(expression, "expression must not be null.");
-
- // attempt to get a unit as an alias first
- if (this.containsUnitName(expression))
- return this.getPrefix(expression);
-
- // force operators to have spaces
- String modifiedExpression = expression;
-
- // format expression
- for (final Entry replacement : EXPRESSION_REPLACEMENTS
- .entrySet()) {
- modifiedExpression = replacement.getKey().matcher(modifiedExpression)
- .replaceAll(replacement.getValue());
- }
-
- return this.prefixExpressionParser.parseExpression(modifiedExpression);
- }
-
- /**
- * @return the prefixRepetitionRule
- * @since 2020-08-26
- */
- public final Predicate> getPrefixRepetitionRule() {
- return this.prefixRepetitionRule;
- }
-
- /**
- * Gets a unit from the database from its name, looking for prefixes.
- *
- * @param name unit's name
- * @return unit
- * @since 2019-01-10
- * @since v0.1.0
- */
- public Unit getUnit(final String name) {
- try {
- final double value = Double.parseDouble(name);
- return SI.ONE.times(value);
- } catch (final NumberFormatException e) {
- final Unit unit = this.units.get(name);
- if (unit == null)
- throw new NoSuchElementException("No unit " + name);
- else if (unit.getPrimaryName().isEmpty())
- return unit.withName(NameSymbol.ofName(name));
- else if (!unit.getPrimaryName().get().equals(name)) {
- final Set otherNames = new HashSet<>(unit.getOtherNames());
- otherNames.add(unit.getPrimaryName().get());
- return unit.withName(NameSymbol.ofNullable(name,
- unit.getSymbol().orElse(null), otherNames));
- } else if (!unit.getOtherNames().contains(name)) {
- final Set otherNames = new HashSet<>(unit.getOtherNames());
- otherNames.add(name);
- return unit.withName(
- NameSymbol.ofNullable(unit.getPrimaryName().orElse(null),
- unit.getSymbol().orElse(null), otherNames));
- } else
- return unit;
- }
-
- }
-
- /**
- * Uses the database's unit data to parse an expression into a unit
- *
- * The expression is a series of any of the following:
- *
- * - The name of a unit, which multiplies or divides the result based on
- * preceding operators
- * - The operators '*' and '/', which multiply and divide (note that just
- * putting two units or values next to each other is equivalent to
- * multiplication)
- * - The operator '^' which exponentiates. Exponents must be integers.
- * - A number which is multiplied or divided
- *
- * This method only works with linear units.
- *
- * @param expression expression to parse
- * @throws IllegalArgumentException if the expression cannot be parsed
- * @throws NullPointerException if expression is null
- * @since 2019-01-07
- * @since v0.1.0
- */
- public Unit getUnitFromExpression(final String expression) {
- Objects.requireNonNull(expression, "expression must not be null.");
-
- // attempt to get a unit as an alias first
- if (this.containsUnitName(expression))
- return this.getUnit(expression);
-
- // force operators to have spaces
- String modifiedExpression = expression;
- modifiedExpression = modifiedExpression.replaceAll("\\+", " \\+ ");
- modifiedExpression = modifiedExpression.replaceAll("-", " - ");
-
- // format expression
- for (final Entry replacement : EXPRESSION_REPLACEMENTS
- .entrySet()) {
- modifiedExpression = replacement.getKey().matcher(modifiedExpression)
- .replaceAll(replacement.getValue());
- }
-
- // the previous operation breaks negative numbers, fix them!
- // (i.e. -2 becomes - 2)
- for (int i = 0; i < modifiedExpression.length(); i++) {
- if (modifiedExpression.charAt(i) == '-'
- && (i < 2 || Arrays.asList('+', '-', '*', '/', '^')
- .contains(modifiedExpression.charAt(i - 2)))) {
- // found a broken negative number
- modifiedExpression = modifiedExpression.substring(0, i + 1)
- + modifiedExpression.substring(i + 2);
- }
- }
-
- return this.unitExpressionParser.parseExpression(modifiedExpression);
- }
-
- /**
- * Adds all dimensions from a file, using data from the database to parse
- * them.
- *
- * Each line in the file should consist of a name and an expression (parsed
- * by getDimensionFromExpression) separated by any number of tab characters.
- *
- *
- * Allowed exceptions:
- *
- * - Anything after a '#' character is considered a comment and
- * ignored.
- * - Blank lines are also ignored
- * - If an expression consists of a single exclamation point, instead of
- * parsing it, this method will search the database for an existing unit. If
- * no unit is found, an IllegalArgumentException is thrown. This is used to
- * define initial units and ensure that the database contains them.
- *
- *
- * @param file file to read
- * @throws IllegalArgumentException if the file cannot be parsed, found or
- * read
- * @throws NullPointerException if file is null
- * @since 2019-01-13
- * @since v0.1.0
- */
- public void loadDimensionFile(final Path file) {
- Objects.requireNonNull(file, "file must not be null.");
- try {
- long lineCounter = 0;
- for (final String line : Files.readAllLines(file)) {
- this.addDimensionFromLine(line, ++lineCounter);
- }
- } catch (final FileNotFoundException e) {
- throw new IllegalArgumentException("Could not find file " + file, e);
- } catch (final IOException e) {
- throw new IllegalArgumentException("Could not read file " + file, e);
- }
- }
-
- /**
- * Adds all units from a file, using data from the database to parse them.
- *
- * Each line in the file should consist of a name and an expression (parsed
- * by getUnitFromExpression) separated by any number of tab characters.
- *
- *
- * Allowed exceptions:
- *
- * - Anything after a '#' character is considered a comment and
- * ignored.
- * - Blank lines are also ignored
- * - If an expression consists of a single exclamation point, instead of
- * parsing it, this method will search the database for an existing unit. If
- * no unit is found, an IllegalArgumentException is thrown. This is used to
- * define initial units and ensure that the database contains them.
- *
- *
- * @param file file to read
- * @throws IllegalArgumentException if the file cannot be parsed, found or
- * read
- * @throws NullPointerException if file is null
- * @since 2019-01-13
- * @since v0.1.0
- */
- public void loadUnitsFile(final Path file) {
- Objects.requireNonNull(file, "file must not be null.");
- try {
- long lineCounter = 0;
- for (final String line : Files.readAllLines(file)) {
- this.addUnitOrPrefixFromLine(line, ++lineCounter);
- }
- } catch (final FileNotFoundException e) {
- throw new IllegalArgumentException("Could not find file " + file, e);
- } catch (final IOException e) {
- throw new IllegalArgumentException("Could not read file " + file, e);
- }
- }
-
- /**
- * @return a map mapping prefix names to prefixes
- * @since 2019-04-13
- * @since v0.2.0
- */
- public Map prefixMap() {
- return Collections.unmodifiableMap(this.prefixes);
- }
-
- /**
- * @param prefixRepetitionRule the prefixRepetitionRule to set
- * @since 2020-08-26
- */
- public final void setPrefixRepetitionRule(
- Predicate> prefixRepetitionRule) {
- this.prefixRepetitionRule = prefixRepetitionRule;
- }
-
- /**
- * @return a string stating the number of units, prefixes and dimensions in
- * the database
- */
- @Override
- public String toString() {
- return String.format(
- "Unit Database with %d units, %d unit prefixes and %d dimensions",
- this.prefixlessUnits.size(), this.prefixes.size(),
- this.dimensions.size());
- }
-
- /**
- * Returns a map mapping unit names to units, including units with prefixes.
- *
- * The returned map is infinite in size if there is at least one unit and at
- * least one prefix. If it is infinite, some operations that only work with
- * finite collections, like converting name/entry sets to arrays, will throw
- * an {@code IllegalStateException}.
- *
- *
- * Specifically, the operations that will throw an IllegalStateException if
- * the map is infinite in size are:
- *
- * - {@code unitMap.entrySet().toArray()} (either overloading)
- * - {@code unitMap.keySet().toArray()} (either overloading)
- *
- *
- *
- * Because of ambiguities between prefixes (i.e. kilokilo = mega), the map's
- * {@link PrefixedUnitMap#containsValue containsValue} and
- * {@link PrefixedUnitMap#values() values()} methods currently ignore
- * prefixes.
- *
- *
- * @return a map mapping unit names to units, including prefixed names
- * @since 2019-04-13
- * @since v0.2.0
- */
- public Map unitMap() {
- return this.units; // PrefixedUnitMap is immutable so I don't need to make
- // an unmodifiable map.
- }
-
- /**
- * @return a map mapping unit names to units, ignoring prefixes
- * @since 2019-04-13
- * @since v0.2.0
- */
- public Map unitMapPrefixless() {
- return Collections.unmodifiableMap(this.prefixlessUnits);
- }
-}
--
cgit v1.2.3