blob: 0e10f55affdcdb77a9a3ff5b17e5c8dce43304d8 [file] [log] [blame]
/**
* Copyright (c) 2005, 2014, Werner Keil and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Werner Keil - initial API and implementation
*/
package org.eclipse.uomo.units;
import java.math.BigDecimal;
import java.math.MathContext;
import org.eclipse.uomo.units.internal.MeasureAmount;
import org.unitsofmeasurement.quantity.Dimensionless;
import org.unitsofmeasurement.quantity.Quantity;
import org.unitsofmeasurement.unit.IncommensurableException;
import org.unitsofmeasurement.unit.UnconvertibleException;
import org.unitsofmeasurement.unit.Unit;
import org.unitsofmeasurement.unit.UnitConverter;
import com.ibm.icu.util.Measure;
import com.ibm.icu.util.MeasureUnit;
/**
* An amount of quantity, consisting of a Number and a Unit. QuantityAmount
* objects are immutable.
*
* @see java.lang.Number
* @see MeasureUnit
* @author <a href="mailto:uomo@catmedia.us">Werner Keil</a>
* @param <Q>
* The type of the quantity.
* @version 1.3.4 ($Revision: 212 $), $Date: 2011-09-12 01:20:44 +0200 (Mo, 12
* Sep 2011) $ XXX rename to Amount, AbstractAmount or MeasureAmount?
* FIXME Bug 338334 overwrite equals()
*/
public abstract class QuantityAmount<Q extends Quantity<Q>>
implements IMeasure<Q> {
private final Measure measure;
/**
* Holds a dimensionless measure of one (exact).
*/
public static final Quantity<Dimensionless> ONE =
QuantityFactory.getInstance(Dimensionless.class).create(
BigDecimal.ONE, AbstractUnit.ONE);
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((measure == null) ? 0 : measure.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
@SuppressWarnings("unchecked")
QuantityAmount<Q> other = (QuantityAmount<Q>) obj;
if (measure == null) {
if (other.measure != null)
return false;
} else if (!measure.equals(other.measure))
return false;
return true;
}
@Override
public String toString() {
return String.valueOf(measure);
}
/**
* Indicates if this measure is exact.
*/
private boolean isExact;
/**
* Holds the exact value (when exact) stated in this measure unit.
*/
// private long _exactValue;
/**
* Holds the minimum value stated in this measure unit. For inexact
* measures: _minimum < _maximum
*/
// private double _minimum;
/**
* Holds the maximum value stated in this measure unit. For inexact
* measures: _maximum > _minimum
*/
// private double _maximum;
protected QuantityAmount(Number number, MeasureUnit unit) {
measure = MeasureAmount.of(number, unit);
}
/**
* Returns the <b>ICU4J</b> <type>Measure</type> object.
* @return the backing measure.
*/
public Measure getMeasure() {
return measure;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.uomo.units.IMeasure#doubleValue(org.unitsofmeasurement.unit
* .Unit)
*/
@Override
public double doubleValue(Unit<Q> unit) {
Unit<Q> myUnit = unit();
try {
UnitConverter converter = unit.getConverterTo(myUnit);
return converter.convert(getNumber().doubleValue());
} catch (UnconvertibleException e) {
throw e;
} // catch (IncommensurableException e) {
// throw new IllegalArgumentException(e.getMessage());
// }
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.uomo.units.IMeasure#longValue(org.unitsofmeasurement.unit
* .Unit)
*/
@Override
public long longValue(Unit<Q> unit) {
Unit<Q> myUnit = unit();
try {
UnitConverter converter = unit.getConverterToAny(myUnit);
return (converter.convert(
BigDecimal.valueOf(getNumber().longValue()),
MathContext.DECIMAL128)).longValue();
} catch (UnconvertibleException e) {
throw e;
} catch (IncommensurableException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
/*
* (non-Javadoc)
*
* @see org.unitsofmeasurement.quantity.Quantity#unit()
*/
@Override
public Unit<Q> unit() {
return internalUnit();
}
/*
* (non-Javadoc)
*
* @see org.unitsofmeasurement.quantity.Quantity#value()
*/
@Override
public Number value() {
return getNumber();
}
/**
* Indicates if this measure amount is exact. An exact amount is guarantee
* exact only when stated in this measure unit (e.g.
* <code>this.longValue()</code>); stating the amount in any other unit may
* introduce conversion errors.
*
* @return <code>true</code> if this measure is exact; <code>false</code>
* otherwise.
*/
public boolean isExact() {
return isExact;
}
public Number getValue() {
return getNumber();
}
public Unit<Q> getUnit() {
return internalUnit();
}
// ////////////////////
// Factory Creation //
// ////////////////////
// private static <Q extends Quantity<Q>> QuantityAmount<Q> create(Number value, Unit<Q> unit) {
//
// }
// @SuppressWarnings("unchecked")
// protected static <Q extends Quantity<Q>> QuantityAmount<Q> newInstance(
// Number value, Unit<?> unit) {
// QuantityAmount<Q> measure = FACTORY.create(value, unit);
//
// measure._unit = (Unit<Q>) unit;
//
// return measure;
// }
/**
* Get the unit (convenience to avoid cast).
*
* @provisional This API might change or be removed in a future release.
*/
@SuppressWarnings("unchecked")
private final AbstractUnit<Q> internalUnit() {
return (AbstractUnit<Q>) measure.getUnit();
}
protected final Number getNumber() {
return measure.getNumber();
}
}