summaryrefslogtreecommitdiff
path: root/src/org/unitConverter/UnitsDatabase.java
diff options
context:
space:
mode:
authorAdrien Hopkins <adrien.p.hopkins@gmail.com>2019-05-03 15:07:16 -0400
committerAdrien Hopkins <adrien.p.hopkins@gmail.com>2019-05-03 15:07:16 -0400
commit50a195ef78af5d15dd6e548d4d6928c281bbaac2 (patch)
treee87ac0509b7e79614a00cc62c88b64358143ad67 /src/org/unitConverter/UnitsDatabase.java
parent2ce65fa76908d77a5e3b045a8eb40c798939b8be (diff)
Added toString to UnitsDatabase and its helper classes.
Diffstat (limited to 'src/org/unitConverter/UnitsDatabase.java')
-rwxr-xr-xsrc/org/unitConverter/UnitsDatabase.java286
1 files changed, 229 insertions, 57 deletions
diff --git a/src/org/unitConverter/UnitsDatabase.java b/src/org/unitConverter/UnitsDatabase.java
index e5d2f67..37d53d4 100755
--- a/src/org/unitConverter/UnitsDatabase.java
+++ b/src/org/unitConverter/UnitsDatabase.java
@@ -75,7 +75,11 @@ public final class UnitsDatabase {
* <p>
* This 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 UnsupportedOperationException}.
+ * {@code IllegalStateException}.
+ * </p>
+ * <p>
+ * Because of ambiguities between prefixes (i.e. kilokilo = mega), {@link #containsValue} and {@link #values()}
+ * currently ignore prefixes.
* </p>
*
* @author Adrien Hopkins
@@ -86,6 +90,12 @@ public final class UnitsDatabase {
/**
* The class used for entry sets.
*
+ * <p>
+ * If the map that created this set is infinite in size (has at least one unit and at least one prefix), this
+ * set is infinite as well. If this set is infinite in size, {@link #toArray} will fail with a
+ * {@code IllegalStateException} instead of creating an infinite-sized array.
+ * </p>
+ *
* @author Adrien Hopkins
* @since 2019-04-13
* @since v0.2.0
@@ -117,6 +127,18 @@ public final class UnitsDatabase {
this.value = value;
}
+ /**
+ * @since 2019-05-03
+ */
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ final Map.Entry<?, ?> other = (Map.Entry<?, ?>) o;
+ return Objects.equals(this.getKey(), other.getKey())
+ && Objects.equals(this.getValue(), other.getValue());
+ }
+
@Override
public String getKey() {
return this.key;
@@ -127,9 +149,29 @@ public final class UnitsDatabase {
return this.value;
}
+ /**
+ * @since 2019-05-03
+ */
+ @Override
+ public int hashCode() {
+ return (this.getKey() == null ? 0 : this.getKey().hashCode())
+ ^ (this.getValue() == null ? 0 : this.getValue().hashCode());
+ }
+
@Override
public Unit setValue(final Unit value) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot set value in an immutable entry");
+ }
+
+ /**
+ * Returns a string representation of the entry. The format of the string is the string representation
+ * of the key, then the equals ({@code =}) character, then the string representation of the value.
+ *
+ * @since 2019-05-03
+ */
+ @Override
+ public String toString() {
+ return this.getKey() + "=" + this.getValue();
}
}
@@ -148,8 +190,8 @@ public final class UnitsDatabase {
// values from the unit entry set
private final Map<String, Unit> map;
- private final List<String> unitNames;
- private final List<String> prefixNames;
+ private transient final List<String> unitNames;
+ private transient final List<String> prefixNames;
/**
* Creates the {@code UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator}.
@@ -157,10 +199,10 @@ public final class UnitsDatabase {
* @since 2019-04-14
* @since v0.2.0
*/
- 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());
+ public PrefixedUnitEntryIterator(final PrefixedUnitMap map) {
+ this.map = map;
+ this.unitNames = new ArrayList<>(map.units.keySet());
+ this.prefixNames = new ArrayList<>(map.prefixes.keySet());
}
/**
@@ -228,8 +270,23 @@ public final class UnitsDatabase {
@Override
public Entry<String, Unit> next() {
+ // get next element
+ final Entry<String, Unit> nextEntry = this.peek();
+
+ // iterate to next position
+ this.incrementPosition();
+
+ return nextEntry;
+ }
+
+ /**
+ * @return the next element in the iterator, without iterating over it
+ * @since 2019-05-03
+ */
+ private Entry<String, Unit> peek() {
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()) {
@@ -241,10 +298,20 @@ public final class UnitsDatabase {
final String nextName = this.getCurrentUnitName();
- this.incrementPosition();
-
return new PrefixedUnitEntry(nextName, this.map.get(nextName));
}
+
+ /**
+ * Returns a string representation of the object. The exact details of the representation are
+ * unspecified and subject to change.
+ *
+ * @since 2019-05-03
+ */
+ @Override
+ public String toString() {
+ return String.format("Iterator iterating over name-unit entries; next value is \"%s\"",
+ this.peek());
+ }
}
// the map that created this set
@@ -264,17 +331,17 @@ public final class UnitsDatabase {
@Override
public boolean add(final Map.Entry<String, Unit> e) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot add to an immutable set");
}
@Override
public boolean addAll(final Collection<? extends Map.Entry<String, Unit>> c) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot add to an immutable set");
}
@Override
public void clear() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot clear an immutable set");
}
@Override
@@ -283,7 +350,7 @@ public final class UnitsDatabase {
final Entry<String, Unit> entry;
try {
- // This is OK because I'm in a try-catch block.
+ // This is OK because I'm in a try-catch block, catching the exact exception that would be thrown.
@SuppressWarnings("unchecked")
final Entry<String, Unit> tempEntry = (Entry<String, Unit>) o;
entry = tempEntry;
@@ -309,27 +376,27 @@ public final class UnitsDatabase {
@Override
public Iterator<Entry<String, Unit>> iterator() {
- return new PrefixedUnitEntryIterator(this);
+ return new PrefixedUnitEntryIterator(this.map);
}
@Override
public boolean remove(final Object o) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove from an immutable set");
}
@Override
public boolean removeAll(final Collection<?> c) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove from an immutable set");
}
@Override
public boolean removeIf(final Predicate<? super Entry<String, Unit>> filter) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove from an immutable set");
}
@Override
public boolean retainAll(final Collection<?> c) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove from an immutable set");
}
@Override
@@ -345,29 +412,51 @@ public final class UnitsDatabase {
}
}
+ /**
+ * @throws IllegalStateException
+ * if the set is infinite in size
+ */
@Override
public Object[] toArray() {
if (this.map.units.isEmpty() || this.map.prefixes.isEmpty())
return super.toArray();
else
// infinite set
- throw new UnsupportedOperationException("Cannot make an infinite set into an array.");
+ throw new IllegalStateException("Cannot make an infinite set into an array.");
}
+ /**
+ * @throws IllegalStateException
+ * if the set is infinite in size
+ */
@Override
public <T> T[] toArray(final T[] a) {
if (this.map.units.isEmpty() || this.map.prefixes.isEmpty())
return super.toArray(a);
else
// infinite set
- throw new UnsupportedOperationException("Cannot make an infinite set into an array.");
+ throw new IllegalStateException("Cannot make an infinite set into an array.");
}
+ @Override
+ public String toString() {
+ if (this.map.units.isEmpty() || this.map.prefixes.isEmpty())
+ return super.toString();
+ else
+ return String.format("Infinite set of name-unit entries created from units %s and prefixes %s",
+ this.map.units, this.map.prefixes);
+ }
}
/**
* The class used for unit name sets.
*
+ * <p>
+ * If the map that created this set is infinite in size (has at least one unit and at least one prefix), this
+ * set is infinite as well. If this set is infinite in size, {@link #toArray} will fail with a
+ * {@code IllegalStateException} instead of creating an infinite-sized array.
+ * </p>
+ *
* @author Adrien Hopkins
* @since 2019-04-13
* @since v0.2.0
@@ -388,8 +477,8 @@ public final class UnitsDatabase {
// values from the unit name set
private final Map<String, Unit> map;
- private final List<String> unitNames;
- private final List<String> prefixNames;
+ private transient final List<String> unitNames;
+ private transient final List<String> prefixNames;
/**
* Creates the {@code UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator}.
@@ -397,10 +486,10 @@ public final class UnitsDatabase {
* @since 2019-04-14
* @since v0.2.0
*/
- 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());
+ public PrefixedUnitNameIterator(final PrefixedUnitMap map) {
+ this.map = map;
+ this.unitNames = new ArrayList<>(map.units.keySet());
+ this.prefixNames = new ArrayList<>(map.prefixes.keySet());
}
/**
@@ -468,6 +557,18 @@ public final class UnitsDatabase {
@Override
public String next() {
+ final String nextName = this.peek();
+
+ this.incrementPosition();
+
+ return nextName;
+ }
+
+ /**
+ * @return the next element in the iterator, without iterating over it
+ * @since 2019-05-03
+ */
+ private String peek() {
if (!this.hasNext())
throw new NoSuchElementException("No units left!");
// if I have prefixes, ensure I'm not using a nonlinear unit
@@ -479,11 +580,18 @@ public final class UnitsDatabase {
}
}
- final String nextName = this.getCurrentUnitName();
-
- this.incrementPosition();
+ return this.getCurrentUnitName();
+ }
- return nextName;
+ /**
+ * Returns a string representation of the object. The exact details of the representation are
+ * unspecified and subject to change.
+ *
+ * @since 2019-05-03
+ */
+ @Override
+ public String toString() {
+ return String.format("Iterator iterating over unit names; next value is \"%s\"", this.peek());
}
}
@@ -504,17 +612,17 @@ public final class UnitsDatabase {
@Override
public boolean add(final String e) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot add to an immutable set");
}
@Override
public boolean addAll(final Collection<? extends String> c) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot add to an immutable set");
}
@Override
public void clear() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot clear an immutable set");
}
@Override
@@ -537,27 +645,27 @@ public final class UnitsDatabase {
@Override
public Iterator<String> iterator() {
- return new PrefixedUnitNameIterator(this);
+ return new PrefixedUnitNameIterator(this.map);
}
@Override
public boolean remove(final Object o) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove from an immutable set");
}
@Override
public boolean removeAll(final Collection<?> c) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove from an immutable set");
}
@Override
public boolean removeIf(final Predicate<? super String> filter) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove from an immutable set");
}
@Override
public boolean retainAll(final Collection<?> c) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove from an immutable set");
}
@Override
@@ -573,23 +681,40 @@ public final class UnitsDatabase {
}
}
+ /**
+ * @throws IllegalStateException
+ * if the set is infinite in size
+ */
@Override
public Object[] toArray() {
if (this.map.units.isEmpty() || this.map.prefixes.isEmpty())
return super.toArray();
else
// infinite set
- throw new UnsupportedOperationException("Cannot make an infinite set into an array.");
+ throw new IllegalStateException("Cannot make an infinite set into an array.");
}
+ /**
+ * @throws IllegalStateException
+ * if the set is infinite in size
+ */
@Override
public <T> T[] toArray(final T[] a) {
if (this.map.units.isEmpty() || this.map.prefixes.isEmpty())
return super.toArray(a);
else
// infinite set
- throw new UnsupportedOperationException("Cannot make an infinite set into an array.");
+ throw new IllegalStateException("Cannot make an infinite set into an array.");
+ }
+
+ @Override
+ public String toString() {
+ if (this.map.units.isEmpty() || this.map.prefixes.isEmpty())
+ return super.toString();
+ else
+ return String.format("Infinite set of name-unit entries created from units %s and prefixes %s",
+ this.map.units, this.map.prefixes);
}
}
@@ -610,9 +735,9 @@ public final class UnitsDatabase {
private final Map<String, UnitPrefix> prefixes;
// caches
- private Collection<Unit> values = null;
- private Set<String> keySet = null;
- private Set<Entry<String, Unit>> entrySet = null;
+ private transient Collection<Unit> values = null;
+ private transient Set<String> keySet = null;
+ private transient Set<Entry<String, Unit>> entrySet = null;
/**
* Creates the {@code PrefixedUnitMap}.
@@ -632,24 +757,24 @@ public final class UnitsDatabase {
@Override
public void clear() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot clear an immutable map");
}
@Override
public Unit compute(final String key,
final BiFunction<? super String, ? super Unit, ? extends Unit> remappingFunction) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot edit an immutable map");
}
@Override
public Unit computeIfAbsent(final String key, final Function<? super String, ? extends Unit> mappingFunction) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot edit an immutable map");
}
@Override
public Unit computeIfPresent(final String key,
final BiFunction<? super String, ? super Unit, ? extends Unit> remappingFunction) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot edit an immutable map");
}
@Override
@@ -685,6 +810,13 @@ public final class UnitsDatabase {
return longestPrefix != null;
}
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * Because of ambiguities between prefixes (i.e. kilokilo = mega), this method only tests for prefixless units.
+ * </p>
+ */
@Override
public boolean containsValue(final Object value) {
return this.units.containsValue(value);
@@ -758,47 +890,47 @@ public final class UnitsDatabase {
@Override
public Unit merge(final String key, final Unit value,
final BiFunction<? super Unit, ? super Unit, ? extends Unit> remappingFunction) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot merge into an immutable map");
}
@Override
public Unit put(final String key, final Unit value) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot add entries to an immutable map");
}
@Override
public void putAll(final Map<? extends String, ? extends Unit> m) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot add entries to an immutable map");
}
@Override
public Unit putIfAbsent(final String key, final Unit value) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot add entries to an immutable map");
}
@Override
public Unit remove(final Object key) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove entries from an immutable map");
}
@Override
public boolean remove(final Object key, final Object value) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot remove entries from an immutable map");
}
@Override
public Unit replace(final String key, final Unit value) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot replace entries in an immutable map");
}
@Override
public boolean replace(final String key, final Unit oldValue, final Unit newValue) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot replace entries in an immutable map");
}
@Override
public void replaceAll(final BiFunction<? super String, ? super Unit, ? extends Unit> function) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Cannot replace entries in an immutable map");
}
@Override
@@ -815,6 +947,22 @@ public final class UnitsDatabase {
}
@Override
+ public String toString() {
+ if (this.units.isEmpty() || this.prefixes.isEmpty())
+ return super.toString();
+ else
+ return String.format("Infinite map of name-unit entries created from units %s and prefixes %s",
+ this.units, this.prefixes);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * Because of ambiguities between prefixes (i.e. kilokilo = mega), this method ignores prefixes.
+ * </p>
+ */
+ @Override
public Collection<Unit> values() {
if (this.values == null) {
this.values = Collections.unmodifiableCollection(this.units.values());
@@ -1459,7 +1607,31 @@ public final class UnitsDatabase {
return Collections.unmodifiableMap(this.prefixes);
}
+ @Override
+ public String toString() {
+ return String.format("Unit Database with %d units and %d unit prefixes", this.prefixlessUnits.size(),
+ this.prefixes.size());
+ }
+
/**
+ * Returns a map mapping unit names to units, including units with prefixes.
+ * <p>
+ * 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}.
+ * </p>
+ * <p>
+ * Specifically, the operations that will throw an IllegalStateException if the map is infinite in size are:
+ * <ul>
+ * <li>{@code unitMap.entrySet().toArray()} (either overloading)</li>
+ * <li>{@code unitMap.keySet().toArray()} (either overloading)</li>
+ * </ul>
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
* @return a map mapping unit names to units, including prefixed names
* @since 2019-04-13
* @since v0.2.0