unitsofmeasurement / indriya

JSR 385 - Reference Implementation
Other
115 stars 40 forks source link

EBNFUnitFormat formats into a string that it cannot parse back anymore #417

Closed milgner closed 2 months ago

milgner commented 3 months ago

Trying to use EBNFUnitFormat as a way to serialize and de-serialize unit information into a database, I found that it can produce output that it cannot parse back anymore.

Example (yes, there are weird units at play, I know :see_no_evil:):

The string "(W/min)/(m^2)" is parsed fine and subsequent formatting produces the string "W/(min·m²)" which, again, can be parsed again to produce the same result.

But after adding a scale factor to it, i.e. "((W/min)/(m^2))/100", the formatted value becomes "W/(min·m²·one100)" , which, due to the missing symbol between one and 100, is not possible to parse this one.

milgner commented 2 months ago

Just found another, more straightforward example. Apparently the root of the problem is with scaling factors.

val symbolMap: SymbolMap = SymbolMap.of(ResourceBundle.getBundle("units"))
val format: UnitFormat = EBNFUnitFormat.getInstance(symbolMap)

val src = "g*10"
val parsed = format.parse(src)
val output = format.format(parsed)

println("Source: $src, Output: $output")

Will result in

Source: g*10, Output: g·one10

The string g·one10 cannot be parsed again, though.

Edit: I'll check out the source code to see whether I can come up with a patch.

milgner commented 2 months ago

It looks like the problem was adding

tech.units.indriya.AbstractUnit.ONE=one

to my .properties file used for the symbol map.

This was done in order to parse the string "one" into AbstractUnit.ONE to represent dimensionless numbers. But it seems like the empty string works for that, too, so I'll change my code accordingly.