blob: 411a6c29c6686818fcd58585466d943e3230c3ea [file] [log] [blame]
/*
* Copyright (c) 2005, 2017, 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.impl;
import java.util.Objects;
import javax.measure.Quantity;
import javax.measure.Unit;
import javax.measure.UnconvertibleException;
import javax.measure.UnitConverter;
import org.eclipse.uomo.units.AbstractQuantity;
import org.eclipse.uomo.units.impl.format.QuantityFormat;
/**
* An amount of quantity, consisting of a Number and a Unit. NumberQuantity objects are immutable.
*
* @see AbstractQuantity
* @see Quantity
* @author <a href="mailto:werner@uom.technology">Werner Keil</a>
* @param <Q>
* The type of the quantity.
* @version 1.0.2, $Date: 2017-05-28 $
* @since 0.7
*/
public class NumberQuantity<Q extends Quantity<Q>> extends AbstractQuantity<Q> {
/**
*
*/
// private static final long serialVersionUID = 7312161895652321241L;
private final Number value;
/**
* Indicates if this quantity is exact.
*/
private final boolean isExact;
/**
* Holds the exact value (when exact) stated in this quantity's unit.
*/
// private long exactValue;
/**
* Holds the minimum value stated in this quantity's unit. For inexact measures: minimum < maximum
*/
// private double minimum;
/**
* Holds the maximum value stated in this quantity's unit. For inexact measures: maximum > minimum
*/
// private double maximum;
protected NumberQuantity(Number number, Unit<Q> unit) {
super(unit);
value = number;
isExact = false;
}
/*
* (non-Javadoc)
*
* @see AbstractQuantity#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (obj instanceof Quantity<?>) {
Quantity<?> that = (Quantity<?>) obj;
return Objects.equals(getUnit(), that.getUnit()) && Equalizer.hasEquality(value, that.getValue());
}
return false;
}
/*
* (non-Javadoc)
*
* @see AbstractQuantity#doubleValue(javax.measure.Unit)
*/
@Override
public double doubleValue(Unit<Q> unit) {
Unit<Q> myUnit = getUnit();
try {
UnitConverter converter = myUnit.getConverterTo(unit);
return converter.convert(getValue().doubleValue());
} catch (UnconvertibleException e) {
throw e;
}
}
protected final int intValue(Unit<Q> unit) throws ArithmeticException {
long longValue = longValue(unit);
if ((longValue < Integer.MIN_VALUE) || (longValue > Integer.MAX_VALUE)) {
throw new ArithmeticException("Cannot convert " + longValue + " to int (overflow)");
}
return (int) longValue;
}
/*
* (non-Javadoc)
*
* @see javax.measure.Quantity#getValue()
*/
public Number getValue() {
return value;
}
/**
* Indicates if this measured quantity is exact. An exact quantity is guaranteed exact only when stated in this quantity's unit (e.g.
* <code>this.longValue()</code>); stating the quantity in any other unit may introduce conversion errors.
*
* @return <code>true</code> if this quantity is exact; <code>false</code> otherwise.
*/
public boolean isExact() {
return isExact;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Quantity<Q> add(AbstractQuantity<Q> that) {
final Quantity<Q> thatToUnit = that.to(getUnit());
return new NumberQuantity(this.getValue().doubleValue() + thatToUnit.getValue().doubleValue(), getUnit());
}
public String toString() {
return String.valueOf(getValue()) + " " + String.valueOf(getUnit());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Quantity<?> multiply(Quantity<?> that) {
final Unit<?> unit = getUnit().multiply(that.getUnit());
return new NumberQuantity((getValue().doubleValue() * that.getValue().doubleValue()), unit);
}
public Quantity<Q> multiply(Number that) {
return (AbstractQuantity<Q>) NumberQuantity.of((getValue().doubleValue() * that.doubleValue()), getUnit());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Quantity<Q> divide(Quantity<?> that) {
final Unit<?> unit = getUnit().divide(that.getUnit());
return new NumberQuantity((getValue().doubleValue() / that.getValue().doubleValue()), unit);
}
public Quantity<Q> divide(Number that) {
return NumberQuantity.of(getValue().doubleValue() / that.doubleValue(), getUnit());
}
@SuppressWarnings("unchecked")
public Quantity<Q> inverse() {
return (AbstractQuantity<Q>) NumberQuantity.of(1d / value.doubleValue(), getUnit().inverse());
}
// public Quantity<Q> inverse() {
// @SuppressWarnings({ "rawtypes", "unchecked" })
// final Quantity<Q> m = new NumberQuantity(1d / getValue().doubleValue(),
// getUnit().inverse());
// return m;
// }
@SuppressWarnings({ "rawtypes", "unchecked" })
public Quantity<Q> subtract(Quantity<Q> that) {
final Quantity<Q> thatToUnit = (Quantity<Q>) that.to(getUnit());
return new NumberQuantity(this.getValue().doubleValue() - thatToUnit.getValue().doubleValue(), getUnit());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Quantity<Q> add(Quantity<Q> that) {
final Quantity<Q> thatToUnit = (Quantity<Q>) that.to(getUnit());
return new NumberQuantity(this.getValue().doubleValue() + thatToUnit.getValue().doubleValue(), getUnit());
}
/**
* Returns the scalar quantity for the specified <code>long</code> stated in the specified unit.
*
* @param longValue
* the quantity value.
* @param unit
* the measurement unit.
* @return the corresponding <code>int</code> quantity.
*/
public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(long longValue, Unit<Q> unit) {
return new LongQuantity<Q>(longValue, unit);
}
/**
* Returns the scalar quantity for the specified <code>int</code> stated in the specified unit.
*
* @param intValue
* the quantity value.
* @param unit
* the measurement unit.
* @return the corresponding <code>int</code> quantity.
*/
public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(int intValue, Unit<Q> unit) {
return new IntegerQuantity<Q>(intValue, unit);
}
/**
* Returns the scalar quantity for the specified <code>short</code> stated in the specified unit.
*
* @param value
* the quantity value.
* @param unit
* the measurement unit.
* @return the corresponding <code>short</code> quantity.
*/
public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(short value, Unit<Q> unit) {
return new ShortQuantity<Q>(value, unit);
}
/**
* Returns the scalar quantity for the specified <code>float</code> stated in the specified unit.
*
* @param floatValue
* the measurement value.
* @param unit
* the measurement unit.
* @return the corresponding <code>float</code> quantity.
*/
public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(float floatValue, Unit<Q> unit) {
return new FloatQuantity<Q>(floatValue, unit);
}
/**
* Returns the scalar quantity for the specified <code>double</code> stated in the specified unit.
*
* @param doubleValue
* the measurement value.
* @param unit
* the measurement unit.
* @return the corresponding <code>double</code> quantity.
*/
public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(double doubleValue, Unit<Q> unit) {
return new DoubleQuantity<Q>(doubleValue, unit);
}
/**
* Returns the decimal quantity of unknown type corresponding to the specified representation. This method can be used to parse dimensionless
* quantities.<br>
* <code>
* Quantity&lt;Dimensionless&gt; proportion = NumberQuantity.parse("0.234").asType(Dimensionless.class);
* </code>
*
* <p>
* Note: This method handles only {@link org.eclipse.uomo.units.SimpleUnitFormat.UnitFormat#getStandard standard} unit format.
* </p>
*
* @param csq
* the decimal value and its unit (if any) separated by space(s).
* @return <code>QuantityFormat.getInstance().parse(csq)</code>
*/
public static Quantity<?> parse(CharSequence csq) {
return QuantityFormat.getInstance().parse(csq);
}
@Override
protected boolean isBig() {
// TODO Auto-generated method stub
return false;
}
}