1

I am looking for a better way to compute using Jscience but the generic pattern is much tougher to get a clear solution. I need to compute price for n units provided the unit price for a unit quantity is defined. like,

    Measure<Double, ? extends Quantity> unitQuantity = Measure.valueOf(1.0,
            Unit.valueOf("kg"));
    Amount<Money> unitPrice = Amount.valueOf(150.0, USD);
    Measure<Double, ? extends Quantity> quantity = Measure.valueOf(500.0,
            MILLI(Unit.valueOf("kg")));
    Amount<Money> amount = unitPrice.times(quantity.to(unitQuantity.getUnit())
                       .getValue() / unitQuantity.getValue());

For the above code I am getting this error:

The method to(Unit<capture#7-of ? extends Quantity>) in the type 
Measure<Double,capture#7-of ? extends Quantity> is not applicable for 
the arguments (Unit<capture#8-of ? extends Quantity>)

I read about generics at Java Tutorials and tried the following, but still no clear solution:

    Amount<Money> amount = compute(unitPrice,unitQuantity,quantity)

    private <T extends Quantity> Amount<Money> compute(Amount<Money> unitPrice,
        Measure<Double, T> unitQuantity, Measure<Double, T> quantity) {
    return unitPrice.times(quantity.to(unitQuantity.getUnit()).getValue()
            / unitQuantity.getValue());
}

Now getting this error:

   The method compute(Amount<Money>, Measure<Double,T>, Measure<Double,T>) 
   in the type JscienceEx is not applicable for the arguments (Amount<Money>, 
   Measure<Double,capture#7-of ? extends Quantity>, Measure<Double,capture#8-of ?    
   extends Quantity>)
Air
  • 8,274
  • 2
  • 53
  • 88
Subhu.rys
  • 25
  • 1
  • 7

2 Answers2

2

The Unit.valueOf("kg") factory method may be convenient in some cases. But in this case, it does not retain enough information. It only returns the unit of "some" Quantity - hence the ? extends Quantity in the return type. But you don't know whether this is quantity is, for example, Mass or Power. And as long as you don't know this, you can not say whether the call to quantity.to(unitQuantity.getUnit()) is valid.

In this case, you can solve this by using a new BaseUnit<Mass>("kg") instead of the Unit.valueOf("kg"):

import static javax.measure.unit.SI.MILLI;

import javax.measure.Measure;
import javax.measure.quantity.Mass;
import javax.measure.unit.BaseUnit;

import org.jscience.economics.money.Currency;
import org.jscience.economics.money.Money;
import org.jscience.physics.amount.Amount;

public class JScienceUnits
{
    public static void main(String[] args)
    {
        BaseUnit<Mass> kg = new BaseUnit<Mass>("kg");
        Measure<Double, Mass> unitQuantity = Measure.valueOf(1.0, kg);
        Amount<Money> unitPrice = Amount.valueOf(150.0, Currency.USD);
        Measure<Double, Mass> quantity = Measure.valueOf(500.0, MILLI(kg));
        Amount<Money> amount = unitPrice.times(
            quantity.to(unitQuantity.getUnit()).getValue() / 
            unitQuantity.getValue());

        System.out.println(
            "Money for "+quantity+
            " with unit price "+unitPrice+
            " is "+amount);
    }
}
Marco13
  • 53,703
  • 9
  • 80
  • 159
0

Found two approaches. ConversionException get thrown when conversion fails.

@SuppressWarnings("unchecked")
public static <U extends Quantity, V extends Quantity> Amount<Money> computeAmount(
        Measure<Double, U> unitQuantity, Amount<Money> unitRate,
        Measure<Double, V> netQuantity) {
    return unitRate.times(netQuantity.to((Unit<V>) unitQuantity.getUnit())
            .getValue() / unitQuantity.getValue());
}

-

public static <U extends Quantity, V extends Quantity> Amount<Money> computeAmount(
        Measure<Double, U> unitQuantity, Amount<Money> unitRate,
        Measure<Double, V> netQuantity) {
    UnitConverter toUnitQuantityUnit = netQuantity.getUnit()
            .getConverterTo(unitQuantity.getUnit());
    return unitRate
            .times(toUnitQuantityUnit.convert(netQuantity.getValue())
                    / unitQuantity.getValue());
}
Subhu.rys
  • 25
  • 1
  • 7