summaryrefslogtreecommitdiff
path: root/src/org/unitConverter/unit/UnitValue.java
blob: 9e565d92dc4a6def2505989d8633d589bd518e30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
113
114
package org.unitConverter.unit;

import java.util.Objects;
import java.util.Optional;

/**
 * A value expressed in a unit.
 * 
 * Unless otherwise indicated, all methods in this class throw a
 * {@code NullPointerException} when an argument is null.
 * 
 * @author Adrien Hopkins
 * @since 2020-07-26
 */
public final class UnitValue {
	/**
	 * @param unit  unit to use
	 * @param value value to use
	 * @return {@code UnitValue} instance
	 */
	public static UnitValue of(Unit unit, double value) {
		return new UnitValue(Objects.requireNonNull(unit, "unit must not be null"), value);
	}

	private final Unit unit;
	private final double value;

	/**
	 * @param unit  the unit being used
	 * @param value the value being represented
	 */
	private UnitValue(Unit unit, double value) {
		this.unit = unit;
		this.value = value;
	}

	/**
	 * @return the unit
	 */
	public final Unit getUnit() {
		return unit;
	}

	/**
	 * @return the value
	 */
	public final double getValue() {
		return value;
	}

	/**
	 * Converts this {@code UnitValue} into an equivalent {@code LinearUnitValue} by
	 * using this unit's base unit.
	 * 
	 * @param newName A new name for the base unit. Use {@link NameSymbol#EMPTY} if
	 *                you don't want one.
	 */
	public final LinearUnitValue asLinearUnitValue(NameSymbol newName) {
		LinearUnit base = LinearUnit.valueOf(unit.getBase(), 1, newName);
		return LinearUnitValue.getExact(base, base.convertToBase(value));
	}

	/**
	 * @param other a {@code Unit}
	 * @return true iff this value can be represented with {@code other}.
	 */
	public final boolean canConvertTo(Unit other) {
		return this.unit.canConvertTo(other);
	}

	/**
	 * Returns a UnitValue that represents the same value expressed in a
	 * different unit
	 * 
	 * @param other new unit to express value in
	 * @return value expressed in {@code other}
	 */
	public final UnitValue convertTo(Unit other) {
		return UnitValue.of(other, this.getUnit().convertTo(other, this.getValue()));
	}

	/**
	 * Returns true if this and obj represent the same value, regardless of whether
	 * or not they are expressed in the same unit. So (1000 m).equals(1 km) returns
	 * true.
	 */
	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof UnitValue))
			return false;
		final UnitValue other = (UnitValue) obj;
		return Objects.equals(this.unit.getBase(), other.unit.getBase())
				&& Double.doubleToLongBits(this.unit.convertToBase(this.getValue())) == Double
						.doubleToLongBits(other.unit.convertToBase(other.getValue()));
	}

	@Override
	public int hashCode() {
		return Objects.hash(this.unit.getBase(), this.unit.convertFromBase(this.getValue()));
	}

	@Override
	public String toString() {
		Optional<String> primaryName = this.getUnit().getPrimaryName();
		Optional<String> symbol = this.getUnit().getSymbol();
		if (primaryName.isEmpty() && symbol.isEmpty()) {
			double baseValue = this.getUnit().convertToBase(this.getValue());
			return String.format("%s unnamed unit (= %s %s)", this.getValue(), baseValue, this.getUnit().getBase());
		} else {
			String unitName = symbol.orElse(primaryName.get());
			return this.getValue() + " " + unitName;
		}
	}
}