unitsofmeasurement / seshat

Seshat Units of Measurement Implementation
Apache License 2.0
7 stars 3 forks source link

ConventionalUnit package private #10

Closed lfoppiano closed 6 years ago

lfoppiano commented 6 years ago

Hi again, I'm trying to use the seshat as a dependency in my project and I get a parsed ConventionalUnit, which I cannot use cause it's package private.

I'm calling the parse method using several parsers until I get a good answer, something like

private javax.measure.Unit tryParsing(String unitRawName, List<UnitFormat> formatServices) {
        javax.measure.Unit unit = null;
        for (UnitFormat formatService : formatServices) {
            try {
                unit = formatService.parse(unitRawName);
                break;
            } catch (Throwable tr) {
                LOGGER.warn("Cannot parse " + unitRawName + " with " + formatService.getClass().getName(), tr);
            }
        }
        return unit;
    }

so I return a Unit object which I then try to figure out which class it's instanciated and cast it. In this case I would need ConventionalUnit to be public. Might not be the best soluiton, feel free to advice, though.

Thanks Luca

(BTW I know that catching Throwable is an orrific sin, but I wanted something simple cause the parse() can throw Exceptions and Errors 😅)

desruisseaux commented 6 years ago

Having the class package-private reduce the risk of breaking user code if we modify the implementation in the future. Can we explore some alternatives for addressing your need first? Do you need to invoke some methods that are specific to ConventionalUnit (not defined in the Unit interface)? If the need is to identify the implementation but not necessarily to invoke methods that are specific to that implementation, would unit.getClass().getCanonicalName() be suitable?

lfoppiano commented 6 years ago

Thanks for the advices.

I'm still exploring the best way to use it. For the time being we can close this ticket and I'm going to modify locally my version. it was more a question than an issue actually 🙂

desruisseaux commented 6 years ago

No problem - I'm closing it, but do not hesitate to reopen it if you need a specific ConventionalUnit functionality which is not accessible from the Unit interface.

lfoppiano commented 6 years ago

Just one more question, for other types like ProductUnit or TransformedUnit I would use the casted unit to get the normalisation to base via for example: transformedUnit.getSystemConverter().convert(numericValue)

but it seems that the ConventionalUnit implementation is slightly different. Is there a way to do the same as the other unit classes?

As a practical example I have μg/ml which I would like to normalise as kg/m^3.

Thank you in advance

desruisseaux commented 6 years ago

Can unit.getConverterTo(unit.getSystemUnit()) do the trick?

Note: if the unit is declared as Unit<?>, the compiler may complain about generic type. The workaround is to define the code in a method like below:

public static <Q extends Quantity<Q>> UnitConverter toStandardUnit(final Unit<Q> unit) {
    return unit.getConverterTo(unit.getSystemUnit());
}

Advantage is that it should work for any unit implementation - no need to cast.