1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.oceanus.format;
18
19 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20 import io.github.tonywasher.joceanus.oceanus.base.OceanusLocale;
21 import io.github.tonywasher.joceanus.oceanus.convert.OceanusDataConverter;
22 import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
23 import io.github.tonywasher.joceanus.oceanus.date.OceanusDateFormatter;
24 import io.github.tonywasher.joceanus.oceanus.date.OceanusDateRange;
25 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusDecimal;
26 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusDecimalFormatter;
27 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusDecimalParser;
28 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
29 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusPrice;
30 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRate;
31 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRatio;
32 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusUnits;
33 import io.github.tonywasher.joceanus.oceanus.profile.OceanusProfile;
34
35 import java.math.BigDecimal;
36 import java.math.BigInteger;
37 import java.time.LocalDate;
38 import java.util.ArrayList;
39 import java.util.Calendar;
40 import java.util.Date;
41 import java.util.List;
42 import java.util.Locale;
43 import java.util.Map;
44
45
46
47
48 public class OceanusDataFormatter {
49
50
51
52 public interface OceanusDataFormatterExtension {
53
54
55
56
57
58
59 String formatObject(Object pValue);
60 }
61
62
63
64
65 private static final String ERROR_CLASS = "Invalid Class: ";
66
67
68
69
70 private final OceanusDateFormatter theDateFormatter;
71
72
73
74
75 private final OceanusDecimalFormatter theDecimalFormatter;
76
77
78
79
80 private final OceanusDecimalParser theDecimalParser;
81
82
83
84
85 private final List<OceanusDataFormatterExtension> theExtensions;
86
87
88
89
90 public OceanusDataFormatter() {
91 this(OceanusLocale.getDefaultLocale());
92 }
93
94
95
96
97
98
99 public OceanusDataFormatter(final Locale pLocale) {
100 theDateFormatter = new OceanusDateFormatter(pLocale);
101 theDecimalFormatter = new OceanusDecimalFormatter(pLocale);
102 theDecimalParser = new OceanusDecimalParser(pLocale);
103 theExtensions = new ArrayList<>();
104 }
105
106
107
108
109
110
111 public OceanusDateFormatter getDateFormatter() {
112 return theDateFormatter;
113 }
114
115
116
117
118
119
120 public OceanusDecimalFormatter getDecimalFormatter() {
121 return theDecimalFormatter;
122 }
123
124
125
126
127
128
129 public OceanusDecimalParser getDecimalParser() {
130 return theDecimalParser;
131 }
132
133
134
135
136
137
138 public void extendFormatter(final OceanusDataFormatterExtension pExtension) {
139 theExtensions.add(pExtension);
140 }
141
142
143
144
145
146
147 public void setAccountingWidth(final int pWidth) {
148
149 theDecimalFormatter.setAccountingWidth(pWidth);
150 }
151
152
153
154
155 public void clearAccounting() {
156
157 theDecimalFormatter.clearAccounting();
158 }
159
160
161
162
163
164
165 public final void setFormat(final String pFormat) {
166
167 theDateFormatter.setFormat(pFormat);
168 }
169
170
171
172
173
174
175 public final void setLocale(final Locale pLocale) {
176
177 theDateFormatter.setLocale(pLocale);
178 theDecimalFormatter.setLocale(pLocale);
179 theDecimalParser.setLocale(pLocale);
180 }
181
182
183
184
185
186
187 public Locale getLocale() {
188
189 return theDateFormatter.getLocale();
190 }
191
192
193
194
195
196
197
198 public String formatObject(final Object pValue) {
199
200 if (pValue == null) {
201 return null;
202 }
203
204
205 for (OceanusDataFormatterExtension myExtension : theExtensions) {
206 final String myResult = myExtension.formatObject(pValue);
207 if (myResult != null) {
208 return myResult;
209 }
210 }
211
212
213 final Class<?> myClass = pValue.getClass();
214
215
216 if (pValue instanceof String s) {
217 return s;
218 }
219 if (pValue instanceof Boolean) {
220 return Boolean.TRUE.equals(pValue)
221 ? "true"
222 : "false";
223 }
224 if (pValue instanceof Short
225 || pValue instanceof Integer
226 || pValue instanceof Long) {
227 return pValue.toString();
228 }
229 if (pValue instanceof Float
230 || pValue instanceof Double) {
231 return pValue.toString();
232 }
233 if (pValue instanceof BigInteger
234 || pValue instanceof BigDecimal) {
235 return pValue.toString();
236 }
237
238
239 if (pValue instanceof Enum) {
240 return pValue.toString();
241 }
242
243
244 if (pValue instanceof Class<?> myClazz) {
245 return myClazz.getCanonicalName();
246 }
247
248
249 if (pValue instanceof byte[] ba) {
250 return OceanusDataConverter.bytesToHexString(ba);
251 }
252 if (pValue instanceof char[] ca) {
253 return new String(ca);
254 }
255
256
257 if (pValue instanceof Calendar myCal) {
258 return theDateFormatter.formatCalendarDay(myCal);
259 }
260 if (pValue instanceof Date myDate) {
261 return theDateFormatter.formatJavaDate(myDate);
262 }
263 if (pValue instanceof LocalDate myDate) {
264 return theDateFormatter.formatLocalDate(myDate);
265 }
266 if (pValue instanceof OceanusDate myDate) {
267 return theDateFormatter.formatDate(myDate);
268 }
269 if (pValue instanceof OceanusDateRange myRange) {
270 return theDateFormatter.formatDateRange(myRange);
271 }
272
273
274 if (pValue instanceof OceanusDecimal myDecimal) {
275 return theDecimalFormatter.formatDecimal(myDecimal);
276 }
277
278
279 if (pValue instanceof OceanusProfile myProfile) {
280
281 return myProfile.getName()
282 + ": "
283 + (myProfile.isRunning()
284 ? myProfile.getStatus()
285 : myProfile.getElapsed());
286 }
287
288
289 if (pValue instanceof OceanusException) {
290 return myClass.getSimpleName();
291 }
292
293
294 return formatBasicValue(pValue);
295 }
296
297
298
299
300
301
302
303
304
305
306
307 public <T> T parseValue(final String pSource,
308 final Class<T> pClazz) {
309 if (Boolean.class.equals(pClazz)) {
310 return pClazz.cast(Boolean.parseBoolean(pSource));
311 }
312 if (Short.class.equals(pClazz)) {
313 return pClazz.cast(Short.parseShort(pSource));
314 }
315 if (Integer.class.equals(pClazz)) {
316 return pClazz.cast(Integer.parseInt(pSource));
317 }
318 if (Long.class.equals(pClazz)) {
319 return pClazz.cast(Long.parseLong(pSource));
320 }
321 if (Float.class.equals(pClazz)) {
322 return pClazz.cast(Float.parseFloat(pSource));
323 }
324 if (Double.class.equals(pClazz)) {
325 return pClazz.cast(Double.parseDouble(pSource));
326 }
327 if (BigInteger.class.equals(pClazz)) {
328 return pClazz.cast(new BigInteger(pSource));
329 }
330 if (BigDecimal.class.equals(pClazz)) {
331 return pClazz.cast(new BigDecimal(pSource));
332 }
333 if (Date.class.equals(pClazz)) {
334
335 return pClazz.cast(theDateFormatter.parseJavaDate(pSource));
336 }
337 if (OceanusDate.class.equals(pClazz)) {
338
339 return pClazz.cast(theDateFormatter.parseDate(pSource));
340 }
341 if (Calendar.class.equals(pClazz)) {
342
343 return pClazz.cast(theDateFormatter.parseCalendarDay(pSource));
344 }
345 if (LocalDate.class.equals(pClazz)) {
346
347 return pClazz.cast(theDateFormatter.parseLocalDate(pSource));
348 }
349 if (OceanusPrice.class.equals(pClazz)) {
350
351 return pClazz.cast(theDecimalParser.parsePriceValue(pSource));
352 }
353 if (OceanusMoney.class.equals(pClazz)) {
354
355 return pClazz.cast(theDecimalParser.parseMoneyValue(pSource));
356 }
357 if (OceanusRate.class.equals(pClazz)) {
358
359 return pClazz.cast(theDecimalParser.parseRateValue(pSource));
360 }
361 if (OceanusUnits.class.equals(pClazz)) {
362
363 return pClazz.cast(theDecimalParser.parseUnitsValue(pSource));
364 }
365 if (OceanusRatio.class.equals(pClazz)) {
366
367 return pClazz.cast(theDecimalParser.parseRatioValue(pSource));
368 }
369 throw new IllegalArgumentException(ERROR_CLASS + pClazz.getSimpleName());
370 }
371
372
373
374
375
376
377
378
379
380
381 public <T> T parseValue(final Double pSource,
382 final Class<T> pClazz) {
383 if (OceanusPrice.class.equals(pClazz)) {
384
385 return pClazz.cast(theDecimalParser.createPriceFromDouble(pSource));
386 }
387 if (OceanusMoney.class.equals(pClazz)) {
388
389 return pClazz.cast(theDecimalParser.createMoneyFromDouble(pSource));
390 }
391 if (OceanusRate.class.equals(pClazz)) {
392
393 return pClazz.cast(theDecimalParser.createRateFromDouble(pSource));
394 }
395 if (OceanusUnits.class.equals(pClazz)) {
396
397 return pClazz.cast(theDecimalParser.createUnitsFromDouble(pSource));
398 }
399 if (OceanusRatio.class.equals(pClazz)) {
400
401 return pClazz.cast(theDecimalParser.createRatioFromDouble(pSource));
402 }
403 throw new IllegalArgumentException(ERROR_CLASS + pClazz.getSimpleName());
404 }
405
406
407
408
409
410
411
412
413
414
415
416 public <T> T parseValue(final Double pSource,
417 final String pCurrCode,
418 final Class<T> pClazz) {
419 if (OceanusPrice.class.equals(pClazz)) {
420
421 return pClazz.cast(theDecimalParser.createPriceFromDouble(pSource, pCurrCode));
422 }
423 if (OceanusMoney.class.equals(pClazz)) {
424
425 return pClazz.cast(theDecimalParser.createMoneyFromDouble(pSource, pCurrCode));
426 }
427 throw new IllegalArgumentException(ERROR_CLASS + pClazz.getSimpleName());
428 }
429
430
431
432
433
434
435
436 private static String formatBasicValue(final Object pValue) {
437
438 final Class<?> myClass = pValue.getClass();
439
440
441 final StringBuilder myBuilder = new StringBuilder();
442 myBuilder.append(myClass.getCanonicalName());
443
444
445 if (pValue instanceof List<?> myList) {
446 formatSize(myBuilder, myList.size());
447 } else if (pValue instanceof Map<?, ?> myMap) {
448 formatSize(myBuilder, myMap.size());
449 }
450
451
452 return myBuilder.toString();
453 }
454
455
456
457
458
459
460
461 private static void formatSize(final StringBuilder pBuilder,
462 final Object pSize) {
463
464 pBuilder.append('(');
465 pBuilder.append(pSize);
466 pBuilder.append(')');
467 }
468 }