diff options
author | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2019-04-10 21:00:49 -0400 |
---|---|---|
committer | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2019-04-10 21:00:49 -0400 |
commit | ec036fdad931fbbd7dec28b864150f8668e91b41 (patch) | |
tree | cb43fbad3089765fa548f8aeb959a686536aaec8 | |
parent | 91ee53876aeeb52e980dd1fa976fae06d890ba19 (diff) |
Edited dimension database code and improved comments.
getDimension() now works with exponents,
Added a dimension parser,
comments can now be in the middle of lines
-rw-r--r-- | CHANGELOG.org | 1 | ||||
-rwxr-xr-x | src/org/unitConverter/UnitsDatabase.java | 181 |
2 files changed, 115 insertions, 67 deletions
diff --git a/CHANGELOG.org b/CHANGELOG.org index 95dc57a..8a79c46 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -6,6 +6,7 @@ All notable changes in this project will be shown in this file. - Moved project to Maven - Downgraded JUnit to 4.11 - BaseUnit is now a subclass of LinearUnit + - Comments can now start in the middle of lines *** Added - GUI for a selection-based unit converter - The UnitDatabase now stores dimensions. diff --git a/src/org/unitConverter/UnitsDatabase.java b/src/org/unitConverter/UnitsDatabase.java index 290a425..69b25d8 100755 --- a/src/org/unitConverter/UnitsDatabase.java +++ b/src/org/unitConverter/UnitsDatabase.java @@ -49,6 +49,32 @@ import org.unitConverter.unit.UnitPrefix; */ public final class UnitsDatabase { /** + * The exponent operator + * + * @param base + * base of exponentiation + * @param exponentUnit + * exponent + * @return result + * @since 2019-04-10 + */ + private static final LinearUnit exponent(final LinearUnit base, final LinearUnit exponentUnit) { + // exponent function - first check if o2 is a number, + if (exponentUnit.getBase().equals(SI.SI.getBaseUnit(UnitDimension.EMPTY))) { + // then check if it is an integer, + final double exponent = exponentUnit.getConversionFactor(); + if (DecimalComparison.equals(exponent % 1, 0)) + // then exponentiate + return base.toExponent((int) (exponent % 1 + 0.5)); + else + // not an integer + throw new UnsupportedOperationException("Decimal exponents are currently not supported."); + } else + // not a number + throw new IllegalArgumentException("Exponents must be numbers."); + } + + /** * The units in this system. * * @since 2019-01-07 @@ -80,22 +106,12 @@ public final class UnitsDatabase { 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("^", (o1, o2) -> { - // exponent function - first check if o2 is a number, - if (o2.getBase().equals(SI.SI.getBaseUnit(UnitDimension.EMPTY))) { - // then check if it is an integer, - final double exponent = o2.getConversionFactor(); - if (DecimalComparison.equals(exponent % 1, 0)) - // then exponentiate - return o1.toExponent((int) (exponent % 1 + 0.5)); - else - // not an integer - throw new UnsupportedOperationException( - "Decimal exponents are currently not supported."); - } else - // not a number - throw new IllegalArgumentException("Exponents must be numbers."); - }, 2).build(); + .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1) + .addBinaryOperator("^", UnitsDatabase::exponent, 2).build(); + + private final ExpressionParser<UnitDimension> 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}. @@ -118,7 +134,7 @@ public final class UnitsDatabase { * <p> * Allowed exceptions: * <ul> - * <li>Any line that begins with the '#' character is considered a comment and ignored.</li> + * <li>Anything after a '#' character is considered a comment and ignored.</li> * <li>Blank lines are also ignored</li> * <li>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 @@ -140,56 +156,7 @@ public final class UnitsDatabase { // while the reader has lines to read, read a line, then parse it, then add it long lineCounter = 0; while (reader.ready()) { - final String line = reader.readLine(); - lineCounter++; - - // ignore lines that start with a # sign - they're comments - if (line.startsWith("#") || line.isEmpty()) { - continue; - } - - // divide line into name and expression - final String[] parts = line.split("\t"); - if (parts.length < 2) - throw new IllegalArgumentException(String.format( - "Lines must consist of a unit name and its definition, separated by tab(s) (line %d).", - lineCounter)); - final String name = parts[0]; - final String expression = parts[parts.length - 1]; - - 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); - } - } + this.addFromLine(reader.readLine(), ++lineCounter); } } catch (final FileNotFoundException e) { throw new IllegalArgumentException("Could not find file " + file, e); @@ -215,6 +182,67 @@ public final class UnitsDatabase { } /** + * 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 + */ + private void addFromLine(final String line, final long lineCounter) { + // ignore lines that start with a # sign - they're comments + if (line.isEmpty()) + return; + if (line.contains("#")) { + this.addFromLine(line.substring(0, line.indexOf("#")), lineCounter); + return; + } + + // divide line into name and expression + final String[] parts = line.split("\t"); + if (parts.length < 2) + throw new IllegalArgumentException(String.format( + "Lines must consist of a unit name and its definition, separated by tab(s) (line %d).", + lineCounter)); + final String name = parts[0]; + final String expression = parts[parts.length - 1]; + + 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); + } + } + } + + /** * Adds a unit prefix to the database. * * @param name @@ -316,12 +344,31 @@ public final class UnitsDatabase { /** * Gets a unit dimension from the database using its name. * + * <p> + * This method accepts exponents, like "L^3" + * </p> + * * @param name * dimension's name * @return dimension * @since 2019-03-14 */ public UnitDimension getDimension(final String name) { + Objects.requireNonNull(name, "name must not be null."); + if (name.contains("^")) { + final String[] baseAndExponent = name.split("\\^"); + + final UnitDimension 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); } |