Skip to content

Commit 3ca4007

Browse files
authored
Merge pull request #681 from raynigon/bugfix/issue-555/newton-metre-symbol
Implement Symbol Aliases
2 parents 4afe16f + 593d628 commit 3ca4007

File tree

7 files changed

+49
-18
lines changed

7 files changed

+49
-18
lines changed

unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/IUnit.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ public interface IUnit<Q extends Quantity<Q>> extends Unit<Q> {
99

1010
Class<Q> getQuantityType();
1111

12+
/**
13+
* Symbol aliases which are also accepted for parsing.
14+
* This is needed because some units have multiple commonly used symbols.
15+
* One example is the Newton meter which is commonly written as "N m" or "N⋅m".
16+
* Another one is the degree Celsius which is commonly written as "°C" or "℃".
17+
*/
18+
default String[] getSymbolAliases() {
19+
return new String[]{};
20+
}
21+
1222
default boolean isSystemUnit() {
1323
return getSystemUnit().getClass().equals(this.getClass());
1424
}

unit-api-core/src/main/java/com/raynigon/unit/api/core/units/general/UnitScanUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ private static Object createInstance(Constructor<?> it) {
3838
try {
3939
return it.newInstance();
4040
} catch (Exception e) {
41-
log.error("Unable to create Unit Instance for " + it.getName(), e);
41+
log.error("Unable to create Unit Instance for {}", it.getName(), e);
4242
return null;
4343
}
4444
}

unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/SISystem.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ private void init() {
3434
private void addUnit(IUnit<?> unit) {
3535
this.units.add(unit);
3636
symbolToUnit.put(unit.getSymbol(), unit);
37+
// Add Symbols Aliases for Parsing
38+
for (String alias : unit.getSymbolAliases()) {
39+
symbolToUnit.put(alias, unit);
40+
}
3741
if (unit.isSystemUnit()) {
3842
systemUnits.put(unit.getQuantityType(), unit);
3943
}

unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/temperature/Celsius.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class Celsius extends TransformedUnit<Temperature> implements IUnit<Tempe
1212
@SuppressWarnings("unchecked")
1313
public Celsius() {
1414
super(
15-
"\u2103",
15+
"°C",
1616
"Celsius",
1717
new Kelvin(),
1818
new Kelvin(),
@@ -28,4 +28,9 @@ public String getSystemId() {
2828
public Class<Temperature> getQuantityType() {
2929
return Temperature.class;
3030
}
31+
32+
@Override
33+
public String[] getSymbolAliases() {
34+
return new String[]{"\u2103"};
35+
}
3136
}

unit-api-core/src/main/java/com/raynigon/unit/api/core/units/si/torque/NewtonMetre.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ public class NewtonMetre extends AlternateUnit<Torque> {
1212

1313
@SuppressWarnings("unchecked")
1414
public NewtonMetre() {
15-
super(SISystem.ID, "Nm", "Newton Metre", (Unit<Torque>) new Newton().multiply(new Metre()), Torque.class);
15+
super(SISystem.ID, "N m", "Newton Metre", (Unit<Torque>) new Newton().multiply(new Metre()), Torque.class);
16+
}
17+
18+
@Override
19+
public String[] getSymbolAliases() {
20+
return new String[]{
21+
"N⋅m", // UTF-8 Middle Dot
22+
"N·m" // UTF-8 Interpunct
23+
};
1624
}
1725
}

unit-api-core/src/test/groovy/com/raynigon/unit/api/core/units/si/SISystemSpec.groovy

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.raynigon.unit.api.core.units.si
22

3+
import com.raynigon.unit.api.core.service.UnitsApiService
34
import com.raynigon.unit.api.core.units.si.acceleration.MetrePerSquaredSecond
45
import com.raynigon.unit.api.core.units.si.energy.Joule
56
import com.raynigon.unit.api.core.units.si.energy.KiloWattHour
@@ -17,12 +18,10 @@ import com.raynigon.unit.api.core.units.si.temperature.Kelvin
1718
import com.raynigon.unit.api.core.units.si.time.Hour
1819
import com.raynigon.unit.api.core.units.si.time.Minute
1920
import com.raynigon.unit.api.core.units.si.time.Second
21+
import com.raynigon.unit.api.core.units.si.torque.NewtonMetre
2022
import spock.lang.Specification
2123
import spock.lang.Unroll
2224

23-
import static com.raynigon.unit.api.core.service.UnitsApiService.quantity
24-
25-
2625
class SISystemSpec extends Specification {
2726

2827
@Unroll
@@ -59,54 +58,59 @@ class SISystemSpec extends Specification {
5958
"km/h" | new KilometrePerHour()
6059
// temperature
6160
"K" | new Kelvin()
61+
"°C" | new Celsius()
6262
"\u2103" | new Celsius()
6363
// time
6464
"s" | new Second()
6565
"min" | new Minute()
6666
"h" | new Hour()
67+
// torque
68+
"N m" | new NewtonMetre()
69+
"N·m" | new NewtonMetre()
70+
"N⋅m" | new NewtonMetre()
6771
}
6872

6973
def 'metre conversion'() {
7074

7175
when:
72-
def quantity = quantity(initialValue, unit)
76+
def quantity = UnitsApiService.quantity(initialValue, unit)
7377

7478
then:
7579
expectedValue == quantity.to(new Metre()).value.intValue()
7680

7781
where:
7882
unit | initialValue | expectedValue
79-
new Metre() | 1 | 1
80-
new Millimetre() | 1000 | 1
81-
new Kilometre() | 1 | 1000
83+
new Metre() | 1 | 1
84+
new Millimetre() | 1000 | 1
85+
new Kilometre() | 1 | 1000
8286
}
8387

8488
def 'energy conversion'() {
8589

8690
when:
87-
def quantity = quantity(initialValue, unit)
91+
def quantity = UnitsApiService.quantity(initialValue, unit)
8892

8993
then:
9094
expectedValue == quantity.to(new Joule()).value.intValue()
9195

9296
where:
9397
unit | initialValue | expectedValue
94-
new Joule() | 1 | 1
95-
new WattHour() | 1 | 3600
96-
new KiloWattHour() | 1 | 3600000
98+
new Joule() | 1 | 1
99+
new WattHour() | 1 | 3600
100+
new KiloWattHour() | 1 | 3600000
97101
}
98102

99103
def 'speed conversion'() {
100104

101105
when:
102-
def quantity = quantity(initialValue, unit)
106+
def quantity = UnitsApiService.quantity(initialValue, unit)
103107

104108
then:
105109
expectedValue == quantity.to(new MetrePerSecond()).value.intValue()
106110

107111
where:
108112
unit | initialValue | expectedValue
109-
new MetrePerSecond() | 1 | 1
110-
new KilometrePerHour() | 36 | 10
113+
new MetrePerSecond() | 1 | 1
114+
new KilometrePerHour() | 36 | 10
111115
}
112116
}

unit-api-jackson/src/test/groovy/com/raynigon/unit/api/jackson/serializer/QuantitySerializerSpec.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class QuantitySerializerSpec extends Specification {
126126
noExceptionThrown()
127127

128128
and:
129-
result == '{"id":"1","temperature":"30 "}'
129+
result == '{"id":"1","temperature":"30 °C"}'
130130
}
131131

132132
def 'object deserialization'() {

0 commit comments

Comments
 (0)