summaryrefslogtreecommitdiff
path: root/src/org/unitConverter/unit/OperatableUnit.java
blob: ae11c418b53be99db449dd867b81d1a5944e8755 (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/**
 * Copyright (C) 2019 Adrien Hopkins
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package org.unitConverter.unit;

/**
 * A unit that can be added, subtracted, multiplied or divided by another operatable unit, and raised to an integer
 * exponent.
 * <p>
 * In order to use two units in an operation, they must be part of the same unit system. In addition, in order for two
 * units to add or subtract, they must measure the same dimension.
 * </p>
 * <p>
 * It is okay for an operation to throw a {@code ClassCastException} if the operator's class cannot operate with another
 * class. However, all classes that implement this interface should be able to interoperate with {@code BaseUnit} and
 * {@code LinearUnit}.
 * </p>
 * 
 * @author Adrien Hopkins
 * @since 2019-03-17
 */
public interface OperatableUnit extends Unit {
	/**
	 * Returns the quotient of this unit and another.
	 * <p>
	 * Two units can be divided if they are part of the same unit system. If {@code divisor} does not meet this
	 * condition, an {@code IllegalArgumentException} should be thrown.
	 * </p>
	 * <p>
	 * It is okay for a unit to throw a {@code ClassCastException} if it cannot operate with {@code divisor}'s class.
	 * However, all classes that implement this interface should be able to interoperate with {@code BaseUnit} and
	 * {@code LinearUnit}.
	 * </p>
	 * 
	 * @param divisor
	 *            unit to divide by
	 * @return quotient
	 * @throws IllegalArgumentException
	 *             if {@code divisor} is not compatible for division as described above
	 * @throws NullPointerException
	 *             if {@code divisor} is null
	 * @throws ClassCastException
	 *             if {@code divisor}'s class is incompatible with this unit's class
	 * @since 2019-03-17
	 */
	default OperatableUnit dividedBy(final OperatableUnit divisor) {
		return this.times(divisor.reciprocal());
	}

	/**
	 * Returns the difference of this unit and another.
	 * <p>
	 * Two units can be subtracted if they meet the following conditions:
	 * <ul>
	 * <li>The two units are part of the same UnitSystem.</li>
	 * <li>The two units have the same {@code dimension}.</li>
	 * </ul>
	 * If {@code subtrahend} does not meet these conditions, an {@code IllegalArgumentException} should be thrown.
	 * </p>
	 * <p>
	 * It is okay for a unit to throw a {@code ClassCastException} if it cannot operate with {@code subtrahend}'s class.
	 * However, all classes that implement this interface should be able to interoperate with {@code BaseUnit} and
	 * {@code LinearUnit}.
	 * </p>
	 * 
	 * @param subtrahend
	 *            unit to subtract
	 * @return difference
	 * @throws IllegalArgumentException
	 *             if {@code subtrahend} is not compatible for subtraction as described above
	 * @throws NullPointerException
	 *             if {@code subtrahend} is null
	 * @throws ClassCastException
	 *             if {@code subtrahend}'s class is incompatible with this unit's class
	 * @since 2019-03-17
	 */
	default OperatableUnit minus(final OperatableUnit subtrahend) {
		return this.plus(subtrahend.negated());
	}

	/**
	 * @return this unit negated, i.e. -this
	 * @since 2019-03-17
	 */
	OperatableUnit negated();

	/**
	 * Returns the sum of this unit and another.
	 * <p>
	 * Two units can be added if they meet the following conditions:
	 * <ul>
	 * <li>The two units are part of the same UnitSystem.</li>
	 * <li>The two units have the same {@code dimension}.</li>
	 * </ul>
	 * If {@code addend} does not meet these conditions, an {@code IllegalArgumentException} should be thrown.
	 * </p>
	 * <p>
	 * It is okay for a unit to throw a {@code ClassCastException} if it cannot operate with {@code addend}'s class.
	 * However, all classes that implement this interface should be able to interoperate with {@code BaseUnit} and
	 * {@code LinearUnit}.
	 * </p>
	 * 
	 * @param addend
	 *            unit to add
	 * @return sum
	 * @throws IllegalArgumentException
	 *             if {@code addend} is not compatible for addition as described above
	 * @throws NullPointerException
	 *             if {@code addend} is null
	 * @throws ClassCastException
	 *             if {@code addend}'s class is incompatible with this unit's class
	 * @since 2019-03-17
	 */
	OperatableUnit plus(OperatableUnit addend);

	/**
	 * @return reciprocal of this unit
	 * @since 2019-03-17
	 */
	OperatableUnit reciprocal();

	/**
	 * Returns the product of this unit and another.
	 * <p>
	 * Two units can be multiplied if they are part of the same unit system. If {@code multiplier} does not meet this
	 * condition, an {@code IllegalArgumentException} should be thrown.
	 * </p>
	 * <p>
	 * It is okay for a unit to throw a {@code ClassCastException} if it cannot operate with {@code multiplier}'s class.
	 * However, all classes that implement this interface should be able to interoperate with {@code BaseUnit} and
	 * {@code LinearUnit}.
	 * </p>
	 * 
	 * @param multiplier
	 *            unit to multiply by
	 * @return product
	 * @throws IllegalArgumentException
	 *             if {@code multiplier} is not compatible for multiplication as described above
	 * @throws NullPointerException
	 *             if {@code multiplier} is null
	 * @throws ClassCastException
	 *             if {@code multiplier}'s class is incompatible with this unit's class
	 * @since 2019-03-17
	 */
	OperatableUnit times(OperatableUnit multiplier);

	/**
	 * Returns the result of raising this unit to the exponent {@code exponent}.
	 * 
	 * @param exponent
	 *            exponent to exponentiate by
	 * @return result of exponentiation
	 * @since 2019-03-17
	 */
	OperatableUnit toExponent(int exponent);
}