diff options
Diffstat (limited to 'src/org/unitConverter/UnitsDatabase.java')
-rwxr-xr-x | src/org/unitConverter/UnitsDatabase.java | 395 |
1 files changed, 259 insertions, 136 deletions
diff --git a/src/org/unitConverter/UnitsDatabase.java b/src/org/unitConverter/UnitsDatabase.java index 901c6ef..959c151 100755 --- a/src/org/unitConverter/UnitsDatabase.java +++ b/src/org/unitConverter/UnitsDatabase.java @@ -30,6 +30,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; import java.util.function.BiFunction; @@ -83,6 +84,153 @@ public final class UnitsDatabase { * @since 2019-04-13 */ private static final class PrefixedUnitEntrySet extends AbstractSet<Map.Entry<String, Unit>> { + /** + * The entry for this set. + * + * @author Adrien Hopkins + * @since 2019-04-14 + */ + private static final class PrefixedUnitEntry implements Entry<String, Unit> { + private final String key; + private final Unit value; + + /** + * Creates the {@code PrefixedUnitEntry}. + * + * @param key + * @param value + * @since 2019-04-14 + */ + public PrefixedUnitEntry(final String key, final Unit value) { + this.key = key; + this.value = value; + } + + @Override + public String getKey() { + return this.key; + } + + @Override + public Unit getValue() { + return this.value; + } + + @Override + public Unit setValue(final Unit value) { + throw new UnsupportedOperationException(); + } + } + + /** + * An iterator that iterates over the units of a {@code PrefixedUnitNameSet}. + * + * @author Adrien Hopkins + * @since 2019-04-14 + */ + private static final class PrefixedUnitEntryIterator implements Iterator<Entry<String, Unit>> { + // position in the unit list + private int unitNamePosition = 0; + // the indices of the prefixes attached to the current unit + private final List<Integer> prefixCoordinates = new ArrayList<>(); + + private final Map<String, Unit> map; + private final List<String> unitNames; + private final List<String> prefixNames; + + /** + * Creates the {@code UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator}. + * + * @since 2019-04-14 + */ + public PrefixedUnitEntryIterator(final PrefixedUnitEntrySet set) { + this.map = set.map; + this.unitNames = new ArrayList<>(set.map.units.keySet()); + this.prefixNames = new ArrayList<>(set.map.prefixes.keySet()); + } + + /** + * @return current unit name + * @since 2019-04-14 + */ + private String getCurrentUnitName() { + final StringBuilder unitName = new StringBuilder(); + for (final int i : this.prefixCoordinates) { + unitName.append(this.prefixNames.get(i)); + } + unitName.append(this.unitNames.get(this.unitNamePosition)); + + return unitName.toString(); + } + + @Override + public boolean hasNext() { + if (this.unitNames.isEmpty()) + return false; + else { + if (this.prefixNames.isEmpty()) + return this.unitNamePosition >= this.unitNames.size() - 1; + else + return true; + } + } + + /** + * Changes this iterator's position to the next available one. + * + * @since 2019-04-14 + */ + private void incrementPosition() { + this.unitNamePosition++; + + if (this.unitNamePosition >= this.unitNames.size()) { + // we have used all of our units, go to a different prefix + this.unitNamePosition = 0; + + // if the prefix coordinates are empty, then set it to [0] + if (this.prefixCoordinates.isEmpty()) { + this.prefixCoordinates.add(0, 0); + } else { + // get the prefix coordinate to increment, then increment + int i = this.prefixCoordinates.size() - 1; + this.prefixCoordinates.set(i, this.prefixCoordinates.get(i) + 1); + + // fix any carrying errors + while (i >= 0 && this.prefixCoordinates.get(i) >= this.prefixNames.size()) { + // carry over + this.prefixCoordinates.set(i--, 0); // null and decrement at the same time + + if (i < 0) { // we need to add a new coordinate + this.prefixCoordinates.add(0, 0); + } else { // increment an existing one + this.prefixCoordinates.set(i, this.prefixCoordinates.get(i) + 1); + } + } + } + } + } + + @Override + public Entry<String, Unit> next() { + if (!this.hasNext()) + throw new NoSuchElementException("No units left!"); + // if I have prefixes, ensure I'm not using a nonlinear unit + // since all of the unprefixed stuff is done, just remove nonlinear units + if (!this.prefixCoordinates.isEmpty()) { + while (this.unitNamePosition < this.unitNames.size() + && !(this.map.get(this.unitNames.get(this.unitNamePosition)) instanceof LinearUnit)) { + this.unitNames.remove(this.unitNamePosition); + } + } + + final String nextName = this.getCurrentUnitName(); + + this.incrementPosition(); + + return new PrefixedUnitEntry(nextName, this.map.get(nextName)); + } + } + // the map that created this set private final PrefixedUnitMap map; @@ -143,83 +291,7 @@ public final class UnitsDatabase { @Override public Iterator<Entry<String, Unit>> iterator() { - return new Iterator<Entry<String, Unit>>() { - // position in the unit list - int unitNamePosition = -1; - // the indices of the prefixes attached to the current unit - List<Integer> prefixCoordinates = new ArrayList<>(); - - List<String> unitNames = new ArrayList<>(PrefixedUnitEntrySet.this.map.units.keySet()); - List<String> prefixNames = new ArrayList<>(PrefixedUnitEntrySet.this.map.prefixes.keySet()); - - @Override - public boolean hasNext() { - if (this.unitNames.isEmpty()) - return false; - else { - if (this.prefixNames.isEmpty()) - return this.unitNamePosition >= this.unitNames.size() - 1; - else - return true; - } - } - - @Override - public Entry<String, Unit> next() { - // increment unit name position - this.unitNamePosition++; - - // if I have prefixes, ensure I'm not using a nonlinear unit - // since all of the unprefixed stuff is done, just remove nonlinear units - if (!this.prefixCoordinates.isEmpty()) { - while (!(PrefixedUnitEntrySet.this.map - .get(this.unitNames.get(this.unitNamePosition)) instanceof LinearUnit)) { - this.unitNames.remove(this.unitNamePosition); - } - } - - // carry over - if (!this.prefixNames.isEmpty() && this.unitNamePosition >= this.unitNames.size() - 1) { - // handle prefix position - this.unitNamePosition = 0; - int i = this.prefixCoordinates.size() - 1; - this.prefixCoordinates.set(i, this.prefixCoordinates.get(i) + 1); - - while (this.prefixCoordinates.get(i) >= this.prefixNames.size() - 1) { - this.prefixCoordinates.set(i, 0); - i--; - if (i < 0) { - this.prefixCoordinates.add(0, 0); - } - } - } - - // create the unit name - final StringBuilder unitNameBuilder = new StringBuilder(); - for (final int i : this.prefixCoordinates) { - unitNameBuilder.append(this.prefixNames.get(i)); - } - unitNameBuilder.append(this.unitNames.get(this.unitNamePosition)); - - final String unitName = unitNameBuilder.toString(); - return new Entry<String, Unit>() { - @Override - public String getKey() { - return unitName; - } - - @Override - public Unit getValue() { - return PrefixedUnitEntrySet.this.map.get(unitName); - } - - @Override - public Unit setValue(final Unit value) { - throw new UnsupportedOperationException(); - } - }; - } - }; + return new PrefixedUnitEntryIterator(this); } @Override @@ -282,6 +354,115 @@ public final class UnitsDatabase { * @since 2019-04-13 */ private static final class PrefixedUnitNameSet extends AbstractSet<String> { + /** + * An iterator that iterates over the units of a {@code PrefixedUnitNameSet}. + * + * @author Adrien Hopkins + * @since 2019-04-14 + */ + private static final class PrefixedUnitNameIterator implements Iterator<String> { + // position in the unit list + private int unitNamePosition = 0; + // the indices of the prefixes attached to the current unit + private final List<Integer> prefixCoordinates = new ArrayList<>(); + + private final Map<String, Unit> map; + private final List<String> unitNames; + private final List<String> prefixNames; + + /** + * Creates the {@code UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator}. + * + * @since 2019-04-14 + */ + public PrefixedUnitNameIterator(final PrefixedUnitNameSet set) { + this.map = set.map; + this.unitNames = new ArrayList<>(set.map.units.keySet()); + this.prefixNames = new ArrayList<>(set.map.prefixes.keySet()); + } + + /** + * @return current unit name + * @since 2019-04-14 + */ + private String getCurrentUnitName() { + final StringBuilder unitName = new StringBuilder(); + for (final int i : this.prefixCoordinates) { + unitName.append(this.prefixNames.get(i)); + } + unitName.append(this.unitNames.get(this.unitNamePosition)); + + return unitName.toString(); + } + + @Override + public boolean hasNext() { + if (this.unitNames.isEmpty()) + return false; + else { + if (this.prefixNames.isEmpty()) + return this.unitNamePosition >= this.unitNames.size() - 1; + else + return true; + } + } + + /** + * Changes this iterator's position to the next available one. + * + * @since 2019-04-14 + */ + private void incrementPosition() { + this.unitNamePosition++; + + if (this.unitNamePosition >= this.unitNames.size()) { + // we have used all of our units, go to a different prefix + this.unitNamePosition = 0; + + // if the prefix coordinates are empty, then set it to [0] + if (this.prefixCoordinates.isEmpty()) { + this.prefixCoordinates.add(0, 0); + } else { + // get the prefix coordinate to increment, then increment + int i = this.prefixCoordinates.size() - 1; + this.prefixCoordinates.set(i, this.prefixCoordinates.get(i) + 1); + + // fix any carrying errors + while (i >= 0 && this.prefixCoordinates.get(i) >= this.prefixNames.size()) { + // carry over + this.prefixCoordinates.set(i--, 0); // null and decrement at the same time + + if (i < 0) { // we need to add a new coordinate + this.prefixCoordinates.add(0, 0); + } else { // increment an existing one + this.prefixCoordinates.set(i, this.prefixCoordinates.get(i) + 1); + } + } + } + } + } + + @Override + public String next() { + if (!this.hasNext()) + throw new NoSuchElementException("No units left!"); + // if I have prefixes, ensure I'm not using a nonlinear unit + // since all of the unprefixed stuff is done, just remove nonlinear units + if (!this.prefixCoordinates.isEmpty()) { + while (this.unitNamePosition < this.unitNames.size() + && !(this.map.get(this.unitNames.get(this.unitNamePosition)) instanceof LinearUnit)) { + this.unitNames.remove(this.unitNamePosition); + } + } + + final String nextName = this.getCurrentUnitName(); + + this.incrementPosition(); + + return nextName; + } + } + // the map that created this set private final PrefixedUnitMap map; @@ -330,65 +511,7 @@ public final class UnitsDatabase { @Override public Iterator<String> iterator() { - return new Iterator<String>() { - // position in the unit list - int unitNamePosition = -1; - // the indices of the prefixes attached to the current unit - List<Integer> prefixCoordinates = new ArrayList<>(); - - List<String> unitNames = new ArrayList<>(PrefixedUnitNameSet.this.map.units.keySet()); - List<String> prefixNames = new ArrayList<>(PrefixedUnitNameSet.this.map.prefixes.keySet()); - - @Override - public boolean hasNext() { - if (this.unitNames.isEmpty()) - return false; - else { - if (this.prefixNames.isEmpty()) - return this.unitNamePosition >= this.unitNames.size() - 1; - else - return true; - } - } - - @Override - public String next() { - // increment unit name position - this.unitNamePosition++; - - // if I have prefixes, ensure I'm not using a nonlinear unit - // since all of the unprefixed stuff is done, just remove nonlinear units - if (!this.prefixCoordinates.isEmpty()) { - while (!(PrefixedUnitNameSet.this.map - .get(this.unitNames.get(this.unitNamePosition)) instanceof LinearUnit)) { - this.unitNames.remove(this.unitNamePosition); - } - } - - // carry over - if (!this.prefixNames.isEmpty() && this.unitNamePosition >= this.unitNames.size() - 1) { - // handle prefix position - this.unitNamePosition = 0; - int i = this.prefixCoordinates.size() - 1; - this.prefixCoordinates.set(i, this.prefixCoordinates.get(i) + 1); - - while (this.prefixCoordinates.get(i) >= this.prefixNames.size() - 1) { - this.prefixCoordinates.set(i, 0); - i--; - if (i < 0) { - this.prefixCoordinates.add(0, 0); - } - } - } - - final StringBuilder unitName = new StringBuilder(); - for (final int i : this.prefixCoordinates) { - unitName.append(this.prefixNames.get(i)); - } - unitName.append(this.unitNames.get(this.unitNamePosition)); - return unitName.toString(); - } - }; + return new PrefixedUnitNameIterator(this); } @Override |