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