diff --git a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/IUnit.java b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/IUnit.java index baa40fd8..94198aa8 100644 --- a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/IUnit.java +++ b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/IUnit.java @@ -9,6 +9,16 @@ public interface IUnit> extends Unit { Class getQuantityType(); + /** + * Symbol aliases which are also accepted for parsing. + * This is needed because some units have multiple commonly used symbols. + * One example is the Newton meter which is commonly written as "N m" or "N⋅m". + * Another one is the degree Celsius which is commonly written as "°C" or "℃". + */ + default String[] getSymbolAliases() { + return new String[]{}; + } + default boolean isSystemUnit() { return getSystemUnit().getClass().equals(this.getClass()); } diff --git a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/UnitScanUtils.java b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/UnitScanUtils.java index fb5f5b0d..6efd2448 100644 --- a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/UnitScanUtils.java +++ b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/UnitScanUtils.java @@ -38,7 +38,7 @@ private static Object createInstance(Constructor it) { try { return it.newInstance(); } catch (Exception e) { - log.error("Unable to create Unit Instance for " + it.getName(), e); + log.error("Unable to create Unit Instance for {}", it.getName(), e); return null; } } diff --git a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/SISystem.java b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/SISystem.java index 35184df7..ca453fca 100644 --- a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/SISystem.java +++ b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/SISystem.java @@ -34,6 +34,10 @@ private void init() { private void addUnit(IUnit unit) { this.units.add(unit); symbolToUnit.put(unit.getSymbol(), unit); + // Add Symbols Aliases for Parsing + for (String alias : unit.getSymbolAliases()) { + symbolToUnit.put(alias, unit); + } if (unit.isSystemUnit()) { systemUnits.put(unit.getQuantityType(), unit); } diff --git a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/temperature/Celsius.java b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/temperature/Celsius.java index 87bd7025..51a531eb 100644 --- a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/temperature/Celsius.java +++ b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/temperature/Celsius.java @@ -12,7 +12,7 @@ public class Celsius extends TransformedUnit implements IUnit getQuantityType() { return Temperature.class; } + + @Override + public String[] getSymbolAliases() { + return new String[]{"\u2103"}; + } } diff --git a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/torque/NewtonMetre.java b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/torque/NewtonMetre.java index 027039d8..4c32eea6 100644 --- a/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/torque/NewtonMetre.java +++ b/unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/torque/NewtonMetre.java @@ -12,6 +12,14 @@ public class NewtonMetre extends AlternateUnit { @SuppressWarnings("unchecked") public NewtonMetre() { - super(SISystem.ID, "Nm", "Newton Metre", (Unit) new Newton().multiply(new Metre()), Torque.class); + super(SISystem.ID, "N m", "Newton Metre", (Unit) new Newton().multiply(new Metre()), Torque.class); + } + + @Override + public String[] getSymbolAliases() { + return new String[]{ + "N⋅m", // UTF-8 Middle Dot + "N·m" // UTF-8 Interpunct + }; } } \ No newline at end of file diff --git a/unit-api-core/src/test/groovy/com/raynigon/unit/api/core/units/si/SISystemSpec.groovy b/unit-api-core/src/test/groovy/com/raynigon/unit/api/core/units/si/SISystemSpec.groovy index 9757a2ec..fe4c768b 100644 --- a/unit-api-core/src/test/groovy/com/raynigon/unit/api/core/units/si/SISystemSpec.groovy +++ b/unit-api-core/src/test/groovy/com/raynigon/unit/api/core/units/si/SISystemSpec.groovy @@ -1,5 +1,6 @@ package com.raynigon.unit.api.core.units.si +import com.raynigon.unit.api.core.service.UnitsApiService import com.raynigon.unit.api.core.units.si.acceleration.MetrePerSquaredSecond import com.raynigon.unit.api.core.units.si.energy.Joule import com.raynigon.unit.api.core.units.si.energy.KiloWattHour @@ -17,12 +18,10 @@ import com.raynigon.unit.api.core.units.si.temperature.Kelvin import com.raynigon.unit.api.core.units.si.time.Hour import com.raynigon.unit.api.core.units.si.time.Minute import com.raynigon.unit.api.core.units.si.time.Second +import com.raynigon.unit.api.core.units.si.torque.NewtonMetre import spock.lang.Specification import spock.lang.Unroll -import static com.raynigon.unit.api.core.service.UnitsApiService.quantity - - class SISystemSpec extends Specification { @Unroll @@ -59,54 +58,59 @@ class SISystemSpec extends Specification { "km/h" | new KilometrePerHour() // temperature "K" | new Kelvin() + "°C" | new Celsius() "\u2103" | new Celsius() // time "s" | new Second() "min" | new Minute() "h" | new Hour() + // torque + "N m" | new NewtonMetre() + "N·m" | new NewtonMetre() + "N⋅m" | new NewtonMetre() } def 'metre conversion'() { when: - def quantity = quantity(initialValue, unit) + def quantity = UnitsApiService.quantity(initialValue, unit) then: expectedValue == quantity.to(new Metre()).value.intValue() where: unit | initialValue | expectedValue - new Metre() | 1 | 1 - new Millimetre() | 1000 | 1 - new Kilometre() | 1 | 1000 + new Metre() | 1 | 1 + new Millimetre() | 1000 | 1 + new Kilometre() | 1 | 1000 } def 'energy conversion'() { when: - def quantity = quantity(initialValue, unit) + def quantity = UnitsApiService.quantity(initialValue, unit) then: expectedValue == quantity.to(new Joule()).value.intValue() where: unit | initialValue | expectedValue - new Joule() | 1 | 1 - new WattHour() | 1 | 3600 - new KiloWattHour() | 1 | 3600000 + new Joule() | 1 | 1 + new WattHour() | 1 | 3600 + new KiloWattHour() | 1 | 3600000 } def 'speed conversion'() { when: - def quantity = quantity(initialValue, unit) + def quantity = UnitsApiService.quantity(initialValue, unit) then: expectedValue == quantity.to(new MetrePerSecond()).value.intValue() where: unit | initialValue | expectedValue - new MetrePerSecond() | 1 | 1 - new KilometrePerHour() | 36 | 10 + new MetrePerSecond() | 1 | 1 + new KilometrePerHour() | 36 | 10 } } diff --git a/unit-api-jackson/src/test/groovy/com/raynigon/unit/api/jackson/serializer/QuantitySerializerSpec.groovy b/unit-api-jackson/src/test/groovy/com/raynigon/unit/api/jackson/serializer/QuantitySerializerSpec.groovy index e6fcf5d3..188f74b3 100644 --- a/unit-api-jackson/src/test/groovy/com/raynigon/unit/api/jackson/serializer/QuantitySerializerSpec.groovy +++ b/unit-api-jackson/src/test/groovy/com/raynigon/unit/api/jackson/serializer/QuantitySerializerSpec.groovy @@ -126,7 +126,7 @@ class QuantitySerializerSpec extends Specification { noExceptionThrown() and: - result == '{"id":"1","temperature":"30 ℃"}' + result == '{"id":"1","temperature":"30 °C"}' } def 'object deserialization'() {