package de.hftstuttgart.units; import java.text.NumberFormat; import java.text.ParseException; import java.util.Locale; import java.util.Optional; import javax.measure.Quantity; import javax.measure.Unit; import tech.units.indriya.format.SimpleQuantityFormat; import tech.units.indriya.quantity.Quantities; /** * A <code>NullableQuantity</code> wraps a <code>javax.measure.Quantity</code> having * a numerical value that is either a <code>Double</code>, a <code>Long</code>, * or <code>null</code>. The latter case represents an unknown numerical * value of a specific unit. On the other hand, the <code>javax.measure.Unit</code> * of the quantity is always defined. */ public class NullableQuantity { 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 { 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$ newNullableQuantity = new NullQuantity(dummy.getUnit()); } catch (final IllegalArgumentException ex1) { // Unit could not be parsed System.out.println("Unit '" + str + "' could not be parsed!"); //TODO ex.printStackTrace(); } } catch (final IllegalArgumentException ex) { // Quantity could not be parsed System.out.println("Quantity '" + str + "' could not be parsed!"); //TODO ex.printStackTrace(); } 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 <code>Optional</code> is returned via subclass. * @return the wrapped <code>javax.measure.Quantity</code> if its numerical value is present */ public Optional<Quantity<?>> getQuantity() { return Optional.of(quantity); } /** * @return numerical value of the wrapped <code>javax.measure.Quantity</code> if present */ public Optional<Number> 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<Quantity<?>> getQuantity() { return Optional.empty(); } @Override public String toString() { return "<unknown> " + getUnit().toString(); } } }