1 /*
2 * Copyright (C) 2020-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
3 */
4 package de.powerstat.validation.values;
5
6
7 import java.util.Objects;
8
9 import de.powerstat.validation.interfaces.IValueObject;
10
11
12 /**
13 * Minute.
14 *
15 * Not DSGVO relevant.
16 *
17 * TODO Listener
18 * TODO secondsWithin = 60
19 * TODO min, max
20 */
21 public final class Minute implements Comparable<Minute>, IValueObject
22 {
23 /**
24 * Overlfow constant.
25 */
26 private static final String OVERFLOW = "Overflow"; //$NON-NLS-1$
27
28 /**
29 * Underflow constant.
30 */
31 private static final String UNDERFLOW = "Underflow"; //$NON-NLS-1$
32
33 /* *
34 * Cache for singletons.
35 */
36 // private static final Map<Integer, Minute> CACHE = new WeakHashMap<>();
37
38 /**
39 * Minute.
40 */
41 private final int minute;
42
43
44 /**
45 * Constructor.
46 *
47 * @param minute Minute 0-59
48 * @throws IndexOutOfBoundsException When the minute is less than 0 or greater than 59
49 */
50 private Minute(final int minute)
51 {
52 super();
53 if ((minute < 0) || (minute > 59))
54 {
55 throw new IndexOutOfBoundsException("Minute number out of range (0-59)!"); //$NON-NLS-1$
56 }
57 this.minute = minute;
58 }
59
60
61 /**
62 * Minute factory.
63 *
64 * @param minute Minute 0-59
65 * @return Minute object
66 */
67 public static Minute of(final int minute)
68 {
69 /*
70 synchronized (Minute.class)
71 {
72 Minute obj = Minute.CACHE.get(minute);
73 if (obj != null)
74 {
75 return obj;
76 }
77 obj = new Minute(minute);
78 Minute.CACHE.put(Integer.valueOf(minute), obj);
79 return obj;
80 }
81 */
82 return new Minute(minute);
83 }
84
85
86 /**
87 * Minute factory.
88 *
89 * @param value Minute 0-59 string
90 * @return Minute object
91 */
92 public static Minute of(final String value)
93 {
94 return of(Integer.parseInt(value));
95 }
96
97
98 /**
99 * Returns the value of this Minute as an int.
100 *
101 * @return The numeric value represented by this object after conversion to type int.
102 */
103 public int intValue()
104 {
105 return this.minute;
106 }
107
108
109 /**
110 * Returns the value of this Minute as an String.
111 *
112 * @return The numeric value represented by this object after conversion to type String.
113 */
114 @Override
115 public String stringValue()
116 {
117 return String.valueOf(this.minute);
118 }
119
120
121 /**
122 * Calculate hash code.
123 *
124 * @return Hash
125 * @see java.lang.Object#hashCode()
126 */
127 @Override
128 public int hashCode()
129 {
130 return Integer.hashCode(this.minute);
131 }
132
133
134 /**
135 * Is equal with another object.
136 *
137 * @param obj Object
138 * @return true when equal, false otherwise
139 * @see java.lang.Object#equals(java.lang.Object)
140 */
141 @Override
142 public boolean equals(final Object obj)
143 {
144 if (this == obj)
145 {
146 return true;
147 }
148 if (!(obj instanceof Minute))
149 {
150 return false;
151 }
152 final Minute other = (Minute)obj;
153 return this.minute == other.minute;
154 }
155
156
157 /**
158 * Returns the string representation of this Minute.
159 *
160 * The exact details of this representation are unspecified and subject to change, but the following may be regarded as typical:
161 *
162 * "Minute[minute=1]"
163 *
164 * @return String representation of this Minute
165 * @see java.lang.Object#toString()
166 */
167 @Override
168 public String toString()
169 {
170 final var builder = new StringBuilder();
171 builder.append("Minute[minute=").append(this.minute).append(']'); //$NON-NLS-1$
172 return builder.toString();
173 }
174
175
176 /**
177 * Compare with another object.
178 *
179 * @param obj Object to compare with
180 * @return 0: equal; 1: greater; -1: smaller
181 * @see java.lang.Comparable#compareTo(java.lang.Object)
182 */
183 @Override
184 public int compareTo(final Minute obj)
185 {
186 Objects.requireNonNull(obj, "obj"); //$NON-NLS-1$
187 return Integer.compare(this.minute, obj.minute);
188 }
189
190
191 /**
192 * Add minutes to this minute.
193 *
194 * @param minutes Minutes to add to this minute
195 * @return New minute after adding the minutes to this minute
196 * @throws ArithmeticException In case of an overflow
197 */
198 public Minute add(final Minutes minutes)
199 {
200 final int newMinute = Math.toIntExact(Math.addExact(this.minute, minutes.longValue()));
201 if (newMinute > 59)
202 {
203 // TODO Listener
204 throw new ArithmeticException(Minute.OVERFLOW);
205 }
206 return Minute.of(newMinute);
207 }
208
209
210 /**
211 * Subtract minutes from this minute.
212 *
213 * @param minutes Minutes to subtract from this minute
214 * @return New minute after subtracting minutes from this minute
215 * @throws ArithmeticException In case of an underflow
216 */
217 public Minute subtract(final Minutes minutes)
218 {
219 final int newMinute = Math.toIntExact(Math.subtractExact(this.minute, minutes.longValue()));
220 if (newMinute < 0)
221 {
222 // TODO Listener
223 throw new ArithmeticException(Minute.UNDERFLOW);
224 }
225 return Minute.of(newMinute);
226 }
227
228
229 /**
230 * Increment this minute.
231 *
232 * @return New minute after incrementing this minute
233 * @throws ArithmeticException In case of an overflow
234 */
235 public Minute increment()
236 {
237 final int newMinute = Math.incrementExact(this.minute);
238 if (newMinute == 60)
239 {
240 // TODO Listener
241 throw new ArithmeticException(Minute.OVERFLOW);
242 }
243 return Minute.of(newMinute);
244 }
245
246
247 /**
248 * Decrement this minute.
249 *
250 * @return New minute after decrement this minute
251 * @throws ArithmeticException In case of an overflow
252 */
253 public Minute decrement()
254 {
255 final int newMinute = Math.decrementExact(this.minute);
256 if (newMinute == -1)
257 {
258 // TODO Listener
259 throw new ArithmeticException(Minute.UNDERFLOW);
260 }
261 return Minute.of(newMinute);
262 }
263
264 }