NullableQuantity.java 3.52 KB
Newer Older
1
2
3
4
5
6
package de.hftstuttgart.cityunits.model;

import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import java.util.Optional;
7
8
import java.util.logging.Level;
import java.util.logging.Logger;
9
10
11
12

import javax.measure.Quantity;
import javax.measure.Unit;

Kai-Holger Brassel's avatar
Kai-Holger Brassel committed
13
14
15
16
17
18
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.Platform;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.eclipse.core.runtime.Status;

19
20
21
22
23
24
25
26
27
28
29
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 {
30
	
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	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
51
				Platform.getLog(NullableQuantity.class).warn("Unit '" + str + "'  could not be parsed!", ex);
52
53
			}
		} catch (final IllegalArgumentException ex) { // Quantity could not be parsed
54
			Platform.getLog(NullableQuantity.class).warn("Quantity '" + str + "'  could not be parsed!", ex);
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
		}
		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();
		}
	}
}