/* | |
* 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<Dimensionless> 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; | |
} | |
} |