1 package com.acumenvelocity.ath.common;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.lang.reflect.Method;
7 import java.net.URI;
8 import java.net.URLEncoder;
9 import java.nio.file.Files;
10 import java.nio.file.attribute.PosixFilePermissions;
11 import java.text.DateFormat;
12 import java.time.Instant;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.Date;
16 import java.util.List;
17 import java.util.Objects;
18 import java.util.Optional;
19 import java.util.UUID;
20
21 import com.fasterxml.jackson.databind.JsonNode;
22
23 import net.sf.okapi.common.BOMAwareInputStream;
24 import net.sf.okapi.common.StreamUtil;
25 import net.sf.okapi.common.Util;
26
27
28
29
30
31
32
33
34
35 public class AthUtil {
36
37
38
39
40
41
42
43
44
45 public static <T> T fallback(T val, T defVal) {
46 return Optional.ofNullable(val).orElse(defVal);
47 }
48
49
50
51
52
53
54
55
56 public static String safeToStr(Object val, String defVal) {
57 return val == null ? defVal : val.toString();
58 }
59
60
61
62
63
64
65
66 public static String safeToStr(String val, String defVal) {
67 return Util.isEmpty(val) ? defVal : val;
68 }
69
70
71
72
73
74
75
76
77
78 public static Integer safeToInt(String val, int defVal) {
79 try {
80 return Integer.valueOf(val);
81
82 } catch (Exception e) {
83 return defVal;
84 }
85 }
86
87 public static UUID safeToUuid(String val, UUID defVal) {
88 try {
89 return UUID.fromString(val);
90
91 } catch (Exception e) {
92 return defVal;
93 }
94 }
95
96 public static List<UUID> safeToUuidList(Object val, List<UUID> defVal) {
97 if (val == null) {
98 return defVal != null ? defVal : Collections.emptyList();
99 }
100
101 List<UUID> result = new ArrayList<>();
102
103 if (val instanceof List) {
104
105 for (Object item : (List<?>) val) {
106 if (item != null) {
107 UUID uuid = safeToUuid(item.toString(), null);
108
109 if (uuid != null) {
110 result.add(uuid);
111 }
112 }
113 }
114 } else if (val instanceof String) {
115
116 String[] uuidStrings = val.toString().split(",");
117
118 for (String uuidStr : uuidStrings) {
119 uuidStr = uuidStr.trim();
120
121 if (!uuidStr.isEmpty()) {
122 UUID uuid = safeToUuid(uuidStr, null);
123
124 if (uuid != null) {
125 result.add(uuid);
126 }
127 }
128 }
129 }
130
131 return result.isEmpty() && defVal != null ? defVal : result;
132 }
133
134 public static <E extends Enum<E>> E safeToEnum(String val, Class<E> enumClass, E defVal) {
135 if (val == null) {
136 return defVal;
137 }
138
139 try {
140
141 return Enum.valueOf(enumClass, val);
142
143 } catch (IllegalArgumentException e) {
144
145 try {
146 Method fromValue = enumClass.getMethod("fromValue", String.class);
147 return enumClass.cast(fromValue.invoke(null, val));
148
149 } catch (Exception ex) {
150 return defVal;
151 }
152 }
153 }
154
155
156
157
158
159
160
161
162
163 public static <E> boolean safeAddToList(List<E> list, E elem) {
164 if (elem == null) {
165 return false;
166 }
167 return list.add(elem);
168 }
169
170
171
172
173
174
175
176
177
178 public static String lastChars(String st, int numChars) {
179 if (Util.isEmpty(st) || st.length() < numChars) {
180 return "";
181 }
182 return st.substring(st.length() - numChars);
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196 public static <T> T clone(T obj, Class<T> cls) {
197 return JacksonUtil.fromJson(JacksonUtil.toJson(obj, false), cls);
198 }
199
200 public static <T> List<T> removeNulls(List<T> list) {
201 list.removeIf(Objects::isNull);
202 return list;
203 }
204
205 public static String fileAsString(final File file) throws IOException {
206 try (final BOMAwareInputStream bis = new BOMAwareInputStream(new FileInputStream(file),
207 "UTF-8")) {
208 return StreamUtil.streamAsString(bis, bis.detectEncoding());
209 }
210 }
211
212
213
214
215
216 public static <T> T safeFromJsonNode(JsonNode node, Class<T> clazz, T defVal) {
217 if (node == null) {
218 return defVal;
219 }
220 try {
221 return JacksonUtil.fromJsonNode(node, clazz);
222 } catch (Exception e) {
223 return defVal;
224 }
225 }
226
227
228
229
230
231 public static Date safeToDate(Object val, Date defVal) {
232 if (val == null) {
233 return defVal;
234 }
235 try {
236 return (Date) val;
237 } catch (ClassCastException e) {
238 return defVal;
239 }
240 }
241
242
243
244
245
246 public static Long safeToLong(String val, Long defVal) {
247 if (val == null) {
248 return defVal;
249 }
250 try {
251 return Long.parseLong(val);
252 } catch (NumberFormatException e) {
253 return defVal;
254 }
255 }
256
257
258
259
260
261 public static Float safeToFloat(Object val, Float defVal) {
262 if (val == null) {
263 return defVal;
264 }
265 try {
266 if (val instanceof Float) {
267 return (Float) val;
268 }
269 return Float.parseFloat(val.toString());
270 } catch (Exception e) {
271 return defVal;
272 }
273 }
274
275
276
277
278
279 public static Double safeToDouble(Object val, Double defVal) {
280 if (val == null) {
281 return defVal;
282 }
283
284 try {
285 if (val instanceof Double) {
286 return (Double) val;
287 }
288
289 return Double.parseDouble(val.toString());
290
291 } catch (Exception e) {
292 return defVal;
293 }
294 }
295
296
297
298
299
300 public static Date safeToDateFromIso(String isoDateStr, Date defVal) {
301 if (Util.isEmpty(isoDateStr)) {
302 return defVal;
303 }
304 try {
305 return Date.from(Instant.parse(isoDateStr));
306 } catch (Exception e) {
307 return defVal;
308 }
309 }
310
311 public static String dateToString(DateFormat dateFormat, Date date) {
312 return dateFormat.format(date);
313 }
314
315 public static File createTempFile() {
316 File file = null;
317
318 try {
319 file = File.createTempFile(Const.TEMP_PREFIX, null);
320 file.deleteOnExit();
321
322
323 try {
324 Files.setPosixFilePermissions(file.toPath(),
325 PosixFilePermissions.fromString("rw-------"));
326
327 } catch (UnsupportedOperationException e) {
328
329 file.setReadable(true);
330 file.setWritable(true);
331 }
332
333 return file;
334
335 } catch (Exception e) {
336 Log.warn(AthUtil.class, "Cannot create a temp file: {}", e.getMessage());
337 return null;
338 }
339 }
340
341
342
343
344
345 public static URI toURI(String uriString) {
346 if (Util.isEmpty(uriString)) {
347 return null;
348 }
349
350 try {
351 String trimmed = uriString.trim();
352
353
354 try {
355 return URI.create(trimmed);
356
357 } catch (IllegalArgumentException e) {
358
359 }
360
361
362 int schemeEnd = trimmed.indexOf("://");
363
364 if (schemeEnd == -1) {
365
366 return URI.create(encodePath(trimmed));
367 }
368
369 String scheme = trimmed.substring(0, schemeEnd);
370 String rest = trimmed.substring(schemeEnd + 3);
371
372
373 int pathStart = rest.indexOf('/');
374
375 if (pathStart == -1) {
376
377 return URI.create(trimmed);
378 }
379
380 String authority = rest.substring(0, pathStart);
381 String pathAndQuery = rest.substring(pathStart + 1);
382
383
384 int queryStart = pathAndQuery.indexOf('?');
385 int fragmentStart = pathAndQuery.indexOf('#');
386
387 String path;
388 String suffix = "";
389
390 if (queryStart != -1) {
391 path = pathAndQuery.substring(0, queryStart);
392 suffix = pathAndQuery.substring(queryStart);
393
394 } else if (fragmentStart != -1) {
395 path = pathAndQuery.substring(0, fragmentStart);
396 suffix = pathAndQuery.substring(fragmentStart);
397
398 } else {
399 path = pathAndQuery;
400 }
401
402
403 String encodedPath = encodePath(path);
404
405 return URI.create(scheme + "://" + authority + "/" + encodedPath + suffix);
406
407 } catch (Exception e) {
408 return null;
409 }
410 }
411
412
413
414
415 private static String encodePath(String path) throws Exception {
416 if (path.isEmpty()) {
417 return path;
418 }
419
420 String[] segments = path.split("/", -1);
421 StringBuilder encoded = new StringBuilder();
422
423 for (int i = 0; i < segments.length; i++) {
424 if (i > 0)
425 encoded.append("/");
426
427 if (!segments[i].isEmpty()) {
428 encoded.append(URLEncoder.encode(segments[i], "UTF-8")
429 .replace("+", "%20"));
430 }
431 }
432
433 return encoded.toString();
434 }
435
436
437
438
439
440
441
442
443 public static String extractLastSection(String path) {
444 Objects.requireNonNull(path, "Path cannot be null");
445
446 int lastSlashIndex = path.lastIndexOf('/');
447
448 if (lastSlashIndex == -1) {
449 return "";
450 }
451
452 return path.substring(lastSlashIndex + 1);
453 }
454
455
456
457
458
459
460
461
462 public static String extractLastSectionOrDefault(String path, String defaultValue) {
463 if (path == null || path.isEmpty()) {
464 return defaultValue;
465 }
466
467 int lastSlashIndex = path.lastIndexOf('/');
468 if (lastSlashIndex == -1 || lastSlashIndex == path.length() - 1) {
469 return defaultValue;
470 }
471
472 return path.substring(lastSlashIndex + 1);
473 }
474 }