package de.hftstuttgart.cityunits.model;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.measure.Quantity;
import javax.measure.Unit;
import tech.units.indriya.format.SimpleQuantityFormat;
import tech.units.indriya.quantity.Quantities;
/**
* A NullableQuantity
wraps a javax.measure.Quantity
having
* a numerical value that is either a Double
, a Long
,
* or null
. The latter case represents an unknown numerical
* value of a specific unit. On the other hand, the javax.measure.Unit
* of the quantity is always defined.
*/
public class NullableQuantity {
static Logger LOGGER = Logger.getLogger("de.hftstuttgart.cityunits");
static {
// TODO Implement specific QuantityFormat to enable custom number format?
// ensure that editing, (de)serialization and default values of units all work
// with the same number format (Decimal point etc.)
Locale.setDefault(Locale.ENGLISH);
// specific additional units for urban simulation like TON (t), PARTS_PER_MILLION (ppm), DECIBEL (dB)
UrbanSimulationUnits.getInstance();
}
public static NullableQuantity create(String str) {
NullableQuantity newNullableQuantity = null;
try {
LOGGER.log(Level.INFO, "Create Quantity from " + str);
NumberFormat.getInstance().parse(str);
newNullableQuantity = new NullableQuantity(str);
} catch (final ParseException ex) { // no number value present: create NullQuantity just with unit
try {
NullableQuantity dummy = new NullableQuantity("1 " + str); //$NON-NLS-1$
LOGGER.log(Level.INFO, "Create Quantity just with unit from " + str);
newNullableQuantity = new NullQuantity(dummy.getUnit());
} catch (final IllegalArgumentException ex1) { // Unit could not be parsed
LOGGER.log(Level.WARNING, "Unit '" + str + "' could not be parsed!", ex);
}
} catch (final IllegalArgumentException ex) { // Quantity could not be parsed
LOGGER.log(Level.WARNING, "Quantity '" + str + "' could not be parsed!", ex);
}
return newNullableQuantity;
}
public static NullableQuantity create(Number number, Unit> unit) {
return number == null ? new NullQuantity(unit) : new NullableQuantity(number, unit);
}
private final Quantity> quantity;
private NullableQuantity(String str) {
quantity = Quantities.getQuantity(str);
}
private NullableQuantity(Number number, Unit> unit) {
quantity = Quantities.getQuantity(number, unit);
}
/**
* In case of an unknown numerical value of the quantity an empty Optional
is returned via subclass.
* @return the wrapped javax.measure.Quantity
if its numerical value is present
*/
public Optional> getQuantity() {
return Optional.of(quantity);
}
/**
* @return numerical value of the wrapped javax.measure.Quantity
if present
*/
public Optional getNumber() {
return getQuantity().map(Quantity::getValue);
}
public Unit> getUnit() {
return quantity.getUnit();
}
@Override
public String toString() {
return SimpleQuantityFormat.getInstance().format(quantity);
}
private static class NullQuantity extends NullableQuantity {
public NullQuantity(Unit> unit) {
super(1, unit);
}
public Optional> getQuantity() {
return Optional.empty();
}
@Override
public String toString() {
return " " + getUnit().toString();
}
}
}