blob: 2f36c56756308b0b08af5b286747cbbfad7c2d85 [file] [log] [blame]
/**
* Unit-API - Units of Measurement API for Java
* Copyright 2013-2014, Jean-Marie Dautelle, Werner Keil, V2COM and individual
* contributors by the @author tag.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.uomo.units.impl;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import org.eclipse.uomo.units.AbstractConverter;
import org.eclipse.uomo.units.AbstractQuantity;
import javax.measure.Quantity;
import javax.measure.IncommensurableException;
import javax.measure.UnconvertibleException;
import javax.measure.Unit;
import javax.measure.UnitConverter;
/**
* An amount of quantity, consisting of a Number and a Unit. BaseMeasurement
* objects are immutable.
*
* @see java.lang.Number
* @see MeasureUnit
* @author <a href="mailto:units@catmedia.us">Werner Keil</a>
* @param <Q>
* The type of the quantity.
* @version 1.6, $Date: 2014-04-08 $
*/
public class BaseQuantity<Q extends Quantity<Q>> extends AbstractQuantity<Q>
implements Quantity<Q>, Comparable<BaseQuantity<Q>> {
//FIXME Bug 338334 overwrite equals()
/**
*
*/
// private static final long serialVersionUID = 7312161895652321241L;
private final Number value;
/*
* (non-Javadoc)
*
* @see AbstractMeasurement#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (this.getClass() == obj.getClass()) {
return super.equals(obj);
} else {
if (obj instanceof Quantity) {
@SuppressWarnings("rawtypes")
Quantity m = (Quantity) obj;
if (m.getValue().getClass() == this.getValue().getClass()
&& m.getUnit().getClass() == this.getUnit().getClass()) {
return super.equals(obj);
} else {
// if (this.getQuantityUnit() instanceof AbstractUnit<?>) {
// if
// }
return super.equals(obj);
}
}
return false;
}
}
/**
* Indicates if this measure is exact.
*/
private final boolean isExact;
/**
* Indicates if this measure is big.
*/
private final boolean isBig;
/**
* 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 BaseQuantity(Number number, Unit<Q> unit) {
super(unit);
value = number;
isExact = false;
isBig = false;;
}
/*
* (non-Javadoc)
*
* @see
* Measurement#doubleValue(javax.measure.Unit)
*/
public double doubleValue(Unit<Q> unit) {
Unit<Q> myUnit = getUnit();
try {
UnitConverter converter = unit.getConverterTo(myUnit);
return converter.convert(getValue().doubleValue());
} catch (UnconvertibleException e) {
throw e;
} // catch (IncommensurableException e) {
// throw new IllegalArgumentException(e.getMessage());
// }
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.uomo.units.AbstractMeasurement#longValue(javax.measure
* .Unit)
*/
public long longValue(Unit<Q> unit) {
Unit<Q> myUnit = getUnit();
try {
UnitConverter converter = unit.getConverterToAny(myUnit);
if ((getValue() instanceof BigDecimal || getValue() instanceof BigInteger)
&& converter instanceof AbstractConverter) {
return (((AbstractConverter)converter).convert(
BigDecimal.valueOf(getValue().longValue()),
MathContext.DECIMAL128)).longValue();
} else {
double result = doubleValue(unit);
if ((result < Long.MIN_VALUE) || (result > Long.MAX_VALUE)) {
throw new ArithmeticException("Overflow (" + result + ")");
}
return (long) result;
}
} catch (UnconvertibleException e) {
throw e;
} catch (IncommensurableException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
/*
* (non-Javadoc)
*
* @see javax.measure.Quantity#getValue()
*/
public Number getValue() {
return value;
}
/**
* Indicates if this measured 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;
}
/**
* Indicates if this measured amount is a big number, i.E. BigDecimal or BigInteger.
* In all other cases this would be false.
*
* @return <code>true</code> if this measure is big; <code>false</code>
* otherwise.
*/
public boolean isBig() {
return isBig;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public BaseQuantity<Q> add(AbstractQuantity<Q> that) {
final AbstractQuantity<Q> thatToUnit = that.to(getUnit());
return new BaseQuantity(this.getValue().doubleValue()
+ thatToUnit.getValue().doubleValue(),
getUnit());
}
public String toString() {
return String.valueOf(getValue()) + " "
+ String.valueOf(getUnit());
}
@Override
public IMeasure<?> multiply(IMeasure<?> that) {
final Unit<?> unit = getUnit().multiply(that.unit());
return of((getValue().doubleValue() * that.value()
.doubleValue()), unit);
}
@Override
public BaseQuantity<?> multiply(Number that) {
return (BaseQuantity<Q>) of((getValue().doubleValue() * that
.doubleValue()), getUnit());
}
@Override
public IMeasure<?> divide(IMeasure<?> that) {
final Unit<?> unit = getUnit().divide(that.unit());
return of((getValue().doubleValue() / that.value()
.doubleValue()), unit);
}
public IMeasure<?> divide(Number that) {
// TODO may use isBig() here, too
if (value instanceof BigDecimal && that instanceof BigDecimal) {
return of(((BigDecimal)value).divide((BigDecimal)that),
getUnit());
}
return of(getValue().doubleValue() / that.doubleValue(),
getUnit());
}
// @Override
// public IMeasure<Q> inverse() {
// @SuppressWarnings({ "rawtypes", "unchecked" })
// final IMeasure<Q> m = new BaseQuantity(getValue(),
// getUnit().inverse()); // TODO keep value same?
// return m;
// }
@Override
public BigDecimal decimalValue(Unit<Q> unit, MathContext ctx)
throws ArithmeticException {
if (value instanceof BigDecimal) {
return (BigDecimal)value;
}
if (value instanceof BigInteger) {
return new BigDecimal((BigInteger)value);
}
return BigDecimal.valueOf(value.doubleValue());
}
@Override
public int compareTo(BaseQuantity<Q> o) {
// TODO Auto-generated method stub
return 0;
}
@Override
public Number value() {
return getValue();
}
@Override
public IMeasure<? extends IMeasure<Q>> inverse() {
final IMeasure<? extends IMeasure<Q>> m = new BaseQuantity(getValue(),
getUnit().inverse()); // TODO keep value same?
return m;
}
}