summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrien Hopkins <adrien.p.hopkins@gmail.com>2019-04-10 21:00:49 -0400
committerAdrien Hopkins <adrien.p.hopkins@gmail.com>2019-04-10 21:00:49 -0400
commitec036fdad931fbbd7dec28b864150f8668e91b41 (patch)
treecb43fbad3089765fa548f8aeb959a686536aaec8
parent91ee53876aeeb52e980dd1fa976fae06d890ba19 (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.org1
-rwxr-xr-xsrc/org/unitConverter/UnitsDatabase.java181
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);
}